From c41c4d971bb17ac1596a684760717a8f449cad8f Mon Sep 17 00:00:00 2001
From: con <qtc-committer@nokia.com>
Date: Thu, 13 Jan 2011 17:34:41 +0100
Subject: [PATCH] Show wrap indicator when searching in text edits.

Adds a showWrapIndicator(parent) method to IFindSupport, to be used by
implementations. First implementation is given for the BaseFindSupport
that's used for all searches in Q(Plain)TextEdits.

Task-number: QTCREATORBUG-2753
---
 src/plugins/find/basetextfind.cpp         |  38 ++++++--
 src/plugins/find/basetextfind.h           |   3 +-
 src/plugins/find/find.pro                 |   3 +-
 src/plugins/find/find.qrc                 |   3 +-
 src/plugins/find/ifindsupport.cpp         | 102 ++++++++++++++++++++++
 src/plugins/find/ifindsupport.h           |   2 +
 src/plugins/find/images/wrapindicator.png | Bin 0 -> 1949 bytes
 7 files changed, 143 insertions(+), 8 deletions(-)
 create mode 100644 src/plugins/find/ifindsupport.cpp
 create mode 100644 src/plugins/find/images/wrapindicator.png

diff --git a/src/plugins/find/basetextfind.cpp b/src/plugins/find/basetextfind.cpp
index 9b3a3c2293..ea24a66729 100644
--- a/src/plugins/find/basetextfind.cpp
+++ b/src/plugins/find/basetextfind.cpp
@@ -50,26 +50,32 @@ struct BaseTextFindPrivate {
 
     QPointer<QTextEdit> m_editor;
     QPointer<QPlainTextEdit> m_plaineditor;
+    QPointer<QWidget> m_widget;
     QTextCursor m_findScopeStart;
     QTextCursor m_findScopeEnd;
     int m_findScopeVerticalBlockSelectionFirstColumn;
     int m_findScopeVerticalBlockSelectionLastColumn;
     int m_incrementalStartPos;
+    bool m_incrementalWrappedState;
 };
 
 BaseTextFindPrivate::BaseTextFindPrivate(QTextEdit *editor)
     : m_editor(editor)
+    , m_widget(editor)
     , m_findScopeVerticalBlockSelectionFirstColumn(-1)
     , m_findScopeVerticalBlockSelectionLastColumn(-1)
     , m_incrementalStartPos(-1)
+    , m_incrementalWrappedState(false)
 {
 }
 
 BaseTextFindPrivate::BaseTextFindPrivate(QPlainTextEdit *editor)
     : m_plaineditor(editor)
+    , m_widget(editor)
     , m_findScopeVerticalBlockSelectionFirstColumn(-1)
     , m_findScopeVerticalBlockSelectionLastColumn(-1)
     , m_incrementalStartPos(-1)
+    , m_incrementalWrappedState(false)
 {
 }
 
@@ -127,6 +133,7 @@ Find::FindFlags BaseTextFind::supportedFindFlags() const
 void BaseTextFind::resetIncrementalSearch()
 {
     d->m_incrementalStartPos = -1;
+    d->m_incrementalWrappedState = false;
 }
 
 void BaseTextFind::clearResults()
@@ -174,7 +181,13 @@ IFindSupport::Result BaseTextFind::findIncremental(const QString &txt, Find::Fin
     if (d->m_incrementalStartPos < 0)
         d->m_incrementalStartPos = cursor.selectionStart();
     cursor.setPosition(d->m_incrementalStartPos);
-    bool found =  find(txt, findFlags, cursor);
+    bool wrapped = false;
+    bool found =  find(txt, findFlags, cursor, &wrapped);
+    if (wrapped != d->m_incrementalWrappedState) {
+        d->m_incrementalWrappedState = wrapped;
+        if (found)
+                showWrapIndicator(d->m_widget);
+    }
     if (found)
         emit highlightAll(txt, findFlags);
     else
@@ -184,9 +197,14 @@ IFindSupport::Result BaseTextFind::findIncremental(const QString &txt, Find::Fin
 
 IFindSupport::Result BaseTextFind::findStep(const QString &txt, Find::FindFlags findFlags)
 {
-    bool found = find(txt, findFlags, textCursor());
-    if (found)
+    bool wrapped = false;
+    bool found = find(txt, findFlags, textCursor(), &wrapped);
+    if (wrapped)
+        showWrapIndicator(d->m_widget);
+    if (found) {
         d->m_incrementalStartPos = textCursor().selectionStart();
+        d->m_incrementalWrappedState = false;
+    }
     return found ? Found : NotFound;
 }
 
@@ -220,7 +238,11 @@ bool BaseTextFind::replaceStep(const QString &before, const QString &after,
     Find::FindFlags findFlags)
 {
     QTextCursor cursor = replaceInternal(before, after, findFlags);
-    return find(before, findFlags, cursor);
+    bool wrapped = false;
+    bool found = find(before, findFlags, cursor, &wrapped);
+    if (wrapped)
+        showWrapIndicator(d->m_widget);
+    return found;
 }
 
 int BaseTextFind::replaceAll(const QString &before, const QString &after,
@@ -254,7 +276,7 @@ int BaseTextFind::replaceAll(const QString &before, const QString &after,
 
 bool BaseTextFind::find(const QString &txt,
                                Find::FindFlags findFlags,
-                               QTextCursor start)
+                               QTextCursor start, bool *wrapped)
 {
     if (txt.isEmpty()) {
         setTextCursor(start);
@@ -264,11 +286,15 @@ bool BaseTextFind::find(const QString &txt,
     regexp.setPatternSyntax((findFlags&Find::FindRegularExpression) ? QRegExp::RegExp : QRegExp::FixedString);
     regexp.setCaseSensitivity((findFlags&Find::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive);
     QTextCursor found = findOne(regexp, start, Find::textDocumentFlagsForFindFlags(findFlags));
+    if (wrapped)
+        *wrapped = false;
 
     if (!d->m_findScopeStart.isNull()) {
 
         // scoped
         if (found.isNull() || !inScope(found.selectionStart(), found.selectionEnd())) {
+            if (wrapped)
+                *wrapped = true;
             if ((findFlags&Find::FindBackward) == 0)
                 start.setPosition(d->m_findScopeStart.position());
             else
@@ -281,6 +307,8 @@ bool BaseTextFind::find(const QString &txt,
 
         // entire document
         if (found.isNull()) {
+            if (wrapped)
+                *wrapped = true;
             if ((findFlags&Find::FindBackward) == 0)
                 start.movePosition(QTextCursor::Start);
             else
diff --git a/src/plugins/find/basetextfind.h b/src/plugins/find/basetextfind.h
index 69a9225664..e61d171b01 100644
--- a/src/plugins/find/basetextfind.h
+++ b/src/plugins/find/basetextfind.h
@@ -85,7 +85,8 @@ signals:
 private:
     bool find(const QString &txt,
               Find::FindFlags findFlags,
-              QTextCursor start);
+              QTextCursor start,
+              bool *wrapped);
     QTextCursor replaceInternal(const QString &before, const QString &after,
                                 Find::FindFlags findFlags);
 
diff --git a/src/plugins/find/find.pro b/src/plugins/find/find.pro
index c0c93d3625..ba9f99fcf2 100644
--- a/src/plugins/find/find.pro
+++ b/src/plugins/find/find.pro
@@ -28,7 +28,8 @@ SOURCES += findtoolwindow.cpp \
     searchresulttreemodel.cpp \
     searchresulttreeview.cpp \
     searchresultwindow.cpp \
-    ifindfilter.cpp
+    ifindfilter.cpp \
+    ifindsupport.cpp
 FORMS += findwidget.ui \
     finddialog.ui
 RESOURCES += find.qrc
diff --git a/src/plugins/find/find.qrc b/src/plugins/find/find.qrc
index 2461cde7be..52d7a810bf 100644
--- a/src/plugins/find/find.qrc
+++ b/src/plugins/find/find.qrc
@@ -1,8 +1,9 @@
 <RCC>
-    <qresource prefix="/find" >
+    <qresource prefix="/find">
         <file>images/casesensitively.png</file>
         <file>images/wholewords.png</file>
         <file>images/regexp.png</file>
         <file>images/expand.png</file>
+        <file>images/wrapindicator.png</file>
     </qresource>
 </RCC>
diff --git a/src/plugins/find/ifindsupport.cpp b/src/plugins/find/ifindsupport.cpp
new file mode 100644
index 0000000000..4eb5ac2796
--- /dev/null
+++ b/src/plugins/find/ifindsupport.cpp
@@ -0,0 +1,102 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "ifindsupport.h"
+
+#include <QtCore/QTimer>
+#include <QtCore/QPropertyAnimation>
+#include <QtGui/QWidget>
+#include <QtGui/QPaintEvent>
+#include <QtGui/QPainter>
+
+namespace Find {
+namespace Internal {
+
+class WrapIndicator : public QWidget
+{
+    Q_OBJECT
+    Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity USER true)
+
+public:
+    WrapIndicator(QWidget *parent = 0)
+        : QWidget(parent),
+          m_opacity(1.0)
+    {
+        if (parent)
+            setGeometry(QRect(parent->rect().center() - QPoint(25, 25),
+                              parent->rect().center() + QPoint(25, 25)));
+    }
+
+    qreal opacity() const { return m_opacity; }
+    void setOpacity(qreal value) { m_opacity = value; update(); }
+
+    void run()
+    {
+        show();
+        QTimer::singleShot(300, this, SLOT(runInternal()));
+    }
+
+protected:
+    void paintEvent(QPaintEvent *)
+    {
+        static QPixmap foreground(QLatin1String(":/find/images/wrapindicator.png"));
+        QPainter p(this);
+        p.setOpacity(m_opacity);
+        p.drawPixmap(rect(), foreground);
+    }
+
+private slots:
+    void runInternal()
+    {
+        QPropertyAnimation *anim = new QPropertyAnimation(this, "opacity", this);
+        anim->setDuration(200);
+        anim->setEndValue(0.);
+        connect(anim, SIGNAL(finished()), this, SLOT(deleteLater()));
+        anim->start(QAbstractAnimation::DeleteWhenStopped);
+    }
+
+private:
+    qreal m_opacity;
+};
+
+} // Internal
+} // Find
+
+using namespace Find;
+
+void IFindSupport::showWrapIndicator(QWidget *parent)
+{
+    (new Internal::WrapIndicator(parent))->run();
+}
+
+#include "ifindsupport.moc"
diff --git a/src/plugins/find/ifindsupport.h b/src/plugins/find/ifindsupport.h
index b9fa85dffb..5ca361a8d3 100644
--- a/src/plugins/find/ifindsupport.h
+++ b/src/plugins/find/ifindsupport.h
@@ -73,6 +73,8 @@ public:
     virtual void defineFindScope(){}
     virtual void clearFindScope(){}
 
+    static void showWrapIndicator(QWidget *parent);
+
 signals:
     void changed();
 };
diff --git a/src/plugins/find/images/wrapindicator.png b/src/plugins/find/images/wrapindicator.png
new file mode 100644
index 0000000000000000000000000000000000000000..a4f8ddf41779e8e845dc9eabfbccb864bc4f593e
GIT binary patch
literal 1949
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
Se`8=^VDNPHb6Mw<&;$VPjgm_M

literal 0
HcmV?d00001

-- 
GitLab