diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecWin.ui b/CasicBioRecWin.ui new file mode 100644 index 0000000..a08a0fd --- /dev/null +++ b/CasicBioRecWin.ui @@ -0,0 +1,29 @@ + + + CasicBioRecWin + + + + 0 + 0 + 1280 + 800 + + + + CasicBioRecWin + + + + + 0 + 0 + 1280 + 800 + + + + + + + diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecWin.ui b/CasicBioRecWin.ui new file mode 100644 index 0000000..a08a0fd --- /dev/null +++ b/CasicBioRecWin.ui @@ -0,0 +1,29 @@ + + + CasicBioRecWin + + + + 0 + 0 + 1280 + 800 + + + + CasicBioRecWin + + + + + 0 + 0 + 1280 + 800 + + + + + + + diff --git a/StartupForm.cpp b/StartupForm.cpp new file mode 100644 index 0000000..7fdf854 --- /dev/null +++ b/StartupForm.cpp @@ -0,0 +1,36 @@ +#include "StartupForm.h" +#include "ui_StartupForm.h" + +StartupForm::StartupForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::StartupForm) +{ + ui->setupUi(this); + + QFile file(QApplication::applicationDirPath() + "/qss/startup.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + this->updateDateAndTime(); + + // 初始化更新界面的定时器 + // 每分钟执行一次 + clockTimer = new QTimer(this); + connect(clockTimer, &QTimer::timeout, this, &StartupForm::updateDateAndTime); + clockTimer->start(1000); +} + +StartupForm::~StartupForm() +{ + delete ui; +} + +void StartupForm::updateDateAndTime() +{ + ui->labTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labDate->setText(QDate::currentDate().toString("yyyy-MM-dd")); +} diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecWin.ui b/CasicBioRecWin.ui new file mode 100644 index 0000000..a08a0fd --- /dev/null +++ b/CasicBioRecWin.ui @@ -0,0 +1,29 @@ + + + CasicBioRecWin + + + + 0 + 0 + 1280 + 800 + + + + CasicBioRecWin + + + + + 0 + 0 + 1280 + 800 + + + + + + + diff --git a/StartupForm.cpp b/StartupForm.cpp new file mode 100644 index 0000000..7fdf854 --- /dev/null +++ b/StartupForm.cpp @@ -0,0 +1,36 @@ +#include "StartupForm.h" +#include "ui_StartupForm.h" + +StartupForm::StartupForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::StartupForm) +{ + ui->setupUi(this); + + QFile file(QApplication::applicationDirPath() + "/qss/startup.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + this->updateDateAndTime(); + + // 初始化更新界面的定时器 + // 每分钟执行一次 + clockTimer = new QTimer(this); + connect(clockTimer, &QTimer::timeout, this, &StartupForm::updateDateAndTime); + clockTimer->start(1000); +} + +StartupForm::~StartupForm() +{ + delete ui; +} + +void StartupForm::updateDateAndTime() +{ + ui->labTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labDate->setText(QDate::currentDate().toString("yyyy-MM-dd")); +} diff --git a/StartupForm.h b/StartupForm.h new file mode 100644 index 0000000..2204b1a --- /dev/null +++ b/StartupForm.h @@ -0,0 +1,31 @@ +#ifndef STARTUPFORM_H +#define STARTUPFORM_H + +#include +#include +#include +#include +#include "utils/SettingConfig.h" + +namespace Ui { +class StartupForm; +} + +class StartupForm : public QWidget +{ + Q_OBJECT + +public: + explicit StartupForm(QWidget *parent = nullptr); + ~StartupForm(); + +private: + Ui::StartupForm *ui; + + QTimer * clockTimer; + +private slots: + void updateDateAndTime(); +}; + +#endif // STARTUPFORM_H diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecWin.ui b/CasicBioRecWin.ui new file mode 100644 index 0000000..a08a0fd --- /dev/null +++ b/CasicBioRecWin.ui @@ -0,0 +1,29 @@ + + + CasicBioRecWin + + + + 0 + 0 + 1280 + 800 + + + + CasicBioRecWin + + + + + 0 + 0 + 1280 + 800 + + + + + + + diff --git a/StartupForm.cpp b/StartupForm.cpp new file mode 100644 index 0000000..7fdf854 --- /dev/null +++ b/StartupForm.cpp @@ -0,0 +1,36 @@ +#include "StartupForm.h" +#include "ui_StartupForm.h" + +StartupForm::StartupForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::StartupForm) +{ + ui->setupUi(this); + + QFile file(QApplication::applicationDirPath() + "/qss/startup.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + this->updateDateAndTime(); + + // 初始化更新界面的定时器 + // 每分钟执行一次 + clockTimer = new QTimer(this); + connect(clockTimer, &QTimer::timeout, this, &StartupForm::updateDateAndTime); + clockTimer->start(1000); +} + +StartupForm::~StartupForm() +{ + delete ui; +} + +void StartupForm::updateDateAndTime() +{ + ui->labTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labDate->setText(QDate::currentDate().toString("yyyy-MM-dd")); +} diff --git a/StartupForm.h b/StartupForm.h new file mode 100644 index 0000000..2204b1a --- /dev/null +++ b/StartupForm.h @@ -0,0 +1,31 @@ +#ifndef STARTUPFORM_H +#define STARTUPFORM_H + +#include +#include +#include +#include +#include "utils/SettingConfig.h" + +namespace Ui { +class StartupForm; +} + +class StartupForm : public QWidget +{ + Q_OBJECT + +public: + explicit StartupForm(QWidget *parent = nullptr); + ~StartupForm(); + +private: + Ui::StartupForm *ui; + + QTimer * clockTimer; + +private slots: + void updateDateAndTime(); +}; + +#endif // STARTUPFORM_H diff --git a/StartupForm.ui b/StartupForm.ui new file mode 100644 index 0000000..1a8c5b2 --- /dev/null +++ b/StartupForm.ui @@ -0,0 +1,87 @@ + + + StartupForm + + + + 0 + 0 + 960 + 600 + + + + Form + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecWin.ui b/CasicBioRecWin.ui new file mode 100644 index 0000000..a08a0fd --- /dev/null +++ b/CasicBioRecWin.ui @@ -0,0 +1,29 @@ + + + CasicBioRecWin + + + + 0 + 0 + 1280 + 800 + + + + CasicBioRecWin + + + + + 0 + 0 + 1280 + 800 + + + + + + + diff --git a/StartupForm.cpp b/StartupForm.cpp new file mode 100644 index 0000000..7fdf854 --- /dev/null +++ b/StartupForm.cpp @@ -0,0 +1,36 @@ +#include "StartupForm.h" +#include "ui_StartupForm.h" + +StartupForm::StartupForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::StartupForm) +{ + ui->setupUi(this); + + QFile file(QApplication::applicationDirPath() + "/qss/startup.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + this->updateDateAndTime(); + + // 初始化更新界面的定时器 + // 每分钟执行一次 + clockTimer = new QTimer(this); + connect(clockTimer, &QTimer::timeout, this, &StartupForm::updateDateAndTime); + clockTimer->start(1000); +} + +StartupForm::~StartupForm() +{ + delete ui; +} + +void StartupForm::updateDateAndTime() +{ + ui->labTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labDate->setText(QDate::currentDate().toString("yyyy-MM-dd")); +} diff --git a/StartupForm.h b/StartupForm.h new file mode 100644 index 0000000..2204b1a --- /dev/null +++ b/StartupForm.h @@ -0,0 +1,31 @@ +#ifndef STARTUPFORM_H +#define STARTUPFORM_H + +#include +#include +#include +#include +#include "utils/SettingConfig.h" + +namespace Ui { +class StartupForm; +} + +class StartupForm : public QWidget +{ + Q_OBJECT + +public: + explicit StartupForm(QWidget *parent = nullptr); + ~StartupForm(); + +private: + Ui::StartupForm *ui; + + QTimer * clockTimer; + +private slots: + void updateDateAndTime(); +}; + +#endif // STARTUPFORM_H diff --git a/StartupForm.ui b/StartupForm.ui new file mode 100644 index 0000000..1a8c5b2 --- /dev/null +++ b/StartupForm.ui @@ -0,0 +1,87 @@ + + + StartupForm + + + + 0 + 0 + 960 + 600 + + + + Form + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/conf/config.ini b/conf/config.ini new file mode 100644 index 0000000..84e31c9 --- /dev/null +++ b/conf/config.ini @@ -0,0 +1,63 @@ +[com] +#电机控制的串口名 +motoPortName=COM3 + +[exe] +#外部exe路径 +outExeFile="D:\\deploy\\superSocket\\superSocketServer.exe" + +[recognize] +#最大允许识别时间(ms) +maxMatchTime=10000 +#识别成功界面停留时间(ms) +successTipsLast=5000 +#识别失败界面停留时间(ms) +failureTipsLast=3000 +#人脸识别最大尝试次数 +maxFaceTryCount=20 +#持续没找到人脸的最大次数 +maxFaceNotFoundCount=500 + +#虹膜识别最大尝试次数 +maxIrisTryCount=10 +#虹膜识别持续没有找到眼的最大次数 +maxEyeNotFoundCount=50 + +#识别方式[1=人脸;2=虹膜;3=双认证;4=任意] +recogType=4 + +[window] +#识别界面窗口宽(px) +width=1280 +#识别界面窗口高(px) +height=800 +#统一背景色 +backgroundColor="#FFFFFF" + +[camera] +#人脸摄像头的编号 +faceIndex=1 +#摄像头拍摄的画面宽(px) +faceFrameWidth=1280 +#摄像头拍摄的画面高(px) +faceFrameHeight=720 +#取一幅画面的时间间隔(ms) +frameInterval=50 +#虹膜相机取一幅画面的时间间隔(ms) +irisFrameInterval=100 +#虹膜相机拍摄宽度 +irisFrameWidth=1280 +#虹膜相机拍摄高度 +irisFrameHeight=960 +#虹膜图像高度 +irisWidth=640 +#虹膜图像高度 +irisHeight=480 + +[stack] +#拍摄图像栈最大值 +capture=50 +#找到的眼睛图像栈最大值 +found=30 +#质量合格图像栈最大值 +qualified=30 diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecWin.ui b/CasicBioRecWin.ui new file mode 100644 index 0000000..a08a0fd --- /dev/null +++ b/CasicBioRecWin.ui @@ -0,0 +1,29 @@ + + + CasicBioRecWin + + + + 0 + 0 + 1280 + 800 + + + + CasicBioRecWin + + + + + 0 + 0 + 1280 + 800 + + + + + + + diff --git a/StartupForm.cpp b/StartupForm.cpp new file mode 100644 index 0000000..7fdf854 --- /dev/null +++ b/StartupForm.cpp @@ -0,0 +1,36 @@ +#include "StartupForm.h" +#include "ui_StartupForm.h" + +StartupForm::StartupForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::StartupForm) +{ + ui->setupUi(this); + + QFile file(QApplication::applicationDirPath() + "/qss/startup.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + this->updateDateAndTime(); + + // 初始化更新界面的定时器 + // 每分钟执行一次 + clockTimer = new QTimer(this); + connect(clockTimer, &QTimer::timeout, this, &StartupForm::updateDateAndTime); + clockTimer->start(1000); +} + +StartupForm::~StartupForm() +{ + delete ui; +} + +void StartupForm::updateDateAndTime() +{ + ui->labTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labDate->setText(QDate::currentDate().toString("yyyy-MM-dd")); +} diff --git a/StartupForm.h b/StartupForm.h new file mode 100644 index 0000000..2204b1a --- /dev/null +++ b/StartupForm.h @@ -0,0 +1,31 @@ +#ifndef STARTUPFORM_H +#define STARTUPFORM_H + +#include +#include +#include +#include +#include "utils/SettingConfig.h" + +namespace Ui { +class StartupForm; +} + +class StartupForm : public QWidget +{ + Q_OBJECT + +public: + explicit StartupForm(QWidget *parent = nullptr); + ~StartupForm(); + +private: + Ui::StartupForm *ui; + + QTimer * clockTimer; + +private slots: + void updateDateAndTime(); +}; + +#endif // STARTUPFORM_H diff --git a/StartupForm.ui b/StartupForm.ui new file mode 100644 index 0000000..1a8c5b2 --- /dev/null +++ b/StartupForm.ui @@ -0,0 +1,87 @@ + + + StartupForm + + + + 0 + 0 + 960 + 600 + + + + Form + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/conf/config.ini b/conf/config.ini new file mode 100644 index 0000000..84e31c9 --- /dev/null +++ b/conf/config.ini @@ -0,0 +1,63 @@ +[com] +#电机控制的串口名 +motoPortName=COM3 + +[exe] +#外部exe路径 +outExeFile="D:\\deploy\\superSocket\\superSocketServer.exe" + +[recognize] +#最大允许识别时间(ms) +maxMatchTime=10000 +#识别成功界面停留时间(ms) +successTipsLast=5000 +#识别失败界面停留时间(ms) +failureTipsLast=3000 +#人脸识别最大尝试次数 +maxFaceTryCount=20 +#持续没找到人脸的最大次数 +maxFaceNotFoundCount=500 + +#虹膜识别最大尝试次数 +maxIrisTryCount=10 +#虹膜识别持续没有找到眼的最大次数 +maxEyeNotFoundCount=50 + +#识别方式[1=人脸;2=虹膜;3=双认证;4=任意] +recogType=4 + +[window] +#识别界面窗口宽(px) +width=1280 +#识别界面窗口高(px) +height=800 +#统一背景色 +backgroundColor="#FFFFFF" + +[camera] +#人脸摄像头的编号 +faceIndex=1 +#摄像头拍摄的画面宽(px) +faceFrameWidth=1280 +#摄像头拍摄的画面高(px) +faceFrameHeight=720 +#取一幅画面的时间间隔(ms) +frameInterval=50 +#虹膜相机取一幅画面的时间间隔(ms) +irisFrameInterval=100 +#虹膜相机拍摄宽度 +irisFrameWidth=1280 +#虹膜相机拍摄高度 +irisFrameHeight=960 +#虹膜图像高度 +irisWidth=640 +#虹膜图像高度 +irisHeight=480 + +[stack] +#拍摄图像栈最大值 +capture=50 +#找到的眼睛图像栈最大值 +found=30 +#质量合格图像栈最大值 +qualified=30 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..51b5337 --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "CasicBioRecWin.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + CasicBioRecWin w; + w.show(); + return a.exec(); +} diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecWin.ui b/CasicBioRecWin.ui new file mode 100644 index 0000000..a08a0fd --- /dev/null +++ b/CasicBioRecWin.ui @@ -0,0 +1,29 @@ + + + CasicBioRecWin + + + + 0 + 0 + 1280 + 800 + + + + CasicBioRecWin + + + + + 0 + 0 + 1280 + 800 + + + + + + + diff --git a/StartupForm.cpp b/StartupForm.cpp new file mode 100644 index 0000000..7fdf854 --- /dev/null +++ b/StartupForm.cpp @@ -0,0 +1,36 @@ +#include "StartupForm.h" +#include "ui_StartupForm.h" + +StartupForm::StartupForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::StartupForm) +{ + ui->setupUi(this); + + QFile file(QApplication::applicationDirPath() + "/qss/startup.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + this->updateDateAndTime(); + + // 初始化更新界面的定时器 + // 每分钟执行一次 + clockTimer = new QTimer(this); + connect(clockTimer, &QTimer::timeout, this, &StartupForm::updateDateAndTime); + clockTimer->start(1000); +} + +StartupForm::~StartupForm() +{ + delete ui; +} + +void StartupForm::updateDateAndTime() +{ + ui->labTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labDate->setText(QDate::currentDate().toString("yyyy-MM-dd")); +} diff --git a/StartupForm.h b/StartupForm.h new file mode 100644 index 0000000..2204b1a --- /dev/null +++ b/StartupForm.h @@ -0,0 +1,31 @@ +#ifndef STARTUPFORM_H +#define STARTUPFORM_H + +#include +#include +#include +#include +#include "utils/SettingConfig.h" + +namespace Ui { +class StartupForm; +} + +class StartupForm : public QWidget +{ + Q_OBJECT + +public: + explicit StartupForm(QWidget *parent = nullptr); + ~StartupForm(); + +private: + Ui::StartupForm *ui; + + QTimer * clockTimer; + +private slots: + void updateDateAndTime(); +}; + +#endif // STARTUPFORM_H diff --git a/StartupForm.ui b/StartupForm.ui new file mode 100644 index 0000000..1a8c5b2 --- /dev/null +++ b/StartupForm.ui @@ -0,0 +1,87 @@ + + + StartupForm + + + + 0 + 0 + 960 + 600 + + + + Form + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/conf/config.ini b/conf/config.ini new file mode 100644 index 0000000..84e31c9 --- /dev/null +++ b/conf/config.ini @@ -0,0 +1,63 @@ +[com] +#电机控制的串口名 +motoPortName=COM3 + +[exe] +#外部exe路径 +outExeFile="D:\\deploy\\superSocket\\superSocketServer.exe" + +[recognize] +#最大允许识别时间(ms) +maxMatchTime=10000 +#识别成功界面停留时间(ms) +successTipsLast=5000 +#识别失败界面停留时间(ms) +failureTipsLast=3000 +#人脸识别最大尝试次数 +maxFaceTryCount=20 +#持续没找到人脸的最大次数 +maxFaceNotFoundCount=500 + +#虹膜识别最大尝试次数 +maxIrisTryCount=10 +#虹膜识别持续没有找到眼的最大次数 +maxEyeNotFoundCount=50 + +#识别方式[1=人脸;2=虹膜;3=双认证;4=任意] +recogType=4 + +[window] +#识别界面窗口宽(px) +width=1280 +#识别界面窗口高(px) +height=800 +#统一背景色 +backgroundColor="#FFFFFF" + +[camera] +#人脸摄像头的编号 +faceIndex=1 +#摄像头拍摄的画面宽(px) +faceFrameWidth=1280 +#摄像头拍摄的画面高(px) +faceFrameHeight=720 +#取一幅画面的时间间隔(ms) +frameInterval=50 +#虹膜相机取一幅画面的时间间隔(ms) +irisFrameInterval=100 +#虹膜相机拍摄宽度 +irisFrameWidth=1280 +#虹膜相机拍摄高度 +irisFrameHeight=960 +#虹膜图像高度 +irisWidth=640 +#虹膜图像高度 +irisHeight=480 + +[stack] +#拍摄图像栈最大值 +capture=50 +#找到的眼睛图像栈最大值 +found=30 +#质量合格图像栈最大值 +qualified=30 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..51b5337 --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "CasicBioRecWin.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + CasicBioRecWin w; + w.show(); + return a.exec(); +} diff --git a/qss/startup.css b/qss/startup.css new file mode 100644 index 0000000..bfad9df --- /dev/null +++ b/qss/startup.css @@ -0,0 +1,12 @@ +QLabel { + color: #6868A6; + font-family: "Microsoft YaHei"; +} + +QLabel#labDate { + font-size: 36px; +} + +QLabel#labTime { + font-size: 100px; +} \ No newline at end of file diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecWin.ui b/CasicBioRecWin.ui new file mode 100644 index 0000000..a08a0fd --- /dev/null +++ b/CasicBioRecWin.ui @@ -0,0 +1,29 @@ + + + CasicBioRecWin + + + + 0 + 0 + 1280 + 800 + + + + CasicBioRecWin + + + + + 0 + 0 + 1280 + 800 + + + + + + + diff --git a/StartupForm.cpp b/StartupForm.cpp new file mode 100644 index 0000000..7fdf854 --- /dev/null +++ b/StartupForm.cpp @@ -0,0 +1,36 @@ +#include "StartupForm.h" +#include "ui_StartupForm.h" + +StartupForm::StartupForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::StartupForm) +{ + ui->setupUi(this); + + QFile file(QApplication::applicationDirPath() + "/qss/startup.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + this->updateDateAndTime(); + + // 初始化更新界面的定时器 + // 每分钟执行一次 + clockTimer = new QTimer(this); + connect(clockTimer, &QTimer::timeout, this, &StartupForm::updateDateAndTime); + clockTimer->start(1000); +} + +StartupForm::~StartupForm() +{ + delete ui; +} + +void StartupForm::updateDateAndTime() +{ + ui->labTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labDate->setText(QDate::currentDate().toString("yyyy-MM-dd")); +} diff --git a/StartupForm.h b/StartupForm.h new file mode 100644 index 0000000..2204b1a --- /dev/null +++ b/StartupForm.h @@ -0,0 +1,31 @@ +#ifndef STARTUPFORM_H +#define STARTUPFORM_H + +#include +#include +#include +#include +#include "utils/SettingConfig.h" + +namespace Ui { +class StartupForm; +} + +class StartupForm : public QWidget +{ + Q_OBJECT + +public: + explicit StartupForm(QWidget *parent = nullptr); + ~StartupForm(); + +private: + Ui::StartupForm *ui; + + QTimer * clockTimer; + +private slots: + void updateDateAndTime(); +}; + +#endif // STARTUPFORM_H diff --git a/StartupForm.ui b/StartupForm.ui new file mode 100644 index 0000000..1a8c5b2 --- /dev/null +++ b/StartupForm.ui @@ -0,0 +1,87 @@ + + + StartupForm + + + + 0 + 0 + 960 + 600 + + + + Form + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/conf/config.ini b/conf/config.ini new file mode 100644 index 0000000..84e31c9 --- /dev/null +++ b/conf/config.ini @@ -0,0 +1,63 @@ +[com] +#电机控制的串口名 +motoPortName=COM3 + +[exe] +#外部exe路径 +outExeFile="D:\\deploy\\superSocket\\superSocketServer.exe" + +[recognize] +#最大允许识别时间(ms) +maxMatchTime=10000 +#识别成功界面停留时间(ms) +successTipsLast=5000 +#识别失败界面停留时间(ms) +failureTipsLast=3000 +#人脸识别最大尝试次数 +maxFaceTryCount=20 +#持续没找到人脸的最大次数 +maxFaceNotFoundCount=500 + +#虹膜识别最大尝试次数 +maxIrisTryCount=10 +#虹膜识别持续没有找到眼的最大次数 +maxEyeNotFoundCount=50 + +#识别方式[1=人脸;2=虹膜;3=双认证;4=任意] +recogType=4 + +[window] +#识别界面窗口宽(px) +width=1280 +#识别界面窗口高(px) +height=800 +#统一背景色 +backgroundColor="#FFFFFF" + +[camera] +#人脸摄像头的编号 +faceIndex=1 +#摄像头拍摄的画面宽(px) +faceFrameWidth=1280 +#摄像头拍摄的画面高(px) +faceFrameHeight=720 +#取一幅画面的时间间隔(ms) +frameInterval=50 +#虹膜相机取一幅画面的时间间隔(ms) +irisFrameInterval=100 +#虹膜相机拍摄宽度 +irisFrameWidth=1280 +#虹膜相机拍摄高度 +irisFrameHeight=960 +#虹膜图像高度 +irisWidth=640 +#虹膜图像高度 +irisHeight=480 + +[stack] +#拍摄图像栈最大值 +capture=50 +#找到的眼睛图像栈最大值 +found=30 +#质量合格图像栈最大值 +qualified=30 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..51b5337 --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "CasicBioRecWin.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + CasicBioRecWin w; + w.show(); + return a.exec(); +} diff --git a/qss/startup.css b/qss/startup.css new file mode 100644 index 0000000..bfad9df --- /dev/null +++ b/qss/startup.css @@ -0,0 +1,12 @@ +QLabel { + color: #6868A6; + font-family: "Microsoft YaHei"; +} + +QLabel#labDate { + font-size: 36px; +} + +QLabel#labTime { + font-size: 100px; +} \ No newline at end of file diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp new file mode 100644 index 0000000..13976d3 --- /dev/null +++ b/utils/SettingConfig.cpp @@ -0,0 +1,46 @@ +#include "SettingConfig.h" +#include + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + WINDOW_WIDTH = getProperty("window", "width").toInt(); + WINDOW_HEIGHT = getProperty("window", "height").toInt(); + WINDOW_BACKGROUND_COLOR = getProperty("window", "backgroundColor").toString(); + + OUT_EXE_FILE = getProperty("exe", "outExeFile").toString(); + + FACE_CAMERA_INDEX = getProperty("camera", "faceIndex").toInt(); + FACE_FRAME_WIDTH = getProperty("camera", "faceFrameWidth").toInt(); + FACE_FRAME_HEIGHT = getProperty("camera", "faceFrameHeight").toInt(); + FACE_FRAME_INTERVAL = getProperty("camera", "frameInterval").toInt(); + IRIS_FRAME_WIDTH = getProperty("camera", "irisFrameWidth").toInt(); + IRIS_FRAME_HEIGHT = getProperty("camera", "irisFrameHeight").toInt(); + IRIS_WIDTH = getProperty("camera", "irisWidth").toInt(); + IRIS_HEIGHT = getProperty("camera", "irisHeight").toInt(); + IRIS_FRAME_INTERVAL = getProperty("camera", "irisFrameInterval").toInt(); + + MAX_MATCH_TIME = getProperty("recognize", "maxMatchTime").toInt(); + SUCCESS_TIPS_LAST = getProperty("recognize", "successTipsLast").toInt(); + FAILURE_TIPS_LAST = getProperty("recognize", "failureTipsLast").toInt(); + MAX_FACE_TRY_COUNT = getProperty("recognize", "maxFaceTryCount").toInt(); + MAX_FACE_NOT_FOUND_COUNT = getProperty("recognize", "maxFaceNotFoundCount").toInt(); + MAX_IRIS_TRY_COUNT = getProperty("recognize", "maxIrisTryCount").toInt(); + MAX_EYE_NOT_FOUND_COUNT = getProperty("recognize", "maxEyeNotFoundCount").toInt(); + + MAX_CAPTURE_STACK_SIZE = getProperty("stack", "capture").toInt(); + MAX_FOUND_STACK_SIZE = getProperty("stack", "found").toInt(); + MAX_QUALIFIED_STACK_SIZE = getProperty("stack", "qualified").toInt(); + + PORT_NAME = getProperty("com", "motoPortName").toString(); + + RECOG_TYPE = getProperty("recognize", "recogType").toInt(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecWin.ui b/CasicBioRecWin.ui new file mode 100644 index 0000000..a08a0fd --- /dev/null +++ b/CasicBioRecWin.ui @@ -0,0 +1,29 @@ + + + CasicBioRecWin + + + + 0 + 0 + 1280 + 800 + + + + CasicBioRecWin + + + + + 0 + 0 + 1280 + 800 + + + + + + + diff --git a/StartupForm.cpp b/StartupForm.cpp new file mode 100644 index 0000000..7fdf854 --- /dev/null +++ b/StartupForm.cpp @@ -0,0 +1,36 @@ +#include "StartupForm.h" +#include "ui_StartupForm.h" + +StartupForm::StartupForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::StartupForm) +{ + ui->setupUi(this); + + QFile file(QApplication::applicationDirPath() + "/qss/startup.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + this->updateDateAndTime(); + + // 初始化更新界面的定时器 + // 每分钟执行一次 + clockTimer = new QTimer(this); + connect(clockTimer, &QTimer::timeout, this, &StartupForm::updateDateAndTime); + clockTimer->start(1000); +} + +StartupForm::~StartupForm() +{ + delete ui; +} + +void StartupForm::updateDateAndTime() +{ + ui->labTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labDate->setText(QDate::currentDate().toString("yyyy-MM-dd")); +} diff --git a/StartupForm.h b/StartupForm.h new file mode 100644 index 0000000..2204b1a --- /dev/null +++ b/StartupForm.h @@ -0,0 +1,31 @@ +#ifndef STARTUPFORM_H +#define STARTUPFORM_H + +#include +#include +#include +#include +#include "utils/SettingConfig.h" + +namespace Ui { +class StartupForm; +} + +class StartupForm : public QWidget +{ + Q_OBJECT + +public: + explicit StartupForm(QWidget *parent = nullptr); + ~StartupForm(); + +private: + Ui::StartupForm *ui; + + QTimer * clockTimer; + +private slots: + void updateDateAndTime(); +}; + +#endif // STARTUPFORM_H diff --git a/StartupForm.ui b/StartupForm.ui new file mode 100644 index 0000000..1a8c5b2 --- /dev/null +++ b/StartupForm.ui @@ -0,0 +1,87 @@ + + + StartupForm + + + + 0 + 0 + 960 + 600 + + + + Form + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/conf/config.ini b/conf/config.ini new file mode 100644 index 0000000..84e31c9 --- /dev/null +++ b/conf/config.ini @@ -0,0 +1,63 @@ +[com] +#电机控制的串口名 +motoPortName=COM3 + +[exe] +#外部exe路径 +outExeFile="D:\\deploy\\superSocket\\superSocketServer.exe" + +[recognize] +#最大允许识别时间(ms) +maxMatchTime=10000 +#识别成功界面停留时间(ms) +successTipsLast=5000 +#识别失败界面停留时间(ms) +failureTipsLast=3000 +#人脸识别最大尝试次数 +maxFaceTryCount=20 +#持续没找到人脸的最大次数 +maxFaceNotFoundCount=500 + +#虹膜识别最大尝试次数 +maxIrisTryCount=10 +#虹膜识别持续没有找到眼的最大次数 +maxEyeNotFoundCount=50 + +#识别方式[1=人脸;2=虹膜;3=双认证;4=任意] +recogType=4 + +[window] +#识别界面窗口宽(px) +width=1280 +#识别界面窗口高(px) +height=800 +#统一背景色 +backgroundColor="#FFFFFF" + +[camera] +#人脸摄像头的编号 +faceIndex=1 +#摄像头拍摄的画面宽(px) +faceFrameWidth=1280 +#摄像头拍摄的画面高(px) +faceFrameHeight=720 +#取一幅画面的时间间隔(ms) +frameInterval=50 +#虹膜相机取一幅画面的时间间隔(ms) +irisFrameInterval=100 +#虹膜相机拍摄宽度 +irisFrameWidth=1280 +#虹膜相机拍摄高度 +irisFrameHeight=960 +#虹膜图像高度 +irisWidth=640 +#虹膜图像高度 +irisHeight=480 + +[stack] +#拍摄图像栈最大值 +capture=50 +#找到的眼睛图像栈最大值 +found=30 +#质量合格图像栈最大值 +qualified=30 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..51b5337 --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "CasicBioRecWin.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + CasicBioRecWin w; + w.show(); + return a.exec(); +} diff --git a/qss/startup.css b/qss/startup.css new file mode 100644 index 0000000..bfad9df --- /dev/null +++ b/qss/startup.css @@ -0,0 +1,12 @@ +QLabel { + color: #6868A6; + font-family: "Microsoft YaHei"; +} + +QLabel#labDate { + font-size: 36px; +} + +QLabel#labTime { + font-size: 100px; +} \ No newline at end of file diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp new file mode 100644 index 0000000..13976d3 --- /dev/null +++ b/utils/SettingConfig.cpp @@ -0,0 +1,46 @@ +#include "SettingConfig.h" +#include + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + WINDOW_WIDTH = getProperty("window", "width").toInt(); + WINDOW_HEIGHT = getProperty("window", "height").toInt(); + WINDOW_BACKGROUND_COLOR = getProperty("window", "backgroundColor").toString(); + + OUT_EXE_FILE = getProperty("exe", "outExeFile").toString(); + + FACE_CAMERA_INDEX = getProperty("camera", "faceIndex").toInt(); + FACE_FRAME_WIDTH = getProperty("camera", "faceFrameWidth").toInt(); + FACE_FRAME_HEIGHT = getProperty("camera", "faceFrameHeight").toInt(); + FACE_FRAME_INTERVAL = getProperty("camera", "frameInterval").toInt(); + IRIS_FRAME_WIDTH = getProperty("camera", "irisFrameWidth").toInt(); + IRIS_FRAME_HEIGHT = getProperty("camera", "irisFrameHeight").toInt(); + IRIS_WIDTH = getProperty("camera", "irisWidth").toInt(); + IRIS_HEIGHT = getProperty("camera", "irisHeight").toInt(); + IRIS_FRAME_INTERVAL = getProperty("camera", "irisFrameInterval").toInt(); + + MAX_MATCH_TIME = getProperty("recognize", "maxMatchTime").toInt(); + SUCCESS_TIPS_LAST = getProperty("recognize", "successTipsLast").toInt(); + FAILURE_TIPS_LAST = getProperty("recognize", "failureTipsLast").toInt(); + MAX_FACE_TRY_COUNT = getProperty("recognize", "maxFaceTryCount").toInt(); + MAX_FACE_NOT_FOUND_COUNT = getProperty("recognize", "maxFaceNotFoundCount").toInt(); + MAX_IRIS_TRY_COUNT = getProperty("recognize", "maxIrisTryCount").toInt(); + MAX_EYE_NOT_FOUND_COUNT = getProperty("recognize", "maxEyeNotFoundCount").toInt(); + + MAX_CAPTURE_STACK_SIZE = getProperty("stack", "capture").toInt(); + MAX_FOUND_STACK_SIZE = getProperty("stack", "found").toInt(); + MAX_QUALIFIED_STACK_SIZE = getProperty("stack", "qualified").toInt(); + + PORT_NAME = getProperty("com", "motoPortName").toString(); + + RECOG_TYPE = getProperty("recognize", "recogType").toInt(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h new file mode 100644 index 0000000..f2f8e98 --- /dev/null +++ b/utils/SettingConfig.h @@ -0,0 +1,68 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + int WINDOW_WIDTH; + int WINDOW_HEIGHT; + QString WINDOW_BACKGROUND_COLOR; + + QString OUT_EXE_FILE; + + int FACE_CAMERA_INDEX; + int FACE_FRAME_WIDTH; + int FACE_FRAME_HEIGHT; + int FACE_FRAME_INTERVAL; + int IRIS_FRAME_INTERVAL; + int IRIS_FRAME_WIDTH; + int IRIS_FRAME_HEIGHT; + int IRIS_WIDTH; + int IRIS_HEIGHT; + + int MAX_MATCH_TIME; + int SUCCESS_TIPS_LAST; + int FAILURE_TIPS_LAST; + int MAX_FACE_TRY_COUNT; + int MAX_FACE_NOT_FOUND_COUNT; + int MAX_IRIS_TRY_COUNT; + int MAX_EYE_NOT_FOUND_COUNT; + + int MAX_CAPTURE_STACK_SIZE; + int MAX_FOUND_STACK_SIZE; + int MAX_QUALIFIED_STACK_SIZE; + + QString PORT_NAME; + + int RECOG_TYPE = 0; + +private: + SettingConfig(); + + QString filename; + QSettings* setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecWin.ui b/CasicBioRecWin.ui new file mode 100644 index 0000000..a08a0fd --- /dev/null +++ b/CasicBioRecWin.ui @@ -0,0 +1,29 @@ + + + CasicBioRecWin + + + + 0 + 0 + 1280 + 800 + + + + CasicBioRecWin + + + + + 0 + 0 + 1280 + 800 + + + + + + + diff --git a/StartupForm.cpp b/StartupForm.cpp new file mode 100644 index 0000000..7fdf854 --- /dev/null +++ b/StartupForm.cpp @@ -0,0 +1,36 @@ +#include "StartupForm.h" +#include "ui_StartupForm.h" + +StartupForm::StartupForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::StartupForm) +{ + ui->setupUi(this); + + QFile file(QApplication::applicationDirPath() + "/qss/startup.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + this->updateDateAndTime(); + + // 初始化更新界面的定时器 + // 每分钟执行一次 + clockTimer = new QTimer(this); + connect(clockTimer, &QTimer::timeout, this, &StartupForm::updateDateAndTime); + clockTimer->start(1000); +} + +StartupForm::~StartupForm() +{ + delete ui; +} + +void StartupForm::updateDateAndTime() +{ + ui->labTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labDate->setText(QDate::currentDate().toString("yyyy-MM-dd")); +} diff --git a/StartupForm.h b/StartupForm.h new file mode 100644 index 0000000..2204b1a --- /dev/null +++ b/StartupForm.h @@ -0,0 +1,31 @@ +#ifndef STARTUPFORM_H +#define STARTUPFORM_H + +#include +#include +#include +#include +#include "utils/SettingConfig.h" + +namespace Ui { +class StartupForm; +} + +class StartupForm : public QWidget +{ + Q_OBJECT + +public: + explicit StartupForm(QWidget *parent = nullptr); + ~StartupForm(); + +private: + Ui::StartupForm *ui; + + QTimer * clockTimer; + +private slots: + void updateDateAndTime(); +}; + +#endif // STARTUPFORM_H diff --git a/StartupForm.ui b/StartupForm.ui new file mode 100644 index 0000000..1a8c5b2 --- /dev/null +++ b/StartupForm.ui @@ -0,0 +1,87 @@ + + + StartupForm + + + + 0 + 0 + 960 + 600 + + + + Form + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/conf/config.ini b/conf/config.ini new file mode 100644 index 0000000..84e31c9 --- /dev/null +++ b/conf/config.ini @@ -0,0 +1,63 @@ +[com] +#电机控制的串口名 +motoPortName=COM3 + +[exe] +#外部exe路径 +outExeFile="D:\\deploy\\superSocket\\superSocketServer.exe" + +[recognize] +#最大允许识别时间(ms) +maxMatchTime=10000 +#识别成功界面停留时间(ms) +successTipsLast=5000 +#识别失败界面停留时间(ms) +failureTipsLast=3000 +#人脸识别最大尝试次数 +maxFaceTryCount=20 +#持续没找到人脸的最大次数 +maxFaceNotFoundCount=500 + +#虹膜识别最大尝试次数 +maxIrisTryCount=10 +#虹膜识别持续没有找到眼的最大次数 +maxEyeNotFoundCount=50 + +#识别方式[1=人脸;2=虹膜;3=双认证;4=任意] +recogType=4 + +[window] +#识别界面窗口宽(px) +width=1280 +#识别界面窗口高(px) +height=800 +#统一背景色 +backgroundColor="#FFFFFF" + +[camera] +#人脸摄像头的编号 +faceIndex=1 +#摄像头拍摄的画面宽(px) +faceFrameWidth=1280 +#摄像头拍摄的画面高(px) +faceFrameHeight=720 +#取一幅画面的时间间隔(ms) +frameInterval=50 +#虹膜相机取一幅画面的时间间隔(ms) +irisFrameInterval=100 +#虹膜相机拍摄宽度 +irisFrameWidth=1280 +#虹膜相机拍摄高度 +irisFrameHeight=960 +#虹膜图像高度 +irisWidth=640 +#虹膜图像高度 +irisHeight=480 + +[stack] +#拍摄图像栈最大值 +capture=50 +#找到的眼睛图像栈最大值 +found=30 +#质量合格图像栈最大值 +qualified=30 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..51b5337 --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "CasicBioRecWin.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + CasicBioRecWin w; + w.show(); + return a.exec(); +} diff --git a/qss/startup.css b/qss/startup.css new file mode 100644 index 0000000..bfad9df --- /dev/null +++ b/qss/startup.css @@ -0,0 +1,12 @@ +QLabel { + color: #6868A6; + font-family: "Microsoft YaHei"; +} + +QLabel#labDate { + font-size: 36px; +} + +QLabel#labTime { + font-size: 100px; +} \ No newline at end of file diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp new file mode 100644 index 0000000..13976d3 --- /dev/null +++ b/utils/SettingConfig.cpp @@ -0,0 +1,46 @@ +#include "SettingConfig.h" +#include + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + WINDOW_WIDTH = getProperty("window", "width").toInt(); + WINDOW_HEIGHT = getProperty("window", "height").toInt(); + WINDOW_BACKGROUND_COLOR = getProperty("window", "backgroundColor").toString(); + + OUT_EXE_FILE = getProperty("exe", "outExeFile").toString(); + + FACE_CAMERA_INDEX = getProperty("camera", "faceIndex").toInt(); + FACE_FRAME_WIDTH = getProperty("camera", "faceFrameWidth").toInt(); + FACE_FRAME_HEIGHT = getProperty("camera", "faceFrameHeight").toInt(); + FACE_FRAME_INTERVAL = getProperty("camera", "frameInterval").toInt(); + IRIS_FRAME_WIDTH = getProperty("camera", "irisFrameWidth").toInt(); + IRIS_FRAME_HEIGHT = getProperty("camera", "irisFrameHeight").toInt(); + IRIS_WIDTH = getProperty("camera", "irisWidth").toInt(); + IRIS_HEIGHT = getProperty("camera", "irisHeight").toInt(); + IRIS_FRAME_INTERVAL = getProperty("camera", "irisFrameInterval").toInt(); + + MAX_MATCH_TIME = getProperty("recognize", "maxMatchTime").toInt(); + SUCCESS_TIPS_LAST = getProperty("recognize", "successTipsLast").toInt(); + FAILURE_TIPS_LAST = getProperty("recognize", "failureTipsLast").toInt(); + MAX_FACE_TRY_COUNT = getProperty("recognize", "maxFaceTryCount").toInt(); + MAX_FACE_NOT_FOUND_COUNT = getProperty("recognize", "maxFaceNotFoundCount").toInt(); + MAX_IRIS_TRY_COUNT = getProperty("recognize", "maxIrisTryCount").toInt(); + MAX_EYE_NOT_FOUND_COUNT = getProperty("recognize", "maxEyeNotFoundCount").toInt(); + + MAX_CAPTURE_STACK_SIZE = getProperty("stack", "capture").toInt(); + MAX_FOUND_STACK_SIZE = getProperty("stack", "found").toInt(); + MAX_QUALIFIED_STACK_SIZE = getProperty("stack", "qualified").toInt(); + + PORT_NAME = getProperty("com", "motoPortName").toString(); + + RECOG_TYPE = getProperty("recognize", "recogType").toInt(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h new file mode 100644 index 0000000..f2f8e98 --- /dev/null +++ b/utils/SettingConfig.h @@ -0,0 +1,68 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + int WINDOW_WIDTH; + int WINDOW_HEIGHT; + QString WINDOW_BACKGROUND_COLOR; + + QString OUT_EXE_FILE; + + int FACE_CAMERA_INDEX; + int FACE_FRAME_WIDTH; + int FACE_FRAME_HEIGHT; + int FACE_FRAME_INTERVAL; + int IRIS_FRAME_INTERVAL; + int IRIS_FRAME_WIDTH; + int IRIS_FRAME_HEIGHT; + int IRIS_WIDTH; + int IRIS_HEIGHT; + + int MAX_MATCH_TIME; + int SUCCESS_TIPS_LAST; + int FAILURE_TIPS_LAST; + int MAX_FACE_TRY_COUNT; + int MAX_FACE_NOT_FOUND_COUNT; + int MAX_IRIS_TRY_COUNT; + int MAX_EYE_NOT_FOUND_COUNT; + + int MAX_CAPTURE_STACK_SIZE; + int MAX_FOUND_STACK_SIZE; + int MAX_QUALIFIED_STACK_SIZE; + + QString PORT_NAME; + + int RECOG_TYPE = 0; + +private: + SettingConfig(); + + QString filename; + QSettings* setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/utils/id/IdWorker.h b/utils/id/IdWorker.h new file mode 100644 index 0000000..6c48aa9 --- /dev/null +++ b/utils/id/IdWorker.h @@ -0,0 +1,218 @@ +#ifndef _JW_CORE_ID_WORKER_H_ +#define _JW_CORE_ID_WORKER_H_ + +#include +#include +#include +#include +#include +#include "Noncopyable.h" +#include "Singleton.h" + +// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 +// #define SNOWFLAKE_ID_WORKER_NO_LOCK + +namespace Jiawa { + + /** + * @brief 核心 + * 核心功能 + */ + namespace Core { + + /** + * @brief 分布式id生成类 + * https://segmentfault.com/a/1190000011282426 + * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala + * + * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + * || || || | | | + * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ + * | + * 不用 + * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. + */ + class SnowflakeIdWorker : private Noncopyable { + + // 实现单例 + friend class Singleton; + + public: + typedef unsigned int UInt; + typedef unsigned long long int UInt64; + +#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK + typedef std::atomic AtomicUInt; + typedef std::atomic AtomicUInt64; +#else + typedef UInt AtomicUInt; + typedef UInt64 AtomicUInt64; +#endif + + void setWorkerId(UInt workerId) { + this->workerId = workerId; + } + + void setDatacenterId(UInt datacenterId) { + this->datacenterId = datacenterId; + } + + UInt64 getId() { + return nextId(); + } + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + UInt64 nextId() { +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::unique_lock lock{ mutex }; + AtomicUInt64 timestamp{ 0 }; +#else + static AtomicUInt64 timestamp{ 0 }; +#endif + timestamp = timeGen(); + + // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + std::ostringstream s; + s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; + throw std::exception(std::runtime_error(s.str())); + } + + if (lastTimestamp == timestamp) { + // 如果是同一时间生成的, 则进行毫秒内序列 + sequence = (sequence + 1) & sequenceMask; + if (0 == sequence) { + // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0; + } + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + lastTimestamp = timestamp; +#else + lastTimestamp = timestamp.load(); +#endif + + // 移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + } + + protected: + SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + UInt64 timeGen() const { + auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); + return t.time_since_epoch().count(); + } + + /** + * 阻塞到下一个毫秒, 直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + UInt64 tilNextMillis(UInt64 lastTimestamp) const { + UInt64 timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + private: + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::mutex mutex; +#endif + + /** + * 开始时间截 (2018-01-01 00:00:00.000) + */ + const UInt64 twepoch = 1514736000000; + + /** + * 机器id所占的位数 + */ + const UInt workerIdBits = 5; + + /** + * 数据中心id所占的位数 + */ + const UInt datacenterIdBits = 5; + + /** + * 序列所占的位数 + */ + const UInt sequenceBits = 12; + + /** + * 机器ID向左移12位 + */ + const UInt workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位 + */ + const UInt datacenterIdShift = workerIdShift + workerIdBits; + + /** + * 时间截向左移22位 + */ + const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; + + /** + * 支持的最大机器id, 结果是31 + */ + const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); + + /** + * 支持的最大数据中心id, 结果是31 + */ + const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); + + /** + * 生成序列的掩码, 这里为4095 + */ + const UInt sequenceMask = -1 ^ (-1 << sequenceBits); + + /** + * 工作机器id(0~31) + */ + UInt workerId; + + /** + * 数据中心id(0~31) + */ + UInt datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + AtomicUInt sequence{ 0 }; + + /** + * 上次生成ID的时间截 + */ + AtomicUInt64 lastTimestamp{ 0 }; + + }; + + typedef SnowflakeIdWorker IdWorker; + } +} + +#endif // _JW_CORE_ID_WORKER_H_ diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecWin.ui b/CasicBioRecWin.ui new file mode 100644 index 0000000..a08a0fd --- /dev/null +++ b/CasicBioRecWin.ui @@ -0,0 +1,29 @@ + + + CasicBioRecWin + + + + 0 + 0 + 1280 + 800 + + + + CasicBioRecWin + + + + + 0 + 0 + 1280 + 800 + + + + + + + diff --git a/StartupForm.cpp b/StartupForm.cpp new file mode 100644 index 0000000..7fdf854 --- /dev/null +++ b/StartupForm.cpp @@ -0,0 +1,36 @@ +#include "StartupForm.h" +#include "ui_StartupForm.h" + +StartupForm::StartupForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::StartupForm) +{ + ui->setupUi(this); + + QFile file(QApplication::applicationDirPath() + "/qss/startup.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + this->updateDateAndTime(); + + // 初始化更新界面的定时器 + // 每分钟执行一次 + clockTimer = new QTimer(this); + connect(clockTimer, &QTimer::timeout, this, &StartupForm::updateDateAndTime); + clockTimer->start(1000); +} + +StartupForm::~StartupForm() +{ + delete ui; +} + +void StartupForm::updateDateAndTime() +{ + ui->labTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labDate->setText(QDate::currentDate().toString("yyyy-MM-dd")); +} diff --git a/StartupForm.h b/StartupForm.h new file mode 100644 index 0000000..2204b1a --- /dev/null +++ b/StartupForm.h @@ -0,0 +1,31 @@ +#ifndef STARTUPFORM_H +#define STARTUPFORM_H + +#include +#include +#include +#include +#include "utils/SettingConfig.h" + +namespace Ui { +class StartupForm; +} + +class StartupForm : public QWidget +{ + Q_OBJECT + +public: + explicit StartupForm(QWidget *parent = nullptr); + ~StartupForm(); + +private: + Ui::StartupForm *ui; + + QTimer * clockTimer; + +private slots: + void updateDateAndTime(); +}; + +#endif // STARTUPFORM_H diff --git a/StartupForm.ui b/StartupForm.ui new file mode 100644 index 0000000..1a8c5b2 --- /dev/null +++ b/StartupForm.ui @@ -0,0 +1,87 @@ + + + StartupForm + + + + 0 + 0 + 960 + 600 + + + + Form + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/conf/config.ini b/conf/config.ini new file mode 100644 index 0000000..84e31c9 --- /dev/null +++ b/conf/config.ini @@ -0,0 +1,63 @@ +[com] +#电机控制的串口名 +motoPortName=COM3 + +[exe] +#外部exe路径 +outExeFile="D:\\deploy\\superSocket\\superSocketServer.exe" + +[recognize] +#最大允许识别时间(ms) +maxMatchTime=10000 +#识别成功界面停留时间(ms) +successTipsLast=5000 +#识别失败界面停留时间(ms) +failureTipsLast=3000 +#人脸识别最大尝试次数 +maxFaceTryCount=20 +#持续没找到人脸的最大次数 +maxFaceNotFoundCount=500 + +#虹膜识别最大尝试次数 +maxIrisTryCount=10 +#虹膜识别持续没有找到眼的最大次数 +maxEyeNotFoundCount=50 + +#识别方式[1=人脸;2=虹膜;3=双认证;4=任意] +recogType=4 + +[window] +#识别界面窗口宽(px) +width=1280 +#识别界面窗口高(px) +height=800 +#统一背景色 +backgroundColor="#FFFFFF" + +[camera] +#人脸摄像头的编号 +faceIndex=1 +#摄像头拍摄的画面宽(px) +faceFrameWidth=1280 +#摄像头拍摄的画面高(px) +faceFrameHeight=720 +#取一幅画面的时间间隔(ms) +frameInterval=50 +#虹膜相机取一幅画面的时间间隔(ms) +irisFrameInterval=100 +#虹膜相机拍摄宽度 +irisFrameWidth=1280 +#虹膜相机拍摄高度 +irisFrameHeight=960 +#虹膜图像高度 +irisWidth=640 +#虹膜图像高度 +irisHeight=480 + +[stack] +#拍摄图像栈最大值 +capture=50 +#找到的眼睛图像栈最大值 +found=30 +#质量合格图像栈最大值 +qualified=30 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..51b5337 --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "CasicBioRecWin.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + CasicBioRecWin w; + w.show(); + return a.exec(); +} diff --git a/qss/startup.css b/qss/startup.css new file mode 100644 index 0000000..bfad9df --- /dev/null +++ b/qss/startup.css @@ -0,0 +1,12 @@ +QLabel { + color: #6868A6; + font-family: "Microsoft YaHei"; +} + +QLabel#labDate { + font-size: 36px; +} + +QLabel#labTime { + font-size: 100px; +} \ No newline at end of file diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp new file mode 100644 index 0000000..13976d3 --- /dev/null +++ b/utils/SettingConfig.cpp @@ -0,0 +1,46 @@ +#include "SettingConfig.h" +#include + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + WINDOW_WIDTH = getProperty("window", "width").toInt(); + WINDOW_HEIGHT = getProperty("window", "height").toInt(); + WINDOW_BACKGROUND_COLOR = getProperty("window", "backgroundColor").toString(); + + OUT_EXE_FILE = getProperty("exe", "outExeFile").toString(); + + FACE_CAMERA_INDEX = getProperty("camera", "faceIndex").toInt(); + FACE_FRAME_WIDTH = getProperty("camera", "faceFrameWidth").toInt(); + FACE_FRAME_HEIGHT = getProperty("camera", "faceFrameHeight").toInt(); + FACE_FRAME_INTERVAL = getProperty("camera", "frameInterval").toInt(); + IRIS_FRAME_WIDTH = getProperty("camera", "irisFrameWidth").toInt(); + IRIS_FRAME_HEIGHT = getProperty("camera", "irisFrameHeight").toInt(); + IRIS_WIDTH = getProperty("camera", "irisWidth").toInt(); + IRIS_HEIGHT = getProperty("camera", "irisHeight").toInt(); + IRIS_FRAME_INTERVAL = getProperty("camera", "irisFrameInterval").toInt(); + + MAX_MATCH_TIME = getProperty("recognize", "maxMatchTime").toInt(); + SUCCESS_TIPS_LAST = getProperty("recognize", "successTipsLast").toInt(); + FAILURE_TIPS_LAST = getProperty("recognize", "failureTipsLast").toInt(); + MAX_FACE_TRY_COUNT = getProperty("recognize", "maxFaceTryCount").toInt(); + MAX_FACE_NOT_FOUND_COUNT = getProperty("recognize", "maxFaceNotFoundCount").toInt(); + MAX_IRIS_TRY_COUNT = getProperty("recognize", "maxIrisTryCount").toInt(); + MAX_EYE_NOT_FOUND_COUNT = getProperty("recognize", "maxEyeNotFoundCount").toInt(); + + MAX_CAPTURE_STACK_SIZE = getProperty("stack", "capture").toInt(); + MAX_FOUND_STACK_SIZE = getProperty("stack", "found").toInt(); + MAX_QUALIFIED_STACK_SIZE = getProperty("stack", "qualified").toInt(); + + PORT_NAME = getProperty("com", "motoPortName").toString(); + + RECOG_TYPE = getProperty("recognize", "recogType").toInt(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h new file mode 100644 index 0000000..f2f8e98 --- /dev/null +++ b/utils/SettingConfig.h @@ -0,0 +1,68 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + int WINDOW_WIDTH; + int WINDOW_HEIGHT; + QString WINDOW_BACKGROUND_COLOR; + + QString OUT_EXE_FILE; + + int FACE_CAMERA_INDEX; + int FACE_FRAME_WIDTH; + int FACE_FRAME_HEIGHT; + int FACE_FRAME_INTERVAL; + int IRIS_FRAME_INTERVAL; + int IRIS_FRAME_WIDTH; + int IRIS_FRAME_HEIGHT; + int IRIS_WIDTH; + int IRIS_HEIGHT; + + int MAX_MATCH_TIME; + int SUCCESS_TIPS_LAST; + int FAILURE_TIPS_LAST; + int MAX_FACE_TRY_COUNT; + int MAX_FACE_NOT_FOUND_COUNT; + int MAX_IRIS_TRY_COUNT; + int MAX_EYE_NOT_FOUND_COUNT; + + int MAX_CAPTURE_STACK_SIZE; + int MAX_FOUND_STACK_SIZE; + int MAX_QUALIFIED_STACK_SIZE; + + QString PORT_NAME; + + int RECOG_TYPE = 0; + +private: + SettingConfig(); + + QString filename; + QSettings* setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/utils/id/IdWorker.h b/utils/id/IdWorker.h new file mode 100644 index 0000000..6c48aa9 --- /dev/null +++ b/utils/id/IdWorker.h @@ -0,0 +1,218 @@ +#ifndef _JW_CORE_ID_WORKER_H_ +#define _JW_CORE_ID_WORKER_H_ + +#include +#include +#include +#include +#include +#include "Noncopyable.h" +#include "Singleton.h" + +// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 +// #define SNOWFLAKE_ID_WORKER_NO_LOCK + +namespace Jiawa { + + /** + * @brief 核心 + * 核心功能 + */ + namespace Core { + + /** + * @brief 分布式id生成类 + * https://segmentfault.com/a/1190000011282426 + * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala + * + * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + * || || || | | | + * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ + * | + * 不用 + * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. + */ + class SnowflakeIdWorker : private Noncopyable { + + // 实现单例 + friend class Singleton; + + public: + typedef unsigned int UInt; + typedef unsigned long long int UInt64; + +#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK + typedef std::atomic AtomicUInt; + typedef std::atomic AtomicUInt64; +#else + typedef UInt AtomicUInt; + typedef UInt64 AtomicUInt64; +#endif + + void setWorkerId(UInt workerId) { + this->workerId = workerId; + } + + void setDatacenterId(UInt datacenterId) { + this->datacenterId = datacenterId; + } + + UInt64 getId() { + return nextId(); + } + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + UInt64 nextId() { +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::unique_lock lock{ mutex }; + AtomicUInt64 timestamp{ 0 }; +#else + static AtomicUInt64 timestamp{ 0 }; +#endif + timestamp = timeGen(); + + // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + std::ostringstream s; + s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; + throw std::exception(std::runtime_error(s.str())); + } + + if (lastTimestamp == timestamp) { + // 如果是同一时间生成的, 则进行毫秒内序列 + sequence = (sequence + 1) & sequenceMask; + if (0 == sequence) { + // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0; + } + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + lastTimestamp = timestamp; +#else + lastTimestamp = timestamp.load(); +#endif + + // 移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + } + + protected: + SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + UInt64 timeGen() const { + auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); + return t.time_since_epoch().count(); + } + + /** + * 阻塞到下一个毫秒, 直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + UInt64 tilNextMillis(UInt64 lastTimestamp) const { + UInt64 timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + private: + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::mutex mutex; +#endif + + /** + * 开始时间截 (2018-01-01 00:00:00.000) + */ + const UInt64 twepoch = 1514736000000; + + /** + * 机器id所占的位数 + */ + const UInt workerIdBits = 5; + + /** + * 数据中心id所占的位数 + */ + const UInt datacenterIdBits = 5; + + /** + * 序列所占的位数 + */ + const UInt sequenceBits = 12; + + /** + * 机器ID向左移12位 + */ + const UInt workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位 + */ + const UInt datacenterIdShift = workerIdShift + workerIdBits; + + /** + * 时间截向左移22位 + */ + const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; + + /** + * 支持的最大机器id, 结果是31 + */ + const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); + + /** + * 支持的最大数据中心id, 结果是31 + */ + const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); + + /** + * 生成序列的掩码, 这里为4095 + */ + const UInt sequenceMask = -1 ^ (-1 << sequenceBits); + + /** + * 工作机器id(0~31) + */ + UInt workerId; + + /** + * 数据中心id(0~31) + */ + UInt datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + AtomicUInt sequence{ 0 }; + + /** + * 上次生成ID的时间截 + */ + AtomicUInt64 lastTimestamp{ 0 }; + + }; + + typedef SnowflakeIdWorker IdWorker; + } +} + +#endif // _JW_CORE_ID_WORKER_H_ diff --git a/utils/id/Noncopyable.h b/utils/id/Noncopyable.h new file mode 100644 index 0000000..d87f58a --- /dev/null +++ b/utils/id/Noncopyable.h @@ -0,0 +1,31 @@ +#ifndef _JW_CORE_NONCOPYABLE_H_ +#define _JW_CORE_NONCOPYABLE_H_ + + +// Private copy constructor and copy assignment ensure classes derived from +// class noncopyable cannot be copied. + +namespace Jiawa { + namespace Core { + + // protection from unintended ADL(Argument Dependent Lookup) + namespace Noncopyable_ { + + class Noncopyable + { + protected: + Noncopyable() = default; + ~Noncopyable() = default; + + Noncopyable(const Noncopyable&) = delete; + Noncopyable(const Noncopyable&&) = delete; + Noncopyable& operator=(const Noncopyable&) = delete; + Noncopyable& operator=(const Noncopyable&&) = delete; + }; + } + + typedef Noncopyable_::Noncopyable Noncopyable; + } +} + +#endif // _JW_CORE_NONCOPYABLE_H_ diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecWin.ui b/CasicBioRecWin.ui new file mode 100644 index 0000000..a08a0fd --- /dev/null +++ b/CasicBioRecWin.ui @@ -0,0 +1,29 @@ + + + CasicBioRecWin + + + + 0 + 0 + 1280 + 800 + + + + CasicBioRecWin + + + + + 0 + 0 + 1280 + 800 + + + + + + + diff --git a/StartupForm.cpp b/StartupForm.cpp new file mode 100644 index 0000000..7fdf854 --- /dev/null +++ b/StartupForm.cpp @@ -0,0 +1,36 @@ +#include "StartupForm.h" +#include "ui_StartupForm.h" + +StartupForm::StartupForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::StartupForm) +{ + ui->setupUi(this); + + QFile file(QApplication::applicationDirPath() + "/qss/startup.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + this->updateDateAndTime(); + + // 初始化更新界面的定时器 + // 每分钟执行一次 + clockTimer = new QTimer(this); + connect(clockTimer, &QTimer::timeout, this, &StartupForm::updateDateAndTime); + clockTimer->start(1000); +} + +StartupForm::~StartupForm() +{ + delete ui; +} + +void StartupForm::updateDateAndTime() +{ + ui->labTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labDate->setText(QDate::currentDate().toString("yyyy-MM-dd")); +} diff --git a/StartupForm.h b/StartupForm.h new file mode 100644 index 0000000..2204b1a --- /dev/null +++ b/StartupForm.h @@ -0,0 +1,31 @@ +#ifndef STARTUPFORM_H +#define STARTUPFORM_H + +#include +#include +#include +#include +#include "utils/SettingConfig.h" + +namespace Ui { +class StartupForm; +} + +class StartupForm : public QWidget +{ + Q_OBJECT + +public: + explicit StartupForm(QWidget *parent = nullptr); + ~StartupForm(); + +private: + Ui::StartupForm *ui; + + QTimer * clockTimer; + +private slots: + void updateDateAndTime(); +}; + +#endif // STARTUPFORM_H diff --git a/StartupForm.ui b/StartupForm.ui new file mode 100644 index 0000000..1a8c5b2 --- /dev/null +++ b/StartupForm.ui @@ -0,0 +1,87 @@ + + + StartupForm + + + + 0 + 0 + 960 + 600 + + + + Form + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/conf/config.ini b/conf/config.ini new file mode 100644 index 0000000..84e31c9 --- /dev/null +++ b/conf/config.ini @@ -0,0 +1,63 @@ +[com] +#电机控制的串口名 +motoPortName=COM3 + +[exe] +#外部exe路径 +outExeFile="D:\\deploy\\superSocket\\superSocketServer.exe" + +[recognize] +#最大允许识别时间(ms) +maxMatchTime=10000 +#识别成功界面停留时间(ms) +successTipsLast=5000 +#识别失败界面停留时间(ms) +failureTipsLast=3000 +#人脸识别最大尝试次数 +maxFaceTryCount=20 +#持续没找到人脸的最大次数 +maxFaceNotFoundCount=500 + +#虹膜识别最大尝试次数 +maxIrisTryCount=10 +#虹膜识别持续没有找到眼的最大次数 +maxEyeNotFoundCount=50 + +#识别方式[1=人脸;2=虹膜;3=双认证;4=任意] +recogType=4 + +[window] +#识别界面窗口宽(px) +width=1280 +#识别界面窗口高(px) +height=800 +#统一背景色 +backgroundColor="#FFFFFF" + +[camera] +#人脸摄像头的编号 +faceIndex=1 +#摄像头拍摄的画面宽(px) +faceFrameWidth=1280 +#摄像头拍摄的画面高(px) +faceFrameHeight=720 +#取一幅画面的时间间隔(ms) +frameInterval=50 +#虹膜相机取一幅画面的时间间隔(ms) +irisFrameInterval=100 +#虹膜相机拍摄宽度 +irisFrameWidth=1280 +#虹膜相机拍摄高度 +irisFrameHeight=960 +#虹膜图像高度 +irisWidth=640 +#虹膜图像高度 +irisHeight=480 + +[stack] +#拍摄图像栈最大值 +capture=50 +#找到的眼睛图像栈最大值 +found=30 +#质量合格图像栈最大值 +qualified=30 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..51b5337 --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "CasicBioRecWin.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + CasicBioRecWin w; + w.show(); + return a.exec(); +} diff --git a/qss/startup.css b/qss/startup.css new file mode 100644 index 0000000..bfad9df --- /dev/null +++ b/qss/startup.css @@ -0,0 +1,12 @@ +QLabel { + color: #6868A6; + font-family: "Microsoft YaHei"; +} + +QLabel#labDate { + font-size: 36px; +} + +QLabel#labTime { + font-size: 100px; +} \ No newline at end of file diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp new file mode 100644 index 0000000..13976d3 --- /dev/null +++ b/utils/SettingConfig.cpp @@ -0,0 +1,46 @@ +#include "SettingConfig.h" +#include + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + WINDOW_WIDTH = getProperty("window", "width").toInt(); + WINDOW_HEIGHT = getProperty("window", "height").toInt(); + WINDOW_BACKGROUND_COLOR = getProperty("window", "backgroundColor").toString(); + + OUT_EXE_FILE = getProperty("exe", "outExeFile").toString(); + + FACE_CAMERA_INDEX = getProperty("camera", "faceIndex").toInt(); + FACE_FRAME_WIDTH = getProperty("camera", "faceFrameWidth").toInt(); + FACE_FRAME_HEIGHT = getProperty("camera", "faceFrameHeight").toInt(); + FACE_FRAME_INTERVAL = getProperty("camera", "frameInterval").toInt(); + IRIS_FRAME_WIDTH = getProperty("camera", "irisFrameWidth").toInt(); + IRIS_FRAME_HEIGHT = getProperty("camera", "irisFrameHeight").toInt(); + IRIS_WIDTH = getProperty("camera", "irisWidth").toInt(); + IRIS_HEIGHT = getProperty("camera", "irisHeight").toInt(); + IRIS_FRAME_INTERVAL = getProperty("camera", "irisFrameInterval").toInt(); + + MAX_MATCH_TIME = getProperty("recognize", "maxMatchTime").toInt(); + SUCCESS_TIPS_LAST = getProperty("recognize", "successTipsLast").toInt(); + FAILURE_TIPS_LAST = getProperty("recognize", "failureTipsLast").toInt(); + MAX_FACE_TRY_COUNT = getProperty("recognize", "maxFaceTryCount").toInt(); + MAX_FACE_NOT_FOUND_COUNT = getProperty("recognize", "maxFaceNotFoundCount").toInt(); + MAX_IRIS_TRY_COUNT = getProperty("recognize", "maxIrisTryCount").toInt(); + MAX_EYE_NOT_FOUND_COUNT = getProperty("recognize", "maxEyeNotFoundCount").toInt(); + + MAX_CAPTURE_STACK_SIZE = getProperty("stack", "capture").toInt(); + MAX_FOUND_STACK_SIZE = getProperty("stack", "found").toInt(); + MAX_QUALIFIED_STACK_SIZE = getProperty("stack", "qualified").toInt(); + + PORT_NAME = getProperty("com", "motoPortName").toString(); + + RECOG_TYPE = getProperty("recognize", "recogType").toInt(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h new file mode 100644 index 0000000..f2f8e98 --- /dev/null +++ b/utils/SettingConfig.h @@ -0,0 +1,68 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + int WINDOW_WIDTH; + int WINDOW_HEIGHT; + QString WINDOW_BACKGROUND_COLOR; + + QString OUT_EXE_FILE; + + int FACE_CAMERA_INDEX; + int FACE_FRAME_WIDTH; + int FACE_FRAME_HEIGHT; + int FACE_FRAME_INTERVAL; + int IRIS_FRAME_INTERVAL; + int IRIS_FRAME_WIDTH; + int IRIS_FRAME_HEIGHT; + int IRIS_WIDTH; + int IRIS_HEIGHT; + + int MAX_MATCH_TIME; + int SUCCESS_TIPS_LAST; + int FAILURE_TIPS_LAST; + int MAX_FACE_TRY_COUNT; + int MAX_FACE_NOT_FOUND_COUNT; + int MAX_IRIS_TRY_COUNT; + int MAX_EYE_NOT_FOUND_COUNT; + + int MAX_CAPTURE_STACK_SIZE; + int MAX_FOUND_STACK_SIZE; + int MAX_QUALIFIED_STACK_SIZE; + + QString PORT_NAME; + + int RECOG_TYPE = 0; + +private: + SettingConfig(); + + QString filename; + QSettings* setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/utils/id/IdWorker.h b/utils/id/IdWorker.h new file mode 100644 index 0000000..6c48aa9 --- /dev/null +++ b/utils/id/IdWorker.h @@ -0,0 +1,218 @@ +#ifndef _JW_CORE_ID_WORKER_H_ +#define _JW_CORE_ID_WORKER_H_ + +#include +#include +#include +#include +#include +#include "Noncopyable.h" +#include "Singleton.h" + +// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 +// #define SNOWFLAKE_ID_WORKER_NO_LOCK + +namespace Jiawa { + + /** + * @brief 核心 + * 核心功能 + */ + namespace Core { + + /** + * @brief 分布式id生成类 + * https://segmentfault.com/a/1190000011282426 + * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala + * + * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + * || || || | | | + * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ + * | + * 不用 + * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. + */ + class SnowflakeIdWorker : private Noncopyable { + + // 实现单例 + friend class Singleton; + + public: + typedef unsigned int UInt; + typedef unsigned long long int UInt64; + +#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK + typedef std::atomic AtomicUInt; + typedef std::atomic AtomicUInt64; +#else + typedef UInt AtomicUInt; + typedef UInt64 AtomicUInt64; +#endif + + void setWorkerId(UInt workerId) { + this->workerId = workerId; + } + + void setDatacenterId(UInt datacenterId) { + this->datacenterId = datacenterId; + } + + UInt64 getId() { + return nextId(); + } + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + UInt64 nextId() { +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::unique_lock lock{ mutex }; + AtomicUInt64 timestamp{ 0 }; +#else + static AtomicUInt64 timestamp{ 0 }; +#endif + timestamp = timeGen(); + + // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + std::ostringstream s; + s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; + throw std::exception(std::runtime_error(s.str())); + } + + if (lastTimestamp == timestamp) { + // 如果是同一时间生成的, 则进行毫秒内序列 + sequence = (sequence + 1) & sequenceMask; + if (0 == sequence) { + // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0; + } + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + lastTimestamp = timestamp; +#else + lastTimestamp = timestamp.load(); +#endif + + // 移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + } + + protected: + SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + UInt64 timeGen() const { + auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); + return t.time_since_epoch().count(); + } + + /** + * 阻塞到下一个毫秒, 直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + UInt64 tilNextMillis(UInt64 lastTimestamp) const { + UInt64 timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + private: + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::mutex mutex; +#endif + + /** + * 开始时间截 (2018-01-01 00:00:00.000) + */ + const UInt64 twepoch = 1514736000000; + + /** + * 机器id所占的位数 + */ + const UInt workerIdBits = 5; + + /** + * 数据中心id所占的位数 + */ + const UInt datacenterIdBits = 5; + + /** + * 序列所占的位数 + */ + const UInt sequenceBits = 12; + + /** + * 机器ID向左移12位 + */ + const UInt workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位 + */ + const UInt datacenterIdShift = workerIdShift + workerIdBits; + + /** + * 时间截向左移22位 + */ + const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; + + /** + * 支持的最大机器id, 结果是31 + */ + const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); + + /** + * 支持的最大数据中心id, 结果是31 + */ + const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); + + /** + * 生成序列的掩码, 这里为4095 + */ + const UInt sequenceMask = -1 ^ (-1 << sequenceBits); + + /** + * 工作机器id(0~31) + */ + UInt workerId; + + /** + * 数据中心id(0~31) + */ + UInt datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + AtomicUInt sequence{ 0 }; + + /** + * 上次生成ID的时间截 + */ + AtomicUInt64 lastTimestamp{ 0 }; + + }; + + typedef SnowflakeIdWorker IdWorker; + } +} + +#endif // _JW_CORE_ID_WORKER_H_ diff --git a/utils/id/Noncopyable.h b/utils/id/Noncopyable.h new file mode 100644 index 0000000..d87f58a --- /dev/null +++ b/utils/id/Noncopyable.h @@ -0,0 +1,31 @@ +#ifndef _JW_CORE_NONCOPYABLE_H_ +#define _JW_CORE_NONCOPYABLE_H_ + + +// Private copy constructor and copy assignment ensure classes derived from +// class noncopyable cannot be copied. + +namespace Jiawa { + namespace Core { + + // protection from unintended ADL(Argument Dependent Lookup) + namespace Noncopyable_ { + + class Noncopyable + { + protected: + Noncopyable() = default; + ~Noncopyable() = default; + + Noncopyable(const Noncopyable&) = delete; + Noncopyable(const Noncopyable&&) = delete; + Noncopyable& operator=(const Noncopyable&) = delete; + Noncopyable& operator=(const Noncopyable&&) = delete; + }; + } + + typedef Noncopyable_::Noncopyable Noncopyable; + } +} + +#endif // _JW_CORE_NONCOPYABLE_H_ diff --git a/utils/id/Singleton.h b/utils/id/Singleton.h new file mode 100644 index 0000000..d1c0553 --- /dev/null +++ b/utils/id/Singleton.h @@ -0,0 +1,60 @@ +#ifndef _JW_CORE_SINGLETON_H_ +#define _JW_CORE_SINGLETON_H_ + +namespace Jiawa { + namespace Core { + + // boost/container/detail/singleton.hpp + // http://blog.csdn.net/fullsail/article/details/8483106 + // T must be: no-throw default constructible and no-throw destructible + template + class Singleton { + private: + Singleton() = default; + ~Singleton() = default; + + private: + struct object_creator + { + // This constructor does nothing more than ensure that instance() + // is called before main() begins, thus creating the static + // T object before multithreading race issues can come up. + object_creator() { Singleton::instance(); } + inline void do_nothing() const { } + }; + static object_creator create_object; + + private: + Singleton(const Singleton&) = delete; + Singleton(const Singleton&&) = delete; + Singleton& operator=(const Singleton&) = delete; + Singleton& operator=(const Singleton&&) = delete; + + public: + typedef T object_type; + + // If, at any point (in user code), Singleton::instance() + // is called, then the following function is instantiated. + static object_type& instance() + { + // This is the object that we return a reference to. + // It is guaranteed to be created before main() begins because of + // the next line. + static object_type obj; + + // The following line does nothing else than force the instantiation + // of Singleton::create_object, whose constructor is + // called before main() begins. + create_object.do_nothing(); + + return obj; + } + }; + + template + typename Singleton::object_creator Singleton::create_object; + } +} + +#endif // _JW_CORE_SINGLETON_H_ + diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecWin.ui b/CasicBioRecWin.ui new file mode 100644 index 0000000..a08a0fd --- /dev/null +++ b/CasicBioRecWin.ui @@ -0,0 +1,29 @@ + + + CasicBioRecWin + + + + 0 + 0 + 1280 + 800 + + + + CasicBioRecWin + + + + + 0 + 0 + 1280 + 800 + + + + + + + diff --git a/StartupForm.cpp b/StartupForm.cpp new file mode 100644 index 0000000..7fdf854 --- /dev/null +++ b/StartupForm.cpp @@ -0,0 +1,36 @@ +#include "StartupForm.h" +#include "ui_StartupForm.h" + +StartupForm::StartupForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::StartupForm) +{ + ui->setupUi(this); + + QFile file(QApplication::applicationDirPath() + "/qss/startup.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + this->updateDateAndTime(); + + // 初始化更新界面的定时器 + // 每分钟执行一次 + clockTimer = new QTimer(this); + connect(clockTimer, &QTimer::timeout, this, &StartupForm::updateDateAndTime); + clockTimer->start(1000); +} + +StartupForm::~StartupForm() +{ + delete ui; +} + +void StartupForm::updateDateAndTime() +{ + ui->labTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labDate->setText(QDate::currentDate().toString("yyyy-MM-dd")); +} diff --git a/StartupForm.h b/StartupForm.h new file mode 100644 index 0000000..2204b1a --- /dev/null +++ b/StartupForm.h @@ -0,0 +1,31 @@ +#ifndef STARTUPFORM_H +#define STARTUPFORM_H + +#include +#include +#include +#include +#include "utils/SettingConfig.h" + +namespace Ui { +class StartupForm; +} + +class StartupForm : public QWidget +{ + Q_OBJECT + +public: + explicit StartupForm(QWidget *parent = nullptr); + ~StartupForm(); + +private: + Ui::StartupForm *ui; + + QTimer * clockTimer; + +private slots: + void updateDateAndTime(); +}; + +#endif // STARTUPFORM_H diff --git a/StartupForm.ui b/StartupForm.ui new file mode 100644 index 0000000..1a8c5b2 --- /dev/null +++ b/StartupForm.ui @@ -0,0 +1,87 @@ + + + StartupForm + + + + 0 + 0 + 960 + 600 + + + + Form + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/conf/config.ini b/conf/config.ini new file mode 100644 index 0000000..84e31c9 --- /dev/null +++ b/conf/config.ini @@ -0,0 +1,63 @@ +[com] +#电机控制的串口名 +motoPortName=COM3 + +[exe] +#外部exe路径 +outExeFile="D:\\deploy\\superSocket\\superSocketServer.exe" + +[recognize] +#最大允许识别时间(ms) +maxMatchTime=10000 +#识别成功界面停留时间(ms) +successTipsLast=5000 +#识别失败界面停留时间(ms) +failureTipsLast=3000 +#人脸识别最大尝试次数 +maxFaceTryCount=20 +#持续没找到人脸的最大次数 +maxFaceNotFoundCount=500 + +#虹膜识别最大尝试次数 +maxIrisTryCount=10 +#虹膜识别持续没有找到眼的最大次数 +maxEyeNotFoundCount=50 + +#识别方式[1=人脸;2=虹膜;3=双认证;4=任意] +recogType=4 + +[window] +#识别界面窗口宽(px) +width=1280 +#识别界面窗口高(px) +height=800 +#统一背景色 +backgroundColor="#FFFFFF" + +[camera] +#人脸摄像头的编号 +faceIndex=1 +#摄像头拍摄的画面宽(px) +faceFrameWidth=1280 +#摄像头拍摄的画面高(px) +faceFrameHeight=720 +#取一幅画面的时间间隔(ms) +frameInterval=50 +#虹膜相机取一幅画面的时间间隔(ms) +irisFrameInterval=100 +#虹膜相机拍摄宽度 +irisFrameWidth=1280 +#虹膜相机拍摄高度 +irisFrameHeight=960 +#虹膜图像高度 +irisWidth=640 +#虹膜图像高度 +irisHeight=480 + +[stack] +#拍摄图像栈最大值 +capture=50 +#找到的眼睛图像栈最大值 +found=30 +#质量合格图像栈最大值 +qualified=30 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..51b5337 --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "CasicBioRecWin.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + CasicBioRecWin w; + w.show(); + return a.exec(); +} diff --git a/qss/startup.css b/qss/startup.css new file mode 100644 index 0000000..bfad9df --- /dev/null +++ b/qss/startup.css @@ -0,0 +1,12 @@ +QLabel { + color: #6868A6; + font-family: "Microsoft YaHei"; +} + +QLabel#labDate { + font-size: 36px; +} + +QLabel#labTime { + font-size: 100px; +} \ No newline at end of file diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp new file mode 100644 index 0000000..13976d3 --- /dev/null +++ b/utils/SettingConfig.cpp @@ -0,0 +1,46 @@ +#include "SettingConfig.h" +#include + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + WINDOW_WIDTH = getProperty("window", "width").toInt(); + WINDOW_HEIGHT = getProperty("window", "height").toInt(); + WINDOW_BACKGROUND_COLOR = getProperty("window", "backgroundColor").toString(); + + OUT_EXE_FILE = getProperty("exe", "outExeFile").toString(); + + FACE_CAMERA_INDEX = getProperty("camera", "faceIndex").toInt(); + FACE_FRAME_WIDTH = getProperty("camera", "faceFrameWidth").toInt(); + FACE_FRAME_HEIGHT = getProperty("camera", "faceFrameHeight").toInt(); + FACE_FRAME_INTERVAL = getProperty("camera", "frameInterval").toInt(); + IRIS_FRAME_WIDTH = getProperty("camera", "irisFrameWidth").toInt(); + IRIS_FRAME_HEIGHT = getProperty("camera", "irisFrameHeight").toInt(); + IRIS_WIDTH = getProperty("camera", "irisWidth").toInt(); + IRIS_HEIGHT = getProperty("camera", "irisHeight").toInt(); + IRIS_FRAME_INTERVAL = getProperty("camera", "irisFrameInterval").toInt(); + + MAX_MATCH_TIME = getProperty("recognize", "maxMatchTime").toInt(); + SUCCESS_TIPS_LAST = getProperty("recognize", "successTipsLast").toInt(); + FAILURE_TIPS_LAST = getProperty("recognize", "failureTipsLast").toInt(); + MAX_FACE_TRY_COUNT = getProperty("recognize", "maxFaceTryCount").toInt(); + MAX_FACE_NOT_FOUND_COUNT = getProperty("recognize", "maxFaceNotFoundCount").toInt(); + MAX_IRIS_TRY_COUNT = getProperty("recognize", "maxIrisTryCount").toInt(); + MAX_EYE_NOT_FOUND_COUNT = getProperty("recognize", "maxEyeNotFoundCount").toInt(); + + MAX_CAPTURE_STACK_SIZE = getProperty("stack", "capture").toInt(); + MAX_FOUND_STACK_SIZE = getProperty("stack", "found").toInt(); + MAX_QUALIFIED_STACK_SIZE = getProperty("stack", "qualified").toInt(); + + PORT_NAME = getProperty("com", "motoPortName").toString(); + + RECOG_TYPE = getProperty("recognize", "recogType").toInt(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h new file mode 100644 index 0000000..f2f8e98 --- /dev/null +++ b/utils/SettingConfig.h @@ -0,0 +1,68 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + int WINDOW_WIDTH; + int WINDOW_HEIGHT; + QString WINDOW_BACKGROUND_COLOR; + + QString OUT_EXE_FILE; + + int FACE_CAMERA_INDEX; + int FACE_FRAME_WIDTH; + int FACE_FRAME_HEIGHT; + int FACE_FRAME_INTERVAL; + int IRIS_FRAME_INTERVAL; + int IRIS_FRAME_WIDTH; + int IRIS_FRAME_HEIGHT; + int IRIS_WIDTH; + int IRIS_HEIGHT; + + int MAX_MATCH_TIME; + int SUCCESS_TIPS_LAST; + int FAILURE_TIPS_LAST; + int MAX_FACE_TRY_COUNT; + int MAX_FACE_NOT_FOUND_COUNT; + int MAX_IRIS_TRY_COUNT; + int MAX_EYE_NOT_FOUND_COUNT; + + int MAX_CAPTURE_STACK_SIZE; + int MAX_FOUND_STACK_SIZE; + int MAX_QUALIFIED_STACK_SIZE; + + QString PORT_NAME; + + int RECOG_TYPE = 0; + +private: + SettingConfig(); + + QString filename; + QSettings* setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/utils/id/IdWorker.h b/utils/id/IdWorker.h new file mode 100644 index 0000000..6c48aa9 --- /dev/null +++ b/utils/id/IdWorker.h @@ -0,0 +1,218 @@ +#ifndef _JW_CORE_ID_WORKER_H_ +#define _JW_CORE_ID_WORKER_H_ + +#include +#include +#include +#include +#include +#include "Noncopyable.h" +#include "Singleton.h" + +// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 +// #define SNOWFLAKE_ID_WORKER_NO_LOCK + +namespace Jiawa { + + /** + * @brief 核心 + * 核心功能 + */ + namespace Core { + + /** + * @brief 分布式id生成类 + * https://segmentfault.com/a/1190000011282426 + * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala + * + * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + * || || || | | | + * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ + * | + * 不用 + * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. + */ + class SnowflakeIdWorker : private Noncopyable { + + // 实现单例 + friend class Singleton; + + public: + typedef unsigned int UInt; + typedef unsigned long long int UInt64; + +#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK + typedef std::atomic AtomicUInt; + typedef std::atomic AtomicUInt64; +#else + typedef UInt AtomicUInt; + typedef UInt64 AtomicUInt64; +#endif + + void setWorkerId(UInt workerId) { + this->workerId = workerId; + } + + void setDatacenterId(UInt datacenterId) { + this->datacenterId = datacenterId; + } + + UInt64 getId() { + return nextId(); + } + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + UInt64 nextId() { +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::unique_lock lock{ mutex }; + AtomicUInt64 timestamp{ 0 }; +#else + static AtomicUInt64 timestamp{ 0 }; +#endif + timestamp = timeGen(); + + // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + std::ostringstream s; + s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; + throw std::exception(std::runtime_error(s.str())); + } + + if (lastTimestamp == timestamp) { + // 如果是同一时间生成的, 则进行毫秒内序列 + sequence = (sequence + 1) & sequenceMask; + if (0 == sequence) { + // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0; + } + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + lastTimestamp = timestamp; +#else + lastTimestamp = timestamp.load(); +#endif + + // 移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + } + + protected: + SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + UInt64 timeGen() const { + auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); + return t.time_since_epoch().count(); + } + + /** + * 阻塞到下一个毫秒, 直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + UInt64 tilNextMillis(UInt64 lastTimestamp) const { + UInt64 timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + private: + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::mutex mutex; +#endif + + /** + * 开始时间截 (2018-01-01 00:00:00.000) + */ + const UInt64 twepoch = 1514736000000; + + /** + * 机器id所占的位数 + */ + const UInt workerIdBits = 5; + + /** + * 数据中心id所占的位数 + */ + const UInt datacenterIdBits = 5; + + /** + * 序列所占的位数 + */ + const UInt sequenceBits = 12; + + /** + * 机器ID向左移12位 + */ + const UInt workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位 + */ + const UInt datacenterIdShift = workerIdShift + workerIdBits; + + /** + * 时间截向左移22位 + */ + const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; + + /** + * 支持的最大机器id, 结果是31 + */ + const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); + + /** + * 支持的最大数据中心id, 结果是31 + */ + const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); + + /** + * 生成序列的掩码, 这里为4095 + */ + const UInt sequenceMask = -1 ^ (-1 << sequenceBits); + + /** + * 工作机器id(0~31) + */ + UInt workerId; + + /** + * 数据中心id(0~31) + */ + UInt datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + AtomicUInt sequence{ 0 }; + + /** + * 上次生成ID的时间截 + */ + AtomicUInt64 lastTimestamp{ 0 }; + + }; + + typedef SnowflakeIdWorker IdWorker; + } +} + +#endif // _JW_CORE_ID_WORKER_H_ diff --git a/utils/id/Noncopyable.h b/utils/id/Noncopyable.h new file mode 100644 index 0000000..d87f58a --- /dev/null +++ b/utils/id/Noncopyable.h @@ -0,0 +1,31 @@ +#ifndef _JW_CORE_NONCOPYABLE_H_ +#define _JW_CORE_NONCOPYABLE_H_ + + +// Private copy constructor and copy assignment ensure classes derived from +// class noncopyable cannot be copied. + +namespace Jiawa { + namespace Core { + + // protection from unintended ADL(Argument Dependent Lookup) + namespace Noncopyable_ { + + class Noncopyable + { + protected: + Noncopyable() = default; + ~Noncopyable() = default; + + Noncopyable(const Noncopyable&) = delete; + Noncopyable(const Noncopyable&&) = delete; + Noncopyable& operator=(const Noncopyable&) = delete; + Noncopyable& operator=(const Noncopyable&&) = delete; + }; + } + + typedef Noncopyable_::Noncopyable Noncopyable; + } +} + +#endif // _JW_CORE_NONCOPYABLE_H_ diff --git a/utils/id/Singleton.h b/utils/id/Singleton.h new file mode 100644 index 0000000..d1c0553 --- /dev/null +++ b/utils/id/Singleton.h @@ -0,0 +1,60 @@ +#ifndef _JW_CORE_SINGLETON_H_ +#define _JW_CORE_SINGLETON_H_ + +namespace Jiawa { + namespace Core { + + // boost/container/detail/singleton.hpp + // http://blog.csdn.net/fullsail/article/details/8483106 + // T must be: no-throw default constructible and no-throw destructible + template + class Singleton { + private: + Singleton() = default; + ~Singleton() = default; + + private: + struct object_creator + { + // This constructor does nothing more than ensure that instance() + // is called before main() begins, thus creating the static + // T object before multithreading race issues can come up. + object_creator() { Singleton::instance(); } + inline void do_nothing() const { } + }; + static object_creator create_object; + + private: + Singleton(const Singleton&) = delete; + Singleton(const Singleton&&) = delete; + Singleton& operator=(const Singleton&) = delete; + Singleton& operator=(const Singleton&&) = delete; + + public: + typedef T object_type; + + // If, at any point (in user code), Singleton::instance() + // is called, then the following function is instantiated. + static object_type& instance() + { + // This is the object that we return a reference to. + // It is guaranteed to be created before main() begins because of + // the next line. + static object_type obj; + + // The following line does nothing else than force the instantiation + // of Singleton::create_object, whose constructor is + // called before main() begins. + create_object.do_nothing(); + + return obj; + } + }; + + template + typename Singleton::object_creator Singleton::create_object; + } +} + +#endif // _JW_CORE_SINGLETON_H_ + diff --git a/utils/id/Timer.h b/utils/id/Timer.h new file mode 100644 index 0000000..0f1ff1b --- /dev/null +++ b/utils/id/Timer.h @@ -0,0 +1,57 @@ +#ifndef _JW_CORE_TIMER_H_ +#define _JW_CORE_TIMER_H_ + +#include + +namespace Jiawa { + + /** + * @brief 核心 + * 核心功能 + */ + namespace Core { + + /** + * @brief 计时器类 + * 计时 + */ + template + class Timer { + public: + + typedef CLOCK clock; + typedef typename CLOCK::rep rep; + typedef typename CLOCK::duration duration; + typedef typename CLOCK::time_point time_point; + + Timer() : m_start(CLOCK::now()) { + } + + /** + * @brief 重置计时器 + * + * @return 开始的时间点 + */ + time_point reset() { + m_start = CLOCK::now(); + return m_start; + } + + /** + * @brief 得到流逝的时间 + * @param UNIT 返回时间的类型 + * + * @return 返回流逝的时间 + */ + template + typename UNIT::duration::rep elapsed() const { + return std::chrono::duration_cast(CLOCK::now() - m_start).count(); + } + + private: + time_point m_start; + }; + } +} + +#endif // _JW_CORE_TIMER_H_ \ No newline at end of file diff --git a/CasicBioRecNew.pro b/CasicBioRecNew.pro new file mode 100644 index 0000000..407d909 --- /dev/null +++ b/CasicBioRecNew.pro @@ -0,0 +1,36 @@ +QT += core gui sql network serialport texttospeech + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(utils/utils.pri) + +SOURCES += main.cpp +SOURCES += CasicBioRecWin.cpp +SOURCES += StartupForm.cpp + +HEADERS += CasicBioRecWin.h +HEADERS += StartupForm.h + +FORMS += CasicBioRecWin.ui +FORMS += StartupForm.ui + +DISTFILES += conf/config.ini +DISTFILES += qss/startup.css + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/CasicBioRecWin.cpp b/CasicBioRecWin.cpp new file mode 100644 index 0000000..dff879e --- /dev/null +++ b/CasicBioRecWin.cpp @@ -0,0 +1,38 @@ +#include "CasicBioRecWin.h" +#include "ui_CasicBioRecWin.h" +#include +#include + +CasicBioRecWin::CasicBioRecWin(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CasicBioRecWin) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::FramelessWindowHint); + this->move(0, 0); + this->resize(SettingConfig::getInstance().WINDOW_WIDTH, + SettingConfig::getInstance().WINDOW_HEIGHT); + + // 通过调色板的颜色来设置窗口的统一背景色 + qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR))); + + startForm = new StartupForm(this); + this->ui->stacked->addWidget(startForm); +} + +CasicBioRecWin::~CasicBioRecWin() +{ + delete ui; +} + +void QWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Escape: + QTimer::singleShot(100, qApp, SLOT(quit())); + +// default: +// QWidget::keyPressEvent(event); + } +} diff --git a/CasicBioRecWin.h b/CasicBioRecWin.h new file mode 100644 index 0000000..3609bfa --- /dev/null +++ b/CasicBioRecWin.h @@ -0,0 +1,29 @@ +#ifndef CASICBIORECWIN_H +#define CASICBIORECWIN_H + +#include + +#include "utils/SettingConfig.h" +//#include "utils/easyloggingpp/easylogging++.h" + +#include "StartupForm.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CasicBioRecWin; } +QT_END_NAMESPACE + +class CasicBioRecWin : public QMainWindow +{ + Q_OBJECT + +public: + CasicBioRecWin(QWidget *parent = nullptr); + ~CasicBioRecWin(); + +private: + Ui::CasicBioRecWin *ui; + + StartupForm * startForm; + +}; +#endif // CASICBIORECWIN_H diff --git a/CasicBioRecWin.ui b/CasicBioRecWin.ui new file mode 100644 index 0000000..a08a0fd --- /dev/null +++ b/CasicBioRecWin.ui @@ -0,0 +1,29 @@ + + + CasicBioRecWin + + + + 0 + 0 + 1280 + 800 + + + + CasicBioRecWin + + + + + 0 + 0 + 1280 + 800 + + + + + + + diff --git a/StartupForm.cpp b/StartupForm.cpp new file mode 100644 index 0000000..7fdf854 --- /dev/null +++ b/StartupForm.cpp @@ -0,0 +1,36 @@ +#include "StartupForm.h" +#include "ui_StartupForm.h" + +StartupForm::StartupForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::StartupForm) +{ + ui->setupUi(this); + + QFile file(QApplication::applicationDirPath() + "/qss/startup.css"); + if (file.open(QFile::ReadOnly)) + { + QString qssStr = QLatin1String(file.readAll()); + this->setStyleSheet(qssStr); + file.close(); + } + + this->updateDateAndTime(); + + // 初始化更新界面的定时器 + // 每分钟执行一次 + clockTimer = new QTimer(this); + connect(clockTimer, &QTimer::timeout, this, &StartupForm::updateDateAndTime); + clockTimer->start(1000); +} + +StartupForm::~StartupForm() +{ + delete ui; +} + +void StartupForm::updateDateAndTime() +{ + ui->labTime->setText(QTime::currentTime().toString("HH:mm:ss")); + ui->labDate->setText(QDate::currentDate().toString("yyyy-MM-dd")); +} diff --git a/StartupForm.h b/StartupForm.h new file mode 100644 index 0000000..2204b1a --- /dev/null +++ b/StartupForm.h @@ -0,0 +1,31 @@ +#ifndef STARTUPFORM_H +#define STARTUPFORM_H + +#include +#include +#include +#include +#include "utils/SettingConfig.h" + +namespace Ui { +class StartupForm; +} + +class StartupForm : public QWidget +{ + Q_OBJECT + +public: + explicit StartupForm(QWidget *parent = nullptr); + ~StartupForm(); + +private: + Ui::StartupForm *ui; + + QTimer * clockTimer; + +private slots: + void updateDateAndTime(); +}; + +#endif // STARTUPFORM_H diff --git a/StartupForm.ui b/StartupForm.ui new file mode 100644 index 0000000..1a8c5b2 --- /dev/null +++ b/StartupForm.ui @@ -0,0 +1,87 @@ + + + StartupForm + + + + 0 + 0 + 960 + 600 + + + + Form + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/conf/config.ini b/conf/config.ini new file mode 100644 index 0000000..84e31c9 --- /dev/null +++ b/conf/config.ini @@ -0,0 +1,63 @@ +[com] +#电机控制的串口名 +motoPortName=COM3 + +[exe] +#外部exe路径 +outExeFile="D:\\deploy\\superSocket\\superSocketServer.exe" + +[recognize] +#最大允许识别时间(ms) +maxMatchTime=10000 +#识别成功界面停留时间(ms) +successTipsLast=5000 +#识别失败界面停留时间(ms) +failureTipsLast=3000 +#人脸识别最大尝试次数 +maxFaceTryCount=20 +#持续没找到人脸的最大次数 +maxFaceNotFoundCount=500 + +#虹膜识别最大尝试次数 +maxIrisTryCount=10 +#虹膜识别持续没有找到眼的最大次数 +maxEyeNotFoundCount=50 + +#识别方式[1=人脸;2=虹膜;3=双认证;4=任意] +recogType=4 + +[window] +#识别界面窗口宽(px) +width=1280 +#识别界面窗口高(px) +height=800 +#统一背景色 +backgroundColor="#FFFFFF" + +[camera] +#人脸摄像头的编号 +faceIndex=1 +#摄像头拍摄的画面宽(px) +faceFrameWidth=1280 +#摄像头拍摄的画面高(px) +faceFrameHeight=720 +#取一幅画面的时间间隔(ms) +frameInterval=50 +#虹膜相机取一幅画面的时间间隔(ms) +irisFrameInterval=100 +#虹膜相机拍摄宽度 +irisFrameWidth=1280 +#虹膜相机拍摄高度 +irisFrameHeight=960 +#虹膜图像高度 +irisWidth=640 +#虹膜图像高度 +irisHeight=480 + +[stack] +#拍摄图像栈最大值 +capture=50 +#找到的眼睛图像栈最大值 +found=30 +#质量合格图像栈最大值 +qualified=30 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..51b5337 --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "CasicBioRecWin.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + CasicBioRecWin w; + w.show(); + return a.exec(); +} diff --git a/qss/startup.css b/qss/startup.css new file mode 100644 index 0000000..bfad9df --- /dev/null +++ b/qss/startup.css @@ -0,0 +1,12 @@ +QLabel { + color: #6868A6; + font-family: "Microsoft YaHei"; +} + +QLabel#labDate { + font-size: 36px; +} + +QLabel#labTime { + font-size: 100px; +} \ No newline at end of file diff --git a/utils/SettingConfig.cpp b/utils/SettingConfig.cpp new file mode 100644 index 0000000..13976d3 --- /dev/null +++ b/utils/SettingConfig.cpp @@ -0,0 +1,46 @@ +#include "SettingConfig.h" +#include + +SettingConfig::SettingConfig() +{ + filename = QApplication::applicationDirPath() + "/conf/config.ini"; + setting = new QSettings(this->filename, QSettings::IniFormat); + + WINDOW_WIDTH = getProperty("window", "width").toInt(); + WINDOW_HEIGHT = getProperty("window", "height").toInt(); + WINDOW_BACKGROUND_COLOR = getProperty("window", "backgroundColor").toString(); + + OUT_EXE_FILE = getProperty("exe", "outExeFile").toString(); + + FACE_CAMERA_INDEX = getProperty("camera", "faceIndex").toInt(); + FACE_FRAME_WIDTH = getProperty("camera", "faceFrameWidth").toInt(); + FACE_FRAME_HEIGHT = getProperty("camera", "faceFrameHeight").toInt(); + FACE_FRAME_INTERVAL = getProperty("camera", "frameInterval").toInt(); + IRIS_FRAME_WIDTH = getProperty("camera", "irisFrameWidth").toInt(); + IRIS_FRAME_HEIGHT = getProperty("camera", "irisFrameHeight").toInt(); + IRIS_WIDTH = getProperty("camera", "irisWidth").toInt(); + IRIS_HEIGHT = getProperty("camera", "irisHeight").toInt(); + IRIS_FRAME_INTERVAL = getProperty("camera", "irisFrameInterval").toInt(); + + MAX_MATCH_TIME = getProperty("recognize", "maxMatchTime").toInt(); + SUCCESS_TIPS_LAST = getProperty("recognize", "successTipsLast").toInt(); + FAILURE_TIPS_LAST = getProperty("recognize", "failureTipsLast").toInt(); + MAX_FACE_TRY_COUNT = getProperty("recognize", "maxFaceTryCount").toInt(); + MAX_FACE_NOT_FOUND_COUNT = getProperty("recognize", "maxFaceNotFoundCount").toInt(); + MAX_IRIS_TRY_COUNT = getProperty("recognize", "maxIrisTryCount").toInt(); + MAX_EYE_NOT_FOUND_COUNT = getProperty("recognize", "maxEyeNotFoundCount").toInt(); + + MAX_CAPTURE_STACK_SIZE = getProperty("stack", "capture").toInt(); + MAX_FOUND_STACK_SIZE = getProperty("stack", "found").toInt(); + MAX_QUALIFIED_STACK_SIZE = getProperty("stack", "qualified").toInt(); + + PORT_NAME = getProperty("com", "motoPortName").toString(); + + RECOG_TYPE = getProperty("recognize", "recogType").toInt(); +} + + +QVariant SettingConfig::getProperty(QString nodeName, QString keyName) { + QVariant var = this->setting->value(QString("/%1/%2").arg(nodeName).arg(keyName)); + return var; +} diff --git a/utils/SettingConfig.h b/utils/SettingConfig.h new file mode 100644 index 0000000..f2f8e98 --- /dev/null +++ b/utils/SettingConfig.h @@ -0,0 +1,68 @@ +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include +#include + +class SettingConfig : public QObject +{ +public: + ~SettingConfig() {}; + SettingConfig(const SettingConfig&)=delete; + SettingConfig& operator=(const SettingConfig&)=delete; + + static SettingConfig& getInstance() { + static SettingConfig instance; + return instance; + } + + /** + * @brief get + * @param nodeName + * @param keyName + * @return QVariant + * @title + */ + QVariant getProperty(QString nodeName, QString keyName); + + /******** 以下为需要的各类参数 ********/ + int WINDOW_WIDTH; + int WINDOW_HEIGHT; + QString WINDOW_BACKGROUND_COLOR; + + QString OUT_EXE_FILE; + + int FACE_CAMERA_INDEX; + int FACE_FRAME_WIDTH; + int FACE_FRAME_HEIGHT; + int FACE_FRAME_INTERVAL; + int IRIS_FRAME_INTERVAL; + int IRIS_FRAME_WIDTH; + int IRIS_FRAME_HEIGHT; + int IRIS_WIDTH; + int IRIS_HEIGHT; + + int MAX_MATCH_TIME; + int SUCCESS_TIPS_LAST; + int FAILURE_TIPS_LAST; + int MAX_FACE_TRY_COUNT; + int MAX_FACE_NOT_FOUND_COUNT; + int MAX_IRIS_TRY_COUNT; + int MAX_EYE_NOT_FOUND_COUNT; + + int MAX_CAPTURE_STACK_SIZE; + int MAX_FOUND_STACK_SIZE; + int MAX_QUALIFIED_STACK_SIZE; + + QString PORT_NAME; + + int RECOG_TYPE = 0; + +private: + SettingConfig(); + + QString filename; + QSettings* setting; +}; + +#endif // SETTINGCONFIG_H diff --git a/utils/id/IdWorker.h b/utils/id/IdWorker.h new file mode 100644 index 0000000..6c48aa9 --- /dev/null +++ b/utils/id/IdWorker.h @@ -0,0 +1,218 @@ +#ifndef _JW_CORE_ID_WORKER_H_ +#define _JW_CORE_ID_WORKER_H_ + +#include +#include +#include +#include +#include +#include "Noncopyable.h" +#include "Singleton.h" + +// 如果不使用 mutex, 则开启下面这个定义, 但是我发现, 还是开启 mutex 功能, 速度比较快 +// #define SNOWFLAKE_ID_WORKER_NO_LOCK + +namespace Jiawa { + + /** + * @brief 核心 + * 核心功能 + */ + namespace Core { + + /** + * @brief 分布式id生成类 + * https://segmentfault.com/a/1190000011282426 + * https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala + * + * 64bit id: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + * || || || | | | + * |└---------------------------时间戳--------------------------┘└中心-┘└机器-┘ └----序列号----┘ + * | + * 不用 + * SnowFlake的优点: 整体上按照时间自增排序, 并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 并且效率较高, 经测试, SnowFlake每秒能够产生26万ID左右. + */ + class SnowflakeIdWorker : private Noncopyable { + + // 实现单例 + friend class Singleton; + + public: + typedef unsigned int UInt; + typedef unsigned long long int UInt64; + +#ifdef SNOWFLAKE_ID_WORKER_NO_LOCK + typedef std::atomic AtomicUInt; + typedef std::atomic AtomicUInt64; +#else + typedef UInt AtomicUInt; + typedef UInt64 AtomicUInt64; +#endif + + void setWorkerId(UInt workerId) { + this->workerId = workerId; + } + + void setDatacenterId(UInt datacenterId) { + this->datacenterId = datacenterId; + } + + UInt64 getId() { + return nextId(); + } + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + UInt64 nextId() { +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::unique_lock lock{ mutex }; + AtomicUInt64 timestamp{ 0 }; +#else + static AtomicUInt64 timestamp{ 0 }; +#endif + timestamp = timeGen(); + + // 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + std::ostringstream s; + s << "clock moved backwards. Refusing to generate id for " << lastTimestamp - timestamp << " milliseconds"; + throw std::exception(std::runtime_error(s.str())); + } + + if (lastTimestamp == timestamp) { + // 如果是同一时间生成的, 则进行毫秒内序列 + sequence = (sequence + 1) & sequenceMask; + if (0 == sequence) { + // 毫秒内序列溢出, 阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0; + } + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + lastTimestamp = timestamp; +#else + lastTimestamp = timestamp.load(); +#endif + + // 移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + } + + protected: + SnowflakeIdWorker() : workerId(0), datacenterId(0), sequence(0), lastTimestamp(0) { } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + UInt64 timeGen() const { + auto t = std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()); + return t.time_since_epoch().count(); + } + + /** + * 阻塞到下一个毫秒, 直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + UInt64 tilNextMillis(UInt64 lastTimestamp) const { + UInt64 timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + private: + +#ifndef SNOWFLAKE_ID_WORKER_NO_LOCK + std::mutex mutex; +#endif + + /** + * 开始时间截 (2018-01-01 00:00:00.000) + */ + const UInt64 twepoch = 1514736000000; + + /** + * 机器id所占的位数 + */ + const UInt workerIdBits = 5; + + /** + * 数据中心id所占的位数 + */ + const UInt datacenterIdBits = 5; + + /** + * 序列所占的位数 + */ + const UInt sequenceBits = 12; + + /** + * 机器ID向左移12位 + */ + const UInt workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位 + */ + const UInt datacenterIdShift = workerIdShift + workerIdBits; + + /** + * 时间截向左移22位 + */ + const UInt timestampLeftShift = datacenterIdShift + datacenterIdBits; + + /** + * 支持的最大机器id, 结果是31 + */ + const UInt maxWorkerId = -1 ^ (-1 << workerIdBits); + + /** + * 支持的最大数据中心id, 结果是31 + */ + const UInt maxDatacenterId = -1 ^ (-1 << datacenterIdBits); + + /** + * 生成序列的掩码, 这里为4095 + */ + const UInt sequenceMask = -1 ^ (-1 << sequenceBits); + + /** + * 工作机器id(0~31) + */ + UInt workerId; + + /** + * 数据中心id(0~31) + */ + UInt datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + AtomicUInt sequence{ 0 }; + + /** + * 上次生成ID的时间截 + */ + AtomicUInt64 lastTimestamp{ 0 }; + + }; + + typedef SnowflakeIdWorker IdWorker; + } +} + +#endif // _JW_CORE_ID_WORKER_H_ diff --git a/utils/id/Noncopyable.h b/utils/id/Noncopyable.h new file mode 100644 index 0000000..d87f58a --- /dev/null +++ b/utils/id/Noncopyable.h @@ -0,0 +1,31 @@ +#ifndef _JW_CORE_NONCOPYABLE_H_ +#define _JW_CORE_NONCOPYABLE_H_ + + +// Private copy constructor and copy assignment ensure classes derived from +// class noncopyable cannot be copied. + +namespace Jiawa { + namespace Core { + + // protection from unintended ADL(Argument Dependent Lookup) + namespace Noncopyable_ { + + class Noncopyable + { + protected: + Noncopyable() = default; + ~Noncopyable() = default; + + Noncopyable(const Noncopyable&) = delete; + Noncopyable(const Noncopyable&&) = delete; + Noncopyable& operator=(const Noncopyable&) = delete; + Noncopyable& operator=(const Noncopyable&&) = delete; + }; + } + + typedef Noncopyable_::Noncopyable Noncopyable; + } +} + +#endif // _JW_CORE_NONCOPYABLE_H_ diff --git a/utils/id/Singleton.h b/utils/id/Singleton.h new file mode 100644 index 0000000..d1c0553 --- /dev/null +++ b/utils/id/Singleton.h @@ -0,0 +1,60 @@ +#ifndef _JW_CORE_SINGLETON_H_ +#define _JW_CORE_SINGLETON_H_ + +namespace Jiawa { + namespace Core { + + // boost/container/detail/singleton.hpp + // http://blog.csdn.net/fullsail/article/details/8483106 + // T must be: no-throw default constructible and no-throw destructible + template + class Singleton { + private: + Singleton() = default; + ~Singleton() = default; + + private: + struct object_creator + { + // This constructor does nothing more than ensure that instance() + // is called before main() begins, thus creating the static + // T object before multithreading race issues can come up. + object_creator() { Singleton::instance(); } + inline void do_nothing() const { } + }; + static object_creator create_object; + + private: + Singleton(const Singleton&) = delete; + Singleton(const Singleton&&) = delete; + Singleton& operator=(const Singleton&) = delete; + Singleton& operator=(const Singleton&&) = delete; + + public: + typedef T object_type; + + // If, at any point (in user code), Singleton::instance() + // is called, then the following function is instantiated. + static object_type& instance() + { + // This is the object that we return a reference to. + // It is guaranteed to be created before main() begins because of + // the next line. + static object_type obj; + + // The following line does nothing else than force the instantiation + // of Singleton::create_object, whose constructor is + // called before main() begins. + create_object.do_nothing(); + + return obj; + } + }; + + template + typename Singleton::object_creator Singleton::create_object; + } +} + +#endif // _JW_CORE_SINGLETON_H_ + diff --git a/utils/id/Timer.h b/utils/id/Timer.h new file mode 100644 index 0000000..0f1ff1b --- /dev/null +++ b/utils/id/Timer.h @@ -0,0 +1,57 @@ +#ifndef _JW_CORE_TIMER_H_ +#define _JW_CORE_TIMER_H_ + +#include + +namespace Jiawa { + + /** + * @brief 核心 + * 核心功能 + */ + namespace Core { + + /** + * @brief 计时器类 + * 计时 + */ + template + class Timer { + public: + + typedef CLOCK clock; + typedef typename CLOCK::rep rep; + typedef typename CLOCK::duration duration; + typedef typename CLOCK::time_point time_point; + + Timer() : m_start(CLOCK::now()) { + } + + /** + * @brief 重置计时器 + * + * @return 开始的时间点 + */ + time_point reset() { + m_start = CLOCK::now(); + return m_start; + } + + /** + * @brief 得到流逝的时间 + * @param UNIT 返回时间的类型 + * + * @return 返回流逝的时间 + */ + template + typename UNIT::duration::rep elapsed() const { + return std::chrono::duration_cast(CLOCK::now() - m_start).count(); + } + + private: + time_point m_start; + }; + } +} + +#endif // _JW_CORE_TIMER_H_ \ No newline at end of file diff --git a/utils/utils.pri b/utils/utils.pri new file mode 100644 index 0000000..a91cf5e --- /dev/null +++ b/utils/utils.pri @@ -0,0 +1,24 @@ + +HEADERS += $$PWD/id/IdWorker.h +HEADERS += $$PWD/id/Noncopyable.h +HEADERS += $$PWD/id/Singleton.h +HEADERS += $$PWD/id/Timer.h + +#HEADERS += $$PWD/easyloggingpp/easylogging++.h +#SOURCES += $$PWD/easyloggingpp/easylogging++.cc + +#HEADERS += $$PWD/QByteUtil.h +#HEADERS += $$PWD/QImageUtil.h +#HEADERS += $$PWD/QSocketClientUtil.h +HEADERS += $$PWD/SettingConfig.h +#HEADERS += $$PWD/TimerCounter.h +#HEADERS += $$PWD/SpeakerUtil.h + + +#SOURCES += $$PWD/QByteUtil.cpp +#SOURCES += $$PWD/QImageUtil.cpp +#SOURCES += $$PWD/QSocketClientUtil.cpp +SOURCES += $$PWD/SettingConfig.cpp +#SOURCES += $$PWD/TimerCounter.cpp +#SOURCES += $$PWD/SpeakerUtil.cpp +