#include "timewidget.h" #include "ui_timewidget.h" #include #include #include #include #include #include "timepartwidget.h" #include "shadowwidget.h" #include "UIStyleManager.h" #include "spdlog/spdlog.h" #include "timepopupwidget.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::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(); } void TimeWidget::setTime(const QTime& t) { ui->dateTimeEdit->setTime(t); ui->lbl_tip->hide(); ui->dateTimeEdit->show(); UpdatePopupTime(ui->dateTimeEdit->dateTime()); m_formerDateTime.setTime(t); } 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(); ShowPopupArea(true); } /* 以弹窗的模式模态显示 */ void TimeWidget::execShow() { QEventLoop loop; connect (this, &TimeWidget::signal_close, &loop, &QEventLoop::quit); this->show(); ShowPopupArea(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::setEditLine(int w, int h) { this->resize(w, h); } /* 设置禁止使用滚轮修改时间 */ void TimeWidget::setWheelDisabled(bool disabled) { m_isDisableWheel = disabled; } /* 设置启用与否*/ void TimeWidget::setEditLineEnable(bool enable) { this->setEnabled(enable); if(!enable) { if(m_pTimePopupWidget != nullptr && m_pTimePopupWidget->isVisible()) { m_isBanPopupShow = true; ShowPopupArea(false); UpdateProperty(this, "hover", false); } ui->btn_tip->hide(); }else { ui->btn_tip->show(); } } /* 设置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()); } } /* 点击了时间图标 */ void TimeWidget::do_pBtn_tip_Clicked() { if(m_pTimePopupWidget == nullptr) { return; } if(m_pTimePopupWidget->isVisible()) { return; } /* 展示弹窗 */ showTimeEditArea(); } /** * @brief 这里添加了两个信号,一个是修改过的新时间,一个是旧时间 * @param obj * @param e * @return */ bool TimeWidget::eventFilter(QObject* obj, QEvent* e) { if (obj == ui->dateTimeEdit) { if(e->type() == QEvent::Wheel && m_isDisableWheel) { // 禁止滚轮修改时间 return true; } if (e->type() == QEvent::FocusIn && m_type == EditLine) { /* 如果Popup正在关闭 */ if(m_isBanPopupShow == true) { m_isBanPopupShow = false; /* 这里需要再次失去焦点,否则下次点击编辑栏无法弹出Popup */ ui->dateTimeEdit->clearFocus(); return QWidget::eventFilter(obj, e); } //qInfo() << "dateTimeEdit focusIn"; ShowPopupArea(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(); ShowPopupArea(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(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())) { if(m_wdgTimeArea == nullptr) { return QWidget::eventFilter(obj, e); } /* Pupop不可见,直接返回 */ if(!m_wdgTimeArea->isVisible()) { return QWidget::eventFilter(obj, e); } /* 如果焦点不在编辑栏,Popup窗口隐藏后,编辑栏会重新获取焦点,将会再次跳出Popup窗口 因此在其没有焦点的时候设置 m_isBanPopupShow ,防止Popup隐藏后编辑栏再次获取焦点再次弹出Popup */ if(!ui->dateTimeEdit->hasFocus()) { m_isBanPopupShow = true; } ShowPopupArea(false); UpdateProperty(this, "hover", false); 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(); } } /* 这个用来实时修改编辑栏的时间 */ void TimeWidget::do_dateTimeChanged(const QTime& dt) { ui->dateTimeEdit->setTime(dt); } /** * @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; } /* 关闭Popup弹窗 */ void TimeWidget::do_closePopup(bool isOk) { if(isOk == false) { ui->dateTimeEdit->setTime(m_formerDateTime.time()); } m_isBanPopupShow = true; ShowPopupArea(false); UpdateProperty(this, "hover", false); if(m_type == Dialog) { this->close(); } } void TimeWidget::UpdateProperty(QObject* obj, const char *name, bool flag) { if (nullptr == obj || nullptr == name) { return; } obj->setProperty(name, flag); QWidget* pWdg = qobject_cast(obj); if (nullptr != pWdg) { this->style()->unpolish(pWdg); this->style()->polish(pWdg); } } /** * @brief 更新popup列表选中时间 * @param dt */ void TimeWidget::UpdatePopupTime(const QDateTime& dt) { // 如果时间列表还没初始化就不会设置时间了 if(m_pTimePopupWidget == nullptr) { return; } m_pTimePopupWidget->setTime(dt); // for (int i = 0; i < m_vecTimeSections.size(); ++i) // { // auto type = m_vecTimeSections.at(i); // TimePartWidget::emSection emType = static_cast(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::ShowPopupArea(bool bShow) { if (m_wdgTimeArea.isNull()) { CreatePopupWidget(); } if (!m_wdgTimeArea.isNull()) { if (bShow) { // 重新定位再显示 QPoint pt = this->mapTo(m_pMainWindow, QPoint(0, 0)); m_wdgTimeArea->move(QPoint(pt.x() - SHADOW_MARGIN, pt.y() + this->height())); /* 设置弹窗Popup的大小,使用默认的固定大小,不允许改变 关于高度:确定取消按钮所占的高度是固定的32,和一节大小一样,所以这里 */ int width = 2 * SHADOW_MARGIN + TIME_AREA_WIDTH * m_vecTimeSections.size(); int height = TIME_AREA_HEIGHT * 7 + 2 * SHADOW_MARGIN + 8; m_wdgTimeArea->resize(QSize(width, height)); UpdatePopupTime(ui->dateTimeEdit->dateTime()); /* 保存现在的时间 */ m_formerDateTime = ui->dateTimeEdit->dateTime(); m_wdgTimeArea->show(); } else { m_wdgTimeArea->hide(); emit signal_close(); /* 关闭显示,发送携带时间的信号,判断一下时间是否改变,不改变不发信号 */ if(m_formerDateTime.time() != ui->dateTimeEdit->time()) { emit signal_timeChanged(m_formerDateTime.time(), ui->dateTimeEdit->time()); } /* 让编辑栏失去焦点 */ ui->dateTimeEdit->clearFocus(); } } } void TimeWidget::CreatePopupWidget() { // CreateTimeArea m_vecTimeSections = {TimePartWidget::HOUR, TimePartWidget::MINUTE, TimePartWidget::SECOND}; // CreateTimeVector(m_vecTimeSections); if(m_pTimePopupWidget == nullptr) { m_pTimePopupWidget = new TimePopupWidget(); m_pTimePopupWidget->Init(m_vecTimeSections); connect(m_pTimePopupWidget, &TimePopupWidget::signal_timeChanged, this, &TimeWidget::do_dateTimeChanged); connect(m_pTimePopupWidget, &TimePopupWidget::signal_closePopup, this, &TimeWidget::do_closePopup); } 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; }"); } /* 创建显示时间条的HBox */ 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()) { m_wdgTimeArea->getLayout()->addWidget(m_pTimePopupWidget); // 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); /* 设置时间图标大小 */ ui->btn_tip->setFixedSize(16, 16); /* 设置初始值 */ QTime t(0, 0, 0); ui->dateTimeEdit->setTime(t); ui->lbl_tip->hide(); /* 使用这个阻止show的时候获取焦点自动弹出Popup */ m_isBanPopupShow = true; ui->dateTimeEdit->show(); m_formerDateTime.setTime(t); connect(ui->btn_tip, &QPushButton::clicked, this, &TimeWidget::do_pBtn_tip_Clicked); connect(ui->dateTimeEdit, &QDateTimeEdit::dateTimeChanged, this, &TimeWidget::onDateTimeChanged); // setDefaultStyle(); }