XComboBox.h
#pragma once
#include <QComboBox>
#include <QStandardItemModel>
#include <QListView>
#include <QKeyEvent>
#include "commonplugin_global.h"
#include <QCompleter>
class QLineEdit;
class QListView;
struct ItemInfo
{
int idx;
QString str;
QVariant userData;
bool bChecked;
ItemInfo()
{
idx = -1;
str = QString::fromLocal8Bit("");
userData = QVariant();
bChecked = false;
}
};
class XListView : public QListView
{
Q_OBJECT
public:
XListView(QWidget* parent= Q_NULLPTR):QListView(parent)
{
}
~XListView()
{
}
protected:
void keyPressEvent(QKeyEvent *e)
{
e->accept();
}
};
class KeyPressEater :public QObject
{
Q_OBJECT
public:
KeyPressEater(QObject* parent = nullptr) :QObject(parent)
{
}
~KeyPressEater()
{
}
signals:
void sigActivated(int idx);
protected:
bool eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Space)
{
QListView* lstV = qobject_cast<QListView*>(obj);
if (nullptr != lstV)
{
int idx = lstV->currentIndex().row();
if (-1 != idx)
{
emit sigActivated(idx);
}
}
}
else if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down)
{
return QObject::eventFilter(obj, event);
}
return true;
}
else
{
return QObject::eventFilter(obj, event);
}
}
};
class XComboBox : public QComboBox
{
Q_OBJECT
public:
XComboBox(QWidget *parent = Q_NULLPTR);
~XComboBox();
//添加item
void AddItem(const QString& str, bool bChecked = false, const QVariant &userData = QVariant());
void AddItems(const QList<ItemInfo>& lstItemInfo);
void AddItems(const QMap<QString, bool>& mapStrChk);
void AddItems(const QList<QString>& lstStr);
void AddItems(const QStringList& lstStr, QList<int> trueIndex);//by lxf
void AddItemContent(const QStringList& lstStr, QStringList currentStr = {});
// 删除item
void RemoveItem(int idx);
// 清空item
void Clear();
// 获取选中的数据字符串列表
QStringList GetSelItemsText();
// 获取选中item的信息
QList<ItemInfo> GetSelItemsInfo();
// 获取item文本
QString GetItemText(int idx);
// 获取item信息
ItemInfo GetItemInfo(int idx);
void setChecked(int index);//设置勾选状态
void iniCompleter(QStringList lineList);//模糊搜索
signals:
// popup显示信号
void showingPopup();
// popup隐藏信号
void hidingPopup();
protected:
void showPopup();
// 重写QComboBox的hidePopup函数
// 目的选择过程中,不隐藏listview
void hidePopup();
virtual void mousePressEvent(QMouseEvent * event);
virtual void mouseReleaseEvent(QMouseEvent * event);
virtual void mouseMoveEvent(QMouseEvent * event);
private:
void UpdateText();
private slots:
void sltActivated(int idx);
private:
QLineEdit* pLineEdit;
QListView* pListView;
QStandardItemModel m_model;
public:
QCompleter * completer;
};
XComboBox.cpp
#include "XComboBox.h"
#include <QLineEdit>
#include <QMouseEvent>
XComboBox::XComboBox(QWidget *parent /* = Q_NULLPTR */)
:QComboBox(parent)
{
pLineEdit = new QLineEdit(this);
pLineEdit->setFont(QFont(QString::fromLocal8Bit(" 微软雅黑 "), 12));
//pLineEdit->setReadOnly(true);
this->setLineEdit(pLineEdit);
this->lineEdit()->disconnect();
KeyPressEater * keyPressEater = new KeyPressEater(this);
pListView = new QListView(this);
pListView->installEventFilter(keyPressEater);
this->setView(pListView);
this->setModel(&m_model);
connect(this, SIGNAL(activated(int)), this, SLOT(sltActivated(int)));
connect(keyPressEater, SIGNAL(sigActivated(int)), this, SLOT(sltActivated(int)));
}
XComboBox::~XComboBox()
{
}
void XComboBox::iniCompleter(QStringList lineList)
{
/* 新建一个公用的completer */
completer = new QCompleter(lineList, this);
/* CaseInsensitive不区分大小写/CaseSensitive区分大小写 */
completer->setCaseSensitivity(Qt::CaseInsensitive);
/* PopupCompletion符合值弹出一个窗口
* InlineCompletion符合值会直接内嵌到文本输入框中
* UnfilteredPopupCompletion所有的筛选条件都列出,符合条件的在最前
*/
completer->setCompletionMode(QCompleter::PopupCompletion);
/* 最大显示符合条件的个数 */
completer->setMaxVisibleItems(10);
// /* 补全路径 */
// QFileSystemModel *model = new QFileSystemModel;
// model->setRootPath(QDir::currentPath());
// completer->setModel(model);
// /* 日期,时间,ip,等等一大堆 */
pLineEdit->setCompleter(completer);
}
void XComboBox::AddItem(const QString& str, bool bChecked /* = false */, const QVariant &userData /* = QVariant() */ )
{
QStandardItem* item = new QStandardItem(str);
item->setCheckable(true);
item->setCheckState(bChecked ? Qt::Checked : Qt::Unchecked);
item->setData(userData, Qt::UserRole + 1);
//item->setCheckState(Qt::Checked);//by lxf
m_model.appendRow(item);
UpdateText();
}
void XComboBox::setChecked(int index)
{
}
void XComboBox::AddItems(const QMap<QString, bool>& mapStrChk)
{
for (auto it = mapStrChk.begin(); it != mapStrChk.end(); ++it)
{
AddItem(it.key(), it.value());
}
}
void XComboBox::AddItems(const QList<ItemInfo>& lstItemInfo)
{
for (auto a : lstItemInfo)
{
AddItem(a.str, a.bChecked, a.userData);
}
}
void XComboBox::AddItems(const QList<QString>& lstStr)
{
for (auto a : lstStr)
{
AddItem(a, false);
}
}
void XComboBox::AddItems(const QStringList& lstStr, QList<int> trueIndex)//by lxf
{
for (int i=0; i<lstStr.size();i++)
{
QString a = lstStr.at(i);
if (trueIndex.contains(i))
AddItem(a, true);
else
AddItem(a, false);
}
}
void XComboBox::AddItemContent(const QStringList& lstStr, QStringList currentStr)//by lxf
{
for each (QString var in lstStr)
{
if (currentStr.contains(var) && var!=" ")
AddItem(var, false);
else
AddItem(var, false);
}
}
void XComboBox::RemoveItem(int idx)
{
m_model.removeRow(idx);
UpdateText();
}
void XComboBox::Clear()
{
m_model.clear();
UpdateText();
}
QStringList XComboBox::GetSelItemsText()
{
QStringList lst;
QString str = pLineEdit->text();
if (str.isEmpty())
{
return lst;
}
else
{
/*return pLineEdit->text().split(",");*/
return pLineEdit->text().split(QString::fromLocal8Bit("、"));
}
}
QList<ItemInfo> XComboBox::GetSelItemsInfo()
{
QList<ItemInfo> lstInfo;
for (int i = 0; i < m_model.rowCount(); i++)
{
QStandardItem* item = m_model.item(i);
if (item->checkState() == Qt::Unchecked) continue;
ItemInfo info;
info.idx = i;
info.str = item->text();
info.bChecked = true;
info.userData = item->data(Qt::UserRole + 1);
lstInfo << info;
}
return lstInfo;
}
QString XComboBox::GetItemText(int idx)
{
if (idx < 0 || idx >= m_model.rowCount())
{
return QString::fromLocal8Bit("");
}
return m_model.item(idx)->text();
}
ItemInfo XComboBox::GetItemInfo(int idx)
{
ItemInfo info;
if (idx < 0 || idx >= m_model.rowCount())
{
return info;
}
QStandardItem* item = m_model.item(idx);
info.idx = idx;
info.str = item->text();
info.bChecked = (item->checkState() == Qt::Checked);
info.userData = item->data(Qt::UserRole + 1);
return info;
}
void XComboBox::showPopup()
{
emit showingPopup();
QComboBox::showPopup();
}
void XComboBox::hidePopup()
{
int width = this->view()->width();
int height = this->view()->height();
int x = QCursor::pos().x() - mapToGlobal(geometry().topLeft()).x() + geometry().x();
int y = QCursor::pos().y() - mapToGlobal(geometry().topLeft()).y() + geometry().y();
QRect rectView(0, this->height(), width, height);
if (!rectView.contains(x, y))
{
emit hidingPopup();
QComboBox::hidePopup();
}
}
void XComboBox::mousePressEvent(QMouseEvent * event)
{
QComboBox::mousePressEvent(event);
event->accept();
}
void XComboBox::mouseReleaseEvent(QMouseEvent * event)
{
QComboBox::mouseReleaseEvent(event);
event->accept();
}
void XComboBox::mouseMoveEvent(QMouseEvent * event)
{
QComboBox::mouseMoveEvent(event);
event->accept();
}
void XComboBox::UpdateText()
{
QStringList lstTxt;
for (int i = 0; i < m_model.rowCount(); ++i)
{
QStandardItem* item = m_model.item(i);
if (item->checkState() == Qt::Unchecked) continue;
lstTxt << item->text();
}
//pLineEdit->setText(lstTxt.join(","));
pLineEdit->setText(lstTxt.join(QString::fromLocal8Bit(",")));
pLineEdit->setToolTip(lstTxt.join("\n"));
}
void XComboBox::sltActivated(int idx)
{
QStandardItem* item = m_model.item(idx);
if (nullptr == item) return;
Qt::CheckState state = (item->checkState() == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
item->setCheckState(state);
UpdateText();
}
使用:
void tempTaskInformation::setXComboxWidget(QStringList& lstStr, QWidget &widget, QString lstStrCurrent)
{
//QGridLayout* hLayout_00;
//XComboBox * xcmb_00;
xcmb_00 = new XComboBox();
xcmb_00->setFixedHeight(34);
QStringList currentList = lstStrCurrent.split(",");
xcmb_00->AddItemContent(lstStr, currentList);
xcmb_00->iniCompleter(lstStr);//模糊检索
hLayout_00 = new QGridLayout();
hLayout_00->addWidget(xcmb_00);
hLayout_00->setMargin(0);
widget.setLayout(hLayout_00);
//widget.setFont(QFont(QString::fromLocal8Bit(" 微软雅黑 "), 12));
}
void tempTaskInformation::changeXComboxWidget(QStringList& lstStr, QString lstStrCurrent)
{
QStringList currentList = lstStrCurrent.split(",");
xcmb_00->clear();
xcmb_00->AddItemContent(lstStr, currentList);
}