summaryrefslogtreecommitdiffstats
path: root/tools/shared/findwidget
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 09:18:55 (GMT)
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 09:18:55 (GMT)
commite5fcad302d86d316390c6b0f62759a067313e8a9 (patch)
treec2afbf6f1066b6ce261f14341cf6d310e5595bc1 /tools/shared/findwidget
downloadQt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip
Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz
Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2
Long live Qt 4.5!
Diffstat (limited to 'tools/shared/findwidget')
-rw-r--r--tools/shared/findwidget/abstractfindwidget.cpp295
-rw-r--r--tools/shared/findwidget/abstractfindwidget.h115
-rw-r--r--tools/shared/findwidget/findwidget.pri4
-rw-r--r--tools/shared/findwidget/findwidget.qrc14
-rw-r--r--tools/shared/findwidget/images/mac/closetab.pngbin0 -> 516 bytes
-rw-r--r--tools/shared/findwidget/images/mac/next.pngbin0 -> 1310 bytes
-rw-r--r--tools/shared/findwidget/images/mac/previous.pngbin0 -> 1080 bytes
-rw-r--r--tools/shared/findwidget/images/mac/searchfind.pngbin0 -> 1836 bytes
-rw-r--r--tools/shared/findwidget/images/win/closetab.pngbin0 -> 375 bytes
-rw-r--r--tools/shared/findwidget/images/win/next.pngbin0 -> 1038 bytes
-rw-r--r--tools/shared/findwidget/images/win/previous.pngbin0 -> 898 bytes
-rw-r--r--tools/shared/findwidget/images/win/searchfind.pngbin0 -> 1944 bytes
-rw-r--r--tools/shared/findwidget/images/wrap.pngbin0 -> 500 bytes
-rw-r--r--tools/shared/findwidget/itemviewfindwidget.cpp317
-rw-r--r--tools/shared/findwidget/itemviewfindwidget.h78
-rw-r--r--tools/shared/findwidget/texteditfindwidget.cpp169
-rw-r--r--tools/shared/findwidget/texteditfindwidget.h73
17 files changed, 1065 insertions, 0 deletions
diff --git a/tools/shared/findwidget/abstractfindwidget.cpp b/tools/shared/findwidget/abstractfindwidget.cpp
new file mode 100644
index 0000000..e52722c
--- /dev/null
+++ b/tools/shared/findwidget/abstractfindwidget.cpp
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*! \class AbstractFindWidget
+
+ \brief A search bar that is commonly added below a searchable widget.
+
+ \internal
+
+ This widget implements a search bar which becomes visible when the user
+ wants to start searching. It is a modern replacement for the commonly used
+ search dialog. It is usually placed below the target widget using a QVBoxLayout.
+
+ The search is incremental and can be set to case sensitive or whole words
+ using buttons available on the search bar.
+ */
+
+#include "abstractfindwidget.h"
+
+#include <QtCore/QEvent>
+#include <QtCore/QFile>
+#include <QtCore/QTimer>
+
+#include <QtGui/QCheckBox>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QLabel>
+#include <QtGui/QLayout>
+#include <QtGui/QLineEdit>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QToolButton>
+
+QT_BEGIN_NAMESPACE
+
+static QIcon createIconSet(const QString &name)
+{
+ QStringList candidates = QStringList()
+ << (QString::fromUtf8(":/trolltech/shared/images/") + name)
+#ifdef Q_WS_MAC
+ << (QString::fromUtf8(":/trolltech/shared/images/mac/") + name);
+#else
+ << (QString::fromUtf8(":/trolltech/shared/images/win/") + name);
+#endif
+
+ foreach (const QString &f, candidates) {
+ if (QFile::exists(f))
+ return QIcon(f);
+ }
+
+ return QIcon();
+}
+
+/*!
+ Constructs an AbstractFindWidget.
+
+ \a flags can change the layout and turn off certain features.
+ \a parent is passed to the QWidget constructor.
+ */
+AbstractFindWidget::AbstractFindWidget(FindFlags flags, QWidget *parent)
+ : QWidget(parent)
+{
+ QBoxLayout *topLayOut;
+ QBoxLayout *layOut;
+ if (flags & NarrowLayout) {
+ topLayOut = new QVBoxLayout(this);
+ layOut = new QHBoxLayout;
+ topLayOut->addLayout(layOut);
+ } else {
+ topLayOut = layOut = new QHBoxLayout(this);
+ }
+#ifndef Q_OS_MAC
+ topLayOut->setSpacing(6);
+ topLayOut->setMargin(0);
+#endif
+
+ m_toolClose = new QToolButton(this);
+ m_toolClose->setIcon(createIconSet(QLatin1String("closetab.png")));
+ m_toolClose->setAutoRaise(true);
+ layOut->addWidget(m_toolClose);
+ connect(m_toolClose, SIGNAL(clicked()), SLOT(deactivate()));
+
+ m_editFind = new QLineEdit(this);
+ layOut->addWidget(m_editFind);
+ connect(m_editFind, SIGNAL(returnPressed()), SLOT(findNext()));
+ connect(m_editFind, SIGNAL(textChanged(QString)), SLOT(findCurrentText()));
+ connect(m_editFind, SIGNAL(textChanged(QString)), SLOT(updateButtons()));
+
+ m_toolPrevious = new QToolButton(this);
+ m_toolPrevious->setAutoRaise(true);
+ m_toolPrevious->setText(tr("&Previous"));
+ m_toolPrevious->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ m_toolPrevious->setIcon(createIconSet(QLatin1String("previous.png")));
+ layOut->addWidget(m_toolPrevious);
+ connect(m_toolPrevious, SIGNAL(clicked()), SLOT(findPrevious()));
+
+ m_toolNext = new QToolButton(this);
+ m_toolNext->setAutoRaise(true);
+ m_toolNext->setText(tr("&Next"));
+ m_toolNext->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ m_toolNext->setIcon(createIconSet(QLatin1String("next.png")));
+ layOut->addWidget(m_toolNext);
+ connect(m_toolNext, SIGNAL(clicked()), SLOT(findNext()));
+
+ if (flags & NarrowLayout) {
+ QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ m_toolPrevious->setSizePolicy(sp);
+ m_toolPrevious->setMinimumWidth(m_toolPrevious->minimumSizeHint().height());
+ m_toolNext->setSizePolicy(sp);
+ m_toolNext->setMinimumWidth(m_toolNext->minimumSizeHint().height());
+
+ QSpacerItem *spacerItem =
+ new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ layOut->addItem(spacerItem);
+
+ layOut = new QHBoxLayout;
+ topLayOut->addLayout(layOut);
+ } else {
+ m_editFind->setMinimumWidth(150);
+ }
+
+ if (!(flags & NoCaseSensitive)) {
+ m_checkCase = new QCheckBox(tr("&Case sensitive"), this);
+ layOut->addWidget(m_checkCase);
+ connect(m_checkCase, SIGNAL(toggled(bool)), SLOT(findCurrentText()));
+ } else {
+ m_checkCase = 0;
+ }
+
+ if (!(flags & NoWholeWords)) {
+ m_checkWholeWords = new QCheckBox(tr("Whole &words"), this);
+ layOut->addWidget(m_checkWholeWords);
+ connect(m_checkWholeWords, SIGNAL(toggled(bool)), SLOT(findCurrentText()));
+ } else {
+ m_checkWholeWords = 0;
+ }
+
+ m_labelWrapped = new QLabel(this);
+ m_labelWrapped->setTextFormat(Qt::RichText);
+ m_labelWrapped->setAlignment(
+ Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter);
+ m_labelWrapped->setText(
+ tr("<img src=\":/trolltech/shared/images/wrap.png\">"
+ "&nbsp;Search wrapped"));
+ m_labelWrapped->hide();
+ layOut->addWidget(m_labelWrapped);
+
+ QSpacerItem *spacerItem =
+ new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ layOut->addItem(spacerItem);
+
+ setMinimumWidth(minimumSizeHint().width());
+
+ updateButtons();
+ hide();
+}
+
+/*!
+ Destroys the AbstractFindWidget.
+ */
+AbstractFindWidget::~AbstractFindWidget()
+{
+}
+
+/*!
+ Returns the icon set to be used for the action that initiates a search.
+ */
+QIcon AbstractFindWidget::findIconSet()
+{
+ return createIconSet(QLatin1String("searchfind.png"));
+}
+
+/*!
+ Activates the find widget, making it visible and having focus on its input
+ field.
+ */
+void AbstractFindWidget::activate()
+{
+ show();
+ m_editFind->selectAll();
+ m_editFind->setFocus(Qt::ShortcutFocusReason);
+}
+
+/*!
+ Deactivates the find widget, making it invisible and handing focus to any
+ associated QTextEdit.
+ */
+void AbstractFindWidget::deactivate()
+{
+ hide();
+}
+
+void AbstractFindWidget::findNext()
+{
+ findInternal(m_editFind->text(), true, false);
+}
+
+void AbstractFindWidget::findPrevious()
+{
+ findInternal(m_editFind->text(), true, true);
+}
+
+void AbstractFindWidget::findCurrentText()
+{
+ findInternal(m_editFind->text(), false, false);
+}
+
+void AbstractFindWidget::keyPressEvent(QKeyEvent *event)
+{
+ if (event->key() == Qt::Key_Escape) {
+ deactivate();
+ return;
+ }
+
+ QWidget::keyPressEvent(event);
+}
+
+void AbstractFindWidget::updateButtons()
+{
+ const bool en = !m_editFind->text().isEmpty();
+ m_toolPrevious->setEnabled(en);
+ m_toolNext->setEnabled(en);
+}
+
+void AbstractFindWidget::findInternal(const QString &ttf, bool skipCurrent, bool backward)
+{
+ bool found = false;
+ bool wrapped = false;
+ find(ttf, skipCurrent, backward, &found, &wrapped);
+ QPalette p;
+ p.setColor(QPalette::Active, QPalette::Base, found ? Qt::white : QColor(255, 102, 102));
+ m_editFind->setPalette(p);
+ m_labelWrapped->setVisible(wrapped);
+}
+
+bool AbstractFindWidget::caseSensitive() const
+{
+ return m_checkCase && m_checkCase->isChecked();
+}
+
+bool AbstractFindWidget::wholeWords() const
+{
+ return m_checkWholeWords && m_checkWholeWords->isChecked();
+}
+
+bool AbstractFindWidget::eventFilter(QObject *object, QEvent *e)
+{
+ if (isVisible() && e->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ if (ke->key() == Qt::Key_Escape) {
+ hide();
+ return true;
+ }
+ }
+
+ return QWidget::eventFilter(object, e);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/shared/findwidget/abstractfindwidget.h b/tools/shared/findwidget/abstractfindwidget.h
new file mode 100644
index 0000000..fe0c932
--- /dev/null
+++ b/tools/shared/findwidget/abstractfindwidget.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTFINDWIDGET_H
+#define ABSTRACTFINDWIDGET_H
+
+#include <QtGui/QIcon>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QCheckBox;
+class QEvent;
+class QKeyEvent;
+class QLabel;
+class QLineEdit;
+class QObject;
+class QToolButton;
+
+class AbstractFindWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ enum FindFlag {
+ /// Use a layout that is roughly half as wide and twice as high as the regular one.
+ NarrowLayout = 1,
+ /// Do not show the "Whole words" checkbox.
+ NoWholeWords = 2,
+ /// Do not show the "Case sensitive" checkbox.
+ NoCaseSensitive = 4
+ };
+ Q_DECLARE_FLAGS(FindFlags, FindFlag)
+
+ AbstractFindWidget(FindFlags flags = FindFlags(), QWidget *parent = 0);
+ virtual ~AbstractFindWidget();
+
+ bool eventFilter(QObject *object, QEvent *e);
+
+ static QIcon findIconSet();
+
+public slots:
+ void activate();
+ virtual void deactivate();
+ void findNext();
+ void findPrevious();
+ void findCurrentText();
+
+protected:
+ void keyPressEvent(QKeyEvent *event);
+
+private slots:
+ void updateButtons();
+
+protected:
+ virtual void find(const QString &textToFind, bool skipCurrent, bool backward, bool *found, bool *wrapped) = 0;
+
+ bool caseSensitive() const;
+ bool wholeWords() const;
+
+private:
+ void findInternal(const QString &textToFind, bool skipCurrent, bool backward);
+
+ QLineEdit *m_editFind;
+ QLabel *m_labelWrapped;
+ QToolButton *m_toolNext;
+ QToolButton *m_toolClose;
+ QToolButton *m_toolPrevious;
+ QCheckBox *m_checkCase;
+ QCheckBox *m_checkWholeWords;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractFindWidget::FindFlags)
+
+QT_END_NAMESPACE
+
+#endif // ABSTRACTFINDWIDGET_H
diff --git a/tools/shared/findwidget/findwidget.pri b/tools/shared/findwidget/findwidget.pri
new file mode 100644
index 0000000..6e0f58a
--- /dev/null
+++ b/tools/shared/findwidget/findwidget.pri
@@ -0,0 +1,4 @@
+INCLUDEPATH += $$PWD
+HEADERS += $$PWD/abstractfindwidget.h $$PWD/texteditfindwidget.h $$PWD/itemviewfindwidget.h
+SOURCES += $$PWD/abstractfindwidget.cpp $$PWD/texteditfindwidget.cpp $$PWD/itemviewfindwidget.cpp
+RESOURCES += $$PWD/findwidget.qrc
diff --git a/tools/shared/findwidget/findwidget.qrc b/tools/shared/findwidget/findwidget.qrc
new file mode 100644
index 0000000..1d45b25
--- /dev/null
+++ b/tools/shared/findwidget/findwidget.qrc
@@ -0,0 +1,14 @@
+<RCC>
+ <qresource prefix="/trolltech/shared">
+ <file>images/mac/closetab.png</file>
+ <file>images/mac/next.png</file>
+ <file>images/mac/previous.png</file>
+ <file>images/mac/searchfind.png</file>
+ <file>images/win/closetab.png</file>
+ <file>images/win/next.png</file>
+ <file>images/win/previous.png</file>
+ <file>images/win/searchfind.png</file>
+ <file>images/wrap.png</file>
+ </qresource>
+</RCC>
+
diff --git a/tools/shared/findwidget/images/mac/closetab.png b/tools/shared/findwidget/images/mac/closetab.png
new file mode 100644
index 0000000..ab9d669
--- /dev/null
+++ b/tools/shared/findwidget/images/mac/closetab.png
Binary files differ
diff --git a/tools/shared/findwidget/images/mac/next.png b/tools/shared/findwidget/images/mac/next.png
new file mode 100644
index 0000000..a585cab
--- /dev/null
+++ b/tools/shared/findwidget/images/mac/next.png
Binary files differ
diff --git a/tools/shared/findwidget/images/mac/previous.png b/tools/shared/findwidget/images/mac/previous.png
new file mode 100644
index 0000000..612fb34
--- /dev/null
+++ b/tools/shared/findwidget/images/mac/previous.png
Binary files differ
diff --git a/tools/shared/findwidget/images/mac/searchfind.png b/tools/shared/findwidget/images/mac/searchfind.png
new file mode 100644
index 0000000..3561745
--- /dev/null
+++ b/tools/shared/findwidget/images/mac/searchfind.png
Binary files differ
diff --git a/tools/shared/findwidget/images/win/closetab.png b/tools/shared/findwidget/images/win/closetab.png
new file mode 100644
index 0000000..ef9e020
--- /dev/null
+++ b/tools/shared/findwidget/images/win/closetab.png
Binary files differ
diff --git a/tools/shared/findwidget/images/win/next.png b/tools/shared/findwidget/images/win/next.png
new file mode 100644
index 0000000..8df4127
--- /dev/null
+++ b/tools/shared/findwidget/images/win/next.png
Binary files differ
diff --git a/tools/shared/findwidget/images/win/previous.png b/tools/shared/findwidget/images/win/previous.png
new file mode 100644
index 0000000..0780bc2
--- /dev/null
+++ b/tools/shared/findwidget/images/win/previous.png
Binary files differ
diff --git a/tools/shared/findwidget/images/win/searchfind.png b/tools/shared/findwidget/images/win/searchfind.png
new file mode 100644
index 0000000..6ea35e9
--- /dev/null
+++ b/tools/shared/findwidget/images/win/searchfind.png
Binary files differ
diff --git a/tools/shared/findwidget/images/wrap.png b/tools/shared/findwidget/images/wrap.png
new file mode 100644
index 0000000..90f18d9
--- /dev/null
+++ b/tools/shared/findwidget/images/wrap.png
Binary files differ
diff --git a/tools/shared/findwidget/itemviewfindwidget.cpp b/tools/shared/findwidget/itemviewfindwidget.cpp
new file mode 100644
index 0000000..e1f8468
--- /dev/null
+++ b/tools/shared/findwidget/itemviewfindwidget.cpp
@@ -0,0 +1,317 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*! \class ItemViewFindWidget
+
+ \brief A search bar that is commonly added below the searchable item view.
+
+ \internal
+
+ This widget implements a search bar which becomes visible when the user
+ wants to start searching. It is a modern replacement for the commonly used
+ search dialog. It is usually placed below a QAbstractItemView using a QVBoxLayout.
+
+ The QAbstractItemView instance will need to be associated with this class using
+ setItemView().
+
+ The search is incremental and can be set to case sensitive or whole words
+ using buttons available on the search bar.
+
+ The item traversal order should fit QTreeView, QTableView and QListView alike.
+ More complex tree structures will work as well, assuming the branch structure
+ is painted left to the items, without crossing lines.
+
+ \sa QAbstractItemView
+ */
+
+#include "itemviewfindwidget.h"
+
+#include <QtGui/QAbstractItemView>
+#include <QtGui/QCheckBox>
+#include <QtGui/QTreeView>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Constructs a ItemViewFindWidget.
+
+ \a flags is passed to the AbstractFindWidget constructor.
+ \a parent is passed to the QWidget constructor.
+ */
+ItemViewFindWidget::ItemViewFindWidget(FindFlags flags, QWidget *parent)
+ : AbstractFindWidget(flags, parent)
+ , m_itemView(0)
+{
+}
+
+/*!
+ Associates a QAbstractItemView with this find widget. Searches done using this find
+ widget will then apply to the given QAbstractItemView.
+
+ An event filter is set on the QAbstractItemView which intercepts the ESC key while
+ the find widget is active, and uses it to deactivate the find widget.
+
+ If the find widget is already associated with a QAbstractItemView, the event filter
+ is removed from this QAbstractItemView first.
+
+ \a itemView may be NULL.
+ */
+void ItemViewFindWidget::setItemView(QAbstractItemView *itemView)
+{
+ if (m_itemView)
+ m_itemView->removeEventFilter(this);
+
+ m_itemView = itemView;
+
+ if (m_itemView)
+ m_itemView->installEventFilter(this);
+}
+
+/*!
+ \reimp
+ */
+void ItemViewFindWidget::deactivate()
+{
+ if (m_itemView)
+ m_itemView->setFocus();
+
+ AbstractFindWidget::deactivate();
+}
+
+// Sorting is needed to find the start/end of the selection.
+// This is utter black magic. And it is damn slow.
+static bool indexLessThan(const QModelIndex &a, const QModelIndex &b)
+{
+ // First determine the nesting of each index in the tree.
+ QModelIndex aa = a;
+ int aDepth = 0;
+ while (aa.parent() != QModelIndex()) {
+ // As a side effect, check if one of the items is the parent of the other.
+ // Children are always displayed below their parents, so sort them further down.
+ if (aa.parent() == b)
+ return true;
+ aa = aa.parent();
+ aDepth++;
+ }
+ QModelIndex ba = b;
+ int bDepth = 0;
+ while (ba.parent() != QModelIndex()) {
+ if (ba.parent() == a)
+ return false;
+ ba = ba.parent();
+ bDepth++;
+ }
+ // Now find indices at comparable depth.
+ for (aa = a; aDepth > bDepth; aDepth--)
+ aa = aa.parent();
+ for (ba = b; aDepth < bDepth; bDepth--)
+ ba = ba.parent();
+ // If they have the same parent, sort them within a top-to-bottom, left-to-right rectangle.
+ if (aa.parent() == ba.parent()) {
+ if (aa.row() < ba.row())
+ return true;
+ if (aa.row() > ba.row())
+ return false;
+ return aa.column() < ba.column();
+ }
+ // Now try to find indices that have the same grandparent. This ends latest at the root node.
+ while (aa.parent().parent() != ba.parent().parent()) {
+ aa = aa.parent();
+ ba = ba.parent();
+ }
+ // A bigger row is always displayed further down.
+ if (aa.parent().row() < ba.parent().row())
+ return true;
+ if (aa.parent().row() > ba.parent().row())
+ return false;
+ // Here's the trick: a child spawned from a bigger column is displayed further *up*.
+ // That's because the tree lines are on the left and are supposed not to cross each other.
+ // This case is mostly academical, as "all" models spawn children from the first column.
+ return aa.parent().column() > ba.parent().column();
+}
+
+/*!
+ \reimp
+ */
+void ItemViewFindWidget::find(const QString &ttf, bool skipCurrent, bool backward, bool *found, bool *wrapped)
+{
+ if (!m_itemView || !m_itemView->model()->hasChildren())
+ return;
+
+ QModelIndex idx;
+ if (skipCurrent && m_itemView->selectionModel()->hasSelection()) {
+ QModelIndexList il = m_itemView->selectionModel()->selectedIndexes();
+ qSort(il.begin(), il.end(), indexLessThan);
+ idx = backward ? il.first() : il.last();
+ } else {
+ idx = m_itemView->currentIndex();
+ }
+
+ *found = true;
+ QModelIndex newIdx = idx;
+
+ if (!ttf.isEmpty()) {
+ if (newIdx.isValid()) {
+ int column = newIdx.column();
+ if (skipCurrent)
+ if (QTreeView *tv = qobject_cast<QTreeView *>(m_itemView))
+ if (tv->allColumnsShowFocus())
+ column = backward ? 0 : m_itemView->model()->columnCount(newIdx.parent()) - 1;
+ newIdx = findHelper(ttf, skipCurrent, backward,
+ newIdx.parent(), newIdx.row(), column);
+ }
+ if (!newIdx.isValid()) {
+ int row = backward ? m_itemView->model()->rowCount() : 0;
+ int column = backward ? 0 : -1;
+ newIdx = findHelper(ttf, true, backward, m_itemView->rootIndex(), row, column);
+ if (!newIdx.isValid()) {
+ *found = false;
+ newIdx = idx;
+ } else {
+ *wrapped = true;
+ }
+ }
+ }
+
+ if (!isVisible())
+ show();
+
+ m_itemView->setCurrentIndex(newIdx);
+}
+
+// You are not expected to understand the following two functions.
+// The traversal order is described in the indexLessThan() comments above.
+
+static inline bool skipForward(const QAbstractItemModel *model, QModelIndex &parent, int &row, int &column)
+{
+ forever {
+ column++;
+ if (column < model->columnCount(parent))
+ return true;
+ forever {
+ while (--column >= 0) {
+ QModelIndex nIdx = model->index(row, column, parent);
+ if (nIdx.isValid()) {
+ if (model->hasChildren(nIdx)) {
+ row = 0;
+ column = 0;
+ parent = nIdx;
+ return true;
+ }
+ }
+ }
+ if (++row < model->rowCount(parent))
+ break;
+ if (!parent.isValid())
+ return false;
+ row = parent.row();
+ column = parent.column();
+ parent = parent.parent();
+ }
+ }
+}
+
+static inline bool skipBackward(const QAbstractItemModel *model, QModelIndex &parent, int &row, int &column)
+{
+ column--;
+ if (column == -1) {
+ if (--row < 0) {
+ if (!parent.isValid())
+ return false;
+ row = parent.row();
+ column = parent.column();
+ parent = parent.parent();
+ }
+ while (++column < model->columnCount(parent)) {
+ QModelIndex nIdx = model->index(row, column, parent);
+ if (nIdx.isValid()) {
+ if (model->hasChildren(nIdx)) {
+ row = model->rowCount(nIdx) - 1;
+ column = -1;
+ parent = nIdx;
+ }
+ }
+ }
+ column--;
+ }
+ return true;
+}
+
+// QAbstractItemModel::match() does not support backwards searching. Still using it would
+// be just a bit inefficient (not much worse than when no match is found).
+// The bigger problem is that QAbstractItemView does not provide a method to sort a
+// set of indices in traversal order (to find the start and end of the selection).
+// Consequently, we do everything by ourselves to be consistent. Of course, this puts
+// constraints on the allowable visualizations.
+QModelIndex ItemViewFindWidget::findHelper(const QString &textToFind, bool skipCurrent, bool backward,
+ QModelIndex parent, int row, int column)
+{
+ const QAbstractItemModel *model = m_itemView->model();
+ forever {
+ if (skipCurrent) {
+ if (backward) {
+ if (!skipBackward(model, parent, row, column))
+ return QModelIndex();
+ } else {
+ if (!skipForward(model, parent, row, column))
+ return QModelIndex();
+ }
+ }
+
+ QModelIndex idx = model->index(row, column, parent);
+ if (idx.isValid()) {
+ Qt::CaseSensitivity cs = caseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive;
+
+ if (wholeWords()) {
+ QString rx = QLatin1String("\\b") + QRegExp::escape(textToFind) + QLatin1String("\\b");
+ if (idx.data().toString().indexOf(QRegExp(rx, cs)) >= 0)
+ return idx;
+ } else {
+ if (idx.data().toString().indexOf(textToFind, 0, cs) >= 0)
+ return idx;
+ }
+ }
+
+ skipCurrent = true;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/shared/findwidget/itemviewfindwidget.h b/tools/shared/findwidget/itemviewfindwidget.h
new file mode 100644
index 0000000..71bb8f6
--- /dev/null
+++ b/tools/shared/findwidget/itemviewfindwidget.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ITEMVIEWFINDWIDGET_H
+#define ITEMVIEWFINDWIDGET_H
+
+#include "abstractfindwidget.h"
+
+#include <QModelIndex>
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractItemView;
+
+class ItemViewFindWidget : public AbstractFindWidget
+{
+ Q_OBJECT
+
+public:
+ ItemViewFindWidget(FindFlags flags = FindFlags(), QWidget *parent = 0);
+
+ QAbstractItemView *itemView() const
+ { return m_itemView; }
+
+ void setItemView(QAbstractItemView *itemView);
+
+protected:
+ virtual void deactivate();
+ virtual void find(const QString &textToFind, bool skipCurrent, bool backward, bool *found, bool *wrapped);
+
+private:
+ QModelIndex findHelper(const QString &textToFind, bool skipCurrent, bool backward,
+ QModelIndex parent, int row, int column);
+
+ QAbstractItemView *m_itemView;
+};
+
+QT_END_NAMESPACE
+
+#endif // ITEMVIEWFINDWIDGET_H
diff --git a/tools/shared/findwidget/texteditfindwidget.cpp b/tools/shared/findwidget/texteditfindwidget.cpp
new file mode 100644
index 0000000..73100f5
--- /dev/null
+++ b/tools/shared/findwidget/texteditfindwidget.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*! \class TextEditFindWidget
+
+ \brief A search bar that is commonly added below the searchable text.
+
+ \internal
+
+ This widget implements a search bar which becomes visible when the user
+ wants to start searching. It is a modern replacement for the commonly used
+ search dialog. It is usually placed below a QTextEdit using a QVBoxLayout.
+
+ The QTextEdit instance will need to be associated with this class using
+ setTextEdit().
+
+ The search is incremental and can be set to case sensitive or whole words
+ using buttons available on the search bar.
+
+ \sa QTextEdit
+ */
+
+#include "texteditfindwidget.h"
+
+#include <QtGui/QCheckBox>
+#include <QtGui/QTextCursor>
+#include <QtGui/QTextEdit>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Constructs a TextEditFindWidget.
+
+ \a flags is passed to the AbstractFindWidget constructor.
+ \a parent is passed to the QWidget constructor.
+ */
+TextEditFindWidget::TextEditFindWidget(FindFlags flags, QWidget *parent)
+ : AbstractFindWidget(flags, parent)
+ , m_textEdit(0)
+{
+}
+
+/*!
+ Associates a QTextEdit with this find widget. Searches done using this find
+ widget will then apply to the given QTextEdit.
+
+ An event filter is set on the QTextEdit which intercepts the ESC key while
+ the find widget is active, and uses it to deactivate the find widget.
+
+ If the find widget is already associated with a QTextEdit, the event filter
+ is removed from this QTextEdit first.
+
+ \a textEdit may be NULL.
+ */
+void TextEditFindWidget::setTextEdit(QTextEdit *textEdit)
+{
+ if (m_textEdit)
+ m_textEdit->removeEventFilter(this);
+
+ m_textEdit = textEdit;
+
+ if (m_textEdit)
+ m_textEdit->installEventFilter(this);
+}
+
+/*!
+ \reimp
+ */
+void TextEditFindWidget::deactivate()
+{
+ // Pass focus to the text edit
+ if (m_textEdit)
+ m_textEdit->setFocus();
+
+ AbstractFindWidget::deactivate();
+}
+
+/*!
+ \reimp
+ */
+void TextEditFindWidget::find(const QString &ttf, bool skipCurrent, bool backward, bool *found, bool *wrapped)
+{
+ if (!m_textEdit)
+ return;
+
+ QTextCursor cursor = m_textEdit->textCursor();
+ QTextDocument *doc = m_textEdit->document();
+
+ if (!doc || cursor.isNull())
+ return;
+
+ if (cursor.hasSelection())
+ cursor.setPosition((skipCurrent && !backward) ? cursor.position() : cursor.anchor());
+
+ *found = true;
+ QTextCursor newCursor = cursor;
+
+ if (!ttf.isEmpty()) {
+ QTextDocument::FindFlags options;
+
+ if (backward)
+ options |= QTextDocument::FindBackward;
+
+ if (caseSensitive())
+ options |= QTextDocument::FindCaseSensitively;
+
+ if (wholeWords())
+ options |= QTextDocument::FindWholeWords;
+
+ newCursor = doc->find(ttf, cursor, options);
+ if (newCursor.isNull()) {
+ QTextCursor ac(doc);
+ ac.movePosition(options & QTextDocument::FindBackward
+ ? QTextCursor::End : QTextCursor::Start);
+ newCursor = doc->find(ttf, ac, options);
+ if (newCursor.isNull()) {
+ *found = false;
+ newCursor = cursor;
+ } else {
+ *wrapped = true;
+ }
+ }
+ }
+
+ if (!isVisible())
+ show();
+
+ m_textEdit->setTextCursor(newCursor);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/shared/findwidget/texteditfindwidget.h b/tools/shared/findwidget/texteditfindwidget.h
new file mode 100644
index 0000000..4074ff0
--- /dev/null
+++ b/tools/shared/findwidget/texteditfindwidget.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TEXTEDITFINDWIDGET_H
+#define TEXTEDITFINDWIDGET_H
+
+#include "abstractfindwidget.h"
+
+QT_BEGIN_NAMESPACE
+
+class QTextEdit;
+
+class TextEditFindWidget : public AbstractFindWidget
+{
+ Q_OBJECT
+
+public:
+ TextEditFindWidget(FindFlags flags = FindFlags(), QWidget *parent = 0);
+
+ QTextEdit *textEdit() const
+ { return m_textEdit; }
+
+ void setTextEdit(QTextEdit *textEdit);
+
+protected:
+ virtual void deactivate();
+ virtual void find(const QString &textToFind, bool skipCurrent, bool backward, bool *found, bool *wrapped);
+
+private:
+ QTextEdit *m_textEdit;
+};
+
+QT_END_NAMESPACE
+
+#endif // TEXTEDITFINDWIDGET_H