Browse Source

添加一个混合控件

program clown 1 year ago
parent
commit
677388d840
3 changed files with 193 additions and 0 deletions
  1. 2 0
      QFD/QFD.pro
  2. 155 0
      QFD/widgets/MixWithComboxInput.cpp
  3. 36 0
      QFD/widgets/MixWithComboxInput.h

+ 2 - 0
QFD/QFD.pro

@@ -118,6 +118,7 @@ SOURCES += \
     widgets/LoginWidget.cpp \
     widgets/MatterElementConfigWidget.cpp \
     widgets/MatterElementItemDelegate.cpp \
+    widgets/MixWithComboxInput.cpp \
     widgets/MultiLevelHeaderView.cpp \
     widgets/ProjectListWidget.cpp \
     widgets/ProjectStateWidget.cpp \
@@ -182,6 +183,7 @@ HEADERS += \
     widgets/LoginWidget.h \
     widgets/MatterElementConfigWidget.h \
     widgets/MatterElementItemDelegate.h \
+    widgets/MixWithComboxInput.h \
     widgets/MultiLevelHeaderView.h \
     widgets/ProjectListWidget.h \
     widgets/ProjectStateWidget.h \

+ 155 - 0
QFD/widgets/MixWithComboxInput.cpp

@@ -0,0 +1,155 @@
+#include "MixWithComboxInput.h"
+
+#include <QComboBox>
+#include <QLabel>
+#include <QHBoxLayout>
+#include <QPainter>
+#include <QAbstractItemView>
+#include <QKeyEvent>
+
+class MixWithComboxInput::Private
+{
+public:
+    QComboBox *combo;
+    QLabel *label;
+    bool inside;
+    bool isFlat;
+};
+
+MixWithComboxInput::MixWithComboxInput(QWidget *parent) : QStackedWidget(parent), d(new Private)
+{
+#ifdef Q_OS_MACOS
+    setAttribute(Qt::WA_MacMiniSize, true);
+#endif
+
+    QWidget *first      = new QWidget(this);
+    QHBoxLayout *layout = new QHBoxLayout(first);
+    layout->setSpacing(0);
+    layout->setMargin(0);
+    d->label = new QLabel(first);
+    d->label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
+    layout->addWidget(d->label, 10);
+    QLabel *icon = new QLabel(first);
+    QStyleOption option;
+    option.state = QStyle::State_Enabled;
+    QPixmap pixmap(16, 16);
+    pixmap.fill(QColor(255, 255, 255, 0));
+    QPainter painter(&pixmap);
+    painter.translate(8, 8);
+    style()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &option, &painter);
+    icon->setPixmap(pixmap);
+    layout->addWidget(icon);
+    addWidget(first);
+    d->combo = new QComboBox(this);
+    d->combo->setMaxVisibleItems(15);
+    d->combo->setEditable(true);
+    d->combo->installEventFilter(this);
+    addWidget(d->combo);
+    d->inside = false;
+    d->isFlat = true;
+
+    connect(d->combo, SIGNAL(activated(QString)), this, SIGNAL(inputLevelChanged(QString)));
+    connect(d->combo, SIGNAL(activated(QString)), this, SLOT(setCurrentInputLevel(QString)));
+}
+
+MixWithComboxInput::~MixWithComboxInput()
+{
+    delete d;
+}
+
+void MixWithComboxInput::enterEvent(QEvent *event)
+{
+    Q_UNUSED(event);
+
+    d->inside = true;
+    if (!isFlat()) {
+        return;
+    }
+
+    if (d->combo->view()) {
+        d->combo->view()->removeEventFilter(this);
+    }
+
+    setCurrentIndex(1);
+}
+
+void MixWithComboxInput::leaveEvent(QEvent *event)
+{
+    Q_UNUSED(event);
+
+    d->inside = false;
+    if (!isFlat()) {
+        return;
+    }
+
+    if (d->combo->view() && d->combo->view()->isVisible()) {
+        d->combo->view()->installEventFilter(this);
+        return;
+    }
+
+    if (!d->combo->hasFocus())
+        setCurrentIndex(0);
+}
+
+void MixWithComboxInput::keyPressEvent(QKeyEvent *event)
+{
+    if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
+        focusNextChild();
+    }
+}
+
+bool MixWithComboxInput::isFlat() const
+{
+    return d->isFlat;
+}
+
+void MixWithComboxInput::setFlat(bool flat)
+{
+    if (flat == d->isFlat) {
+        return;
+    }
+
+    d->isFlat = flat;
+
+    if (flat) {
+        d->combo->installEventFilter(this);
+        if (d->inside) {
+            enterEvent(nullptr);
+        } else {
+            leaveEvent(nullptr);
+        }
+        d->combo->setEditable(true);
+    } else {
+        d->combo->removeEventFilter(this);
+        if (d->combo->view()) {
+            d->combo->view()->removeEventFilter(this);
+        }
+        d->combo->setCurrentIndex(d->combo->findText(d->label->text()));
+        d->combo->setEditable(false);
+        setCurrentIndex(1);
+    }
+}
+
+void MixWithComboxInput::setInputLevels(const QStringList &levels)
+{
+    d->combo->clear();
+    d->combo->addItems(levels);
+}
+
+void MixWithComboxInput::setCurrentInputLevel(const QString &level)
+{
+    d->combo->setCurrentIndex(d->combo->findText(level));
+    d->label->setText(level);
+}
+
+bool MixWithComboxInput::eventFilter(QObject *watched, QEvent *event)
+{
+    if (watched == d->combo->view() && event->type() == QEvent::Hide) {
+        focusNextChild();
+        setCurrentIndex(0);
+    } else if (watched == d->combo && event->type() == QEvent::FocusOut
+               && (d->combo->view() && !d->combo->view()->hasFocus()) && !d->inside) {
+        setCurrentIndex(0);
+    }
+    return false;
+}

+ 36 - 0
QFD/widgets/MixWithComboxInput.h

@@ -0,0 +1,36 @@
+#ifndef MIXWITHCOMBOXINPUT_H
+#define MIXWITHCOMBOXINPUT_H
+
+#include <QStackedWidget>
+
+class MixWithComboxInput : public QStackedWidget
+{
+    Q_OBJECT
+public:
+    explicit MixWithComboxInput(QWidget *parent = 0);
+    ~MixWithComboxInput() override;
+
+    bool isFlat() const;
+    void setFlat(bool flat);
+
+    void setInputLevels(const QStringList &levels);
+
+    bool eventFilter(QObject *watched, QEvent *event) override;
+
+public slots:
+    void setCurrentInputLevel(const QString &level);
+
+Q_SIGNALS:
+    void inputLevelChanged(const QString &level);
+
+protected:
+    void enterEvent(QEvent *event) override;
+    void leaveEvent(QEvent *event) override;
+    void keyPressEvent(QKeyEvent *event) override;
+
+private:
+    class Private;
+    Private *const d;
+};
+
+#endif  // MIXWITHCOMBOXINPUT_H