|
|
@@ -0,0 +1,540 @@
|
|
|
+#include "functionbutton.h"
|
|
|
+#include <QAbstractAnimation>
|
|
|
+#include <QApplication>
|
|
|
+#include <QGuiApplication>
|
|
|
+#include <QPropertyAnimation>
|
|
|
+#include <QScreen>
|
|
|
+#include <QDebug>
|
|
|
+#include <QResizeEvent>
|
|
|
+
|
|
|
+namespace Colors {
|
|
|
+// Element Plus 主题色
|
|
|
+const QColor Primary = QColor(64, 158, 255); // #409EFF
|
|
|
+const QColor PrimaryLight = QColor(144, 202, 249); // #90CAF9
|
|
|
+const QColor PrimaryDark = QColor(25, 118, 210); // #1976D2
|
|
|
+
|
|
|
+// 功能色
|
|
|
+const QColor Success = QColor(103, 194, 58); // #67C23A
|
|
|
+const QColor Warning = QColor(230, 162, 60); // #E6A23C
|
|
|
+const QColor Danger = QColor(245, 108, 108); // #F56C6C
|
|
|
+const QColor Info = QColor(144, 147, 153); // #909399
|
|
|
+
|
|
|
+// 中性色
|
|
|
+const QColor TextPrimary = QColor(48, 49, 51); // #303133
|
|
|
+const QColor TextRegular = QColor(96, 98, 102); // #606266
|
|
|
+const QColor TextSecondary = QColor(144, 147, 153); // #909399
|
|
|
+const QColor TextPlaceholder = QColor(192, 196, 204); // #C0C4CC
|
|
|
+
|
|
|
+// 边框色
|
|
|
+const QColor BorderBase = QColor(220, 223, 230); // #DCDFE6
|
|
|
+const QColor BorderLight = QColor(228, 231, 237); // #E4E7ED
|
|
|
+const QColor BorderLighter = QColor(235, 238, 245); // #EBEEF5
|
|
|
+const QColor BorderExtraLight = QColor(244, 245, 247); // #F4F5F7
|
|
|
+
|
|
|
+// 背景色
|
|
|
+const QColor Background = Qt::white; // #FFFFFF
|
|
|
+const QColor BackgroundPage = QColor(245, 245, 245); // #F5F5F5
|
|
|
+const QColor BackgroundBase = QColor(248, 249, 250); // #F8F9FA
|
|
|
+
|
|
|
+// 兼容旧版本
|
|
|
+const QColor PrimaryHover = PrimaryLight;
|
|
|
+const QColor PrimaryPressed = PrimaryDark;
|
|
|
+const QColor Border = BorderBase;
|
|
|
+const QColor Text = TextPrimary;
|
|
|
+const QColor SecondaryText = TextSecondary;
|
|
|
+const QColor Shadow = QColor(0, 0, 0, 60);
|
|
|
+const QColor Indicator = Info;
|
|
|
+} // namespace Colors
|
|
|
+namespace Fonts {
|
|
|
+static QFont buttonFont()
|
|
|
+{
|
|
|
+ QFont font;
|
|
|
+ font.setPointSize(10);
|
|
|
+ font.setWeight(QFont::Medium);
|
|
|
+ return font;
|
|
|
+}
|
|
|
+} // namespace Fonts
|
|
|
+
|
|
|
+// PopoverTriggerButton 实现
|
|
|
+PopoverTriggerButton::PopoverTriggerButton(QWidget* parent)
|
|
|
+ : QPushButton(parent)
|
|
|
+{
|
|
|
+ setCursor(Qt::PointingHandCursor);
|
|
|
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
|
+ setFixedSize(20, 70);
|
|
|
+ setMinimumSize(20, 70);
|
|
|
+ setMaximumSize(20, 70);
|
|
|
+}
|
|
|
+
|
|
|
+QSize PopoverTriggerButton::sizeHint() const
|
|
|
+{
|
|
|
+ return QSize(20, 70); // 强制返回固定大小
|
|
|
+}
|
|
|
+
|
|
|
+QSize PopoverTriggerButton::minimumSizeHint() const
|
|
|
+{
|
|
|
+ return QSize(20, 70); // 强制返回固定最小大小
|
|
|
+}
|
|
|
+
|
|
|
+void PopoverTriggerButton::resizeEvent(QResizeEvent* event)
|
|
|
+{
|
|
|
+ // 强制保持固定大小,忽略任何外部尺寸变化
|
|
|
+ if (size() != QSize(20, 70)) {
|
|
|
+ setFixedSize(20, 70);
|
|
|
+ }
|
|
|
+ QPushButton::resizeEvent(event);
|
|
|
+}
|
|
|
+
|
|
|
+Popover::Popover(QWidget* parent)
|
|
|
+ : QWidget(parent)
|
|
|
+{
|
|
|
+ // 使用更安全的窗口标志组合,避免分层窗口问题
|
|
|
+ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
|
|
|
+
|
|
|
+ // 移除透明背景属性,避免UpdateLayeredWindowIndirect错误
|
|
|
+ // setAttribute(Qt::WA_TranslucentBackground);
|
|
|
+
|
|
|
+ // 设置窗口属性
|
|
|
+ setAttribute(Qt::WA_DeleteOnClose, false);
|
|
|
+ setAttribute(Qt::WA_ShowWithoutActivating, true);
|
|
|
+ setAttribute(Qt::WA_X11NetWmWindowTypePopupMenu, true);
|
|
|
+
|
|
|
+ // 暂时移除阴影效果,避免分层窗口问题
|
|
|
+ // 我们将在paintEvent中手动绘制阴影
|
|
|
+ /*
|
|
|
+ auto shadow = new QGraphicsDropShadowEffect(this);
|
|
|
+ shadow->setBlurRadius(qMax(0.0, 20.0));
|
|
|
+ shadow->setColor(Colors::Shadow);
|
|
|
+ shadow->setXOffset(0);
|
|
|
+ shadow->setYOffset(qMax(0.0, 5.0));
|
|
|
+ setGraphicsEffect(shadow);
|
|
|
+ */
|
|
|
+
|
|
|
+ mainLayout = new QVBoxLayout(this);
|
|
|
+ mainLayout->setContentsMargins(25, 25, 25, 25);
|
|
|
+ mainLayout->setSpacing(10);
|
|
|
+
|
|
|
+ // 移除样式表,使用paintEvent手动绘制背景
|
|
|
+ // setStyleSheet("QWidget { background-color: white; border: 1px solid #e0e0e0; border-radius: 8px; }");
|
|
|
+
|
|
|
+ // 连接应用程序状态变化信号
|
|
|
+ connect(qApp, &QApplication::applicationStateChanged, this, [this](Qt::ApplicationState state) {
|
|
|
+ if (state != Qt::ApplicationActive && isVisible()) {
|
|
|
+ hideAnimated();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 安装事件过滤器以检测点击外部区域
|
|
|
+ qApp->installEventFilter(this);
|
|
|
+}
|
|
|
+
|
|
|
+Popover::~Popover()
|
|
|
+{
|
|
|
+ // 移除事件过滤器
|
|
|
+ qApp->removeEventFilter(this);
|
|
|
+}
|
|
|
+
|
|
|
+void Popover::setContentWidget(QWidget* widget)
|
|
|
+{
|
|
|
+ // 清除现有内容
|
|
|
+ QLayoutItem* child;
|
|
|
+ while ((child = mainLayout->takeAt(0)) != nullptr) {
|
|
|
+ delete child->widget();
|
|
|
+ delete child;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加新内容
|
|
|
+ mainLayout->addWidget(widget);
|
|
|
+
|
|
|
+ // 动态计算最小尺寸,考虑阴影边距
|
|
|
+ if (widget->minimumSize().isValid()) {
|
|
|
+ QMargins margins = mainLayout->contentsMargins();
|
|
|
+ int extraWidth = margins.left() + margins.right();
|
|
|
+ int extraHeight = margins.top() + margins.bottom();
|
|
|
+ setMinimumSize(widget->minimumSize() + QSize(extraWidth, extraHeight));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Popover::showAnimated(const QPoint& position)
|
|
|
+{
|
|
|
+ setOpacity(0.0);
|
|
|
+
|
|
|
+ // 确保窗口尺寸有效
|
|
|
+ if (width() <= 0 || height() <= 0) {
|
|
|
+ adjustSize();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 确保位置在屏幕范围内
|
|
|
+ QScreen* screen = QGuiApplication::screenAt(position);
|
|
|
+ if (!screen) {
|
|
|
+ screen = QGuiApplication::primaryScreen();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (screen) {
|
|
|
+ QRect screenGeometry = screen->availableGeometry();
|
|
|
+ QPoint adjustedPos = position;
|
|
|
+
|
|
|
+ // 计算阴影边距,确保为正值
|
|
|
+ QMargins shadowMargins = this->shadowMargins();
|
|
|
+ int leftMargin = qMax(0, shadowMargins.left());
|
|
|
+ int topMargin = qMax(0, shadowMargins.top());
|
|
|
+ int rightMargin = qMax(0, shadowMargins.right());
|
|
|
+ int bottomMargin = qMax(0, shadowMargins.bottom());
|
|
|
+
|
|
|
+ // 确保窗口完全在屏幕内
|
|
|
+ int minX = screenGeometry.left() + leftMargin;
|
|
|
+ int minY = screenGeometry.top() + topMargin;
|
|
|
+ int maxX = screenGeometry.right() - width() - rightMargin;
|
|
|
+ int maxY = screenGeometry.bottom() - height() - bottomMargin;
|
|
|
+
|
|
|
+ // 调整X坐标
|
|
|
+ adjustedPos.setX(qBound(minX, adjustedPos.x(), maxX));
|
|
|
+
|
|
|
+ // 调整Y坐标
|
|
|
+ adjustedPos.setY(qBound(minY, adjustedPos.y(), maxY));
|
|
|
+
|
|
|
+ // 最终验证位置的有效性
|
|
|
+ if (adjustedPos.x() >= 0 && adjustedPos.y() >= 0) {
|
|
|
+ move(adjustedPos);
|
|
|
+ } else {
|
|
|
+ // 如果计算出的位置仍然无效,使用屏幕中心
|
|
|
+ QPoint centerPos = screenGeometry.center() - QPoint(width() / 2, height() / 2);
|
|
|
+ move(centerPos);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 如果无法获取屏幕信息,确保位置为正值
|
|
|
+ QPoint safePos = QPoint(qMax(0, position.x()), qMax(0, position.y()));
|
|
|
+ move(safePos);
|
|
|
+ }
|
|
|
+
|
|
|
+ show();
|
|
|
+
|
|
|
+ QPropertyAnimation* animation = new QPropertyAnimation(this, "opacity");
|
|
|
+ animation->setDuration(200);
|
|
|
+ animation->setStartValue(0.0);
|
|
|
+ animation->setEndValue(1.0);
|
|
|
+ animation->setEasingCurve(QEasingCurve::OutCubic);
|
|
|
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
|
|
|
+}
|
|
|
+
|
|
|
+void Popover::hideAnimated()
|
|
|
+{
|
|
|
+ QPropertyAnimation* animation = new QPropertyAnimation(this, "opacity");
|
|
|
+ animation->setDuration(150);
|
|
|
+ animation->setStartValue(1.0);
|
|
|
+ animation->setEndValue(0.0);
|
|
|
+ animation->setEasingCurve(QEasingCurve::InCubic);
|
|
|
+ connect(animation, &QPropertyAnimation::finished, this, &Popover::hide);
|
|
|
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
|
|
|
+}
|
|
|
+
|
|
|
+void Popover::setOpacity(qreal opacity)
|
|
|
+{
|
|
|
+ m_opacity = opacity;
|
|
|
+ setWindowOpacity(opacity);
|
|
|
+}
|
|
|
+
|
|
|
+QMargins Popover::shadowMargins() const
|
|
|
+{
|
|
|
+ // 返回固定的小边距,用于手动绘制的阴影
|
|
|
+ return QMargins(5, 5, 5, 5);
|
|
|
+}
|
|
|
+
|
|
|
+void Popover::closeEvent(QCloseEvent* event)
|
|
|
+{
|
|
|
+ emit popoverClosed();
|
|
|
+ QWidget::closeEvent(event);
|
|
|
+}
|
|
|
+
|
|
|
+void Popover::paintEvent(QPaintEvent* event)
|
|
|
+{
|
|
|
+ Q_UNUSED(event);
|
|
|
+
|
|
|
+ QPainter painter(this);
|
|
|
+ painter.setRenderHint(QPainter::Antialiasing);
|
|
|
+
|
|
|
+ QRect widgetRect = rect();
|
|
|
+
|
|
|
+ // 手动绘制简单的阴影效果
|
|
|
+ QMargins shadow = shadowMargins();
|
|
|
+
|
|
|
+ // 绘制阴影 - 简单的偏移矩形
|
|
|
+ QRect shadowRect = widgetRect.adjusted(shadow.left(), shadow.top(), 0, 0);
|
|
|
+ if (shadowRect.width() > 0 && shadowRect.height() > 0) {
|
|
|
+ painter.setPen(Qt::NoPen);
|
|
|
+ painter.setBrush(QColor(0, 0, 0, 30)); // 半透明黑色阴影
|
|
|
+ painter.drawRoundedRect(shadowRect, 8, 8);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 绘制主背景
|
|
|
+ QRect bgRect = widgetRect.adjusted(0, 0, -shadow.right(), -shadow.bottom());
|
|
|
+ if (bgRect.width() > 0 && bgRect.height() > 0) {
|
|
|
+ painter.setPen(Colors::Border);
|
|
|
+ painter.setBrush(Colors::Background);
|
|
|
+ painter.drawRoundedRect(bgRect, 8, 8);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+QSize Popover::sizeHint() const
|
|
|
+{
|
|
|
+ if (mainLayout->count() > 0) {
|
|
|
+ QWidget* content = mainLayout->itemAt(0)->widget();
|
|
|
+ if (content) {
|
|
|
+ QMargins margins = mainLayout->contentsMargins();
|
|
|
+ return content->sizeHint()
|
|
|
+ + QSize(margins.left() + margins.right(), margins.top() + margins.bottom());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return QWidget::sizeHint();
|
|
|
+}
|
|
|
+
|
|
|
+bool Popover::eventFilter(QObject* obj, QEvent* event)
|
|
|
+{
|
|
|
+ if (event->type() == QEvent::MouseButtonPress
|
|
|
+ || event->type() == QEvent::NonClientAreaMouseButtonPress) {
|
|
|
+ QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
|
|
|
+ // 检查点击是否在弹窗外部,如果是则关闭弹窗
|
|
|
+ if (isVisible() && !geometry().contains(mouseEvent->globalPos())) {
|
|
|
+ // 如果点击的是父窗口或其他任何地方,都关闭弹窗
|
|
|
+ hideAnimated();
|
|
|
+ return false; // 不阻止事件传播,让父窗口能正常处理点击
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 检测窗口激活状态变化
|
|
|
+ else if (event->type() == QEvent::WindowActivate) {
|
|
|
+ // 如果其他窗口被激活,关闭弹窗
|
|
|
+ if (isVisible() && obj != this) {
|
|
|
+ hideAnimated();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return QWidget::eventFilter(obj, event);
|
|
|
+}
|
|
|
+
|
|
|
+///////////////////
|
|
|
+
|
|
|
+// FunctionButton 实现
|
|
|
+FunctionButton::FunctionButton(const QIcon& icon, const QString& text, QWidget* parent)
|
|
|
+ : QPushButton(parent)
|
|
|
+ , m_icon(icon)
|
|
|
+ , m_text(text)
|
|
|
+{
|
|
|
+ setFixedSize(100, 70); // 固定大小
|
|
|
+ setCursor(Qt::PointingHandCursor);
|
|
|
+}
|
|
|
+
|
|
|
+void FunctionButton::paintEvent(QPaintEvent* event)
|
|
|
+{
|
|
|
+ Q_UNUSED(event);
|
|
|
+
|
|
|
+ QPainter painter(this);
|
|
|
+ painter.setRenderHint(QPainter::Antialiasing);
|
|
|
+
|
|
|
+ // 绘制按钮背景
|
|
|
+ QRect rect = this->rect();
|
|
|
+ QColor bgColor = Colors::Primary;
|
|
|
+
|
|
|
+ if (isDown()) {
|
|
|
+ bgColor = Colors::PrimaryPressed;
|
|
|
+ } else if (underMouse()) {
|
|
|
+ bgColor = Colors::PrimaryHover;
|
|
|
+ }
|
|
|
+
|
|
|
+ painter.setPen(Qt::NoPen);
|
|
|
+ painter.setBrush(bgColor);
|
|
|
+ painter.drawRoundedRect(rect, 5, 5);
|
|
|
+
|
|
|
+ // 绘制图标
|
|
|
+ if (!m_icon.isNull()) {
|
|
|
+ int iconSize = 24;
|
|
|
+ int iconLeft = (width() - iconSize) / 2;
|
|
|
+ int iconTop = 10;
|
|
|
+ QRect iconRect(iconLeft, iconTop, iconSize, iconSize);
|
|
|
+ m_icon.paint(&painter, iconRect);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 绘制文本
|
|
|
+ painter.setPen(Qt::white);
|
|
|
+ QFont font = Fonts::buttonFont();
|
|
|
+ painter.setFont(font);
|
|
|
+
|
|
|
+ QFontMetrics metrics(font);
|
|
|
+ int textWidth = metrics.horizontalAdvance(m_text);
|
|
|
+ int textLeft = (width() - textWidth) / 2;
|
|
|
+ int textTop = 45; // 文本在图标下方
|
|
|
+ painter.drawText(QRect(textLeft, textTop, textWidth, 20), Qt::AlignCenter, m_text);
|
|
|
+}
|
|
|
+
|
|
|
+void FunctionButton::enterEvent(QEvent* event)
|
|
|
+{
|
|
|
+ QPushButton::enterEvent(event);
|
|
|
+ update();
|
|
|
+}
|
|
|
+
|
|
|
+void FunctionButton::leaveEvent(QEvent* event)
|
|
|
+{
|
|
|
+ QPushButton::leaveEvent(event);
|
|
|
+ update();
|
|
|
+}
|
|
|
+
|
|
|
+// PopoverButtonGroup 实现
|
|
|
+PopoverButtonGroup::PopoverButtonGroup(Qt::Orientation orientation, QWidget* parent)
|
|
|
+ : QWidget(parent)
|
|
|
+{
|
|
|
+ if (orientation == Qt::Horizontal) {
|
|
|
+ QHBoxLayout* hLayout = new QHBoxLayout(this);
|
|
|
+ hLayout->setSpacing(15);
|
|
|
+ hLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
+ hLayout->setAlignment(Qt::AlignLeft); // 左对齐,避免拉伸
|
|
|
+ layout = hLayout;
|
|
|
+ } else {
|
|
|
+ QVBoxLayout* vLayout = new QVBoxLayout(this);
|
|
|
+ vLayout->setSpacing(15);
|
|
|
+ vLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
+ vLayout->setAlignment(Qt::AlignTop); // 顶部对齐,避免拉伸
|
|
|
+ layout = vLayout;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void PopoverButtonGroup::addButton(FunctionButton* button, Popover* popover)
|
|
|
+{
|
|
|
+ // 创建容器布局来组合功能按钮和Popover按钮
|
|
|
+ QWidget* container = new QWidget;
|
|
|
+ QHBoxLayout* containerLayout = new QHBoxLayout(container);
|
|
|
+ containerLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
+ containerLayout->setSpacing(0);
|
|
|
+
|
|
|
+ // 添加功能按钮
|
|
|
+ containerLayout->addWidget(button);
|
|
|
+ buttons.append(button);
|
|
|
+
|
|
|
+ if (popover) {
|
|
|
+ // 创建Popover触发按钮
|
|
|
+ QPushButton* popoverBtn = createPopoverTriggerButton();
|
|
|
+ containerLayout->addWidget(popoverBtn);
|
|
|
+
|
|
|
+ // 存储关联关系
|
|
|
+ popoverMap[popoverBtn] = popover;
|
|
|
+ buttonPopoverMap[button] = popoverBtn;
|
|
|
+
|
|
|
+ // 连接Popover按钮点击事件
|
|
|
+ connect(popoverBtn, &QPushButton::clicked, this, [this, popoverBtn]() {
|
|
|
+ togglePopover(popoverBtn);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加容器到主布局
|
|
|
+ layout->addWidget(container);
|
|
|
+}
|
|
|
+
|
|
|
+void PopoverButtonGroup::addPopoverToButton(FunctionButton* button, Popover* popover)
|
|
|
+{
|
|
|
+ if (buttons.contains(button) && !buttonPopoverMap.contains(button)) {
|
|
|
+ // 找到按钮所在的容器
|
|
|
+ QWidget* container = button->parentWidget();
|
|
|
+ if (!container)
|
|
|
+ return;
|
|
|
+
|
|
|
+ // 创建Popover触发按钮
|
|
|
+ QPushButton* popoverBtn = createPopoverTriggerButton();
|
|
|
+ QHBoxLayout* containerLayout = qobject_cast<QHBoxLayout*>(container->layout());
|
|
|
+ if (containerLayout) {
|
|
|
+ containerLayout->addWidget(popoverBtn);
|
|
|
+
|
|
|
+ // 存储关联关系
|
|
|
+ popoverMap[popoverBtn] = popover;
|
|
|
+ buttonPopoverMap[button] = popoverBtn;
|
|
|
+
|
|
|
+ // 连接Popover按钮点击事件
|
|
|
+ connect(popoverBtn, &QPushButton::clicked, this, [this, popoverBtn]() {
|
|
|
+ togglePopover(popoverBtn);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+QPushButton* PopoverButtonGroup::createPopoverTriggerButton()
|
|
|
+{
|
|
|
+ auto btn = new PopoverTriggerButton(this);
|
|
|
+
|
|
|
+ // 绘制下拉箭头(垂直居中)
|
|
|
+ QPixmap pixmap(16, 16);
|
|
|
+ pixmap.fill(Qt::transparent);
|
|
|
+ QPainter painter(&pixmap);
|
|
|
+ painter.setRenderHint(QPainter::Antialiasing);
|
|
|
+ painter.setPen(QPen(Colors::Primary, 2));
|
|
|
+
|
|
|
+ QPolygon arrow;
|
|
|
+ arrow << QPoint(4, 6) << QPoint(8, 10) << QPoint(12, 6);
|
|
|
+ painter.drawPolyline(arrow);
|
|
|
+
|
|
|
+ btn->setIcon(QIcon(pixmap));
|
|
|
+ btn->setIconSize(QSize(16, 16));
|
|
|
+
|
|
|
+ return btn;
|
|
|
+}
|
|
|
+
|
|
|
+void PopoverButtonGroup::togglePopover(QPushButton* popoverBtn)
|
|
|
+{
|
|
|
+ if (!popoverMap.contains(popoverBtn))
|
|
|
+ return;
|
|
|
+
|
|
|
+ Popover* popover = popoverMap[popoverBtn];
|
|
|
+
|
|
|
+ if (popover->isVisible()) {
|
|
|
+ popover->hideAnimated();
|
|
|
+ } else {
|
|
|
+ // 关闭其他Popover
|
|
|
+ for (auto btn : popoverMap.keys()) {
|
|
|
+ if (btn != popoverBtn && popoverMap[btn]->isVisible()) {
|
|
|
+ popoverMap[btn]->hideAnimated();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 显示当前Popover
|
|
|
+ QPoint pos = popoverBtn->mapToGlobal(QPoint(0, popoverBtn->height()));
|
|
|
+ popover->showAnimated(pos);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+QSize PopoverButtonGroup::sizeHint() const
|
|
|
+{
|
|
|
+ if (buttons.isEmpty()) {
|
|
|
+ return QSize(0, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 每个FunctionButton的固定大小
|
|
|
+ const int buttonWidth = 100;
|
|
|
+ const int buttonHeight = 70;
|
|
|
+ const int spacing = 15; // 与构造函数中设置的spacing保持一致
|
|
|
+
|
|
|
+ // 计算Popover触发按钮的宽度(如果有的话)
|
|
|
+ const int popoverBtnWidth = 20; // createPopoverTriggerButton中设置的宽度
|
|
|
+
|
|
|
+ int totalWidth = 0;
|
|
|
+ int maxHeight = buttonHeight;
|
|
|
+
|
|
|
+ if (qobject_cast<QHBoxLayout*>(layout)) {
|
|
|
+ // 水平布局:累加宽度
|
|
|
+ for (int i = 0; i < buttons.size(); ++i) {
|
|
|
+ totalWidth += buttonWidth;
|
|
|
+
|
|
|
+ // 检查是否有对应的Popover按钮
|
|
|
+ FunctionButton* btn = buttons[i];
|
|
|
+ if (buttonPopoverMap.contains(btn)) {
|
|
|
+ totalWidth += popoverBtnWidth; // 添加Popover按钮宽度
|
|
|
+ }
|
|
|
+
|
|
|
+ if (i > 0) totalWidth += spacing;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 垂直布局:累加高度,取最大宽度
|
|
|
+ totalWidth = buttonWidth + popoverBtnWidth; // 最大可能宽度
|
|
|
+ maxHeight = 0;
|
|
|
+ for (int i = 0; i < buttons.size(); ++i) {
|
|
|
+ maxHeight += buttonHeight;
|
|
|
+ if (i > 0) maxHeight += spacing;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return QSize(totalWidth, maxHeight);
|
|
|
+}
|