> The creation of the moc_* file is not trigged by including it.

Mmmh, it seems that including it triggers its creation, take a look at the
lyx_automoc macro. For how I've understood it, it checks all the file against
the following regexp:

#include +["<]moc_[^]+\\.cpp[">]

And then runs the moc generator on each match. Moreover... Adding it solved
everything. :P
Peter confirmed that.

> You should either add moc_fancylineedit.cpp to fancylineedit.cpp or
> separately build and link moc_fancylineedit.cpp. As we do not add
> them to the msvc project file, we have to include the moc_* files
> in the *.cpp files.

I was confused by the fact that other LyX classes (PanelStack itself for
instance) didn't include the moc file, but that's not true, simply the #include
is at the end of the file (don't know why) and I didn't saw it. :P

> > I'm a bit confused by all the build systems we're using.
> 
> We're using autotools and CMake. As CMake is cross-platform and
> autotools is not, we need CMake for Windows. The tendency is now
> to at least make CMake do all the thing autotools can do and to
> make it the default build system for all platforms.

And... Scons? :P However I'll test it under Linux with autotools to be sure
everything is right.

> > Thanks for the quick reply ;) Have you tried the patch what 
> do you think of the
> > result?
> 
> No not yet, I'm busy with other things right now. And I have 
> to think again
> how I'm gonna apply a patch to my tree.

Np.

OK, here's the version of the patch with fancylineedit in frontends/qt4 (which I
think it's the right place). Moreover I've moved back it to frontend namespace.

If there aren't big issues with the build system or credits I'll switch to the
next feature.

venom00

Index: src/frontends/qt4/fancylineedit.cpp
===================================================================
--- src/frontends/qt4/fancylineedit.cpp (revisione 0)
+++ src/frontends/qt4/fancylineedit.cpp (revisione 0)
@@ -0,0 +1,305 @@
+/**
+ * \file fancylineedit.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Nokia Corporation (qt-i...@nokia.com)
+ *
+ * Full author contact details are available in file CREDITS.
+ *
+ */
+
+// Code taken from the Qt Creator project and customized a little
+
+#include "fancylineedit.h"
+
+#include <QtCore/QEvent>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+#include <QtCore/QPropertyAnimation>
+#include <QtGui/QApplication>
+#include <QtGui/QMenu>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QLabel>
+#include <QtGui/QAbstractButton>
+#include <QtGui/QPainter>
+#include <QtGui/QStyle>
+#include <QtGui/QPaintEvent>
+
+enum { margin = 6 };
+
+#define ICONBUTTON_HEIGHT 18
+#define FADE_TIME 160
+
+
+namespace lyx {
+namespace frontend {
+
+// --------- FancyLineEditPrivate
+class FancyLineEditPrivate : public QObject {
+public:
+    explicit FancyLineEditPrivate(FancyLineEdit *parent);
+
+    virtual bool eventFilter(QObject *obj, QEvent *event);
+
+    FancyLineEdit  *m_lineEdit;
+    QPixmap m_pixmap[2];
+    QMenu *m_menu[2];
+    bool m_menuTabFocusTrigger[2];
+    IconButton *m_iconbutton[2];
+    bool m_iconEnabled[2];
+};
+
+
+FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent) :
+    QObject(parent),
+    m_lineEdit(parent)
+{
+    for (int i = 0; i < 2; ++i) {
+        m_menu[i] = 0;
+        m_menuTabFocusTrigger[i] = false;
+        m_iconbutton[i] = new IconButton(parent);
+        m_iconbutton[i]->installEventFilter(this);
+        m_iconbutton[i]->hide();
+        m_iconbutton[i]->setAutoHide(false);
+        m_iconEnabled[i] = false;
+    }
+}
+
+bool FancyLineEditPrivate::eventFilter(QObject *obj, QEvent *event)
+{
+    int buttonIndex = -1;
+    for (int i = 0; i < 2; ++i) {
+        if (obj == m_iconbutton[i]) {
+            buttonIndex = i;
+            break;
+        }
+    }
+    if (buttonIndex == -1)
+        return QObject::eventFilter(obj, event);
+    switch (event->type()) {
+    case QEvent::FocusIn:
+        if (m_menuTabFocusTrigger[buttonIndex] && m_menu[buttonIndex]) {
+            m_lineEdit->setFocus();
+            m_menu[buttonIndex]->exec(m_iconbutton[buttonIndex]->mapToGlobal(
+                    m_iconbutton[buttonIndex]->rect().center()));
+            return true;
+        }
+    default:
+        break;
+    }
+    return QObject::eventFilter(obj, event);
+}
+
+
+// --------- FancyLineEdit
+FancyLineEdit::FancyLineEdit(QWidget *parent) :
+    QLineEdit(parent),
+    m_d(new FancyLineEditPrivate(this))
+{
+    ensurePolished();
+    updateMargins();
+
+    connect(this, SIGNAL(textChanged(QString)), this,
SLOT(checkButtons(QString)));
+    connect(m_d->m_iconbutton[Left], SIGNAL(clicked()), this,
SLOT(iconClicked()));
+    connect(m_d->m_iconbutton[Right], SIGNAL(clicked()), this,
SLOT(iconClicked()));
+}
+
+void FancyLineEdit::checkButtons(const QString &text)
+{
+    if (m_oldText.isEmpty() || text.isEmpty()) {
+        for (int i = 0; i < 2; ++i) {
+            if (m_d->m_iconbutton[i]->hasAutoHide())
+                m_d->m_iconbutton[i]->animateShow(!text.isEmpty());
+        }
+        m_oldText = text;
+    }
+}
+
+FancyLineEdit::~FancyLineEdit()
+{
+}
+
+void FancyLineEdit::setButtonVisible(Side side, bool visible)
+{
+    m_d->m_iconbutton[side]->setVisible(visible);
+    m_d->m_iconEnabled[side] = visible;
+    updateMargins();
+}
+
+bool FancyLineEdit::isButtonVisible(Side side) const
+{
+    return m_d->m_iconEnabled[side];
+}
+
+void FancyLineEdit::iconClicked()
+{
+    IconButton *button = qobject_cast<IconButton *>(sender());
+    int index = -1;
+    for (int i = 0; i < 2; ++i)
+        if (m_d->m_iconbutton[i] == button)
+            index = i;
+    if (index == -1)
+        return;
+    if (m_d->m_menu[index]) {
+        m_d->m_menu[index]->exec(QCursor::pos());
+    } else {
+               buttonClicked((Side)index);
+        if (index == Left)
+                       leftButtonClicked();
+        else if (index == Right)
+                       rightButtonClicked();
+    }
+}
+
+void FancyLineEdit::updateMargins()
+{
+    bool leftToRight = (layoutDirection() == Qt::LeftToRight);
+    Side realLeft = (leftToRight ? Left : Right);
+    Side realRight = (leftToRight ? Right : Left);
+
+    int leftMargin = m_d->m_iconbutton[realLeft]->pixmap().width() + 8;
+    int rightMargin = m_d->m_iconbutton[realRight]->pixmap().width() + 8;
+    // Note KDE does not reserve space for the highlight color
+    if (style()->inherits("OxygenStyle")) {
+        leftMargin = qMax(24, leftMargin);
+        rightMargin = qMax(24, rightMargin);
+    }
+
+    QMargins margins((m_d->m_iconEnabled[realLeft] ? leftMargin : 0), 0,
+                     (m_d->m_iconEnabled[realRight] ? rightMargin : 0), 0);
+
+    setTextMargins(margins);
+}
+
+void FancyLineEdit::updateButtonPositions()
+{
+    QRect contentRect = rect();
+    for (int i = 0; i < 2; ++i) {
+        Side iconpos = (Side)i;
+        if (layoutDirection() == Qt::RightToLeft)
+            iconpos = (iconpos == Left ? Right : Left);
+
+        if (iconpos == FancyLineEdit::Right) {
+            const int iconoffset = textMargins().right() + 4;
+            m_d->m_iconbutton[i]->setGeometry(contentRect.adjusted(width() -
iconoffset, 0, 0, 0));
+        } else {
+            const int iconoffset = textMargins().left() + 4;
+            m_d->m_iconbutton[i]->setGeometry(contentRect.adjusted(0, 0,
-width() + iconoffset, 0));
+        }
+    }
+}
+
+void FancyLineEdit::resizeEvent(QResizeEvent *)
+{
+    updateButtonPositions();
+}
+
+void FancyLineEdit::setButtonPixmap(Side side, const QPixmap &buttonPixmap)
+{
+    m_d->m_iconbutton[side]->setPixmap(buttonPixmap);
+    updateMargins();
+    updateButtonPositions();
+    update();
+}
+
+QPixmap FancyLineEdit::buttonPixmap(Side side) const
+{
+    return m_d->m_pixmap[side];
+}
+
+void FancyLineEdit::setButtonMenu(Side side, QMenu *buttonMenu)
+{
+     m_d->m_menu[side] = buttonMenu;
+     m_d->m_iconbutton[side]->setIconOpacity(1.0);
+ }
+
+QMenu *FancyLineEdit::buttonMenu(Side side) const
+{
+    return  m_d->m_menu[side];
+}
+
+bool FancyLineEdit::hasMenuTabFocusTrigger(Side side) const
+{
+    return m_d->m_menuTabFocusTrigger[side];
+}
+
+void FancyLineEdit::setMenuTabFocusTrigger(Side side, bool v)
+{
+    if (m_d->m_menuTabFocusTrigger[side] == v)
+        return;
+
+    m_d->m_menuTabFocusTrigger[side] = v;
+    m_d->m_iconbutton[side]->setFocusPolicy(v ? Qt::TabFocus : Qt::NoFocus);
+}
+
+bool FancyLineEdit::hasAutoHideButton(Side side) const
+{
+    return m_d->m_iconbutton[side]->hasAutoHide();
+}
+
+void FancyLineEdit::setAutoHideButton(Side side, bool h)
+{
+    m_d->m_iconbutton[side]->setAutoHide(h);
+    if (h)
+        m_d->m_iconbutton[side]->setIconOpacity(text().isEmpty() ?  0.0 : 1.0);
+    else
+        m_d->m_iconbutton[side]->setIconOpacity(1.0);
+}
+
+void FancyLineEdit::setButtonToolTip(Side side, const QString &tip)
+{
+    m_d->m_iconbutton[side]->setToolTip(tip);
+}
+
+void FancyLineEdit::setButtonFocusPolicy(Side side, Qt::FocusPolicy policy)
+{
+    m_d->m_iconbutton[side]->setFocusPolicy(policy);
+}
+
+// IconButton - helper class to represent a clickable icon
+
+IconButton::IconButton(QWidget *parent)
+    : QAbstractButton(parent), m_autoHide(false)
+{
+    setCursor(Qt::ArrowCursor);
+    setFocusPolicy(Qt::NoFocus);
+}
+
+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;
+    QRect pixmapRect = QRect(0, 0, m_pixmap.width(), m_pixmap.height());
+    pixmapRect.moveCenter(rect().center());
+
+    if (m_autoHide)
+        painter.setOpacity(m_iconOpacity);
+
+    painter.drawPixmap(pixmapRect, m_pixmap);
+}
+
+void IconButton::animateShow(bool visible)
+{
+    if (visible) {
+        QPropertyAnimation *animation = new QPropertyAnimation(this,
"iconOpacity");
+        animation->setDuration(FADE_TIME);
+        animation->setEndValue(1.0);
+        animation->start(QAbstractAnimation::DeleteWhenStopped);
+    } else {
+        QPropertyAnimation *animation = new QPropertyAnimation(this,
"iconOpacity");
+        animation->setDuration(FADE_TIME);
+        animation->setEndValue(0.0);
+        animation->start(QAbstractAnimation::DeleteWhenStopped);
+    }
+}
+
+}
+
+}
+
+#include "moc_fancylineedit.cpp"
Index: src/frontends/qt4/fancylineedit.h
===================================================================
--- src/frontends/qt4/fancylineedit.h   (revisione 0)
+++ src/frontends/qt4/fancylineedit.h   (revisione 0)
@@ -0,0 +1,111 @@
+/**
+ * \file fancylineedit.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Nokia Corporation (qt-i...@nokia.com)
+ *
+ * Full author contact details are available in file CREDITS.
+ *
+ */
+
+// Code taken from the Qt Creator project and customized a little
+
+#ifndef FANCYLINEEDIT_H
+#define FANCYLINEEDIT_H
+
+#include <QtGui/QLineEdit>
+#include <QtGui/QAbstractButton>
+
+namespace lyx {
+namespace frontend {
+
+class FancyLineEditPrivate;
+
+class IconButton: public QAbstractButton
+{
+       Q_OBJECT
+       Q_PROPERTY(float iconOpacity READ iconOpacity WRITE setIconOpacity)
+       Q_PROPERTY(bool autoHide READ hasAutoHide WRITE setAutoHide)
+       Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap)
+public:
+    explicit IconButton(QWidget *parent = 0);
+    void paintEvent(QPaintEvent *event);
+    void setPixmap(const QPixmap &pixmap) { m_pixmap = pixmap; update(); }
+    QPixmap pixmap() const { return m_pixmap; }
+    float iconOpacity() { return m_iconOpacity; }
+    void setIconOpacity(float value) { m_iconOpacity = value; update(); }
+    void animateShow(bool visible);
+
+    void setAutoHide(bool hide) { m_autoHide = hide; }
+    bool hasAutoHide() const { return m_autoHide; }
+private:
+    float m_iconOpacity;
+    bool m_autoHide;
+    QPixmap m_pixmap;
+};
+
+
+/* A line edit with an embedded pixmap on one side that is connected to
+ * a menu. Additionally, it can display a grayed hintText (like "Type Here to")
+ * when not focused and empty. When connecting to the changed signals and
+ * querying text, one has to be aware that the text is set to that hint
+ * text if isShowingHintText() returns true (that is, does not contain
+ * valid user input).
+ */
+class FancyLineEdit : public QLineEdit
+{
+       Q_DISABLE_COPY(FancyLineEdit)
+       Q_OBJECT
+       Q_ENUMS(Side)
+
+public:
+    enum Side {Left = 0, Right = 1};
+
+    explicit FancyLineEdit(QWidget *parent = 0);
+    ~FancyLineEdit();
+
+    QPixmap buttonPixmap(Side side) const;
+    void setButtonPixmap(Side side, const QPixmap &pixmap);
+
+    QMenu *buttonMenu(Side side) const;
+    void setButtonMenu(Side side, QMenu *menu);
+
+    void setButtonVisible(Side side, bool visible);
+    bool isButtonVisible(Side side) const;
+
+    void setButtonToolTip(Side side, const QString &);
+    void setButtonFocusPolicy(Side side, Qt::FocusPolicy policy);
+
+    // Set whether tabbing in will trigger the menu.
+    void setMenuTabFocusTrigger(Side side, bool v);
+    bool hasMenuTabFocusTrigger(Side side) const;
+
+    // Set if icon should be hidden when text is empty
+    void setAutoHideButton(Side side, bool h);
+    bool hasAutoHideButton(Side side) const;
+
+Q_SIGNALS:
+       void buttonClicked(Side side);
+    void leftButtonClicked();
+    void rightButtonClicked();
+
+private Q_SLOTS:
+    void checkButtons(const QString &);
+    void iconClicked();
+
+protected:
+    virtual void resizeEvent(QResizeEvent *e);
+
+private:
+    void updateMargins();
+       void updateButtonPositions();
+
+    FancyLineEditPrivate *m_d;
+    QString m_oldText;
+};
+
+}
+}
+
+#endif // FANCYLINEEDIT_H
Index: src/frontends/qt4/PanelStack.cpp
===================================================================
--- src/frontends/qt4/PanelStack.cpp    (revisione 38779)
+++ src/frontends/qt4/PanelStack.cpp    (copia locale)
@@ -14,16 +14,28 @@
 
 #include "qt_helpers.h"
 
+#include "GuiApplication.h"
 #include "support/debug.h"
+#include "support/foreach.h"
+#include "support/lassert.h"
 
+#include <QAbstractButton>
+#include <QApplication>
+#include <QColorGroup>
+#include <QComboBox>
 #include <QFontMetrics>
+#include <QGroupBox>
 #include <QHBoxLayout>
 #include <QHeaderView>
+#include <QLabel>
+#include <QLineEdit>
+#include <QListWidget>
+#include <QPalette>
+#include <QPushButton>
 #include <QStackedWidget>
 #include <QTreeWidget>
+#include <QVBoxLayout>
 
-#include "support/lassert.h"
-
 using namespace std;
 
 namespace lyx {
@@ -33,9 +45,16 @@
 PanelStack::PanelStack(QWidget * parent)
        : QWidget(parent)
 {
+       delay_search_ = new QTimer(this);
        list_ = new QTreeWidget(this);
        stack_ = new QStackedWidget(this);
+       search_ = new FancyLineEdit(this);
 
+       // Configure the timer
+       delay_search_->setSingleShot(true);
+       connect(delay_search_, SIGNAL(timeout()), this, SLOT(search()));
+
+       // Configure tree
        list_->setRootIsDecorated(false);
        list_->setColumnCount(1);
        list_->header()->hide();
@@ -48,9 +67,31 @@
        connect(list_, SIGNAL(itemClicked (QTreeWidgetItem*, int)),
                this, SLOT(itemSelected(QTreeWidgetItem *, int)));
 
-       QHBoxLayout * layout = new QHBoxLayout(this);
-       layout->addWidget(list_, 0);
-       layout->addWidget(stack_, 1);
+       // Configure the search box
+#if QT_VERSION >= 0x040700
+       search_->setPlaceholderText(qt_("Search"));
+#endif
+
+       search_->setButtonPixmap(FancyLineEdit::Right, getPixmap("images/",
"editclear", "png"));
+       search_->setButtonVisible(FancyLineEdit::Right, true);
+       search_->setButtonToolTip(FancyLineEdit::Right, qt_("Clear text"));
+       search_->setAutoHideButton(FancyLineEdit::Right, true);
+       connect(search_, SIGNAL(rightButtonClicked()), this,
SLOT(resetSearch()));
+       connect(search_, SIGNAL(textEdited(QString)), this,
SLOT(filterChanged(QString)));
+
+       // Create a HBox for the search box and the reset button
+       QHBoxLayout * search_layout = new QHBoxLayout();
+       search_layout->addWidget(search_, 0);
+
+       // Create the output layout, horizontal plus a VBox on the left with the
search
+       // box and the tree
+       QVBoxLayout * left_layout = new QVBoxLayout();
+       left_layout->addLayout(search_layout, 0);
+       left_layout->addWidget(list_, 1);
+
+       QHBoxLayout * main_layout = new QHBoxLayout(this);
+       main_layout->addLayout(left_layout, 0);
+       main_layout->addWidget(stack_, 1);
 }
 
 
@@ -132,22 +173,156 @@
                             QTreeWidgetItem * previous)
 {
        // do nothing when clicked on whitespace (item=NULL)
-       if( !item )
+       if (!item)
                return;
 
        // if we have a category, expand the tree and go to the
-       // first item
+       // first enabled item
        if (item->childCount() > 0) {
                item->setExpanded(true);
-               if (previous && previous->parent() != item)
-                       switchPanel( item->child(0), previous );
+               if (previous && previous->parent() != item) {
+                       // Looks for a child not disabled
+                       for (int i = 0; i < item->childCount(); ++i) {
+                               if (item->child(i)->flags() & Qt::ItemIsEnabled)
{
+                                       switchPanel(item->child(i), previous);
+                                       break;
+                               }
+                       }
+               }
        }
        else if (QWidget * w = widget_map_.value(item, 0)) {
                stack_->setCurrentWidget(w);
        }
 }
 
+bool matches(QString const & input, QString const & search)
+{
+       QString text = input;
 
+       // Check if the input contains the search string
+       return text.remove('&').contains(search, Qt::CaseInsensitive);
+}
+
+void setTreeItemStatus(QTreeWidgetItem * tree_item, bool enabled)
+{
+       // Enable/disable the item
+       tree_item->setDisabled(!enabled);
+
+       // Change the color from black to gray or viceversa
+       QPalette::ColorGroup new_color = enabled ? QPalette::Active :
QPalette::Disabled;
+       tree_item->setTextColor(0, QApplication::palette().color(new_color,
QPalette::Text));
+}
+
+void PanelStack::hideEvent(QHideEvent * event)
+{
+       QWidget::hideEvent(event);
+
+       // Programatically hidden (not simply minimized by the user)
+       if (!event->spontaneous()) {
+               resetSearch();
+       }
+}
+
+void PanelStack::resetSearch()
+{
+       search_->setText(QString());
+       search();
+}
+
+void PanelStack::filterChanged(QString const & /*search*/)
+{
+       // The text in the search box is changed, reset the timer
+       // and then search in the widgets
+       delay_search_->start(300);
+}
+
+void PanelStack::search()
+{
+       QString search = search_->text();
+       bool enable_all = search.isEmpty();
+
+       // If the search string is empty we enable all the items
+       // otherwise we disable everything and then selectively
+       // re-enable matching items
+       foreach (QTreeWidgetItem * tree_item, panel_map_) {
+               setTreeItemStatus(tree_item, enable_all);
+       }
+
+       foreach (QTreeWidgetItem * tree_item, panel_map_) {
+
+               // Current widget
+               QWidget * pane_widget = widget_map_[tree_item];
+
+               // First of all we look in the pane name
+               bool pane_matches = tree_item->text(0).contains(search,
Qt::CaseInsensitive);
+
+               // If the tree item has an associated pane
+               if (pane_widget) {
+
+                       // Loops on the list of children widgets (recursive)
+                       QWidgetList children = pane_widget->findChildren<QWidget
*>();
+                       foreach (QWidget * child_widget, children) {
+                               bool widget_matches = false;
+
+                               // Try to cast to the most common widgets and
looks in it's content
+                               // It's bad OOP, it would be nice to have a
QWidget::toString() overloaded by
+                               // each widget, but this would require to change
Qt or subclass each widget.
+                               // Note that we have to ignore the amperstand
symbol
+                               if (QAbstractButton * button =
qobject_cast<QAbstractButton *>(child_widget)) {
+                                       widget_matches = matches(button->text(),
search);
+
+                               } else if (QGroupBox * group_box =
qobject_cast<QGroupBox *>(child_widget)) {
+                                       widget_matches =
matches(group_box->title(), search);
+
+                               } else if (QLabel * label = qobject_cast<QLabel
*>(child_widget)) {
+                                       widget_matches = matches(label->text(),
search);
+
+                               } else if (QLineEdit * line_edit =
qobject_cast<QLineEdit *>(child_widget)) {
+                                       widget_matches =
matches(line_edit->text(), search);
+
+                               } else if (QListWidget * list_widget =
qobject_cast<QListWidget *>(child_widget)) {
+                                       widget_matches =
(list_widget->findItems(search, Qt::MatchContains)).count() > 0;
+
+                               } else if (QTreeWidget * tree_view =
qobject_cast<QTreeWidget *>(child_widget)) {
+                                       widget_matches =
(tree_view->findItems(search, Qt::MatchContains)).count() > 0;
+
+                               } else if (QComboBox * combo_box =
qobject_cast<QComboBox *>(child_widget)) {
+                                       widget_matches =
(combo_box->findText(search, Qt::MatchContains)) != -1;
+
+                               } else {
+                                       continue;
+                               }
+
+                               // If this widget meets the search criteria
+                               if (widget_matches && !enable_all) {
+                                       // The pane too meets the search
criteria
+                                       pane_matches = true;
+
+                                       // Highlight the widget
+                                       QPalette widget_palette =
child_widget->palette();
+
widget_palette.setColor(child_widget->foregroundRole(), Qt::red);
+
child_widget->setPalette(widget_palette);
+                               } else {
+                                       // Reset the color of the widget
+
child_widget->setPalette(QApplication::palette(child_widget));
+                               }
+                       }
+
+                       // If the pane meets the search criteria
+                       if (pane_matches && !enable_all) {
+                               // Expand and enable the pane and his ancestors
(typically just the parent)
+                               QTreeWidgetItem * item = tree_item;
+                               do {
+                                       item->setExpanded(true);
+                                       setTreeItemStatus(item, true);
+                                       item = item->parent();
+                               } while (item);
+                       }
+               }
+
+       }
+}
+
 void PanelStack::itemSelected(QTreeWidgetItem * item, int)
 {
        // de-select the category if a child is selected
Index: src/frontends/qt4/PanelStack.h
===================================================================
--- src/frontends/qt4/PanelStack.h      (revisione 38779)
+++ src/frontends/qt4/PanelStack.h      (copia locale)
@@ -13,12 +13,19 @@
 #ifndef PANELSTACK_H
 #define PANELSTACK_H
 
+#include "fancylineedit.h"
+
+#include <QHash>
+#include <QHideEvent>
+#include <QTimer>
 #include <QWidget>
-#include <QHash>
 
+class QAbstractButton;
+class QLineEdit;
+class QPushButton;
+class QStackedWidget;
 class QTreeWidget;
 class QTreeWidgetItem;
-class QStackedWidget;
 
 namespace lyx {
 namespace frontend {
@@ -46,11 +53,21 @@
        QSize sizeHint() const;
 
 public Q_SLOTS:
+       /// the option filter changed
+       void filterChanged(QString const & search);
+       /// perform the search
+       void search();
+       /// reset the search box
+       void resetSearch();
        /// set current panel from an item
        void switchPanel(QTreeWidgetItem * it, QTreeWidgetItem * previous = 0);
        /// click on the tree
        void itemSelected(QTreeWidgetItem *, int);
 
+protected:
+       /// widget hidden
+       void hideEvent(QHideEvent * event);
+
 private:
        ///
        typedef QHash<QString, QTreeWidgetItem *> PanelMap;
@@ -61,11 +78,18 @@
 
        WidgetMap widget_map_;
 
+       /// contains the search box
+       FancyLineEdit * search_;
+
        /// contains the items
        QTreeWidget * list_;
 
        /// contains the panes
        QStackedWidget * stack_;
+
+       // timer to delay the search between options
+       QTimer * delay_search_;
+
 };
 
 } // namespace frontend
Index: src/support/Makefile.am
===================================================================
--- src/support/Makefile.am     (revisione 38779)
+++ src/support/Makefile.am     (copia locale)
@@ -48,6 +48,8 @@
        environment.h \
        environment.cpp \
        ExceptionMessage.h \
+       fancylineedit.cpp \
+       fancylineedit.h \
        FileName.cpp \
        FileName.h \
        FileNameList.h \
Index: src/frontends/qt4/fancylineedit.cpp
===================================================================
--- src/frontends/qt4/fancylineedit.cpp	(revisione 0)
+++ src/frontends/qt4/fancylineedit.cpp	(revisione 0)
@@ -0,0 +1,305 @@
+/**
+ * \file fancylineedit.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Nokia Corporation (qt-i...@nokia.com)
+ *
+ * Full author contact details are available in file CREDITS.
+ *
+ */
+
+// Code taken from the Qt Creator project and customized a little
+
+#include "fancylineedit.h"
+
+#include <QtCore/QEvent>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+#include <QtCore/QPropertyAnimation>
+#include <QtGui/QApplication>
+#include <QtGui/QMenu>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QLabel>
+#include <QtGui/QAbstractButton>
+#include <QtGui/QPainter>
+#include <QtGui/QStyle>
+#include <QtGui/QPaintEvent>
+
+enum { margin = 6 };
+
+#define ICONBUTTON_HEIGHT 18
+#define FADE_TIME 160
+
+
+namespace lyx {
+namespace frontend {
+
+// --------- FancyLineEditPrivate
+class FancyLineEditPrivate : public QObject {
+public:
+    explicit FancyLineEditPrivate(FancyLineEdit *parent);
+
+    virtual bool eventFilter(QObject *obj, QEvent *event);
+
+    FancyLineEdit  *m_lineEdit;
+    QPixmap m_pixmap[2];
+    QMenu *m_menu[2];
+    bool m_menuTabFocusTrigger[2];
+    IconButton *m_iconbutton[2];
+    bool m_iconEnabled[2];
+};
+
+
+FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent) :
+    QObject(parent),
+    m_lineEdit(parent)
+{
+    for (int i = 0; i < 2; ++i) {
+        m_menu[i] = 0;
+        m_menuTabFocusTrigger[i] = false;
+        m_iconbutton[i] = new IconButton(parent);
+        m_iconbutton[i]->installEventFilter(this);
+        m_iconbutton[i]->hide();
+        m_iconbutton[i]->setAutoHide(false);
+        m_iconEnabled[i] = false;
+    }
+}
+
+bool FancyLineEditPrivate::eventFilter(QObject *obj, QEvent *event)
+{
+    int buttonIndex = -1;
+    for (int i = 0; i < 2; ++i) {
+        if (obj == m_iconbutton[i]) {
+            buttonIndex = i;
+            break;
+        }
+    }
+    if (buttonIndex == -1)
+        return QObject::eventFilter(obj, event);
+    switch (event->type()) {
+    case QEvent::FocusIn:
+        if (m_menuTabFocusTrigger[buttonIndex] && m_menu[buttonIndex]) {
+            m_lineEdit->setFocus();
+            m_menu[buttonIndex]->exec(m_iconbutton[buttonIndex]->mapToGlobal(
+                    m_iconbutton[buttonIndex]->rect().center()));
+            return true;
+        }
+    default:
+        break;
+    }
+    return QObject::eventFilter(obj, event);
+}
+
+
+// --------- FancyLineEdit
+FancyLineEdit::FancyLineEdit(QWidget *parent) :
+    QLineEdit(parent),
+    m_d(new FancyLineEditPrivate(this))
+{
+    ensurePolished();
+    updateMargins();
+
+    connect(this, SIGNAL(textChanged(QString)), this, SLOT(checkButtons(QString)));
+    connect(m_d->m_iconbutton[Left], SIGNAL(clicked()), this, SLOT(iconClicked()));
+    connect(m_d->m_iconbutton[Right], SIGNAL(clicked()), this, SLOT(iconClicked()));
+}
+
+void FancyLineEdit::checkButtons(const QString &text)
+{
+    if (m_oldText.isEmpty() || text.isEmpty()) {
+        for (int i = 0; i < 2; ++i) {
+            if (m_d->m_iconbutton[i]->hasAutoHide())
+                m_d->m_iconbutton[i]->animateShow(!text.isEmpty());
+        }
+        m_oldText = text;
+    }
+}
+
+FancyLineEdit::~FancyLineEdit()
+{
+}
+
+void FancyLineEdit::setButtonVisible(Side side, bool visible)
+{
+    m_d->m_iconbutton[side]->setVisible(visible);
+    m_d->m_iconEnabled[side] = visible;
+    updateMargins();
+}
+
+bool FancyLineEdit::isButtonVisible(Side side) const
+{
+    return m_d->m_iconEnabled[side];
+}
+
+void FancyLineEdit::iconClicked()
+{
+    IconButton *button = qobject_cast<IconButton *>(sender());
+    int index = -1;
+    for (int i = 0; i < 2; ++i)
+        if (m_d->m_iconbutton[i] == button)
+            index = i;
+    if (index == -1)
+        return;
+    if (m_d->m_menu[index]) {
+        m_d->m_menu[index]->exec(QCursor::pos());
+    } else {
+		buttonClicked((Side)index);
+        if (index == Left)
+			leftButtonClicked();
+        else if (index == Right)
+			rightButtonClicked();
+    }
+}
+
+void FancyLineEdit::updateMargins()
+{
+    bool leftToRight = (layoutDirection() == Qt::LeftToRight);
+    Side realLeft = (leftToRight ? Left : Right);
+    Side realRight = (leftToRight ? Right : Left);
+
+    int leftMargin = m_d->m_iconbutton[realLeft]->pixmap().width() + 8;
+    int rightMargin = m_d->m_iconbutton[realRight]->pixmap().width() + 8;
+    // Note KDE does not reserve space for the highlight color
+    if (style()->inherits("OxygenStyle")) {
+        leftMargin = qMax(24, leftMargin);
+        rightMargin = qMax(24, rightMargin);
+    }
+
+    QMargins margins((m_d->m_iconEnabled[realLeft] ? leftMargin : 0), 0,
+                     (m_d->m_iconEnabled[realRight] ? rightMargin : 0), 0);
+
+    setTextMargins(margins);
+}
+
+void FancyLineEdit::updateButtonPositions()
+{
+    QRect contentRect = rect();
+    for (int i = 0; i < 2; ++i) {
+        Side iconpos = (Side)i;
+        if (layoutDirection() == Qt::RightToLeft)
+            iconpos = (iconpos == Left ? Right : Left);
+
+        if (iconpos == FancyLineEdit::Right) {
+            const int iconoffset = textMargins().right() + 4;
+            m_d->m_iconbutton[i]->setGeometry(contentRect.adjusted(width() - iconoffset, 0, 0, 0));
+        } else {
+            const int iconoffset = textMargins().left() + 4;
+            m_d->m_iconbutton[i]->setGeometry(contentRect.adjusted(0, 0, -width() + iconoffset, 0));
+        }
+    }
+}
+
+void FancyLineEdit::resizeEvent(QResizeEvent *)
+{
+    updateButtonPositions();
+}
+
+void FancyLineEdit::setButtonPixmap(Side side, const QPixmap &buttonPixmap)
+{
+    m_d->m_iconbutton[side]->setPixmap(buttonPixmap);
+    updateMargins();
+    updateButtonPositions();
+    update();
+}
+
+QPixmap FancyLineEdit::buttonPixmap(Side side) const
+{
+    return m_d->m_pixmap[side];
+}
+
+void FancyLineEdit::setButtonMenu(Side side, QMenu *buttonMenu)
+{
+     m_d->m_menu[side] = buttonMenu;
+     m_d->m_iconbutton[side]->setIconOpacity(1.0);
+ }
+
+QMenu *FancyLineEdit::buttonMenu(Side side) const
+{
+    return  m_d->m_menu[side];
+}
+
+bool FancyLineEdit::hasMenuTabFocusTrigger(Side side) const
+{
+    return m_d->m_menuTabFocusTrigger[side];
+}
+
+void FancyLineEdit::setMenuTabFocusTrigger(Side side, bool v)
+{
+    if (m_d->m_menuTabFocusTrigger[side] == v)
+        return;
+
+    m_d->m_menuTabFocusTrigger[side] = v;
+    m_d->m_iconbutton[side]->setFocusPolicy(v ? Qt::TabFocus : Qt::NoFocus);
+}
+
+bool FancyLineEdit::hasAutoHideButton(Side side) const
+{
+    return m_d->m_iconbutton[side]->hasAutoHide();
+}
+
+void FancyLineEdit::setAutoHideButton(Side side, bool h)
+{
+    m_d->m_iconbutton[side]->setAutoHide(h);
+    if (h)
+        m_d->m_iconbutton[side]->setIconOpacity(text().isEmpty() ?  0.0 : 1.0);
+    else
+        m_d->m_iconbutton[side]->setIconOpacity(1.0);
+}
+
+void FancyLineEdit::setButtonToolTip(Side side, const QString &tip)
+{
+    m_d->m_iconbutton[side]->setToolTip(tip);
+}
+
+void FancyLineEdit::setButtonFocusPolicy(Side side, Qt::FocusPolicy policy)
+{
+    m_d->m_iconbutton[side]->setFocusPolicy(policy);
+}
+
+// IconButton - helper class to represent a clickable icon
+
+IconButton::IconButton(QWidget *parent)
+    : QAbstractButton(parent), m_autoHide(false)
+{
+    setCursor(Qt::ArrowCursor);
+    setFocusPolicy(Qt::NoFocus);
+}
+
+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;
+    QRect pixmapRect = QRect(0, 0, m_pixmap.width(), m_pixmap.height());
+    pixmapRect.moveCenter(rect().center());
+
+    if (m_autoHide)
+        painter.setOpacity(m_iconOpacity);
+
+    painter.drawPixmap(pixmapRect, m_pixmap);
+}
+
+void IconButton::animateShow(bool visible)
+{
+    if (visible) {
+        QPropertyAnimation *animation = new QPropertyAnimation(this, "iconOpacity");
+        animation->setDuration(FADE_TIME);
+        animation->setEndValue(1.0);
+        animation->start(QAbstractAnimation::DeleteWhenStopped);
+    } else {
+        QPropertyAnimation *animation = new QPropertyAnimation(this, "iconOpacity");
+        animation->setDuration(FADE_TIME);
+        animation->setEndValue(0.0);
+        animation->start(QAbstractAnimation::DeleteWhenStopped);
+    }
+}
+
+}
+
+}
+
+#include "moc_fancylineedit.cpp"
Index: src/frontends/qt4/fancylineedit.h
===================================================================
--- src/frontends/qt4/fancylineedit.h	(revisione 0)
+++ src/frontends/qt4/fancylineedit.h	(revisione 0)
@@ -0,0 +1,111 @@
+/**
+ * \file fancylineedit.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Nokia Corporation (qt-i...@nokia.com)
+ *
+ * Full author contact details are available in file CREDITS.
+ *
+ */
+
+// Code taken from the Qt Creator project and customized a little
+
+#ifndef FANCYLINEEDIT_H
+#define FANCYLINEEDIT_H
+
+#include <QtGui/QLineEdit>
+#include <QtGui/QAbstractButton>
+
+namespace lyx {
+namespace frontend {
+
+class FancyLineEditPrivate;
+
+class IconButton: public QAbstractButton
+{
+	Q_OBJECT
+	Q_PROPERTY(float iconOpacity READ iconOpacity WRITE setIconOpacity)
+	Q_PROPERTY(bool autoHide READ hasAutoHide WRITE setAutoHide)
+	Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap)
+public:
+    explicit IconButton(QWidget *parent = 0);
+    void paintEvent(QPaintEvent *event);
+    void setPixmap(const QPixmap &pixmap) { m_pixmap = pixmap; update(); }
+    QPixmap pixmap() const { return m_pixmap; }
+    float iconOpacity() { return m_iconOpacity; }
+    void setIconOpacity(float value) { m_iconOpacity = value; update(); }
+    void animateShow(bool visible);
+
+    void setAutoHide(bool hide) { m_autoHide = hide; }
+    bool hasAutoHide() const { return m_autoHide; }
+private:
+    float m_iconOpacity;
+    bool m_autoHide;
+    QPixmap m_pixmap;
+};
+
+
+/* A line edit with an embedded pixmap on one side that is connected to
+ * a menu. Additionally, it can display a grayed hintText (like "Type Here to")
+ * when not focused and empty. When connecting to the changed signals and
+ * querying text, one has to be aware that the text is set to that hint
+ * text if isShowingHintText() returns true (that is, does not contain
+ * valid user input).
+ */
+class FancyLineEdit : public QLineEdit
+{
+	Q_DISABLE_COPY(FancyLineEdit)
+	Q_OBJECT
+	Q_ENUMS(Side)
+
+public:
+    enum Side {Left = 0, Right = 1};
+
+    explicit FancyLineEdit(QWidget *parent = 0);
+    ~FancyLineEdit();
+
+    QPixmap buttonPixmap(Side side) const;
+    void setButtonPixmap(Side side, const QPixmap &pixmap);
+
+    QMenu *buttonMenu(Side side) const;
+    void setButtonMenu(Side side, QMenu *menu);
+
+    void setButtonVisible(Side side, bool visible);
+    bool isButtonVisible(Side side) const;
+
+    void setButtonToolTip(Side side, const QString &);
+    void setButtonFocusPolicy(Side side, Qt::FocusPolicy policy);
+
+    // Set whether tabbing in will trigger the menu.
+    void setMenuTabFocusTrigger(Side side, bool v);
+    bool hasMenuTabFocusTrigger(Side side) const;
+
+    // Set if icon should be hidden when text is empty
+    void setAutoHideButton(Side side, bool h);
+    bool hasAutoHideButton(Side side) const;
+
+Q_SIGNALS:
+	void buttonClicked(Side side);
+    void leftButtonClicked();
+    void rightButtonClicked();
+
+private Q_SLOTS:
+    void checkButtons(const QString &);
+    void iconClicked();
+
+protected:
+    virtual void resizeEvent(QResizeEvent *e);
+
+private:
+    void updateMargins();
+	void updateButtonPositions();
+
+    FancyLineEditPrivate *m_d;
+    QString m_oldText;
+};
+
+}
+}
+
+#endif // FANCYLINEEDIT_H
Index: src/frontends/qt4/PanelStack.cpp
===================================================================
--- src/frontends/qt4/PanelStack.cpp	(revisione 38779)
+++ src/frontends/qt4/PanelStack.cpp	(copia locale)
@@ -14,16 +14,28 @@
 
 #include "qt_helpers.h"
 
+#include "GuiApplication.h"
 #include "support/debug.h"
+#include "support/foreach.h"
+#include "support/lassert.h"
 
+#include <QAbstractButton>
+#include <QApplication>
+#include <QColorGroup>
+#include <QComboBox>
 #include <QFontMetrics>
+#include <QGroupBox>
 #include <QHBoxLayout>
 #include <QHeaderView>
+#include <QLabel>
+#include <QLineEdit>
+#include <QListWidget>
+#include <QPalette>
+#include <QPushButton>
 #include <QStackedWidget>
 #include <QTreeWidget>
+#include <QVBoxLayout>
 
-#include "support/lassert.h"
-
 using namespace std;
 
 namespace lyx {
@@ -33,9 +45,16 @@
 PanelStack::PanelStack(QWidget * parent)
 	: QWidget(parent)
 {
+	delay_search_ = new QTimer(this);
 	list_ = new QTreeWidget(this);
 	stack_ = new QStackedWidget(this);
+	search_ = new FancyLineEdit(this);
 
+	// Configure the timer
+	delay_search_->setSingleShot(true);
+	connect(delay_search_, SIGNAL(timeout()), this, SLOT(search()));
+
+	// Configure tree
 	list_->setRootIsDecorated(false);
 	list_->setColumnCount(1);
 	list_->header()->hide();
@@ -48,9 +67,31 @@
 	connect(list_, SIGNAL(itemClicked (QTreeWidgetItem*, int)),
 		this, SLOT(itemSelected(QTreeWidgetItem *, int)));
 
-	QHBoxLayout * layout = new QHBoxLayout(this);
-	layout->addWidget(list_, 0);
-	layout->addWidget(stack_, 1);
+	// Configure the search box
+#if QT_VERSION >= 0x040700
+	search_->setPlaceholderText(qt_("Search"));
+#endif
+
+	search_->setButtonPixmap(FancyLineEdit::Right, getPixmap("images/", "editclear", "png"));
+	search_->setButtonVisible(FancyLineEdit::Right, true);
+	search_->setButtonToolTip(FancyLineEdit::Right, qt_("Clear text"));
+	search_->setAutoHideButton(FancyLineEdit::Right, true);
+	connect(search_, SIGNAL(rightButtonClicked()), this, SLOT(resetSearch()));
+	connect(search_, SIGNAL(textEdited(QString)), this, SLOT(filterChanged(QString)));
+
+	// Create a HBox for the search box and the reset button
+	QHBoxLayout * search_layout = new QHBoxLayout();
+	search_layout->addWidget(search_, 0);
+
+	// Create the output layout, horizontal plus a VBox on the left with the search
+	// box and the tree
+	QVBoxLayout * left_layout = new QVBoxLayout();
+	left_layout->addLayout(search_layout, 0);
+	left_layout->addWidget(list_, 1);
+
+	QHBoxLayout * main_layout = new QHBoxLayout(this);
+	main_layout->addLayout(left_layout, 0);
+	main_layout->addWidget(stack_, 1);
 }
 
 
@@ -132,22 +173,156 @@
 			     QTreeWidgetItem * previous)
 {
 	// do nothing when clicked on whitespace (item=NULL)
-	if( !item )
+	if (!item)
 		return;
 
 	// if we have a category, expand the tree and go to the
-	// first item
+	// first enabled item
 	if (item->childCount() > 0) {
 		item->setExpanded(true);
-		if (previous && previous->parent() != item)
-			switchPanel( item->child(0), previous );
+		if (previous && previous->parent() != item) {
+			// Looks for a child not disabled
+			for (int i = 0; i < item->childCount(); ++i) {
+				if (item->child(i)->flags() & Qt::ItemIsEnabled) {
+					switchPanel(item->child(i), previous);
+					break;
+				}
+			}
+		}
 	}
 	else if (QWidget * w = widget_map_.value(item, 0)) {
 		stack_->setCurrentWidget(w);
 	}
 }
 
+bool matches(QString const & input, QString const & search)
+{
+	QString text = input;
 
+	// Check if the input contains the search string
+	return text.remove('&').contains(search, Qt::CaseInsensitive);
+}
+
+void setTreeItemStatus(QTreeWidgetItem * tree_item, bool enabled)
+{
+	// Enable/disable the item
+	tree_item->setDisabled(!enabled);
+
+	// Change the color from black to gray or viceversa
+	QPalette::ColorGroup new_color = enabled ? QPalette::Active : QPalette::Disabled;
+	tree_item->setTextColor(0, QApplication::palette().color(new_color, QPalette::Text));
+}
+
+void PanelStack::hideEvent(QHideEvent * event)
+{
+	QWidget::hideEvent(event);
+
+	// Programatically hidden (not simply minimized by the user)
+	if (!event->spontaneous()) {
+		resetSearch();
+	}
+}
+
+void PanelStack::resetSearch()
+{
+	search_->setText(QString());
+	search();
+}
+
+void PanelStack::filterChanged(QString const & /*search*/)
+{
+	// The text in the search box is changed, reset the timer
+	// and then search in the widgets
+	delay_search_->start(300);
+}
+
+void PanelStack::search()
+{
+	QString search = search_->text();
+	bool enable_all = search.isEmpty();
+
+	// If the search string is empty we enable all the items
+	// otherwise we disable everything and then selectively
+	// re-enable matching items
+	foreach (QTreeWidgetItem * tree_item, panel_map_) {
+		setTreeItemStatus(tree_item, enable_all);
+	}
+
+	foreach (QTreeWidgetItem * tree_item, panel_map_) {
+
+		// Current widget
+		QWidget * pane_widget = widget_map_[tree_item];
+
+		// First of all we look in the pane name
+		bool pane_matches = tree_item->text(0).contains(search, Qt::CaseInsensitive);
+
+		// If the tree item has an associated pane
+		if (pane_widget) {
+
+			// Loops on the list of children widgets (recursive)
+			QWidgetList children = pane_widget->findChildren<QWidget *>();
+			foreach (QWidget * child_widget, children) {
+				bool widget_matches = false;
+
+				// Try to cast to the most common widgets and looks in it's content
+				// It's bad OOP, it would be nice to have a QWidget::toString() overloaded by
+				// each widget, but this would require to change Qt or subclass each widget.
+				// Note that we have to ignore the amperstand symbol
+				if (QAbstractButton * button = qobject_cast<QAbstractButton *>(child_widget)) {
+					widget_matches = matches(button->text(), search);
+
+				} else if (QGroupBox * group_box = qobject_cast<QGroupBox *>(child_widget)) {
+					widget_matches = matches(group_box->title(), search);
+
+				} else if (QLabel * label = qobject_cast<QLabel *>(child_widget)) {
+					widget_matches = matches(label->text(), search);
+
+				} else if (QLineEdit * line_edit = qobject_cast<QLineEdit *>(child_widget)) {
+					widget_matches = matches(line_edit->text(), search);
+
+				} else if (QListWidget * list_widget = qobject_cast<QListWidget *>(child_widget)) {
+					widget_matches = (list_widget->findItems(search, Qt::MatchContains)).count() > 0;
+
+				} else if (QTreeWidget * tree_view = qobject_cast<QTreeWidget *>(child_widget)) {
+					widget_matches = (tree_view->findItems(search, Qt::MatchContains)).count() > 0;
+
+				} else if (QComboBox * combo_box = qobject_cast<QComboBox *>(child_widget)) {
+					widget_matches = (combo_box->findText(search, Qt::MatchContains)) != -1;
+
+				} else {
+					continue;
+				}
+
+				// If this widget meets the search criteria
+				if (widget_matches && !enable_all) {
+					// The pane too meets the search criteria
+					pane_matches = true;
+
+					// Highlight the widget
+					QPalette widget_palette = child_widget->palette();
+					widget_palette.setColor(child_widget->foregroundRole(), Qt::red);
+					child_widget->setPalette(widget_palette);
+				} else {
+					// Reset the color of the widget
+					child_widget->setPalette(QApplication::palette(child_widget));
+				}
+			}
+
+			// If the pane meets the search criteria
+			if (pane_matches && !enable_all) {
+				// Expand and enable the pane and his ancestors	(typically just the parent)
+				QTreeWidgetItem * item = tree_item;
+				do {
+					item->setExpanded(true);
+					setTreeItemStatus(item, true);
+					item = item->parent();
+				} while (item);
+			}
+		}
+
+	}
+}
+
 void PanelStack::itemSelected(QTreeWidgetItem * item, int)
 {
 	// de-select the category if a child is selected
Index: src/frontends/qt4/PanelStack.h
===================================================================
--- src/frontends/qt4/PanelStack.h	(revisione 38779)
+++ src/frontends/qt4/PanelStack.h	(copia locale)
@@ -13,12 +13,19 @@
 #ifndef PANELSTACK_H
 #define PANELSTACK_H
 
+#include "fancylineedit.h"
+
+#include <QHash>
+#include <QHideEvent>
+#include <QTimer>
 #include <QWidget>
-#include <QHash>
 
+class QAbstractButton;
+class QLineEdit;
+class QPushButton;
+class QStackedWidget;
 class QTreeWidget;
 class QTreeWidgetItem;
-class QStackedWidget;
 
 namespace lyx {
 namespace frontend {
@@ -46,11 +53,21 @@
 	QSize sizeHint() const;
 
 public Q_SLOTS:
+	/// the option filter changed
+	void filterChanged(QString const & search);
+	/// perform the search
+	void search();
+	/// reset the search box
+	void resetSearch();
 	/// set current panel from an item
 	void switchPanel(QTreeWidgetItem * it, QTreeWidgetItem * previous = 0);
 	/// click on the tree
 	void itemSelected(QTreeWidgetItem *, int);
 
+protected:
+	/// widget hidden
+	void hideEvent(QHideEvent * event);
+
 private:
 	///
 	typedef QHash<QString, QTreeWidgetItem *> PanelMap;
@@ -61,11 +78,18 @@
 
 	WidgetMap widget_map_;
 
+	/// contains the search box
+	FancyLineEdit * search_;
+
 	/// contains the items
 	QTreeWidget * list_;
 
 	/// contains the panes
 	QStackedWidget * stack_;
+
+	// timer to delay the search between options
+	QTimer * delay_search_;
+
 };
 
 } // namespace frontend
Index: src/support/Makefile.am
===================================================================
--- src/support/Makefile.am	(revisione 38779)
+++ src/support/Makefile.am	(copia locale)
@@ -48,6 +48,8 @@
 	environment.h \
 	environment.cpp \
 	ExceptionMessage.h \
+	fancylineedit.cpp \
+	fancylineedit.h \
 	FileName.cpp \
 	FileName.h \
 	FileNameList.h \

<<attachment: editclear.png>>

Reply via email to