On 13-4-2011 16:26, venom00 wrote:
> Here's the patch. I hope works fine. It would be nice to put it in 2.0 but I 
> think it's impossible as it's late and I've added a string ("Search", maybe 
> we already have it). Moreover it's my first patch in C++ to LyX, so probably 
> it will be full of inconsistencies.
> 
> It adds a search box to Tools -> Preferences and Document -> Settings. It 
> looks for the searched text in all the widgets of the panes and highlights 
> them if match. Panes without matching widgets are disabled and grayed.
> 
> Some questions:
> - I'm using QLineEdit::setPlaceHolder(), which was introduced in Qt 4.7, it 
> that OK?
> - To translate the string I used tr("Search"), is that correct?
> - Currently the widgets are highlighted in red, alternative ideas?
> 
> I took insipiration from Qt Creator and Eclipse.
> 
> Hope you like it.
> venom00
> 
> Index: src/frontends/qt4/PanelStack.cpp
> ===================================================================
> --- src/frontends/qt4/PanelStack.cpp  (revisione 38358)
> +++ src/frontends/qt4/PanelStack.cpp  (copia locale)
> @@ -18,9 +18,17 @@
>  
>  #include <QFontMetrics>
>  #include <QHBoxLayout>
> +#include <QVBoxLayout>
>  #include <QHeaderView>
>  #include <QStackedWidget>
>  #include <QTreeWidget>
> +#include <QLineEdit>
> +#include <QGroupBox>
> +#include <QLabel>
> +#include <QAbstractButton>
> +#include <QComboBox>
> +#include <QApplication>
> +#include <QListWidget>

We try to sort the includes.

>  
> -     QHBoxLayout * layout = new QHBoxLayout(this);
> -     layout->addWidget(list_, 0);
> -     layout->addWidget(stack_, 1);
> +     // Configure the search box

#if QT_VERSION >= 0x040700
> +     search_->setPlaceholderText(tr("Search"));
#endif

> +
> +     connect(search_, SIGNAL(textEdited(QString)), this, 
> SLOT(filterChanged(QString)));
> +
> @@ -136,11 +158,18 @@
>               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) {

                                if (!item->child(i)->isDisabled()) {
(although now I see this is introduced in Qt 4.3)

> +                                     switchPanel( item->child(i), previous );

Style: no spaces next to the braces.

> +                                     break;
> +                             }
> +                     }
> +             }
>       }
>       else if (QWidget * w = widget_map_.value(item, 0)) {
>               stack_->setCurrentWidget(w);
> @@ -148,6 +177,115 @@
>  }
>  
>  
> +void PanelStack::filterChanged(QString search) {
> +     bool enable_all = search.length() == 0;

bool const enable_all = search.isEmpty();

> +
> +     // Iterator for the tree
> +     QHashIterator<QString, QTreeWidgetItem *> 
> panes_iterator(this->panel_map_);

"this" is unnecessary.

Usually we use iterators like:

PanelMap::const_iterator it = panel_map_.begin();
PanelMap::const_iterator end = panel_map_.end();
for (; it != end; ++it) {
        QTreeWidgetItem * item = *it;
        [..]
}

> +
> +     // If the search string is empty we have to re-enable everything
        > +     if (enable_all) {
> +             while (panes_iterator.hasNext()) {
> +                     panes_iterator.next();
> +                     panes_iterator.value()->setDisabled(false);
> +                     panes_iterator.value()->setTextColor(0, 
> QApplication::palette().color(QPalette::Active, QPalette::Text));
> +             }
> +     } else {
> +             // Otherwise disable everything and then re-enable panes 
> matching the
> +             // search criteria
> +             while (panes_iterator.hasNext()) {
> +                     panes_iterator.next();
> +                     panes_iterator.value()->setDisabled(true);
> +                     panes_iterator.value()->setTextColor(0, 
> QApplication::palette().color(QPalette::Disabled, QPalette::Text));
> +             }
> +     }

It's strange that Qt doesn't paint the items in the Disabled color whenever the 
item is disabled.

> +
> +     // Reset the iterator
> +     panes_iterator.toFront();

it = panel_map_.begin();

> +
> +     while (panes_iterator.hasNext()) {
> +             panes_iterator.next();
> +
> +             // Current widget
> +             QWidget * pane_widget = 
> this->widget_map_[panes_iterator.value()];
> +
> +             // First of all we look in the pane name
> +             bool pane_matches = 
> panes_iterator.value()->text(0).contains(search, Qt::CaseInsensitive);
> +
> +             // If the tree item has an associated pane
> +             if (pane_widget) {
> +
> +                     // Collect all the children widgets (recursive)
> +                     QList<QWidget *> children = 
> pane_widget->findChildren<QWidget *>();
> +
> +                     // Loops on the list of children widgets
> +                     size_t last_child = children.size();
> +                     for (size_t child_index = 0; child_index != last_child; 
> ++child_index) {
> +                             bool widget_matches = false;
> +
> +                             // Try to cast to the most common widgets and 
> looks in it's content by each
> +                             // 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 *>(children[child_index])) {
> +                                     widget_matches = (new 
> QString(button->text()))->replace('&', "")
> +                                             .contains(search, 
> Qt::CaseInsensitive);
> +
> +                             } else if (QGroupBox * group_box = 
> qobject_cast<QGroupBox *>(children[child_index])) {
> +                                     widget_matches = (new 
> QString(group_box->title()))->replace('&', "")
> +                                             .contains(search, 
> Qt::CaseInsensitive);
> +
> +                             } else if (QLabel * label = qobject_cast<QLabel 
> *>(children[child_index])) {
> +                                     widget_matches = (new 
> QString(label->text()))->replace('&', "")
> +                                             .contains(search, 
> Qt::CaseInsensitive);
> +
> +                             } else if (QLineEdit * line_edit = 
> qobject_cast<QLineEdit *>(children[child_index])) {
> +                                     widget_matches = (new 
> QString(line_edit->text()))->replace('&', "")
> +                                             .contains(search, 
> Qt::CaseInsensitive);
> +
> +                             } else if (QListWidget * list_widget = 
> qobject_cast<QListWidget *>(children[child_index])) {
> +                                     widget_matches = 
> (list_widget->findItems(search, Qt::MatchContains)).count() != 0;
> +
> +                             } else if (QTreeWidget * tree_view = 
> qobject_cast<QTreeWidget *>(children[child_index])) {
> +                                     widget_matches = 
> (tree_view->findItems(search, Qt::MatchContains)).count() != 0;
> +
> +                             } else if (QComboBox * combo_box = 
> qobject_cast<QComboBox *>(children[child_index])) {
> +                                     widget_matches = 
> (combo_box->findText(search, Qt::MatchContains)) != -1;
> +
> +                             } else {
> +                                     continue;
> +                             }
> +


This is really ugly, but I can't think of how to solve it right now.


> +                             // 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 = 
> children[child_index]->palette();
> +                                     
> widget_palette.setColor(children[child_index]->foregroundRole(), Qt::red);
> +                                     
> children[child_index]->setPalette(widget_palette);
> +                             } else {
> +                                     // Reset the color of the widget
> +                                     children[child_index]->setPalette( 
> QApplication::palette( children[child_index] ) );
> +                             }
> +                     }
> +
> +                     // 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 = panes_iterator.value();
> +                             do {
> +                                     item->setExpanded(true);
> +                                     item->setDisabled(false);
> +                                     item->setTextColor(0, 
> QApplication::palette().color(QPalette::Active, QPalette::Text));
> +                                     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 38358)
> +++ src/frontends/qt4/PanelStack.h    (copia locale)
> @@ -19,6 +19,7 @@
>  class QTreeWidget;
>  class QTreeWidgetItem;
>  class QStackedWidget;
> +class QLineEdit;

I guess we try to sort this as well.

Vincent

Reply via email to