152 lines
4.3 KiB
C++
152 lines
4.3 KiB
C++
#include "ecombobox.h"
|
|
|
|
#include "clineedit.h"
|
|
#include "qabstractitemview.h"
|
|
#include "qad_types.h"
|
|
#include "qwidget.h"
|
|
|
|
#include <QApplication>
|
|
#include <QHeaderView>
|
|
#include <QLabel>
|
|
#include <QLayout>
|
|
#include <QStandardItemModel>
|
|
#include <QTreeView>
|
|
|
|
|
|
class EModel: public QStandardItemModel {
|
|
public:
|
|
EModel(QObject * parent = nullptr): QStandardItemModel(parent) {
|
|
#if QT_VERSION < 0x050000
|
|
setSupportedDragActions(Qt::MoveAction);
|
|
#endif
|
|
}
|
|
|
|
protected:
|
|
virtual Qt::ItemFlags flags(const QModelIndex & index) const override {
|
|
Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
|
|
if (!index.isValid()) f |= Qt::ItemIsDropEnabled;
|
|
return f;
|
|
}
|
|
#if QT_VERSION >= 0x050000
|
|
Qt::DropActions supportedDragActions() const override { return Qt::MoveAction; }
|
|
Qt::DropActions supportedDropActions() const override { return Qt::MoveAction; }
|
|
#endif
|
|
};
|
|
|
|
|
|
EComboBox::EComboBox(QWidget * parent)
|
|
: QComboBox(parent)
|
|
, iv(new QTreeView(this))
|
|
, header(new QWidget(this))
|
|
, icon(new QLabel(this))
|
|
, filter(new CLineEdit(this)) {
|
|
setView(iv);
|
|
setModel(new EModel());
|
|
iv->setTextElideMode(Qt::ElideMiddle);
|
|
iv->setRootIsDecorated(false);
|
|
iv->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
|
iv->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
|
iv->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
iv->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
iv->setMinimumHeight(100);
|
|
icon->setPixmap(QPixmap(":/icons/edit-find.png"));
|
|
icon->setScaledContents(true);
|
|
icon->setFixedSize(preferredIconSize(1.2, this));
|
|
ifont = nfont = font();
|
|
ifont.setItalic(true);
|
|
#if QT_VERSION >= 0x040700
|
|
filter->setPlaceholderText(tr("Filter"));
|
|
filter->setFont(ifont);
|
|
#endif
|
|
header->setAutoFillBackground(true);
|
|
header->setLayout(new QBoxLayout(QBoxLayout::LeftToRight));
|
|
header->layout()->setSpacing(2);
|
|
header->layout()->setContentsMargins(2, 0, 0, 0);
|
|
header->layout()->addWidget(icon);
|
|
header->layout()->addWidget(filter);
|
|
header->setParent(iv->header());
|
|
connect(filter, &CLineEdit::textChanged, this, [this](const QString & text) { EComboBox::filterChanged(text, false); });
|
|
connect(model(), &EModel::layoutChanged, this, &EComboBox::rowsChanged);
|
|
connect(filter, &QLineEdit::returnPressed, this, [this]() {
|
|
if (rows_visible != 1) return;
|
|
setCurrentIndex(first_index.row());
|
|
});
|
|
}
|
|
|
|
|
|
QSize EComboBox::sizeHint() const {
|
|
QSize s = QComboBox::sizeHint();
|
|
s.setWidth(s.width() + 16);
|
|
return s;
|
|
}
|
|
|
|
|
|
void EComboBox::showPopup() {
|
|
iv->setDragDropMode(isEditable() ? QAbstractItemView::InternalMove : QAbstractItemView::NoDragDrop);
|
|
filterChanged(filter->text(), true);
|
|
QComboBox::showPopup();
|
|
QRect r = iv->header()->rect();
|
|
header->setGeometry(r.x(), r.y(), r.width(), r.height() - 1);
|
|
filter->setFocus();
|
|
filter->selectAll();
|
|
}
|
|
|
|
|
|
void EComboBox::changeEvent(QEvent * e) {
|
|
QComboBox::changeEvent(e);
|
|
switch (e->type()) {
|
|
case QEvent::LanguageChange:
|
|
#if QT_VERSION >= 0x040700
|
|
filter->setPlaceholderText(tr("Filter"));
|
|
#endif
|
|
break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
|
|
void EComboBox::filterChanged(const QString & text, bool first) {
|
|
if (filter->text().isEmpty()) {
|
|
filter->setFont(ifont);
|
|
} else {
|
|
filter->setFont(nfont);
|
|
}
|
|
iv->hide();
|
|
QModelIndex pi = iv->rootIndex();
|
|
int row_count = iv->model()->rowCount();
|
|
rows_visible = 0;
|
|
if (text.isEmpty()) {
|
|
for (int i = 0; i < row_count; ++i) {
|
|
iv->setRowHidden(i, pi, false);
|
|
iv->model()->setData(iv->model()->index(i, 0), iv->model()->index(i, 0, pi).data().toString(), Qt::ToolTipRole);
|
|
}
|
|
iv->show();
|
|
if (first) return;
|
|
hidePopup();
|
|
showPopup();
|
|
qApp->processEvents();
|
|
QRect r = iv->header()->rect();
|
|
header->setGeometry(r.x(), r.y(), r.width(), r.height() - 1);
|
|
return;
|
|
}
|
|
for (int i = 0; i < row_count; ++i) {
|
|
bool hidden = !iv->model()->index(i, 0, pi).data().toString().contains(
|
|
#if QT_VERSION_MAJOR <= 5
|
|
QRegExp(text, Qt::CaseInsensitive)
|
|
#else
|
|
QRegularExpression(text, QRegularExpression::CaseInsensitiveOption)
|
|
#endif
|
|
);
|
|
if (!hidden) {
|
|
if (rows_visible == 0) first_index = iv->model()->index(i, 0);
|
|
++rows_visible;
|
|
}
|
|
iv->setRowHidden(i, pi, hidden);
|
|
iv->model()->setData(iv->model()->index(i, 0), iv->model()->index(i, 0, pi).data().toString(), Qt::ToolTipRole);
|
|
}
|
|
iv->show();
|
|
qApp->processEvents();
|
|
QRect r = iv->header()->rect();
|
|
header->setGeometry(r.x(), r.y(), r.width(), r.height() - 1);
|
|
}
|