PDA

View Full Version : QComboBox with a clickable button while popup is active



ProstoDen
18th August 2020, 10:36
I have created the ComboBox widget like this:
13530

In addition to default QComboBox, it contains a custom clickable widget to the left of popup button. I pushed this widget as a child of QComboBox, but there is still one problem I cannot solve. I want this widget to be clickable while the popup is open, but the popup is closed when I press to thewidget's arrows, and the widget itself doesn't receive any mouse events. Is there any way to make this widget available for mouse events while the popup is active?

Here is the current combobox implementation:

CarMarksComboBox.h (the arrows widget is CarModelsSwitcher)

#pragma once

#include "VehiclesData.h"
#include "widgets.h"

class CarMarksComboBox: public QComboBox
{
Q_OBJECT
public:
CarMarksComboBox(QWidget* parent = nullptr);

void init(const VehicleNamesMap& vehicleNamesMap);

bool eventFilter(QObject* obj, QEvent* ev) override;
void showPopup() override;
void hidePopup() override;

protected:
void resizeEvent(QResizeEvent* event) override;

private:
void updateArrowsWidgetPosition();

private:
CarModelsSwitcher* m_carModelsSwitcher = nullptr;
};

CarMarksComboBox.cpp

#include "CarMarksComboBox.h"

#include "CarMarksModel.h"

CarMarksComboBox::CarMarksComboBox(QWidget* parent)
: QComboBox{parent}
{
}

void CarMarksComboBox::init(const VehicleNamesMap& vehicleNamesMap)
{
CarMarksModel* carMarksModel = new CarMarksModel(vehicleNamesMap);
carMarksModel->setSelectionFacility(false);

QTreeView* carMarksView = new QTreeView;
carMarksView->header()->setVisible(false);
carMarksView->setMinimumHeight(300);

setView(carMarksView);
setModel(carMarksModel);

m_carModelsSwitcher = new CarModelsSwitcher(this);
m_carModelsSwitcher->installEventFilter(this);
m_carModelsSwitcher->setVisible(false);
}

bool CarMarksComboBox::eventFilter(QObject* obj, QEvent* ev)
{
if (obj == m_carModelsSwitcher && ev->type() == QEvent::Resize)
updateArrowsWidgetPosition();

return QComboBox::eventFilter(obj, ev);
}

void CarMarksComboBox::showPopup()
{
const CarMarksModel* carMarksModel = static_cast<const CarMarksModel*>(model());
if (carMarksModel)
{
const int checkedModelsCount = carMarksModel->getCheckedModelsCount();
if (checkedModelsCount > 0)
{
m_carModelsSwitcher->setText(QString::number(checkedModelsCount));
m_carModelsSwitcher->setVisible(true);
}
}

QComboBox::showPopup();
}

void CarMarksComboBox::hidePopup()
{
m_carModelsSwitcher->setVisible(false);
QComboBox::hidePopup();
}

void CarMarksComboBox::resizeEvent(QResizeEvent* event)
{
updateArrowsWidgetPosition();

QComboBox::resizeEvent(event);
}

void CarMarksComboBox::updateArrowsWidgetPosition()
{
m_carModelsSwitcher->move(width() - m_carModelsSwitcher->width() - 28, (height() - m_carModelsSwitcher->height()) / 2);
}