From c4ca96871280f9dd896d62fe5ea3e01b79b106e6 Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@digia.com>
Date: Fri, 8 Feb 2013 12:40:51 +0100
Subject: [PATCH] Improve QAxSelect dialog.

- Add filter widget from tools (slightly modified to contain
  the image as XPM). Add filter model, wire signals
  accordingly, add handling for the case none is selected
  (disabling the "Ok"-button).
- Use QDialogButtonBox instead of Buttons
- Remove obsolete context help button.
- Maintain "Binary compatibility" by replacing the QScopedPointer
  of the UI by a private class.

Change-Id: I1f4740cab6845525e0a71a3096feb2f2a4b2172a
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
---
 src/activeqt/container/container.pro    |   2 +
 src/activeqt/container/filterwidget.cpp | 321 ++++++++++++++++++++++++
 src/activeqt/container/filterwidget_p.h | 151 +++++++++++
 src/activeqt/container/qaxselect.cpp    |  74 ++++--
 src/activeqt/container/qaxselect.h      |  13 +-
 src/activeqt/container/qaxselect.ui     | 201 ++++++---------
 6 files changed, 611 insertions(+), 151 deletions(-)
 create mode 100644 src/activeqt/container/filterwidget.cpp
 create mode 100644 src/activeqt/container/filterwidget_p.h

diff --git a/src/activeqt/container/container.pro b/src/activeqt/container/container.pro
index 3972e5bc..1c42144d 100644
--- a/src/activeqt/container/container.pro
+++ b/src/activeqt/container/container.pro
@@ -9,6 +9,7 @@ HEADERS =   ../control/qaxaggregated.h \
             qaxobject.h \
             qaxscript.h \
             qaxselect.h \
+            filterwidget_p.h \
             ../shared/qaxtypes.h
 
 SOURCES =   qaxbase.cpp \
@@ -18,6 +19,7 @@ SOURCES =   qaxbase.cpp \
             qaxscript.cpp \
             qaxscriptwrapper.cpp \
             qaxselect.cpp \
+            filterwidget.cpp \
             ../shared/qaxtypes.cpp
 
 FORMS =     qaxselect.ui
diff --git a/src/activeqt/container/filterwidget.cpp b/src/activeqt/container/filterwidget.cpp
new file mode 100644
index 00000000..0e6912af
--- /dev/null
+++ b/src/activeqt/container/filterwidget.cpp
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "filterwidget_p.h"
+
+#include <QtWidgets/QVBoxLayout>
+#include <QtWidgets/QHBoxLayout>
+#include <QtWidgets/QLineEdit>
+#include <QtGui/QFocusEvent>
+#include <QtGui/QPalette>
+#include <QtGui/QCursor>
+#include <QtWidgets/QToolButton>
+#include <QtGui/QPainter>
+#include <QtWidgets/QStyle>
+#include <QtWidgets/QStyleOption>
+
+#include <QtCore/QDebug>
+#include <QtCore/QPropertyAnimation>
+
+enum { debugFilter = 0 };
+
+/* XPM */
+static const char *cleartext_xpm[] = {
+"16 16 53 1",
+"  c None",
+". c #2B2B2B",
+"+ c #2D2D2D",
+"@ c #2F2F2F",
+"# c #323232",
+"$ c #373737",
+"% c #3C3C3C",
+"& c #3E3E3E",
+"* c #363636",
+"= c #404040",
+"- c #494949",
+"; c #4E4E4E",
+"> c #525252",
+", c #444444",
+"' c #4F4F4F",
+") c #9C9C9C",
+"! c #6B6B6B",
+"~ c #626262",
+"{ c #333333",
+"] c #414141",
+"^ c #9B9B9B",
+"/ c #FFFFFF",
+"( c #E5E5E5",
+"_ c #737373",
+": c #3A3A3A",
+"< c #4A4A4A",
+"[ c #555555",
+"} c #5D5D5D",
+"| c #E0E0E0",
+"1 c #E7E7E7",
+"2 c #3F3F3F",
+"3 c #5A5A5A",
+"4 c #4B4B4B",
+"5 c #E2E2E2",
+"6 c #424242",
+"7 c #5E5E5E",
+"8 c #5B5B5B",
+"9 c #505050",
+"0 c #6A6A6A",
+"a c #E3E3E3",
+"b c #4D4D4D",
+"c c #545454",
+"d c #999999",
+"e c #DEDEDE",
+"f c #474747",
+"g c #878787",
+"h c #434343",
+"i c #414140",
+"j c #454545",
+"k c #484848",
+"l c #484949",
+"m c #484748",
+"n c #444544",
+"                ",
+"     .+@@+.     ",
+"    #$%&&%$#    ",
+"   *=-;>>;-=*   ",
+"  $,')!~~!)',$  ",
+" {]'^/(__(/^']{ ",
+" :<[}|/11/|}[<: ",
+" 2'3>45//54>3'2 ",
+" 6>}785//587}>6 ",
+" ]930a/||/a039] ",
+" &bcd/e%%e/dcb& ",
+"  f;6gh]ihg6;f  ",
+"   -f=j99j=f-   ",
+"    k<b99b<k    ",
+"     jkl-mn     ",
+"                "};
+
+QT_BEGIN_NAMESPACE
+
+HintLineEdit::HintLineEdit(QWidget *parent) :
+    QLineEdit(parent),
+    m_defaultFocusPolicy(focusPolicy()),
+    m_refuseFocus(false)
+{
+}
+
+IconButton::IconButton(QWidget *parent)
+    : QToolButton(parent), m_fader(0)
+{
+    setCursor(Qt::ArrowCursor);
+}
+
+void IconButton::paintEvent(QPaintEvent *)
+{
+    QPainter painter(this);
+    // Note isDown should really use the active state but in most styles
+    // this has no proper feedback
+    QIcon::Mode state = QIcon::Disabled;
+    if (isEnabled())
+        state = isDown() ? QIcon::Selected : QIcon::Normal;
+    QPixmap iconpixmap = icon().pixmap(QSize(ICONBUTTON_SIZE, ICONBUTTON_SIZE),
+                                       state, QIcon::Off);
+    QRect pixmapRect = QRect(0, 0, iconpixmap.width(), iconpixmap.height());
+    pixmapRect.moveCenter(rect().center());
+    painter.setOpacity(m_fader);
+    painter.drawPixmap(pixmapRect, iconpixmap);
+}
+
+void IconButton::animateShow(bool visible)
+{
+    if (visible) {
+        QPropertyAnimation *animation = new QPropertyAnimation(this, "fader");
+        animation->setDuration(160);
+        animation->setEndValue(1.0);
+        animation->start(QAbstractAnimation::DeleteWhenStopped);
+    } else {
+        QPropertyAnimation *animation = new QPropertyAnimation(this, "fader");
+        animation->setDuration(160);
+        animation->setEndValue(0.0);
+        animation->start(QAbstractAnimation::DeleteWhenStopped);
+    }
+}
+
+bool HintLineEdit::refuseFocus() const
+{
+    return m_refuseFocus;
+}
+
+void HintLineEdit::setRefuseFocus(bool v)
+{
+    if (v == m_refuseFocus)
+        return;
+    m_refuseFocus = v;
+    setFocusPolicy(m_refuseFocus ? Qt::NoFocus : m_defaultFocusPolicy);
+}
+
+void HintLineEdit::mousePressEvent(QMouseEvent *e)
+{
+    if (debugFilter)
+        qDebug() << Q_FUNC_INFO;
+    // Explicitly focus on click.
+    if (m_refuseFocus && !hasFocus())
+        setFocus(Qt::OtherFocusReason);
+    QLineEdit::mousePressEvent(e);
+}
+
+void HintLineEdit::focusInEvent(QFocusEvent *e)
+{
+    if (debugFilter)
+        qDebug() << Q_FUNC_INFO;
+    if (m_refuseFocus) {
+        // Refuse the focus if the mouse is outside. In addition to the mouse
+        // press logic, this prevents a re-focusing which occurs once
+        // we actually have focus
+        const Qt::FocusReason reason = e->reason();
+        if (reason == Qt::ActiveWindowFocusReason || reason == Qt::PopupFocusReason) {
+            const QPoint mousePos = mapFromGlobal(QCursor::pos());
+            const bool refuse = !geometry().contains(mousePos);
+            if (debugFilter)
+                qDebug() << Q_FUNC_INFO << refuse;
+            if (refuse) {
+                e->ignore();
+                return;
+            }
+        }
+    }
+
+    QLineEdit::focusInEvent(e);
+}
+
+// ------------------- FilterWidget
+FilterWidget::FilterWidget(QWidget *parent, LayoutMode lm)  :
+    QWidget(parent),
+    m_editor(new HintLineEdit(this)),
+    m_button(new IconButton(m_editor)),
+    m_buttonwidth(0)
+{
+    m_editor->setPlaceholderText(tr("Filter"));
+
+    // Let the style determine minimum height for our widget
+    QSize size(ICONBUTTON_SIZE + 6, ICONBUTTON_SIZE + 2);
+
+    // Note KDE does not reserve space for the highlight color
+    if (style()->inherits("OxygenStyle"))
+        size = size.expandedTo(QSize(24, 0));
+
+    // Make room for clear icon
+    QMargins margins = m_editor->textMargins();
+    if (layoutDirection() == Qt::LeftToRight)
+        margins.setRight(size.width());
+    else
+        margins.setLeft(size.width());
+
+    m_editor->setTextMargins(margins);
+
+    QHBoxLayout *l = new QHBoxLayout(this);
+    l->setMargin(0);
+    l->setSpacing(0);
+    if (lm == LayoutAlignRight)
+        l->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
+
+    l->addWidget(m_editor);
+
+    // KDE has custom icons for this. Notice that icon namings are counter intuitive
+    // If these icons are not available we use the freedesktop standard name before
+    // falling back to a bundled resource
+    QIcon icon = QIcon::fromTheme(layoutDirection() == Qt::LeftToRight ?
+                     QStringLiteral("edit-clear-locationbar-rtl") :
+                     QStringLiteral("edit-clear-locationbar-ltr"),
+                     QIcon::fromTheme(QStringLiteral("edit-clear"),
+                                      QIcon(QPixmap(cleartext_xpm))));
+    Q_ASSERT(!icon.availableSizes().isEmpty());
+    m_button->setIcon(icon);
+    m_button->setToolTip(tr("Clear text"));
+    connect(m_button, SIGNAL(clicked()), this, SLOT(reset()));
+    connect(m_editor, SIGNAL(textChanged(QString)), this, SLOT(checkButton(QString)));
+    connect(m_editor, SIGNAL(textEdited(QString)), this, SIGNAL(filterChanged(QString)));
+}
+
+QString FilterWidget::text() const
+{
+    return m_editor->text();
+}
+
+void FilterWidget::checkButton(const QString &text)
+{
+    if (m_oldText.isEmpty() || text.isEmpty())
+        m_button->animateShow(!m_editor->text().isEmpty());
+    m_oldText = text;
+}
+
+void FilterWidget::reset()
+{
+    if (debugFilter)
+        qDebug() << Q_FUNC_INFO;
+
+    if (!m_editor->text().isEmpty()) {
+        // Editor has lost focus once this is pressed
+        m_editor->clear();
+        emit filterChanged(QString());
+    }
+}
+
+void FilterWidget::resizeEvent(QResizeEvent *)
+{
+    QRect contentRect = m_editor->rect();
+    if (layoutDirection() == Qt::LeftToRight) {
+        const int iconoffset = m_editor->textMargins().right() + 4;
+        m_button->setGeometry(contentRect.adjusted(m_editor->width() - iconoffset, 0, 0, 0));
+    } else {
+        const int iconoffset = m_editor->textMargins().left() + 4;
+        m_button->setGeometry(contentRect.adjusted(0, 0, -m_editor->width() + iconoffset, 0));
+    }
+}
+
+bool FilterWidget::refuseFocus() const
+{
+    return m_editor->refuseFocus();
+}
+
+void FilterWidget::setRefuseFocus(bool v)
+{
+    m_editor->setRefuseFocus(v);
+}
+
+QT_END_NAMESPACE
diff --git a/src/activeqt/container/filterwidget_p.h b/src/activeqt/container/filterwidget_p.h
new file mode 100644
index 00000000..48c555e4
--- /dev/null
+++ b/src/activeqt/container/filterwidget_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for the convenience
+// of Qt Designer.  This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef FILTERWIDGET_H
+#define FILTERWIDGET_H
+
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QLineEdit>
+#include <QtGui/QColor>
+#include <QtWidgets/QToolButton>
+
+QT_BEGIN_NAMESPACE
+
+class QToolButton;
+
+/* Note: This a copy of the filter widget found in the qtools repository
+ * which was modified to contain cleartext.png as inline XPM image data
+ * and to have LayoutAlignNone as default parameter in the constructor to
+ * to suit the QAxSelect dialog's needs.
+ *
+ * This widget should never have initial focus
+ * (ie, be the first widget of a dialog, otherwise the hint cannot be displayed.
+ * For situations, where it is the only focusable control (widget box),
+ * there is a special "refuseFocus()" mode, in which it clears the focus
+ * policy and focuses explicitly on click (note that setting Qt::ClickFocus
+ * is not sufficient for that as an ActivationFocus will occur). */
+
+#define ICONBUTTON_SIZE 16
+
+class HintLineEdit : public QLineEdit {
+    Q_OBJECT
+public:
+    explicit HintLineEdit(QWidget *parent = 0);
+
+    bool refuseFocus() const;
+    void setRefuseFocus(bool v);
+
+protected:
+    virtual void mousePressEvent(QMouseEvent *event);
+    virtual void focusInEvent(QFocusEvent *e);
+
+private:
+    const Qt::FocusPolicy m_defaultFocusPolicy;
+    bool m_refuseFocus;
+};
+
+// IconButton: This is a simple helper class that represents clickable icons
+
+class IconButton: public QToolButton
+{
+    Q_OBJECT
+    Q_PROPERTY(float fader READ fader WRITE setFader)
+public:
+    IconButton(QWidget *parent);
+    void paintEvent(QPaintEvent *event);
+    float fader() { return m_fader; }
+    void setFader(float value) { m_fader = value; update(); }
+    void animateShow(bool visible);
+
+private:
+    float m_fader;
+};
+
+// FilterWidget: For filtering item views, with reset button Uses HintLineEdit.
+
+class FilterWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    enum LayoutMode {
+        // For use in toolbars: Expand to the right
+        LayoutAlignRight,
+        // No special alignment
+        LayoutAlignNone
+    };
+
+    explicit FilterWidget(QWidget *parent = 0, LayoutMode lm = LayoutAlignNone);
+
+    QString text() const;
+    void resizeEvent(QResizeEvent *);
+    bool refuseFocus() const; // see HintLineEdit
+    void setRefuseFocus(bool v);
+
+signals:
+    void filterChanged(const QString &);
+
+public slots:
+    void reset();
+
+private slots:
+    void checkButton(const QString &text);
+
+private:
+    HintLineEdit *m_editor;
+    IconButton *m_button;
+    int m_buttonwidth;
+    QString m_oldText;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/activeqt/container/qaxselect.cpp b/src/activeqt/container/qaxselect.cpp
index abfdf769..cfd9d694 100644
--- a/src/activeqt/container/qaxselect.cpp
+++ b/src/activeqt/container/qaxselect.cpp
@@ -43,6 +43,10 @@
 #ifndef QT_NO_WIN_ACTIVEQT
 #include "ui_qaxselect.h"
 
+#include <QtCore/QSortFilterProxyModel>
+#include <QtCore/QItemSelectionModel>
+#include <QtWidgets/QPushButton>
+
 #include <qt_windows.h>
 
 QT_BEGIN_NAMESPACE
@@ -121,6 +125,26 @@ QVariant ControlList::data(const QModelIndex &index, int role) const
     return QVariant();
 }
 
+class QAxSelectPrivate {
+public:
+    inline QString clsidAt(const QModelIndex &index) const
+    {
+        if (index.isValid()) {
+            const QModelIndex sourceIndex = filterModel->mapToSource(index);
+            if (sourceIndex.isValid())
+                return sourceIndex.data(Qt::UserRole).toString();
+        }
+        return QString();
+    }
+
+    inline QPushButton *okButton() const { return selectUi.buttonBox->button(QDialogButtonBox::Ok); }
+
+    inline void setOkButtonEnabled(bool enabled) { okButton()->setEnabled(enabled); }
+
+    Ui::QAxSelect selectUi;
+    QSortFilterProxyModel *filterModel;
+};
+
 /*!
     \class QAxSelect
     \brief The QAxSelect class provides a selection dialog for registered COM components.
@@ -141,22 +165,36 @@ QVariant ControlList::data(const QModelIndex &index, int role) const
     optionally specified with \a parent and \a flags parameters, respectively.
 */
 QAxSelect::QAxSelect(QWidget *parent, Qt::WindowFlags flags)
-: QDialog(parent, flags), selectUi(new Ui::QAxSelect)
+    : QDialog(parent, flags)
+    , d(new QAxSelectPrivate)
 {
+    setWindowFlags(windowFlags() &~ Qt::WindowContextHelpButtonHint);
+    d->selectUi.setupUi(this);
+    d->setOkButtonEnabled(false);
+
 #ifndef QT_NO_CURSOR
     QApplication::setOverrideCursor(Qt::WaitCursor);
 #endif
-    selectUi->setupUi(this);
-    selectUi->ActiveXList->setModel(new ControlList(this));
-    connect(selectUi->ActiveXList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
-        this, SLOT(on_ActiveXList_clicked(QModelIndex)));
+
+    d->filterModel = new QSortFilterProxyModel(this);
+    d->filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+    d->filterModel->setSourceModel(new ControlList(this));
+    d->selectUi.ActiveXList->setModel(d->filterModel);
+
+    connect(d->selectUi.ActiveXList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
+            this, SLOT(onActiveXListCurrentChanged(QModelIndex)));
+    connect(d->selectUi.ActiveXList, SIGNAL(activated(QModelIndex)),
+            this, SLOT(onActiveXListActivated()));
+
 #ifndef QT_NO_CURSOR
     QApplication::restoreOverrideCursor();
 #endif
-    selectUi->ActiveXList->setFocus();
+    d->selectUi.ActiveXList->setFocus();
 
-    connect(selectUi->buttonOk, SIGNAL(clicked()), this, SLOT(accept()));
-    connect(selectUi->buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
+    connect(d->selectUi.buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+    connect(d->selectUi.buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+    connect(d->selectUi.filterLineEdit, SIGNAL(filterChanged(QString)),
+            this, SLOT(onFilterLineEditChanged(QString)));
 }
 
 /*!
@@ -173,21 +211,25 @@ QAxSelect::~QAxSelect()
 */
 QString QAxSelect::clsid() const
 {
-    return selectUi->ActiveX->text();
+    return d->selectUi.ActiveX->text().trimmed();
 }
 
-void QAxSelect::on_ActiveXList_clicked(const QModelIndex &index)
+void QAxSelect::onActiveXListCurrentChanged(const QModelIndex &index)
 {
-    QVariant clsid = selectUi->ActiveXList->model()->data(index, Qt::UserRole);
-    selectUi->ActiveX->setText(clsid.toString());
+    const QString newClsid = d->clsidAt(index);
+    d->selectUi.ActiveX->setText(newClsid);
+    d->setOkButtonEnabled(!newClsid.isEmpty());
 }
 
-void QAxSelect::on_ActiveXList_doubleClicked(const QModelIndex &index)
+void QAxSelect::onActiveXListActivated()
 {
-    QVariant clsid = selectUi->ActiveXList->model()->data(index, Qt::UserRole);
-    selectUi->ActiveX->setText(clsid.toString());
+    if (!clsid().isEmpty())
+        d->okButton()->animateClick();
+}
 
-    accept();
+void QAxSelect::onFilterLineEditChanged(const QString &text)
+{
+    d->filterModel->setFilterFixedString(text);
 }
 
 QT_END_NAMESPACE
diff --git a/src/activeqt/container/qaxselect.h b/src/activeqt/container/qaxselect.h
index 8feed381..80ccd82e 100644
--- a/src/activeqt/container/qaxselect.h
+++ b/src/activeqt/container/qaxselect.h
@@ -46,9 +46,8 @@ QT_BEGIN_NAMESPACE
 
 #ifndef QT_NO_WIN_ACTIVEQT
 
-namespace Ui {
-    class QAxSelect;
-}
+class QAxSelectPrivate;
+class QModelIndex;
 
 class QAxSelect : public QDialog
 {
@@ -59,10 +58,12 @@ public:
     QString clsid() const;
 
 private Q_SLOTS:
-    void on_ActiveXList_clicked(const QModelIndex &index);
-    void on_ActiveXList_doubleClicked(const QModelIndex &index);
+    void onActiveXListCurrentChanged(const QModelIndex &);
+    void onActiveXListActivated();
+    void onFilterLineEditChanged(const QString &);
+
 private:
-    QScopedPointer<Ui::QAxSelect> selectUi;
+    QScopedPointer<QAxSelectPrivate> d;
 };
 
 QT_END_NAMESPACE
diff --git a/src/activeqt/container/qaxselect.ui b/src/activeqt/container/qaxselect.ui
index 945c8ddc..700286d3 100644
--- a/src/activeqt/container/qaxselect.ui
+++ b/src/activeqt/container/qaxselect.ui
@@ -39,136 +39,79 @@
 ** $QT_END_LICENSE$
 **
 *********************************************************************</comment>
-  <widget class="QDialog" name="QAxSelect" >
-    <property name="objectName" >
-      <string notr="true" >QAxSelect</string>
-    </property>
-    <property name="geometry" >
-      <rect>
-        <x>0</x>
-        <y>0</y>
-        <width>439</width>
-        <height>326</height>
-      </rect>
-    </property>
-    <property name="windowTitle" >
-      <string>Select ActiveX Control</string>
-    </property>
-    <property name="sizeGripEnabled" >
-      <bool>true</bool>
-    </property>
-    <layout class="QGridLayout" >
-      <property name="objectName" >
-        <string notr="true" >unnamed</string>
-      </property>
-      <property name="margin" >
-        <number>11</number>
-      </property>
-      <property name="spacing" >
+ <class>QAxSelect</class>
+ <widget class="QDialog" name="QAxSelect">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>439</width>
+    <height>326</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Select ActiveX Control</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <item>
+    <layout class="QVBoxLayout" name="verticalLayout">
+     <item>
+      <widget class="FilterWidget" name="filterLineEdit"/>
+     </item>
+     <item>
+      <widget class="QListView" name="ActiveXList"/>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" name="unnamed">
+       <property name="spacing">
         <number>6</number>
-      </property>
-      <item rowspan="2" row="0" column="1" colspan="1" >
-        <layout class="QVBoxLayout" >
-          <property name="objectName" >
-            <string notr="true" >unnamed</string>
-          </property>
-          <property name="margin" >
-            <number>0</number>
-          </property>
-          <property name="spacing" >
-            <number>6</number>
-          </property>
-          <item>
-            <widget class="QPushButton" name="buttonOk" >
-              <property name="objectName" >
-                <string notr="true" >buttonOk</string>
-              </property>
-              <property name="text" >
-                <string>OK</string>
-              </property>
-              <property name="autoDefault" >
-                <bool>true</bool>
-              </property>
-              <property name="default" >
-                <bool>true</bool>
-              </property>
-            </widget>
-          </item>
-          <item>
-            <widget class="QPushButton" name="buttonCancel" >
-              <property name="objectName" >
-                <string notr="true" >buttonCancel</string>
-              </property>
-              <property name="text" >
-                <string>&amp;Cancel</string>
-              </property>
-              <property name="autoDefault" >
-                <bool>true</bool>
-              </property>
-            </widget>
-          </item>
-          <item>
-            <spacer name="Spacer2" >
-              <property name="sizeHint" >
-                <size>
-                  <width>20</width>
-                  <height>0</height>
-                </size>
-              </property>
-              <property name="sizeType" >
-                <enum>Expanding</enum>
-              </property>
-              <property name="orientation" >
-                <enum>Vertical</enum>
-              </property>
-            </spacer>
-          </item>
-        </layout>
-      </item>
-      <item row="0" column="0" >
-        <widget class="QListView" name="ActiveXList" >
-          <property name="objectName" >
-            <string notr="true" >ActiveXList</string>
-          </property>
+       </property>
+       <property name="margin">
+        <number>0</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="TextLabel1">
+         <property name="text">
+          <string>COM &amp;Object:</string>
+         </property>
+         <property name="buddy">
+          <cstring>ActiveX</cstring>
+         </property>
         </widget>
-      </item>
-      <item row="1" column="0" >
-        <layout class="QHBoxLayout" >
-          <property name="objectName" >
-            <string notr="true" >unnamed</string>
-          </property>
-          <property name="margin" >
-            <number>0</number>
-          </property>
-          <property name="spacing" >
-            <number>6</number>
-          </property>
-          <item>
-            <widget class="QLabel" name="TextLabel1" >
-              <property name="objectName" >
-                <string notr="true" >TextLabel1</string>
-              </property>
-              <property name="text" >
-                <string>COM &amp;Object:</string>
-              </property>
-              <property name="buddy" stdset="0" >
-                <cstring>ActiveX</cstring>
-              </property>
-            </widget>
-          </item>
-          <item>
-            <widget class="QLineEdit" name="ActiveX" >
-              <property name="objectName" >
-                <string notr="true" >ActiveX</string>
-              </property>
-            </widget>
-          </item>
-        </layout>
-      </item>
+       </item>
+       <item>
+        <widget class="QLineEdit" name="ActiveX"/>
+       </item>
+      </layout>
+     </item>
     </layout>
-  </widget>
-  <layoutdefault spacing="6" margin="11" />
-  <includes>
-    <include location="local" >qaxwidget.h</include>
-  </includes>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <customwidgets>
+  <customwidget>
+   <class>FilterWidget</class>
+   <extends>QWidget</extends>
+   <header>filterwidget_p.h</header>
+  </customwidget>
+ </customwidgets>
+ <includes>
+  <include location="local">qaxwidget.h</include>
+ </includes>
+ <resources/>
+ <connections/>
 </ui>
-- 
GitLab