Переглянути джерело

V0.3.1
1、添加了时间选择器

apple 3 тижнів тому
батько
коміт
b329e4ab06
27 змінених файлів з 1665 додано та 2 видалено
  1. 5 2
      SettingLibrary/CMakeLists.txt
  2. 32 0
      SettingLibrary/DataBase/GlobalVariable.h
  3. 8 0
      SettingLibrary/Modules/CheckPeriod/checkperiodwidget.cpp
  4. 15 0
      SettingLibrary/Modules/CheckPeriod/checkperiodwidget.h
  5. 36 0
      SettingLibrary/Modules/CheckPeriod/ondetectplan.cpp
  6. 31 0
      SettingLibrary/Modules/CheckPeriod/ondetectplan.h
  7. 131 0
      SettingLibrary/Modules/CheckPeriod/ondetectplan.ui
  8. 142 0
      SettingLibrary/Resources/qss/white/ondetectplan.qss
  9. 6 0
      SettingLibrary/Resources/qss/white/setinfowidget.qss
  10. 54 0
      SettingLibrary/common/SelectTime/Res/dark/timepartwidget.qss
  11. 20 0
      SettingLibrary/common/SelectTime/Res/dark/timewidget.qss
  12. BIN
      SettingLibrary/common/SelectTime/Res/image/time.png
  13. BIN
      SettingLibrary/common/SelectTime/Res/image/timing_black.png
  14. BIN
      SettingLibrary/common/SelectTime/Res/image/timing_blue.png
  15. 55 0
      SettingLibrary/common/SelectTime/Res/light/timepartwidget.qss
  16. 20 0
      SettingLibrary/common/SelectTime/Res/light/timewidget.qss
  17. 9 0
      SettingLibrary/common/SelectTime/SelectTime.qrc
  18. 25 0
      SettingLibrary/common/SelectTime/mytimedelegate.cpp
  19. 16 0
      SettingLibrary/common/SelectTime/mytimedelegate.h
  20. 40 0
      SettingLibrary/common/SelectTime/shadowwidget.cpp
  21. 20 0
      SettingLibrary/common/SelectTime/shadowwidget.h
  22. 185 0
      SettingLibrary/common/SelectTime/timepartwidget.cpp
  23. 52 0
      SettingLibrary/common/SelectTime/timepartwidget.h
  24. 61 0
      SettingLibrary/common/SelectTime/timepartwidget.ui
  25. 509 0
      SettingLibrary/common/SelectTime/timewidget.cpp
  26. 112 0
      SettingLibrary/common/SelectTime/timewidget.h
  27. 81 0
      SettingLibrary/common/SelectTime/timewidget.ui

+ 5 - 2
SettingLibrary/CMakeLists.txt

@@ -20,6 +20,9 @@ file(GLOB LOCAL_SRC
     ${CMAKE_CURRENT_SOURCE_DIR}/*.rc
     ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/*.ui
+    ${CMAKE_CURRENT_SOURCE_DIR}/common/LHLog/*.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/common/SelectTime/*.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/common/SelectTime/*.qrc
     ${CMAKE_CURRENT_SOURCE_DIR}/DataBase/*.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/Resources/*.qrc
     ${CMAKE_CURRENT_SOURCE_DIR}/Modules/AICompare/*.cpp
@@ -30,7 +33,6 @@ file(GLOB LOCAL_SRC
     ${CMAKE_CURRENT_SOURCE_DIR}/Modules/warning/*.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/UIStyle/*.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/DialogBase/*.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/common/LHLog/*.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/Network/*.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/DataManager/*.cpp
     
@@ -73,6 +75,8 @@ target_include_directories(${libName} PRIVATE
 
 
     ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/common/LHLog
+    ${CMAKE_CURRENT_SOURCE_DIR}/common/SelectTime
     ${CMAKE_CURRENT_SOURCE_DIR}/DataBase
     ${CMAKE_CURRENT_SOURCE_DIR}/Modules
     ${CMAKE_CURRENT_SOURCE_DIR}/Modules/AICompare
@@ -83,7 +87,6 @@ target_include_directories(${libName} PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}/Modules/warning
     ${CMAKE_CURRENT_SOURCE_DIR}/UIStyle
     ${CMAKE_CURRENT_SOURCE_DIR}/DialogBase
-    ${CMAKE_CURRENT_SOURCE_DIR}/common/LHLog
     ${CMAKE_CURRENT_SOURCE_DIR}/Network
     ${CMAKE_CURRENT_SOURCE_DIR}/DataManager
 

+ 32 - 0
SettingLibrary/DataBase/GlobalVariable.h

@@ -7,6 +7,38 @@
 #include <QChar>
 #include <QMap>
 
+#include <QDateTime>
+
+/**
+ * @brief 星期枚举定义,星期八是带有日期的特殊日
+ * 
+ */
+enum class eWeekType
+{
+    Week_Monday = 1,    /* 星期一 */
+    Week_Tuesday,       /* 星期二 */
+    Week_Wednesday,     /* 星期三 */
+    Week_Thursday,      /* 星期四 */
+    Week_Friday,        /* 星期五 */
+    Week_Saturday,      /* 星期六 */
+    Week_Sunday,        /* 星期日 */
+    Week_Special,       /* 特殊日期 */
+};
+
+
+/**
+ * @brief 一条计划
+ * 
+ */
+struct OnePlan_t
+{
+    eWeekType weekType;     /* 星期类型 */
+    QDate date;             /* 日期,格式为YYYY-MM-DD */
+    QTime timeStart;        /* 时间,格式为HH:mm:ss */
+    QTime timeEnd;          /* 时间,格式为HH:mm:ss */
+};
+
+
 
 /* ====================================================================
  * 声卡相关信息结构体

+ 8 - 0
SettingLibrary/Modules/CheckPeriod/checkperiodwidget.cpp

@@ -35,14 +35,22 @@ CheckPeriodWidget::~CheckPeriodWidget()
     delete ui;
 }
 
+/* 添加一个检测计划 */
 void CheckPeriodWidget::do_pBtn_addDetectPlan_clicked()
 {
     AddPeriodDialog dlg(PERIOD_WEEK);
     dlg.exec();
 }
 
+/* 添加一个不检测计划 */
 void CheckPeriodWidget::do_pBtn_addNoDetectPlan_clicked()
 {
     AddPeriodDialog dlg(PERIOD_DATE);
     dlg.exec();
 }
+
+/* 添加一个检测计划 */
+void CheckPeriodWidget::addDetectPlan(OnePlan_t& plan)
+{
+    
+}

+ 15 - 0
SettingLibrary/Modules/CheckPeriod/checkperiodwidget.h

@@ -3,12 +3,21 @@
 
 #include <QWidget>
 #include "spdlog/spdlog.h"
+#include "GlobalVariable.h"
+
 
 
 namespace Ui {
 class CheckPeriodWidget;
 }
 
+
+/**
+ * @brief 检测周期设置界面
+ * 
+ * 该界面用于设置检测周期,包括添加检测计划和不检测计划
+ */
+
 class CheckPeriodWidget : public QWidget
 {
     Q_OBJECT
@@ -18,9 +27,15 @@ public:
     ~CheckPeriodWidget();
 
 private slots:
+    /* 添加一个检测计划 */
     void do_pBtn_addDetectPlan_clicked();
+    /* 添加一个不检测计划 */
     void do_pBtn_addNoDetectPlan_clicked();
 
+private:
+    /* 添加一个检测计划 */
+    void addDetectPlan(OnePlan_t& plan);
+
 private:
     Ui::CheckPeriodWidget *ui;
     std::shared_ptr<spdlog::logger> m_logger = nullptr;

+ 36 - 0
SettingLibrary/Modules/CheckPeriod/ondetectplan.cpp

@@ -0,0 +1,36 @@
+#include "ondetectplan.h"
+#include "ui_ondetectplan.h"
+
+#include "timewidget.h"
+#include "customcombobox.h"
+
+
+OnDetectPlan::OnDetectPlan(QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::OnDetectPlan)
+{
+    ui->setupUi(this);
+
+
+    /* 设置下拉框阴影 */
+    ui->comboBox->setViewShadowEffect();
+
+}
+
+OnDetectPlan::~OnDetectPlan()
+{
+    delete ui;
+}
+
+
+/* 设置QSS */
+void OnDetectPlan::setQSS(const QString &qss)
+{
+    if(qss.isEmpty())
+    {
+        return;
+    }
+
+    /* 设置QSS */
+    this->setStyleSheet(qss);
+}

+ 31 - 0
SettingLibrary/Modules/CheckPeriod/ondetectplan.h

@@ -0,0 +1,31 @@
+#ifndef ONDETECTPLAN_H
+#define ONDETECTPLAN_H
+
+#include <QWidget>
+
+namespace Ui {
+class OnDetectPlan;
+}
+
+
+/**
+ * @brief 不一致检测计划
+ * 
+ */
+class OnDetectPlan : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit OnDetectPlan(QWidget *parent = nullptr);
+    ~OnDetectPlan();
+
+    /* 设置QSS */
+    void setQSS(const QString &qss);
+    
+
+private:
+    Ui::OnDetectPlan *ui;
+};
+
+#endif // ONDETECTPLAN_H

+ 131 - 0
SettingLibrary/Modules/CheckPeriod/ondetectplan.ui

@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>OnDetectPlan</class>
+ <widget class="QWidget" name="OnDetectPlan">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>344</width>
+    <height>32</height>
+   </rect>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>0</width>
+    <height>32</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="CustomComboBox" name="comboBox">
+     <property name="minimumSize">
+      <size>
+       <width>100</width>
+       <height>32</height>
+      </size>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="TimeWidget" name="timeEdit_start">
+     <property name="minimumSize">
+      <size>
+       <width>94</width>
+       <height>32</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>94</width>
+       <height>16777215</height>
+      </size>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="minimumSize">
+      <size>
+       <width>8</width>
+       <height>32</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>8</width>
+       <height>16777215</height>
+      </size>
+     </property>
+     <property name="text">
+      <string>-</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="TimeWidget" name="timeEdit_end">
+     <property name="minimumSize">
+      <size>
+       <width>94</width>
+       <height>32</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>94</width>
+       <height>16777215</height>
+      </size>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QPushButton" name="pBtn_close">
+     <property name="minimumSize">
+      <size>
+       <width>32</width>
+       <height>32</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>32</width>
+       <height>32</height>
+      </size>
+     </property>
+     <property name="text">
+      <string/>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>CustomComboBox</class>
+   <extends>QComboBox</extends>
+   <header location="global">customcombobox.h</header>
+  </customwidget>
+  <customwidget>
+   <class>TimeWidget</class>
+   <extends>QTimeEdit</extends>
+   <header location="global">timewidget.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>

+ 142 - 0
SettingLibrary/Resources/qss/white/ondetectplan.qss

@@ -0,0 +1,142 @@
+
+
+QPushButton#pBtn_close
+{
+	border-image: url(:/icon/del.png);
+}
+QPushButton#pBtn_close:hover
+{
+	border-image: url(:/icon/del_hover.png);
+}
+
+
+/* ==========================================================
+ *  TimeWidget
+ * ========================================================== */
+
+TimeWidget
+{
+	background: #FFFFFF;
+	border-radius: 4px;
+	border: 1px solid #E6E9F4;
+	padding-left: 12px;
+	font-weight: 400;
+	font-size: 14px;
+	color: #3A3F63;
+}
+
+TimeWidget:hover
+{
+	border: 1px solid #4458FE;
+}
+
+
+/* ==========================================================
+ *  QComboBox(这个是在用的)
+ * ========================================================== */
+
+QComboBox:enabled
+{
+    background-color:#FFFFFF;
+    border: 1px solid #E6E9F4;
+    border-radius: 4px;
+    font-size:14px;
+    font-weight: 400;
+    color:#3A3F63;
+    padding-left: 12px;
+}
+
+/* 不能编辑的时候的样式,setEnable(false) */
+QComboBox:!enabled
+{
+    background:rgba(0,0,0,0.04);
+	border: 1px solid #E6E9F4;
+    border-radius: 4px;
+    font-size:14px;
+    font-weight: 400;
+    color:rgba(58,63,99,0.65);
+    padding-left: 12px;
+}
+
+QComboBox:hover
+{
+    border: 1px solid #4458FE;
+    border-radius: 4px;
+    background:transparent;
+}
+
+/* 下拉箭头所在的位置方框 */
+QComboBox::drop-down
+{
+    width: 24px;
+    border: none;
+}
+/* 下拉箭头图标 */
+QComboBox::down-arrow
+{
+    image: url(:/icon/down_arrow.png);
+    height:16px;
+    width:16px;
+}
+
+/* 下拉条样式,就是view,整个下拉窗体的样式 */
+QComboBox QAbstractItemView
+{
+    background-color: #FFFFFF;
+    margin: 12px;
+    outline:0px;
+    font-size:14px;
+    color: #3A3F63;
+    border-radius: 4px;
+}
+
+/* 使下面两句生效,需要加上如下语句 */
+/* m_comBoxDev->setView(new QListView()); */
+QComboBox QAbstractItemView::item
+{
+    background-color: #FFFFFF;
+    border-radius:4px;
+    color: #3A3F63;
+    padding-left: 12px;
+    height: 32px;
+}
+
+QComboBox QAbstractItemView::item:hover
+{
+    border-radius:4px;
+    background-color: #EEF2FF;
+}
+
+/******** combobox 滚动条  *********/
+/*主体部分*/
+QComboBox QScrollBar::vertical
+{ 
+    width:8px;
+    background:transparent;
+    border:none;
+    border-radius:5px;
+}
+/*滑块主体*/
+QComboBox QScrollBar::handle::vertical
+{
+    width: 8px;
+    background: #E2E2E2;
+    border-radius: 3px;
+    min-width: 8px;
+}
+QComboBox QScrollBar::handle::vertical::hover
+{
+    background:transparent;
+}
+/*上箭头*/
+QComboBox QScrollBar::add-line::vertical
+{
+    border:none;
+}
+/*下箭头*/
+QComboBox QScrollBar::sub-line::vertical
+{
+    border:none;
+}
+
+

+ 6 - 0
SettingLibrary/Resources/qss/white/setinfowidget.qss

@@ -4,6 +4,12 @@
  *  QTabWidget
  * ========================================================== */
 
+QWidget#widget_bottom
+{
+	background: #FFFFFF;
+}
+
+
 QTabWidget#tabWidget
 {
 	background: #FFFFFF;

+ 54 - 0
SettingLibrary/common/SelectTime/Res/dark/timepartwidget.qss

@@ -0,0 +1,54 @@
+
+
+QWidget
+{
+    border-radius: 0px;
+    background: #373639;
+}
+
+QListWidget
+{
+    font-size: 14px;
+    color: rgba(255,255,255,0.9);
+	border: none;
+	border-right: 1px solid rgba(0, 0, 0, 0.06);
+	background: #747578;
+	outline: 0px;
+}
+QListView::item:hover 
+{
+    background-color: rgb(227, 238, 255);
+    color: "#3A3F63";
+}
+
+QListView::item:selected 
+{
+    background-color: #438EFF;
+    color: rgba(255,255,255,0.9);
+	outline: none;
+}
+
+QScrollBar:vertical
+{
+	border:none;
+    background-color: #e2e2e2;
+    width: 4px;
+}
+
+QScrollBar::handle:vertical
+{
+	background: #e2e2e2;
+    border-radius: 2px;
+}
+
+QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical
+{
+	background: #ffffff;/*transparent;*/
+    border: none;
+}
+
+QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical
+{
+	background: #ffffff;/*transparent;*/
+    border: none;
+}

+ 20 - 0
SettingLibrary/common/SelectTime/Res/dark/timewidget.qss

@@ -0,0 +1,20 @@
+QPushButton
+{
+	border-image: url(:/images/datetime.png);
+}
+QPushButton[selected=true]
+{
+	border-image: url(:/images/datetime.png);
+}
+QPushButton::hover[selected=true]
+{
+	border-image: url(:/images/cancle.png);
+}
+
+QDateTimeEdit
+{
+	padding-left: 0px;
+	border: 0px solid #D8D8D8;
+}
+
+

BIN
SettingLibrary/common/SelectTime/Res/image/time.png


BIN
SettingLibrary/common/SelectTime/Res/image/timing_black.png


BIN
SettingLibrary/common/SelectTime/Res/image/timing_blue.png


+ 55 - 0
SettingLibrary/common/SelectTime/Res/light/timepartwidget.qss

@@ -0,0 +1,55 @@
+
+QWidget
+{
+    border-radius: 0px;
+    background: #FFFFFF;
+}
+
+
+
+QListWidget
+{
+    font-size: 14px;
+    color: "#3A3F63";
+	border: none;
+	border-right: 1px solid rgba(0, 0, 0, 0.06);
+	background: #ffffff;
+	outline: 0px;
+}
+QListView::item:hover 
+{
+	background-color: rgb(245,245,245);
+    color: "#3A3F63";
+}
+
+QListView::item:selected 
+{
+	background-color: rgb(227, 238, 255);
+    color: "#3A3F63";
+	outline: none;
+}
+
+QScrollBar:vertical
+{
+	border:none;
+    background-color: #e2e2e2;
+    width: 4px;
+}
+
+QScrollBar::handle:vertical
+{
+	background: #e2e2e2;
+    border-radius: 2px;
+}
+
+QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical
+{
+	background: #ffffff;/*transparent;*/
+    border: none;
+}
+
+QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical
+{
+	background: #ffffff;/*transparent;*/
+    border: none;
+}

+ 20 - 0
SettingLibrary/common/SelectTime/Res/light/timewidget.qss

@@ -0,0 +1,20 @@
+QPushButton
+{
+	border-image: url(:/Res/image/time.png);
+}
+
+QPushButton[selected=true]
+{
+	border-image: url(:/Res/image/time.png);
+}
+
+QPushButton::hover[selected=true]
+{
+	border-image: url(:/Res/image/time.png);
+}
+
+QDateTimeEdit
+{
+	padding-left: 0px;
+	border: 0px solid #D8D8D8;
+}

+ 9 - 0
SettingLibrary/common/SelectTime/SelectTime.qrc

@@ -0,0 +1,9 @@
+<RCC>
+    <qresource prefix="/">
+    <file>Res/image/time.png</file>
+    <file>Res/light/timepartwidget.qss</file>
+    <file>Res/light/timewidget.qss</file>
+    <file>Res/dark/timepartwidget.qss</file>
+    <file>Res/dark/timewidget.qss</file>
+    </qresource>
+</RCC>

+ 25 - 0
SettingLibrary/common/SelectTime/mytimedelegate.cpp

@@ -0,0 +1,25 @@
+#include "mytimedelegate.h"
+#include <QPainter>
+#include <QMouseEvent>
+
+MyTimeDelegate::MyTimeDelegate(QObject* parent) :
+    QStyledItemDelegate(parent)
+{
+
+}
+
+void MyTimeDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+    if (nullptr == painter || !index.isValid()) {
+        return;
+    }
+    QString data = index.data().toString();
+    if (data.isEmpty()) {
+        if ((option.state & QStyle::State_MouseOver) ||
+                (option.state & QStyle::State_Selected)) {
+            painter->fillRect(option.rect, c_bkColor);
+            return;
+        }
+    }
+    QStyledItemDelegate::paint(painter, option, index);
+}

+ 16 - 0
SettingLibrary/common/SelectTime/mytimedelegate.h

@@ -0,0 +1,16 @@
+#ifndef MYTIMEDELEGATE_H
+#define MYTIMEDELEGATE_H
+
+#include <QStyledItemDelegate>
+
+class MyTimeDelegate : public QStyledItemDelegate
+{
+    Q_OBJECT
+public:
+    const QColor c_bkColor = QColor(255,255,255);
+    explicit MyTimeDelegate(QObject *parent = nullptr);
+protected:
+     void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
+};
+
+#endif // MYTIMEDELEGATE_H

+ 40 - 0
SettingLibrary/common/SelectTime/shadowwidget.cpp

@@ -0,0 +1,40 @@
+#include "shadowwidget.h"
+#include <QLayout>
+#include <QGraphicsDropShadowEffect>
+#include <QDebug>
+
+ShadowWidget::ShadowWidget(QWidget *parent)
+    : QWidget(parent)
+    , m_pCentralWidget(new QWidget(this))
+{
+    setWindowFlags(Qt::FramelessWindowHint);
+    setAttribute(Qt::WA_TranslucentBackground);
+
+    QHBoxLayout* pLayout = new QHBoxLayout();
+    if (nullptr != pLayout) {
+        pLayout->addWidget(m_pCentralWidget);
+        this->setLayout(pLayout);
+    }
+
+    QGraphicsDropShadowEffect *pShadowEffect = new QGraphicsDropShadowEffect(this);
+    pShadowEffect->setBlurRadius(16);               // 模糊度
+    pShadowEffect->setColor(QColor(0, 0, 0, 90));   // 阴影的颜色
+    pShadowEffect->setOffset(0, 0);                 // 水平和垂直偏移量
+    m_pCentralWidget->setGraphicsEffect(pShadowEffect);
+}
+
+
+void ShadowWidget::setCentralLayout(QLayout *layout)
+{
+    if (nullptr != m_pCentralWidget) {
+        m_pCentralWidget->setLayout(layout);
+    }
+}
+
+QLayout* ShadowWidget::getLayout() const
+{
+    if (nullptr != m_pCentralWidget) {
+        return m_pCentralWidget->layout();
+    }
+    return nullptr;
+}

+ 20 - 0
SettingLibrary/common/SelectTime/shadowwidget.h

@@ -0,0 +1,20 @@
+#ifndef SHADOWWIDGET_H
+#define SHADOWWIDGET_H
+
+#include <QWidget>
+
+class ShadowWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit ShadowWidget(QWidget *parent = nullptr);
+
+    QWidget* centralWidget() {return m_pCentralWidget;}
+    void setCentralLayout(QLayout* layout);
+    QLayout* getLayout() const;
+signals:
+private:
+    QWidget* m_pCentralWidget{nullptr};
+};
+
+#endif // SHADOWWIDGET_H

+ 185 - 0
SettingLibrary/common/SelectTime/timepartwidget.cpp

@@ -0,0 +1,185 @@
+#include "timepartwidget.h"
+#include "ui_timepartwidget.h"
+#include <QListWidgetItem>
+#include <QScrollBar>
+#include <QDateTime>
+#include <QMouseEvent>
+#include <QDebug>
+#include <QFile>
+#include "mytimedelegate.h"
+// #include "lhstylemanager.h"
+// #include "LHQLogApi.h"
+#include "UIStyleManager.h"
+#include "spdlog/spdlog.h"
+
+TimePartWidget::TimePartWidget(QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::TimePartWidget)
+{
+    ui->setupUi(this);
+}
+
+TimePartWidget::TimePartWidget(TimePartWidget::emSection type, QWidget* parent) :
+    TimePartWidget(parent)
+{
+    m_type = type;
+    // 设置代理
+    m_delegate.reset(new MyTimeDelegate(this));
+    if (nullptr != m_delegate.data()) {
+        ui->listWidget->setItemDelegate(m_delegate.data());
+    }
+
+    // 设置滚动条
+    m_pListBar.reset(new QScrollBar(Qt::Orientation::Vertical, ui->listWidget));
+    if (nullptr != m_pListBar.data()) {
+        m_pListBar->move(width() - 4, 1); // 宽度4,与右侧距离2
+        m_pListBar->setMinimumHeight(this->height() - 2);
+        m_pListBar->setMaximumHeight(this->height() - 2);
+        m_pListBar->hide();
+        connect(ui->listWidget->verticalScrollBar(), &QScrollBar::valueChanged, m_pListBar.data(), &QScrollBar::setValue);
+        connect(ui->listWidget->verticalScrollBar(), &QScrollBar::rangeChanged, m_pListBar.data(), &QScrollBar::setRange);
+        connect(m_pListBar.data(), &QScrollBar::valueChanged, ui->listWidget->verticalScrollBar(), &QScrollBar::setValue);
+    }
+    /* 设置QSS */
+    setQSS();
+
+    switch (type) {
+    case MINUTE:
+    case SECOND: {
+        InitListWidget(60);
+        break;
+    }
+    case HOUR: {
+        InitListWidget(24);
+        break;
+    }
+    default:
+        break;
+    }
+    ui->listWidget->setCurrentRow(0);
+    ui->listWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+    auto pf = [this](QListWidgetItem* item){
+        ui->listWidget->scrollToItem(item, QAbstractItemView::PositionAtTop); // 滚到最顶部
+    };
+    connect(ui->listWidget, &QListWidget::itemPressed, this, pf);
+    connect(ui->listWidget, &QListWidget::itemPressed, this, &TimePartWidget::sigItemClicked);
+}
+
+TimePartWidget::~TimePartWidget()
+{
+    delete ui;
+}
+
+void TimePartWidget::SetTime(const QDateTime &dt)
+{
+    switch (m_type) {
+    case HOUR:
+        SelectListItem(dt.time().hour());
+        break;
+    case MINUTE:
+        SelectListItem(dt.time().minute());
+        break;
+    case SECOND:
+        SelectListItem(dt.time().second());
+        break;
+    default:
+        break;
+    }
+}
+
+void TimePartWidget::SetMaxWidth(int w)
+{
+    // 更新滚动条位置
+    if (!m_pListBar.isNull()) {
+        m_pListBar->move(w - 4, 1);
+    }
+}
+
+void TimePartWidget::ScrollToSelect()
+{
+    auto items = ui->listWidget->selectedItems();
+    if (items.count() > 0) {
+        ui->listWidget->scrollToItem(items.at(0), QAbstractItemView::PositionAtTop);
+    }
+}
+
+/* 设置QSS */
+void TimePartWidget::setQSS()
+{
+    QString qssPath;
+    if(UIStyle.getUIStyle() == EUIStyle::UI_Light)
+    {
+        qssPath = QString(":/Res/light/timepartwidget.qss");
+    }
+    else if(UIStyle.getUIStyle() == EUIStyle::UI_Dark)
+    {
+        qssPath = QString(":/Res/dark/timepartwidget.qss");
+    }
+
+    QFile file(qssPath);
+    if(file.open(QFile::ReadOnly))
+    {
+        QString styleSheet = QLatin1String(file.readAll());
+        setStyleSheet(styleSheet);
+        file.close();
+    }
+    else 
+    {
+        SPDLOG_ERROR("open qss file failed: {}", qssPath.toStdString());
+    }
+}
+
+void TimePartWidget::enterEvent(QEvent *event)
+{
+    if (!m_pListBar.isNull()) {
+        m_pListBar->show();
+    }
+
+    QWidget::enterEvent(event);
+}
+
+void TimePartWidget::leaveEvent(QEvent *event)
+{
+    if (!m_pListBar.isNull()) {
+        m_pListBar->hide();
+    }
+    QWidget::leaveEvent(event);
+}
+
+void TimePartWidget::InitListWidget(int total)
+{
+    ui->listWidget->clear();
+    for (int i = 0; i < total; ++i) {
+        QListWidgetItem* pItem = new QListWidgetItem;
+        if (nullptr == pItem) {
+            continue;
+        }
+        pItem->setTextAlignment(Qt::AlignCenter);
+        pItem->setText(QString("%1").arg(i, 2, 10, QLatin1Char('0')));
+        pItem->setSizeHint(QSize(32, 32));
+        ui->listWidget->addItem(pItem);
+    }
+    // 填充4个不可选空白项
+    for (int i = 0; i < 4; ++i) {
+        QListWidgetItem* pItem = new QListWidgetItem;
+        if (nullptr == pItem) continue;
+        pItem->setSizeHint(QSize(32, 32));
+        pItem->setFlags(pItem->flags() & ~Qt::ItemIsEnabled & ~Qt::ItemIsSelectable);
+        ui->listWidget->addItem(pItem);
+    }
+}
+
+void TimePartWidget::SelectListItem(int time)
+{
+    for (int i = 0; i < ui->listWidget->count(); ++i) {
+        QListWidgetItem* pItem = ui->listWidget->item(i);
+        if (nullptr == pItem) continue;
+        // 注意时间填充了0
+        if (pItem->text() == QString("%1").arg(time, 2, 10, QLatin1Char('0'))) {
+            //qInfo() << "SelectListItem: " << "滚动到最顶部, time: " << time;
+            pItem->setSelected(true);
+            ui->listWidget->scrollToItem(pItem, QAbstractItemView::PositionAtTop); // 滚到最顶部
+            break;
+        }
+    }
+}

+ 52 - 0
SettingLibrary/common/SelectTime/timepartwidget.h

@@ -0,0 +1,52 @@
+#ifndef TIMEPARTWIDGET_H
+#define TIMEPARTWIDGET_H
+
+#include <QWidget>
+
+class MyTimeDelegate;
+class QListWidgetItem;
+class QScrollBar;
+
+namespace Ui {
+class TimePartWidget;
+}
+
+class TimePartWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    enum emSection {
+        HOUR = 0,
+        MINUTE = 1,
+        SECOND = 2,
+        MAX_SECTION
+    };
+public:
+    explicit TimePartWidget(QWidget *parent = nullptr);
+    TimePartWidget(emSection type, QWidget* parent = nullptr);
+    ~TimePartWidget();
+
+    emSection GetType() const {return m_type;}
+    void SetTime(const QDateTime& dt);
+    void SetMaxWidth(int w);
+    void ScrollToSelect();
+
+    /* 设置QSS */
+    void setQSS();
+
+protected:
+    void enterEvent(QEvent* event) override;
+    void leaveEvent(QEvent* event) override;
+signals:
+    void sigItemClicked(QListWidgetItem* item);
+private:
+    void InitListWidget(int total);
+    void SelectListItem(int time);
+private:
+    Ui::TimePartWidget *ui;
+    emSection m_type;
+    QScopedPointer<MyTimeDelegate> m_delegate;
+    QScopedPointer<QScrollBar> m_pListBar;
+};
+
+#endif // TIMEPARTWIDGET_H

+ 61 - 0
SettingLibrary/common/SelectTime/timepartwidget.ui

@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>TimePartWidget</class>
+ <widget class="QWidget" name="TimePartWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>116</width>
+    <height>192</height>
+   </rect>
+  </property>
+  <property name="maximumSize">
+   <size>
+    <width>16777215</width>
+    <height>16777215</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="spacing">
+    <number>0</number>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QListWidget" name="listWidget">
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>0</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>16777215</width>
+       <height>16777215</height>
+      </size>
+     </property>
+     <property name="styleSheet">
+      <string notr="true"/>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 509 - 0
SettingLibrary/common/SelectTime/timewidget.cpp

@@ -0,0 +1,509 @@
+#include "timewidget.h"
+#include "ui_timewidget.h"
+#include <QListWidgetItem>
+#include <QMouseEvent>
+#include <QDebug>
+#include <QSizePolicy>
+#include <QFile>
+#include "timepartwidget.h"
+#include "shadowwidget.h"
+#include "UIStyleManager.h"
+#include "spdlog/spdlog.h"
+
+TimeWidget::TimeWidget(QWidget *parent , ShowType type) :
+    QFrame(parent),
+    ui(new Ui::TimeWidget),
+    m_wdgTimeArea(nullptr),
+    m_pMainWindow(parent),
+    m_type(type)
+{
+    ui->setupUi(this);
+    Init();
+}
+
+
+TimeWidget::TimeWidget(ShowType type) : 
+    QFrame(nullptr),
+    ui(new Ui::TimeWidget),
+    m_wdgTimeArea(nullptr),
+    m_pMainWindow(nullptr),
+    m_type(type)
+{
+    ui->setupUi(this);
+    Init();
+}
+
+TimeWidget::~TimeWidget()
+{
+    delete ui;
+}
+
+void TimeWidget::CreateTimeVector(const QVector<int> &types)
+{
+    ClearVector(m_vecTimePart);
+    for (auto& type : types) {
+        TimePartWidget::emSection emType = static_cast<TimePartWidget::emSection>(type);
+        if (emType >= TimePartWidget::emSection::MAX_SECTION) {
+            continue;
+        }
+        TimePartWidget* pTmp = new TimePartWidget(emType, this);
+        if (nullptr != pTmp) {
+            pTmp->SetMaxWidth(width() / types.count());
+            m_vecTimePart.append(pTmp);
+        }
+    }
+}
+
+void TimeWidget::ClearVector(QVector<TimePartWidget *> &vec)
+{
+    for (auto& pWdg : vec) {
+        if (nullptr != pWdg) {
+            delete pWdg;
+            pWdg = nullptr;
+        }
+    }
+    vec.clear();
+}
+
+void TimeWidget::SetMainWindow(QWidget* pWidget)
+{
+    if (nullptr != m_pMainWindow) {
+        this->removeEventFilter(m_pMainWindow);
+    }
+    if (nullptr != pWidget) {
+        pWidget->installEventFilter(this);
+    }
+    m_pMainWindow = pWidget;
+}
+
+/* 返回时间 */
+QTime TimeWidget::getTime()
+{
+    return ui->dateTimeEdit->time();
+}
+
+
+/**
+ * @brief 存在时间就返回hh:mm:ss.zzz格式字符串,否则返回提示信息
+ * @return
+ */
+QString TimeWidget::getTimeStr()
+{
+    QString ret(ui->lbl_tip->text());
+    if (!ui->dateTimeEdit->isHidden()) {
+        ret = ui->dateTimeEdit->time().toString("hh:mm:ss");//.zzz
+    }
+    return ret;
+}
+/**
+ * @brief 存在返回时间,否则返回00:00:00
+ * @return
+ */
+QTime TimeWidget::getFormTime() const
+{
+    return ui->dateTimeEdit->isHidden() ? QTime(0, 0, 0) : ui->dateTimeEdit->time();
+}
+
+void TimeWidget::setTime(const QString& t)
+{
+    QTime time = QTime::fromString(t, "hh:mm:ss");
+    ui->dateTimeEdit->setTime(time);
+    ui->lbl_tip->hide();
+    ui->dateTimeEdit->show();
+    UpdatePopupTime(ui->dateTimeEdit->dateTime());//
+}
+
+void TimeWidget::setTime(const QTime& t)
+{
+    ui->dateTimeEdit->setTime(t);
+    ui->lbl_tip->hide();
+    ui->dateTimeEdit->show();
+    UpdatePopupTime(ui->dateTimeEdit->dateTime());
+}
+
+void TimeWidget::clearTime()
+{
+    ui->dateTimeEdit->setTime(QTime(0, 0, 0));
+    ui->dateTimeEdit->hide();
+    ui->lbl_tip->show();
+}
+
+QString TimeWidget::tipText() const
+{
+    return ui->lbl_tip->text();
+}
+/* 设置时间选择区域的大小,不能超过时间编辑栏的大小,这个主要是防止时间栏太宽,影响美观 */
+void TimeWidget::setTimeAreaWidth(int w)
+{
+    if(w < 0)
+    {
+        m_width = 0;
+    }
+    else if(w > this->width())
+    {
+        m_width = this->width();
+    }
+    else
+    {
+        m_width = w;
+    }
+}
+
+void TimeWidget::showTimeEditArea()
+{
+    this->show();
+    ShowTimeArea(true);
+}
+
+/* 以弹窗的模式模态显示 */
+void TimeWidget::execShow()
+{
+    QEventLoop loop;
+    connect (this, &TimeWidget::signal_close, &loop, &QEventLoop::quit);
+    this->show();
+    ShowTimeArea(true);
+    loop.exec();
+
+    deleteLater();
+}
+
+/* 设置时间图标 */
+void TimeWidget::setIcon(const QString& icon)
+{
+    /* 设置图片适应按钮大小 */
+    QString ss = QString("border-image: url(%1)").arg(icon);
+    ui->btn_tip->setStyleSheet(ss);
+    ui->btn_tip->show();
+}
+
+/* 设置图标显示 */
+void TimeWidget::setIconShow(bool isShow)
+{
+    if(isShow)
+    {
+        ui->btn_tip->show();
+    }else {
+        ui->btn_tip->hide();
+    }
+}
+
+/* 设置图标大小 */
+void TimeWidget::setIconSize(int w, int h)
+{
+    ui->btn_tip->setMinimumSize(w, h);
+    /* 设置为固定大小 */
+    ui->btn_tip->setFixedSize(w, h);
+    // ui->btn_tip->resize(w, h);
+}
+
+/* 设置默认的样式 */
+void TimeWidget::setDefaultStyle()
+{
+    /* 判断显示类型,如果是弹窗直接显示编辑区 */
+    if(m_type == Dialog)
+    {
+        ui->btn_tip->hide();
+        this->resize(136,36);
+//        ShowTimeArea(false);
+        /* 设置编辑栏样式 */
+        // this->setStyleSheet(R"(
+        //     TimeWidget
+        //     {
+        //         padding-left:15px;
+        //         background: #FFFFFF;
+        //         border-radius: 4px;
+        //         border: 1px solid #E6E9F4;
+        //     }
+        // )");
+    }
+}
+
+/* 设置编辑栏大小 */
+void TimeWidget::setEditLine(int w, int h)
+{
+    this->resize(w, h);
+}
+
+/* 设置QSS */
+void TimeWidget::setQSS()
+{
+    QString qssPath;
+    if(UIStyle.getUIStyle() == EUIStyle::UI_Light)
+    {
+        qssPath = ":/Res/light/timewidget.qss";
+    } else {
+        qssPath = ":/Res/dark/timewidget.qss";
+    }
+
+    QFile file(qssPath);
+    if(file.open(QFile::ReadOnly))
+    {
+        QString styleSheet = QLatin1String(file.readAll());
+        setStyleSheet(styleSheet);
+        file.close();
+    }
+    else 
+    {
+        SPDLOG_ERROR("open qss file failed: {}", qssPath.toStdString());
+    }
+}
+
+/**
+ * @brief 点击提示信息
+ */
+void TimeWidget::onBtnTipClicked()
+{
+    bool isSelected = ui->btn_tip->property("selected").toBool();
+    if (!isSelected) {
+        // 显示日期
+        ui->lbl_tip->hide();
+        ui->dateTimeEdit->show();
+        ShowTimeArea(true);
+    } else {
+        // 清除时间
+        ui->dateTimeEdit->setTime(QTime(0, 0, 0));
+        UpdateProperty(ui->btn_tip, "selected", false);
+        QDateTime dt;
+        dt.setTime(QTime(0, 0, 0));
+        UpdatePopupTime(dt);
+        ShowTimeArea(false);
+        ui->dateTimeEdit->hide();
+        ui->lbl_tip->show();
+    }
+}
+
+/**
+ * @brief 这里添加了两个信号,一个是修改过的新时间,一个是旧时间
+ * @param obj
+ * @param e
+ * @return
+ */
+bool TimeWidget::eventFilter(QObject* obj, QEvent* e)
+{
+    if (obj == ui->dateTimeEdit) {
+        if (e->type() == QEvent::FocusIn && m_type == EditLine)
+        {
+            //qInfo() << "dateTimeEdit focusIn";
+            ShowTimeArea(true);
+            UpdateProperty(ui->btn_tip, "selected", true);
+            emit signal_formerTimer(ui->dateTimeEdit->time());
+        }
+        return QWidget::eventFilter(obj, e);
+    } else if (obj == ui->lbl_tip) {
+        if (e->type() == QEvent::MouseButtonPress && m_type == EditLine)
+        {
+            //qInfo() << "mouseButtonPress";
+            ui->dateTimeEdit->show();
+            ui->lbl_tip->hide();
+            ShowTimeArea(true);
+            //ui->dateTimeEdit->setFocus();//
+            return QWidget::eventFilter(obj, e);
+        }
+    } else if (obj == this) {
+        if (e->type() == QEvent::Enter) {
+            UpdateProperty(this, "hover", true);
+        } else if (e->type() == QEvent::Leave &&
+                   ((m_wdgTimeArea.isNull() && !ui->dateTimeEdit->hasFocus()) ||
+                    (m_wdgTimeArea && m_wdgTimeArea->isHidden())) ) {
+            UpdateProperty(this, "hover", false);
+        }
+    }
+    /* 判断是不是显示区外面,是的话就隐藏 */
+    QMouseEvent* pMouse = reinterpret_cast<QMouseEvent*>(e);
+    if (nullptr != pMouse) {
+        if (pMouse->type() == QEvent::MouseButtonPress) {
+            //qInfo() << "focusOut";
+            QPoint gtl = this->mapToGlobal(rect().topLeft());
+            QRect rc(gtl.x(), gtl.y(), width(), height()); // 全局位置判断
+            if (!rc.contains(pMouse->globalPos())) {
+                ShowTimeArea(false);
+                ui->dateTimeEdit->clearFocus();
+                UpdateProperty(this, "hover", false);
+                /* 关闭显示,发送携带时间的信号 */
+                emit signal_nowTime(ui->dateTimeEdit->time());
+                if(m_type == Dialog)
+                {
+                    this->close();
+                }
+            }
+        }
+    }
+
+    return QWidget::eventFilter(obj, e);
+}
+/**
+ * @brief m_wdgTimeArea跟随时间栏移动
+ * @param event
+ */
+void TimeWidget::moveEvent(QMoveEvent *event)
+{
+    if(m_type == Dialog && m_wdgTimeArea != nullptr)
+    {
+        QPoint pt = this->mapTo(m_pMainWindow, QPoint(0, 0));
+        m_wdgTimeArea->move(QPoint(pt.x() - SHADOW_MARGIN, pt.y() + this->height()));
+//        qDebug() << "posX:" << pt.x() << "posY:" << pt.y();
+    }
+}
+/**
+ * @brief 时间列表选中事件
+ * @param item
+ */
+void TimeWidget::onListItemClicked(QListWidgetItem *item)
+{
+    if (nullptr == item) return;
+    TimePartWidget* pWdg = reinterpret_cast<TimePartWidget*>(QObject::sender());
+    if (nullptr == pWdg) return;
+
+    QString data(item->text());
+    if (data.isEmpty()) return; // 过滤空白项
+    QDateTime oldDt(ui->dateTimeEdit->dateTime());
+    QTime t(ui->dateTimeEdit->time());
+    switch (pWdg->GetType()) {
+    case TimePartWidget::HOUR: {
+        t.setHMS(data.toInt(), t.minute(), t.second());
+        break;
+    }
+    case TimePartWidget::MINUTE: {
+        t.setHMS(t.hour(), data.toInt(), t.second());
+        break;
+    }
+    case TimePartWidget::SECOND: {
+        t.setHMS(t.hour(), t.minute(), data.toInt());
+        break;
+    }
+    default:
+        break;
+    }
+    if (oldDt.time() != t) {
+        m_bTimeFlag = true;
+        ui->dateTimeEdit->setTime(t);
+    }
+}
+/**
+ * @brief QDateTimeEdit控件时间改变事件
+ * @param dt
+ */
+void TimeWidget::onDateTimeChanged(const QDateTime& dt)
+{
+    if (dt.time() != QTime(0, 0, 0)) {
+        UpdateProperty(ui->btn_tip, "selected", true);
+    }
+    // 同步到popupWidget
+    if (!m_bTimeFlag) {
+        UpdatePopupTime(dt);
+    }
+    m_bTimeFlag = false;
+}
+
+void TimeWidget::UpdateProperty(QObject* obj, const char *name, bool flag)
+{
+    if (nullptr == obj || nullptr == name) {
+        return;
+    }
+    obj->setProperty(name, flag);
+    QWidget* pWdg = qobject_cast<QWidget*>(obj);
+    if (nullptr != pWdg) {
+        this->style()->unpolish(pWdg);
+        this->style()->polish(pWdg);
+    }
+}
+/**
+ * @brief 更新popup列表选中时间
+ * @param dt
+ */
+void TimeWidget::UpdatePopupTime(const QDateTime& dt)
+{
+    // 如果时间列表还没初始化就不会设置时间了
+    for (int i = 0; i < m_vecTimeSections.size(); ++i) {
+        auto type = m_vecTimeSections.at(i);
+        TimePartWidget::emSection emType = static_cast<TimePartWidget::emSection>(type);
+        if (emType >= TimePartWidget::emSection::MAX_SECTION) {
+            continue;
+        }
+        if (i < m_vecTimePart.size()) {
+            TimePartWidget* pWdg = m_vecTimePart.at(i);
+            if (nullptr == pWdg) continue;
+            pWdg->SetTime(dt);
+        }
+    }
+}
+
+/**
+ * @brief wdgTimeArea区域是创建出来的,不属于ui区域,他的父类是m_pMainWindow,因此移动的时候需要使用m_pMainWindow的坐标
+ * @param bShow
+ */
+void TimeWidget::ShowTimeArea(bool bShow)
+{
+    if (m_wdgTimeArea.isNull()) {
+        CreatePopupWidget();
+    }
+    if (!m_wdgTimeArea.isNull()) {
+        if (bShow) {
+            //UpdatePopupTime(ui->dateTimeEdit->dateTime());
+            // 重新定位再显示
+            QPoint pt = this->mapTo(m_pMainWindow, QPoint(0, 0));
+            m_wdgTimeArea->move(QPoint(pt.x() - SHADOW_MARGIN, pt.y() + this->height()));
+            /* 设置选择条的大小,如果没有设置m_width,就是用时间编辑栏的宽度 */
+            m_wdgTimeArea->resize((m_width == 0 ? width() : m_width) + 2 * SHADOW_MARGIN, TIME_AREA_HEIGHT * 6 + 2 * SHADOW_MARGIN);
+            m_wdgTimeArea->setMaximumWidth(width() + 2 * SHADOW_MARGIN);
+            m_wdgTimeArea->show();
+            UpdatePopupTime(ui->dateTimeEdit->dateTime());
+        } else {
+            m_wdgTimeArea->hide();
+            emit signal_close();
+        }
+    }
+}
+
+void TimeWidget::CreatePopupWidget()
+{
+    // CreateTimeArea
+    m_vecTimeSections = {TimePartWidget::HOUR, TimePartWidget::MINUTE, TimePartWidget::SECOND};
+    CreateTimeVector(m_vecTimeSections);
+    m_wdgTimeArea.reset(new ShadowWidget(m_pMainWindow));
+    if (!m_wdgTimeArea.isNull()) {
+        if (m_wdgTimeArea->centralWidget() != nullptr) {
+            m_wdgTimeArea->centralWidget()->setObjectName(QLatin1String("wdg_TimeArea"));
+            m_wdgTimeArea->centralWidget()->setStyleSheet("QWidget#wdg_TimeArea{border-radius: 2px;border: none; }");
+        }
+        QHBoxLayout* hLayout = new QHBoxLayout();
+        hLayout->setMargin(1);
+        hLayout->setSpacing(0);
+        m_wdgTimeArea->setCentralLayout(hLayout);
+        if (nullptr == m_wdgTimeArea->getLayout()) {
+            delete hLayout;
+            hLayout = nullptr;
+        }
+        m_wdgTimeArea->resize(QSize(width() + 2 * SHADOW_MARGIN, TIME_AREA_HEIGHT * 6 + 2 * SHADOW_MARGIN));
+        m_wdgTimeArea->setMaximumWidth(width() + 2 * SHADOW_MARGIN);
+        m_wdgTimeArea->hide();
+
+        if (nullptr != m_wdgTimeArea->getLayout()) {
+            foreach (auto wdg, m_vecTimePart) {
+                m_wdgTimeArea->getLayout()->addWidget(wdg);
+                connect(wdg, &TimePartWidget::sigItemClicked, this, &TimeWidget::onListItemClicked);
+            }
+        }
+    }
+}
+
+/* 初始化函数 */
+void TimeWidget::Init()
+{
+    /* 设置QSS */
+    setQSS();
+    // InitUI
+    ui->dateTimeEdit->hide();
+    ui->dateTimeEdit->installEventFilter(this);
+    this->installEventFilter(this);
+    ui->lbl_tip->installEventFilter(this);
+    if (nullptr != m_pMainWindow) {
+        m_pMainWindow->installEventFilter(this);
+    }
+    ui->btn_tip->setProperty("selected", false);
+
+    connect(ui->btn_tip, &QPushButton::clicked, this, &TimeWidget::onBtnTipClicked);
+    connect(ui->dateTimeEdit, &QDateTimeEdit::dateTimeChanged, this, &TimeWidget::onDateTimeChanged);
+
+    setDefaultStyle();
+}

+ 112 - 0
SettingLibrary/common/SelectTime/timewidget.h

@@ -0,0 +1,112 @@
+#ifndef TIMEWIDGET_H
+#define TIMEWIDGET_H
+
+
+
+/**
+ * 使用说明
+ *  1、这个时间选择器支持两种方式
+ *      * 提升QTimeEdit,作为编辑栏修改时间
+ *      * 以弹窗的方式出现
+ *  2、时间选择区域m_wdgTimeArea和时间编辑栏(在UI中)不是统一的,时间选择区域可以点击时间编辑栏
+ *     创建出来,也可以在弹窗中直接显示出来,所以moveEvent事件就是用来移动m_wdgTimeArea的。
+ *  3、在原来的基础上新添加了两个信号,在关闭的时候发送
+ *  4、使用Dialog模式的时候,点击空白处隐藏就会close掉,然后发送新的时间信号
+ *  5、使用Dialog模式,执行execShow()函数,会阻塞运行,直到关闭
+*/
+
+
+
+#include <QFrame>
+#include <QTime>
+
+class TimePartWidget;
+class QListWidgetItem;
+class ShadowWidget;
+
+namespace Ui {
+class TimeWidget;
+}
+
+/* 添加ShowType类型,判断这个控件是编辑栏还是弹窗 */
+class TimeWidget : public QFrame
+{
+    Q_OBJECT
+
+public:
+    enum ShowType{
+        EditLine = 0,           /* 时间编辑栏 */
+        Dialog = 1,             /* 以弹窗的形式出现 */
+    };
+    explicit TimeWidget(QWidget *parent = nullptr , ShowType type = EditLine);
+    explicit TimeWidget(ShowType type = EditLine);
+    ~TimeWidget();
+
+    void CreateTimeVector(const QVector<int>& types);
+    void ClearVector(QVector<TimePartWidget*>& vec);
+    // 在父窗口无法容纳控件时,这是必要的
+    void SetMainWindow(QWidget* pWidget);
+    QTime getTime();
+    QString getTimeStr();
+    QTime getFormTime() const;
+    void setTime(const QString& t);
+    void setTime(const QTime& t);
+    void clearTime();
+    QString tipText() const;
+    /* 新增一个设置时间条宽度的函数 */
+    void setTimeAreaWidth(int w);
+    /***** 2024-05-25 添加两个信号 ******/
+    void showTimeEditArea();
+    /* 以弹窗的模式模态显示 */
+    void execShow();
+    /* 设置时间图标 */
+    void setIcon(const QString& icon);
+    /* 设置图标显示 */
+    void setIconShow(bool isShow);
+    /* 设置图标大小 */
+    void setIconSize(int w, int h);
+    /* 设置默认的样式 */
+    void setDefaultStyle();
+    /* 设置编辑栏大小 */
+    void setEditLine(int w, int h);
+
+    /* 设置QSS */
+    void setQSS();
+signals:
+    void signal_nowTime(const QTime& time);
+    void signal_formerTimer(const QTime& time);
+    void signal_close();
+
+protected:
+    bool eventFilter(QObject* obj, QEvent* e) override;
+    void moveEvent(QMoveEvent *event) override;
+
+
+private slots:
+    void onBtnTipClicked();
+    void onListItemClicked(QListWidgetItem* item);
+    void onDateTimeChanged(const QDateTime& dt);
+private:
+    void UpdateProperty(QObject* obj, const char* name, bool flag);
+    void UpdatePopupTime(const QDateTime& dt);
+    void ShowTimeArea(bool bShow);
+    void CreatePopupWidget();
+    /* 初始化函数 */
+    void Init();
+private:
+    const int TIME_AREA_WIDTH = 56;
+    const int TIME_AREA_HEIGHT = 32;
+    const int SHADOW_MARGIN = 9;    // 对应BlurRadius模糊半径16px
+
+    Ui::TimeWidget *ui;
+    QVector<TimePartWidget*> m_vecTimePart;
+    QVector<int> m_vecTimeSections;
+    bool m_bTimeFlag{false};                     // 时间更新标志
+    QScopedPointer<ShadowWidget> m_wdgTimeArea;  // 时间选择窗口
+    QWidget* m_pMainWindow;                      // 外层祖辈窗口,能容纳时间控件高度即可(默认父窗口)
+    ShowType m_type;                            /* 显示类型 */
+    int m_width = 0;                            /* TimeArea宽度 */
+
+};
+
+#endif // TIMEWIDGET_H

+ 81 - 0
SettingLibrary/common/SelectTime/timewidget.ui

@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>TimeWidget</class>
+ <widget class="QFrame" name="TimeWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>190</width>
+    <height>43</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true"/>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout_2">
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>8</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QLabel" name="lbl_tip">
+     <property name="styleSheet">
+      <string notr="true"/>
+     </property>
+     <property name="text">
+      <string>请选择</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDateTimeEdit" name="dateTimeEdit">
+     <property name="styleSheet">
+      <string notr="true"/>
+     </property>
+     <property name="buttonSymbols">
+      <enum>QAbstractSpinBox::NoButtons</enum>
+     </property>
+     <property name="displayFormat">
+      <string>hh:mm:ss</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QPushButton" name="btn_tip">
+     <property name="minimumSize">
+      <size>
+       <width>18</width>
+       <height>18</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>18</width>
+       <height>18</height>
+      </size>
+     </property>
+     <property name="styleSheet">
+      <string notr="true"/>
+     </property>
+     <property name="text">
+      <string/>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>