|
|
@@ -0,0 +1,435 @@
|
|
|
+#include "DialogBase.h"
|
|
|
+
|
|
|
+#include <QMouseEvent>
|
|
|
+#include <QVBoxLayout>
|
|
|
+#include <QLabel>
|
|
|
+#include <QPushButton>
|
|
|
+#include <QBoxLayout>
|
|
|
+#include <QStyle>
|
|
|
+#include <qsize.h>
|
|
|
+#include <QGuiApplication>
|
|
|
+#include <QScreen>
|
|
|
+
|
|
|
+
|
|
|
+#include "OneShadowEffect.h"
|
|
|
+
|
|
|
+
|
|
|
+DialogBase::DialogBase(QWidget *parent)
|
|
|
+ : QDialog(parent)
|
|
|
+{
|
|
|
+ m_logger = spdlog::get("ACASetting");
|
|
|
+ if(m_logger == nullptr)
|
|
|
+ {
|
|
|
+ fmt::print("DialogBase: 未发现ACASetting日志记录器,请检查日志记录器是否已初始化。\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ initUI();
|
|
|
+ initSettings();
|
|
|
+ /* 设置qss */
|
|
|
+ connect(&UIStyle, &UIStyleManager::signal_qssChanged, this, &DialogBase::do_setQSS);
|
|
|
+ /* 设置默认的UI */
|
|
|
+ setParentQSS();
|
|
|
+}
|
|
|
+
|
|
|
+DialogBase::DialogBase(bool isFullScreen, QWidget *parent)
|
|
|
+ : QDialog(parent), m_isFullScreen(isFullScreen)
|
|
|
+{
|
|
|
+ m_logger = spdlog::get("ACASetting");
|
|
|
+ if(m_logger == nullptr)
|
|
|
+ {
|
|
|
+ fmt::print("DialogBase: 未发现ACASetting日志记录器,请检查日志记录器是否已初始化。\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ initUI();
|
|
|
+ initSettings();
|
|
|
+ /* 设置qss */
|
|
|
+ connect(&UIStyle, &UIStyleManager::signal_qssChanged, this, &DialogBase::do_setQSS);
|
|
|
+ /* 设置默认的UI */
|
|
|
+ setParentQSS();
|
|
|
+}
|
|
|
+
|
|
|
+DialogBase::~DialogBase()
|
|
|
+{
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/* 设置标题 */
|
|
|
+void DialogBase::setTitle(const QString &title, QSize size)
|
|
|
+{
|
|
|
+ m_labelTitle->setText(title);
|
|
|
+ m_labelTitle->setFixedSize(size);
|
|
|
+}
|
|
|
+
|
|
|
+/* 获取标题 */
|
|
|
+QString DialogBase::getTitle() const
|
|
|
+{
|
|
|
+ return m_labelTitle ? m_labelTitle->text() : QString();
|
|
|
+}
|
|
|
+
|
|
|
+/* 设置内容容器 */
|
|
|
+bool DialogBase::setContentWidget(QWidget *widget)
|
|
|
+{
|
|
|
+ if(widget == nullptr)
|
|
|
+ {
|
|
|
+ SPDLOG_LOGGER_ERROR(m_logger, "设置内容容器失败,widget为nullptr");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if(m_widgetContent == widget)
|
|
|
+ {
|
|
|
+ return true; // 如果已经是这个widget了,就不需要重新设置
|
|
|
+ }
|
|
|
+ if(m_widgetContent != nullptr)
|
|
|
+ {
|
|
|
+ m_layoutBackground->removeWidget(m_widgetContent);
|
|
|
+ delete m_widgetContent;
|
|
|
+ m_widgetContent = nullptr;
|
|
|
+ }
|
|
|
+ m_widgetContent = widget;
|
|
|
+ m_layoutBackground->insertWidget(1, m_widgetContent);
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+/* 设置低栏容器 */
|
|
|
+bool DialogBase::setBottomWidget(QWidget *widget)
|
|
|
+{
|
|
|
+ if(widget == nullptr)
|
|
|
+ {
|
|
|
+ SPDLOG_LOGGER_ERROR(m_logger, "设置底部容器失败,widget为nullptr");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if(m_widgetBottom != nullptr)
|
|
|
+ {
|
|
|
+ m_layoutBackground->removeWidget(m_widgetBottom);
|
|
|
+ delete m_widgetBottom;
|
|
|
+ m_widgetBottom = nullptr;
|
|
|
+ }
|
|
|
+ m_widgetBottom = widget;
|
|
|
+ m_layoutBackground->insertWidget(2, m_widgetBottom);
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+/* 移除底栏 */
|
|
|
+bool DialogBase::removeBottomWidget()
|
|
|
+{
|
|
|
+ if(m_widgetBottom == nullptr)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ m_layoutBackground->removeWidget(m_widgetBottom);
|
|
|
+ delete m_widgetBottom;
|
|
|
+ m_widgetBottom = nullptr;
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+/* 点击确定按钮之前执行的操作 */
|
|
|
+bool DialogBase::isOKClicked()
|
|
|
+{
|
|
|
+ /* 默认返回true,子类可以重载这个函数来实现自定义的逻辑 */
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+/* 点击关闭按钮之后执行的操作 */
|
|
|
+bool DialogBase::isCloseClicked()
|
|
|
+{
|
|
|
+ /* 默认什么都不做,子类可以重载这个函数来实现自定义的逻辑 */
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+/* 设置一个控件报警,边框显示红色
|
|
|
+ * 注意:这个功能需要在qss里设置属性[Warn=true],并实现相应的报警样式 */
|
|
|
+void DialogBase::setWarn(QWidget* widget, bool isWarn)
|
|
|
+{
|
|
|
+ if(widget == nullptr)
|
|
|
+ {
|
|
|
+ SPDLOG_LOGGER_ERROR(m_logger, "设置控件报警失败,widget为nullptr");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ widget->setProperty("Warn", isWarn);
|
|
|
+ widget->style()->unpolish(widget);
|
|
|
+ widget->style()->polish(widget);
|
|
|
+ widget->update();
|
|
|
+}
|
|
|
+
|
|
|
+/* 初始化UI */
|
|
|
+void DialogBase::initUI()
|
|
|
+{
|
|
|
+ /*--------------------- 设置对话框的属性 -----------------------*/
|
|
|
+ this->setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
|
|
|
+ this->setAttribute(Qt::WA_TranslucentBackground, true);
|
|
|
+ // this->setObjectName("DialogBase");
|
|
|
+
|
|
|
+
|
|
|
+ /*--------------------- 初始化背景容器 -----------------------*/
|
|
|
+ /* 如果需要背后接近透明的全屏遮罩,就设置为true,在this和m_widgetBackground之间添加
|
|
|
+ * 一层接近透明的遮罩 */
|
|
|
+ if(m_isFullScreen)
|
|
|
+ {
|
|
|
+ auto screenRect = QGuiApplication::screenAt(QCursor::pos())->geometry();
|
|
|
+ this->resize(screenRect.width(), screenRect.height());
|
|
|
+ /* 创建最外层的透明背景 */
|
|
|
+ m_widgetTransparent = new QWidget(this);
|
|
|
+ m_widgetTransparent->setObjectName("widget_transparent");
|
|
|
+ m_widgetTransparent->setStyleSheet(R"(
|
|
|
+ QWidget#widget_transparent {background: rgba(0, 0, 0, 0.01)};
|
|
|
+ )");
|
|
|
+
|
|
|
+ m_widgetTransparent->resize(screenRect.width(), screenRect.height());
|
|
|
+ m_widgetTransparent->move(0, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 创建真正的容器 */
|
|
|
+ m_widgetBackground = new QWidget(this);
|
|
|
+ m_widgetBackground->setObjectName("widget_content__");
|
|
|
+ // m_widgetBackground->resize(400, 300);
|
|
|
+ /* 判断m_widgetBackground是哪一层 */
|
|
|
+ if(m_isFullScreen)
|
|
|
+ {
|
|
|
+ m_widgetBackground->setParent(m_widgetTransparent);
|
|
|
+ /* 设置设置区域居中显示 */
|
|
|
+ m_widgetBackground->move(m_widgetTransparent->width() / 2 - m_widgetBackground->width() / 2,
|
|
|
+ m_widgetTransparent->height() / 2 - m_widgetBackground->height() / 2);
|
|
|
+ }else {
|
|
|
+ QVBoxLayout* layout = new QVBoxLayout(this);
|
|
|
+ /* 设置边距,就是阴影的宽度 */
|
|
|
+ layout->setContentsMargins(20, 20, 20, 20);
|
|
|
+ layout->setSpacing(0);
|
|
|
+ this->setLayout(layout);
|
|
|
+ layout->addWidget(m_widgetBackground);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 创建背景容器内部的布局 */
|
|
|
+ m_layoutBackground = new QVBoxLayout(m_widgetBackground);
|
|
|
+ m_layoutBackground->setContentsMargins(0, 0, 0, 0);
|
|
|
+ m_layoutBackground->setSpacing(0);
|
|
|
+ m_widgetBackground->setLayout(m_layoutBackground);
|
|
|
+
|
|
|
+ /*--------------------- 初始顶栏 -----------------------*/
|
|
|
+ /* 初始化顶部标题栏,高度56,下面分割线高度1 */
|
|
|
+ m_widgetTop = new QWidget(this);
|
|
|
+ m_widgetTop->setObjectName("widget_top");
|
|
|
+ m_widgetTop->setFixedHeight(56);
|
|
|
+ m_layoutBackground->addWidget(m_widgetTop);
|
|
|
+ QHBoxLayout* topHBoxLayout = new QHBoxLayout(m_widgetTop);
|
|
|
+ m_widgetTop->setLayout(topHBoxLayout);
|
|
|
+
|
|
|
+ /* 初始化标题栏 */
|
|
|
+ m_labelTitle = new QLabel(m_widgetTop);
|
|
|
+ m_labelTitle->setObjectName("label_title");
|
|
|
+ m_labelTitle->setText("Dialog Title");
|
|
|
+ m_labelTitle->setFixedSize(120, 18);
|
|
|
+ m_labelTitle->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
|
|
+ /* 初始化关闭按钮 */
|
|
|
+ m_pBtn_Close = new QPushButton(m_widgetTop);
|
|
|
+ m_pBtn_Close->setObjectName("pBtn_Close");
|
|
|
+ m_pBtn_Close->resize(32, 32);
|
|
|
+ /* 安装事件过滤器,主要是处理鼠标悬停事件 */
|
|
|
+ m_pBtn_Close->installEventFilter(this);
|
|
|
+ /* 重新布局顶栏 */
|
|
|
+ layoutTop();
|
|
|
+
|
|
|
+ /*--------------------- 初始化内容栏 -----------------------*/
|
|
|
+ // m_widgetContent = new QWidget(this);
|
|
|
+ // m_widgetContent->resize(400, 300);
|
|
|
+ // m_layoutBackground->addWidget(m_widgetContent);
|
|
|
+
|
|
|
+ /*--------------------- 初始底栏 -----------------------*/
|
|
|
+ m_widgetBottom = new QWidget(this);
|
|
|
+ m_widgetBottom->setObjectName("widget_bottom");
|
|
|
+ m_widgetBottom->setFixedHeight(88);
|
|
|
+ m_layoutBackground->addWidget(m_widgetBottom);
|
|
|
+ QHBoxLayout* bottomHBoxLayout = new QHBoxLayout(m_widgetBottom);
|
|
|
+ m_widgetBottom->setLayout(bottomHBoxLayout);
|
|
|
+ /* 初始化取消按钮 */
|
|
|
+ m_pBtn_Cancel = new QPushButton(m_widgetBottom);
|
|
|
+ m_pBtn_Cancel->setObjectName("pBtn_Cancel");
|
|
|
+ m_pBtn_Cancel->setText("取消");
|
|
|
+ m_pBtn_Cancel->setFixedSize(60, 32);
|
|
|
+ bottomHBoxLayout->addWidget(m_pBtn_Cancel, 0, Qt::AlignRight | Qt::AlignVCenter);
|
|
|
+ /* 初始化确认按钮 */
|
|
|
+ m_pBtn_OK = new QPushButton(m_widgetBottom);
|
|
|
+ m_pBtn_OK->setObjectName("pBtn_OK");
|
|
|
+ m_pBtn_OK->setText("确定");
|
|
|
+ m_pBtn_OK->setFixedSize(60, 32);
|
|
|
+ bottomHBoxLayout->addWidget(m_pBtn_OK, 0, Qt::AlignRight | Qt::AlignVCenter);
|
|
|
+ /* 添加一个底部横向弹簧 */
|
|
|
+ bottomHBoxLayout->insertStretch(0, 1);
|
|
|
+ /* 设置底部按钮的间距 */
|
|
|
+ bottomHBoxLayout->setContentsMargins(32, 24, 32, 32);
|
|
|
+ bottomHBoxLayout->setSpacing(16);
|
|
|
+
|
|
|
+ /*--------------------- 创建阴影 -----------------------*/
|
|
|
+ auto pShadow = new OneShadowEffect(this);
|
|
|
+ m_widgetBackground->setGraphicsEffect(pShadow);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/* 初始化其他设置 */
|
|
|
+void DialogBase::initSettings()
|
|
|
+{
|
|
|
+ /* 初始化变量 */
|
|
|
+ m_lastPos = QPoint(0, 0);
|
|
|
+ /* 连接信号和槽 */
|
|
|
+ connect(m_pBtn_Close, &QPushButton::clicked, this, &DialogBase::do_pBtn_Close_Clicked);
|
|
|
+ connect(m_pBtn_OK, &QPushButton::clicked, this, &DialogBase::do_pBtn_OK_Clicked);
|
|
|
+ connect(m_pBtn_Cancel, &QPushButton::clicked, this, &DialogBase::do_pBtnCancel_clicked);
|
|
|
+
|
|
|
+ /* 设置样式表 */
|
|
|
+ setParentQSS();
|
|
|
+}
|
|
|
+
|
|
|
+/* 加载QSS */
|
|
|
+void DialogBase::setParentQSS()
|
|
|
+{
|
|
|
+ /* 获取样式表路径 */
|
|
|
+ QString qssPath = UIStyle.getQSSPath() + "/dialogbase.qss";
|
|
|
+ QFile file(qssPath);
|
|
|
+ if(file.open(QFile::ReadOnly))
|
|
|
+ {
|
|
|
+ QString qss = file.readAll();
|
|
|
+ file.close();
|
|
|
+ m_widgetBackground->setStyleSheet(qss);
|
|
|
+ } else
|
|
|
+ {
|
|
|
+ SPDLOG_LOGGER_ERROR(m_logger, "打开QSS文件失败: {}", qssPath.toStdString());
|
|
|
+ SPDLOG_LOGGER_ERROR(m_logger, "错误信息: {}", file.errorString().toStdString());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 设置top栏的位置布局,标题和关闭按钮的高度起始位置不一样,不方便使用布局,所有手动修改坐标
|
|
|
+ * 标题位置32,18,高度18
|
|
|
+ * 关闭按钮右对齐16,y12,大小32x32 */
|
|
|
+void DialogBase::layoutTop()
|
|
|
+{
|
|
|
+ m_labelTitle->move(32, 18);
|
|
|
+ int x = m_widgetTop->width() - m_pBtn_Close->width() - 16;
|
|
|
+ m_pBtn_Close->move(x, 12);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/* 关闭按钮点击事件 */
|
|
|
+void DialogBase::do_pBtn_Close_Clicked()
|
|
|
+{
|
|
|
+ if(!isCloseClicked())
|
|
|
+ {
|
|
|
+ /* 如果子类没有重载这个函数,默认返回true */
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this->close();
|
|
|
+}
|
|
|
+
|
|
|
+/* 确认按钮点击事件 */
|
|
|
+void DialogBase::do_pBtn_OK_Clicked()
|
|
|
+{
|
|
|
+ if(!isOKClicked())
|
|
|
+ {
|
|
|
+ /* 如果子类没有重载这个函数,默认返回true */
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ m_isOK = true;
|
|
|
+ this->accept();
|
|
|
+}
|
|
|
+
|
|
|
+/* 设置QSS */
|
|
|
+void DialogBase::do_setQSS(EUIStyle style)
|
|
|
+{
|
|
|
+ setParentQSS();
|
|
|
+}
|
|
|
+
|
|
|
+/* 重写鼠标按下事件 */
|
|
|
+void DialogBase::mousePressEvent(QMouseEvent *event)
|
|
|
+{
|
|
|
+ m_lastPos = event->globalPos();
|
|
|
+ event->accept();
|
|
|
+}
|
|
|
+
|
|
|
+/* 重写鼠标移动事件 */
|
|
|
+void DialogBase::mouseMoveEvent(QMouseEvent *event)
|
|
|
+{
|
|
|
+ auto point = m_widgetTop->mapToGlobal(QPoint(0, 0));
|
|
|
+ QRect rect(point, m_widgetTop->size());
|
|
|
+
|
|
|
+ if(!rect.contains(m_lastPos))
|
|
|
+ {
|
|
|
+ event->accept();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ int dx = event->globalX() - m_lastPos.x();
|
|
|
+ int dy = event->globalY() - m_lastPos.y();
|
|
|
+ if(m_isFullScreen)
|
|
|
+ {
|
|
|
+ m_widgetBackground->move(m_widgetBackground->x() + dx, m_widgetBackground->y() + dy);
|
|
|
+ }else {
|
|
|
+ move(x() + dx, y() + dy);
|
|
|
+ }
|
|
|
+
|
|
|
+ m_lastPos = event->globalPos();
|
|
|
+ event->accept();
|
|
|
+}
|
|
|
+
|
|
|
+/* 重写鼠标释放事件 */
|
|
|
+void DialogBase::mouseReleaseEvent(QMouseEvent *event)
|
|
|
+{
|
|
|
+ event->accept();
|
|
|
+}
|
|
|
+
|
|
|
+/* 显示事件 */
|
|
|
+void DialogBase::showEvent(QShowEvent *event)
|
|
|
+{
|
|
|
+ QDialog::showEvent(event);
|
|
|
+
|
|
|
+ if(m_isFullScreen)
|
|
|
+ {
|
|
|
+ /* 设置设置区域居中显示 */
|
|
|
+ m_widgetBackground->move(m_widgetTransparent->width() / 2 - m_widgetBackground->width() / 2,
|
|
|
+ m_widgetTransparent->height() / 2 - m_widgetBackground->height() / 2);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 重新布局顶栏 */
|
|
|
+ layoutTop();
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/* 重新设置大小 */
|
|
|
+void DialogBase::resizeEvent(QResizeEvent *event)
|
|
|
+{
|
|
|
+ QDialog::resizeEvent(event);
|
|
|
+
|
|
|
+ if(m_isFullScreen)
|
|
|
+ {
|
|
|
+ /* 设置设置区域居中显示 */
|
|
|
+ m_widgetBackground->move(m_widgetTransparent->width() / 2 - m_widgetBackground->width() / 2,
|
|
|
+ m_widgetTransparent->height() / 2 - m_widgetBackground->height() / 2);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 重新布局顶栏 */
|
|
|
+ layoutTop();
|
|
|
+}
|
|
|
+
|
|
|
+/* 事件过滤器 */
|
|
|
+bool DialogBase::eventFilter(QObject *watched, QEvent *event)
|
|
|
+{
|
|
|
+ if(watched == m_pBtn_Close && event->type() == QEvent::HoverEnter)
|
|
|
+ {
|
|
|
+ m_pBtn_Close->setProperty("Hover", true);
|
|
|
+ m_pBtn_Close->style()->unpolish(m_pBtn_Close);
|
|
|
+ m_pBtn_Close->style()->polish(m_pBtn_Close);
|
|
|
+ m_pBtn_Close->update();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else if(watched == m_pBtn_Close && event->type() == QEvent::HoverLeave)
|
|
|
+ {
|
|
|
+ m_pBtn_Close->setProperty("Hover", false);
|
|
|
+ m_pBtn_Close->style()->unpolish(m_pBtn_Close);
|
|
|
+ m_pBtn_Close->style()->polish(m_pBtn_Close);
|
|
|
+ m_pBtn_Close->update();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return QDialog::eventFilter(watched, event);
|
|
|
+}
|
|
|
+
|