You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
271 lines
8.5 KiB
C++
271 lines
8.5 KiB
C++
#include "multiselectcombobox.h"
|
|
#include "qscrollbar.h"
|
|
#include <QLineEdit>
|
|
#include <QCheckBox>
|
|
#include <QEvent>
|
|
#include "mycheckbox.h"
|
|
#include <QScrollBar>
|
|
|
|
MultiSelectComboBox::MultiSelectComboBox(QWidget *parent)
|
|
: QComboBox(parent)
|
|
, hidden_flag_(true)
|
|
, show_flag_(false)
|
|
{
|
|
list_widget_ = new QListWidget();
|
|
line_edit_ = new QLineEdit();
|
|
search_bar_ = new QLineEdit();
|
|
|
|
/* 设置搜索框 */
|
|
QListWidgetItem* currentItem = new QListWidgetItem(list_widget_);
|
|
// 设置搜索框提示信息.
|
|
search_bar_->setPlaceholderText("Search.........");
|
|
// 显示清除按钮.
|
|
search_bar_->setClearButtonEnabled(true);
|
|
list_widget_->addItem(currentItem);
|
|
list_widget_->setItemWidget(currentItem, search_bar_);
|
|
|
|
/* 设置文本框 */
|
|
// 设为只读,因为该输入框只用来显示选中的选项,称为文本框更合适些.
|
|
line_edit_->setReadOnly(true);
|
|
// 把当前对象安装(或注册)为事件过滤器,当前也称为过滤器对象。事件过滤器通常在构造函数中进行注册.
|
|
line_edit_->installEventFilter(this);
|
|
// 设置禁用样式,因为不受样式表控制,临时这样解决.
|
|
line_edit_->setStyleSheet("QLineEdit:disabled{background:rgb(233,233,233);}");
|
|
|
|
this->setModel(list_widget_->model());
|
|
this->setView(list_widget_);
|
|
this->setLineEdit(line_edit_);
|
|
connect(search_bar_, SIGNAL(textChanged(const QString&)), this, SLOT(onSearch(const QString&)));
|
|
connect(this, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &MultiSelectComboBox::itemClicked);
|
|
}
|
|
|
|
MultiSelectComboBox::~MultiSelectComboBox()
|
|
{
|
|
}
|
|
// 隐藏下拉框.
|
|
void MultiSelectComboBox::hidePopup()
|
|
{
|
|
show_flag_ = false;
|
|
int width = this->width();
|
|
int height = this->height();
|
|
int x = QCursor::pos().x() - mapToGlobal(geometry().topLeft()).x() + geometry().x();
|
|
int y = QCursor::pos().y() - mapToGlobal(geometry().topLeft()).y() + geometry().y();
|
|
if (x >= 0 && x <= width && y >= this->height() && y <= height + this->height())
|
|
{
|
|
}
|
|
else
|
|
{
|
|
this->scroll_value = this->list_widget_->verticalScrollBar()->value();
|
|
QComboBox::hidePopup();
|
|
}
|
|
}
|
|
// 添加一条选项.
|
|
void MultiSelectComboBox::addItem(const QString& _text, const QVariant& _variant)
|
|
{
|
|
Q_UNUSED(_variant);
|
|
QListWidgetItem* item = new QListWidgetItem(list_widget_);
|
|
MyCheckBox* checkbox = new MyCheckBox(this);
|
|
checkbox->setText(_text);
|
|
list_widget_->addItem(item);
|
|
list_widget_->setItemWidget(item, checkbox);
|
|
connect(checkbox, &MyCheckBox::stateChanged, this, &MultiSelectComboBox::stateChange);
|
|
}
|
|
// 添加多条选项.
|
|
void MultiSelectComboBox::addItems(const QStringList& _text_list)
|
|
{
|
|
for (const auto& text_one : _text_list)
|
|
{
|
|
addItem(text_one);
|
|
}
|
|
}
|
|
// 返回当前选中选项.
|
|
QStringList MultiSelectComboBox::currentText()
|
|
{
|
|
QStringList text_list;
|
|
if (!line_edit_->text().isEmpty())
|
|
{
|
|
// 以;为分隔符分割字符串.
|
|
text_list = line_edit_->text().split(':');
|
|
}
|
|
return text_list;
|
|
}
|
|
// 返回当前选项条数.
|
|
int MultiSelectComboBox::count() const
|
|
{
|
|
int count = list_widget_->count() - 1;
|
|
if (count < 0)
|
|
{
|
|
count = 0;
|
|
}
|
|
return count;
|
|
}
|
|
// 设置搜索框默认文字.
|
|
void MultiSelectComboBox::SetSearchBarPlaceHolderText(const QString _text)
|
|
{
|
|
search_bar_->setPlaceholderText(_text);
|
|
}
|
|
// 设置文本框默认文字.
|
|
void MultiSelectComboBox::SetPlaceHolderText(const QString& _text)
|
|
{
|
|
line_edit_->setPlaceholderText(_text);
|
|
}
|
|
// 下拉框状态恢复默认(所有选项都恢复为未选中状态).
|
|
void MultiSelectComboBox::ResetSelection()
|
|
{
|
|
int count = list_widget_->count();
|
|
for (int i = 1; i < count; i++)
|
|
{
|
|
// 获取对应位置的QWidget对象.
|
|
QWidget *widget = list_widget_->itemWidget(list_widget_->item(i));
|
|
// 将QWidget对象转换成对应的类型.
|
|
MyCheckBox *check_box = static_cast<MyCheckBox*>(widget);
|
|
check_box->setChecked(false);
|
|
}
|
|
}
|
|
// 清空所有内容(选项内容全部清空).
|
|
void MultiSelectComboBox::clear()
|
|
{
|
|
line_edit_->clear();
|
|
list_widget_->clear();
|
|
QListWidgetItem* currentItem = new QListWidgetItem(list_widget_);
|
|
search_bar_->setPlaceholderText("Search.........");
|
|
search_bar_->setClearButtonEnabled(true);
|
|
list_widget_->addItem(currentItem);
|
|
list_widget_->setItemWidget(currentItem, search_bar_);
|
|
SetSearchBarHidden(hidden_flag_);
|
|
connect(search_bar_, SIGNAL(textChanged(const QString&)), this, SLOT(onSearch(const QString&)));
|
|
}
|
|
// 文本框内容清空(选项内容不清空,所有选项都恢复为未选中状态,文本框清空).
|
|
void MultiSelectComboBox::TextClear()
|
|
{
|
|
line_edit_->clear();
|
|
ResetSelection();
|
|
}
|
|
// 设置选中文本--单.
|
|
void MultiSelectComboBox::setCurrentText(const QString& _text)
|
|
{
|
|
int count = list_widget_->count();
|
|
for (int i = 1; i < count; i++)
|
|
{
|
|
// 获取对应位置的QWidget对象.
|
|
QWidget *widget = list_widget_->itemWidget(list_widget_->item(i));
|
|
// 将QWidget对象转换成对应的类型.
|
|
MyCheckBox *check_box = static_cast<MyCheckBox*>(widget);
|
|
if (_text.compare(check_box->text()))
|
|
check_box->setChecked(true);
|
|
}
|
|
}
|
|
// 设置选中文本--多.
|
|
void MultiSelectComboBox::setCurrentText(const QStringList& _text_list)
|
|
{
|
|
int count = list_widget_->count();
|
|
for (int i = 1; i < count; i++)
|
|
{
|
|
// 获取对应位置的QWidget对象.
|
|
QWidget *widget = list_widget_->itemWidget(list_widget_->item(i));
|
|
// 将QWidget对象转换成对应的类型.
|
|
MyCheckBox *check_box = static_cast<MyCheckBox*>(widget);
|
|
if (_text_list.contains(check_box->text()))
|
|
check_box->setChecked(true);
|
|
}
|
|
}
|
|
// 设置搜索框是否禁用.
|
|
void MultiSelectComboBox::SetSearchBarHidden(bool _flag)
|
|
{
|
|
hidden_flag_ = _flag;
|
|
list_widget_->item(0)->setHidden(hidden_flag_);
|
|
}
|
|
|
|
bool MultiSelectComboBox::eventFilter(QObject *watched, QEvent *event)
|
|
{
|
|
// 设置点击输入框也可以弹出下拉框.
|
|
//qDebug() << event->type();
|
|
if (watched == line_edit_ && event->type() == QEvent::MouseButtonRelease && this->isEnabled())
|
|
{
|
|
if (show_flag_)
|
|
hidePopup();
|
|
else
|
|
showPopup();
|
|
show_flag_ = !show_flag_;
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
}
|
|
|
|
void MultiSelectComboBox::wheelEvent(QWheelEvent *event)
|
|
{
|
|
// 禁用QComboBox默认的滚轮事件.
|
|
Q_UNUSED(event);
|
|
}
|
|
|
|
void MultiSelectComboBox::keyPressEvent(QKeyEvent *event)
|
|
{
|
|
QComboBox::keyPressEvent(event);
|
|
}
|
|
// 槽函数:文本框文本变化.
|
|
void MultiSelectComboBox::stateChange(int _row)
|
|
{
|
|
Q_UNUSED(_row);
|
|
// QString selected_data("");
|
|
selected_data = "";
|
|
int count = list_widget_->count();
|
|
for (int i = 1; i < count; i++)
|
|
{
|
|
QWidget *widget = list_widget_->itemWidget(list_widget_->item(i));
|
|
MyCheckBox *check_box = static_cast<MyCheckBox*>(widget);
|
|
if (check_box->isChecked())
|
|
{
|
|
selected_data.append(check_box->text()).append(";");
|
|
}
|
|
}
|
|
selected_data.chop(1);
|
|
if (!selected_data.isEmpty())
|
|
{
|
|
line_edit_->setText(selected_data);
|
|
}
|
|
else
|
|
{
|
|
line_edit_->clear();
|
|
}
|
|
line_edit_->setToolTip(selected_data);
|
|
emit selectionChange(selected_data);
|
|
}
|
|
// 槽函数:搜索框文本变化
|
|
void MultiSelectComboBox::onSearch(const QString& _text)
|
|
{
|
|
for (int i = 1; i < list_widget_->count(); i++)
|
|
{
|
|
MyCheckBox *check_box = static_cast<MyCheckBox*>(list_widget_->itemWidget(list_widget_->item(i)));
|
|
// 文本匹配则显示,反之隐藏
|
|
//Qt::CaseInsensitive模糊查询.
|
|
if (check_box->text().contains(_text, Qt::CaseInsensitive))
|
|
list_widget_->item(i)->setHidden(false);
|
|
else
|
|
list_widget_->item(i)->setHidden(true);
|
|
}
|
|
}
|
|
// 槽函数:点击下拉框选项
|
|
void MultiSelectComboBox::itemClicked(int _index)
|
|
{
|
|
if (_index != 0)
|
|
{
|
|
MyCheckBox *check_box = static_cast<MyCheckBox*>(list_widget_->itemWidget(list_widget_->item(_index)));
|
|
check_box->setChecked(!check_box->isChecked());
|
|
}
|
|
}
|
|
|
|
void MultiSelectComboBox::showPopup()
|
|
{
|
|
QComboBox::showPopup();
|
|
this->list_widget_->verticalScrollBar()->setSliderPosition(this->scroll_value);
|
|
// this->list_widget_->verticalScrollBar()->setValue(this->scroll_value);
|
|
|
|
QWidget *popup = this->findChild<QFrame*>();
|
|
popup->move(popup->x(), popup->y() + 5);
|
|
|
|
//激活当前下拉框对象.
|
|
list_widget_->activateWindow();
|
|
|
|
}
|