OSDN Git Service

It's 2011 now.
[qt-creator-jp/qt-creator-jp.git] / src / plugins / find / findtoolbar.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "findtoolbar.h"
35 #include "findplugin.h"
36 #include "textfindconstants.h"
37
38 #include <coreplugin/coreconstants.h>
39 #include <coreplugin/icontext.h>
40 #include <coreplugin/icore.h>
41 #include <coreplugin/actionmanager/actionmanager.h>
42 #include <coreplugin/actionmanager/actioncontainer.h>
43 #include <coreplugin/actionmanager/command.h>
44 #include <coreplugin/findplaceholder.h>
45 #include <coreplugin/uniqueidmanager.h>
46
47 #include <extensionsystem/pluginmanager.h>
48
49 #include <utils/stylehelper.h>
50
51 #include <QtCore/QDebug>
52 #include <QtCore/QSettings>
53
54 #include <QtGui/QClipboard>
55 #include <QtGui/QCompleter>
56 #include <QtGui/QKeyEvent>
57 #include <QtGui/QLineEdit>
58 #include <QtGui/QMenu>
59 #include <QtGui/QPushButton>
60 #include <QtGui/QToolButton>
61 #include <QtGui/QPainter>
62 #include <QtGui/QPixmapCache>
63 #include <QtGui/QStringListModel>
64
65 Q_DECLARE_METATYPE(QStringList)
66 Q_DECLARE_METATYPE(Find::IFindFilter*)
67
68 using namespace Find;
69 using namespace Find::Internal;
70
71 FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumentFind)
72     : m_plugin(plugin),
73       m_currentDocumentFind(currentDocumentFind),
74       m_findCompleter(new QCompleter(this)),
75       m_replaceCompleter(new QCompleter(this)),
76       m_enterFindStringAction(0),
77       m_findNextAction(0),
78       m_findPreviousAction(0),
79       m_replaceAction(0),
80       m_replaceNextAction(0),
81       m_replacePreviousAction(0),
82       m_casesensitiveIcon(":/find/images/casesensitively.png"),
83       m_regexpIcon(":/find/images/regexp.png"),
84       m_wholewordsIcon(":/find/images/wholewords.png"),
85       m_findIncrementalTimer(this), m_findStepTimer(this),
86       m_useFakeVim(false),
87       m_eventFiltersInstalled(false)
88 {
89     //setup ui
90     m_ui.setupUi(this);
91     setFocusProxy(m_ui.findEdit);
92     setProperty("topBorder", true);
93     setSingleRow(false);
94     m_ui.findEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
95     m_ui.replaceEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
96
97     connect(m_ui.findEdit, SIGNAL(editingFinished()), this, SLOT(invokeResetIncrementalSearch()));
98
99     m_ui.close->setIcon(QIcon(QLatin1String(Core::Constants::ICON_CLOSE)));
100     connect(m_ui.close, SIGNAL(clicked()), this, SLOT(hideAndResetFocus()));
101
102     m_findCompleter->setModel(m_plugin->findCompletionModel());
103     m_replaceCompleter->setModel(m_plugin->replaceCompletionModel());
104     m_ui.findEdit->setCompleter(m_findCompleter);
105     m_ui.replaceEdit->setCompleter(m_replaceCompleter);
106
107     QMenu *lineEditMenu = new QMenu(m_ui.findEdit);
108     m_ui.findEdit->setButtonMenu(Utils::FancyLineEdit::Left, lineEditMenu);
109     m_ui.findEdit->setButtonVisible(Utils::FancyLineEdit::Left, true);
110     m_ui.findEdit->setPlaceholderText(QString());
111     m_ui.replaceEdit->setPlaceholderText(QString());
112
113     connect(m_ui.findEdit, SIGNAL(textChanged(const QString&)), this, SLOT(invokeFindIncremental()));
114     connect(m_ui.findEdit, SIGNAL(returnPressed()), this, SLOT(invokeFindEnter()));
115     connect(m_ui.replaceEdit, SIGNAL(returnPressed()), this, SLOT(invokeReplaceEnter()));
116
117     QAction *shiftEnterAction = new QAction(m_ui.findEdit);
118     shiftEnterAction->setShortcut(QKeySequence("Shift+Enter"));
119     shiftEnterAction->setShortcutContext(Qt::WidgetShortcut);
120     connect(shiftEnterAction, SIGNAL(triggered()), this, SLOT(invokeFindPrevious()));
121     m_ui.findEdit->addAction(shiftEnterAction);
122     QAction *shiftReturnAction = new QAction(m_ui.findEdit);
123     shiftReturnAction->setShortcut(QKeySequence("Shift+Return"));
124     shiftReturnAction->setShortcutContext(Qt::WidgetShortcut);
125     connect(shiftReturnAction, SIGNAL(triggered()), this, SLOT(invokeFindPrevious()));
126     m_ui.findEdit->addAction(shiftReturnAction);
127
128     QAction *shiftEnterReplaceAction = new QAction(m_ui.replaceEdit);
129     shiftEnterReplaceAction->setShortcut(QKeySequence("Shift+Enter"));
130     shiftEnterReplaceAction->setShortcutContext(Qt::WidgetShortcut);
131     connect(shiftEnterReplaceAction, SIGNAL(triggered()), this, SLOT(invokeReplacePrevious()));
132     m_ui.replaceEdit->addAction(shiftEnterReplaceAction);
133     QAction *shiftReturnReplaceAction = new QAction(m_ui.replaceEdit);
134     shiftReturnReplaceAction->setShortcut(QKeySequence("Shift+Return"));
135     shiftReturnReplaceAction->setShortcutContext(Qt::WidgetShortcut);
136     connect(shiftReturnReplaceAction, SIGNAL(triggered()), this, SLOT(invokeReplacePrevious()));
137     m_ui.replaceEdit->addAction(shiftReturnReplaceAction);
138
139     // need to make sure QStringList is registered as metatype
140     QMetaTypeId<QStringList>::qt_metatype_id();
141
142     // register actions
143     Core::Context globalcontext(Core::Constants::C_GLOBAL);
144     Core::ActionManager *am = Core::ICore::instance()->actionManager();
145     Core::ActionContainer *mfind = am->actionContainer(Constants::M_FIND);
146     Core::Command *cmd;
147
148     m_ui.advancedButton->setDefaultAction(am->command(Constants::ADVANCED_FIND)->action());
149
150     QIcon icon = QIcon::fromTheme(QLatin1String("edit-find-replace"));
151     m_findInDocumentAction = new QAction(icon, tr("Find/Replace"), this);
152     cmd = am->registerAction(m_findInDocumentAction, Constants::FIND_IN_DOCUMENT, globalcontext);
153     cmd->setDefaultKeySequence(QKeySequence::Find);
154     mfind->addAction(cmd, Constants::G_FIND_CURRENTDOCUMENT);
155     connect(m_findInDocumentAction, SIGNAL(triggered()), this, SLOT(openFind()));
156
157     if (QApplication::clipboard()->supportsFindBuffer()) {
158         m_enterFindStringAction = new QAction(tr("Enter Find String"), this);
159         cmd = am->registerAction(m_enterFindStringAction, "Find.EnterFindString", globalcontext);
160         cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E")));
161         mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
162         connect(m_enterFindStringAction, SIGNAL(triggered()), this, SLOT(putSelectionToFindClipboard()));
163         connect(QApplication::clipboard(), SIGNAL(findBufferChanged()), this, SLOT(updateFromFindClipboard()));
164     }
165
166     m_findNextAction = new QAction(tr("Find Next"), this);
167     cmd = am->registerAction(m_findNextAction, Constants::FIND_NEXT, globalcontext);
168     cmd->setDefaultKeySequence(QKeySequence::FindNext);
169     mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
170     connect(m_findNextAction, SIGNAL(triggered()), this, SLOT(invokeFindNext()));
171     m_ui.findNextButton->setDefaultAction(cmd->action());
172
173     m_findPreviousAction = new QAction(tr("Find Previous"), this);
174     cmd = am->registerAction(m_findPreviousAction, Constants::FIND_PREVIOUS, globalcontext);
175     cmd->setDefaultKeySequence(QKeySequence::FindPrevious);
176     mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
177     connect(m_findPreviousAction, SIGNAL(triggered()), this, SLOT(invokeFindPrevious()));
178     m_ui.findPreviousButton->setDefaultAction(cmd->action());
179
180     m_replaceAction = new QAction(tr("Replace"), this);
181     cmd = am->registerAction(m_replaceAction, Constants::REPLACE, globalcontext);
182     cmd->setDefaultKeySequence(QKeySequence());
183     mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
184     connect(m_replaceAction, SIGNAL(triggered()), this, SLOT(invokeReplace()));
185     m_ui.replaceButton->setDefaultAction(cmd->action());
186
187     m_replaceNextAction = new QAction(tr("Replace && Find"), this);
188     m_replaceNextAction->setIconText(tr("Replace && Find")); // work around bug in Qt that kills ampersands in tool button
189     cmd = am->registerAction(m_replaceNextAction, Constants::REPLACE_NEXT, globalcontext);
190     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+=")));
191     mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
192     connect(m_replaceNextAction, SIGNAL(triggered()), this, SLOT(invokeReplaceNext()));
193     m_ui.replaceNextButton->setDefaultAction(cmd->action());
194
195     m_replacePreviousAction = new QAction(tr("Replace && Find Previous"), this);
196     cmd = am->registerAction(m_replacePreviousAction, Constants::REPLACE_PREVIOUS, globalcontext);
197     // shortcut removed, clashes with Ctrl++ on many keyboard layouts
198     //cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+=")));
199     mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
200     connect(m_replacePreviousAction, SIGNAL(triggered()), this, SLOT(invokeReplacePrevious()));
201
202     m_replaceAllAction = new QAction(tr("Replace All"), this);
203     cmd = am->registerAction(m_replaceAllAction, Constants::REPLACE_ALL, globalcontext);
204     mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
205     connect(m_replaceAllAction, SIGNAL(triggered()), this, SLOT(invokeReplaceAll()));
206     m_ui.replaceAllButton->setDefaultAction(cmd->action());
207
208     m_caseSensitiveAction = new QAction(tr("Case Sensitive"), this);
209     m_caseSensitiveAction->setIcon(QIcon(QLatin1String(":/find/images/casesensitively.png")));
210     m_caseSensitiveAction->setCheckable(true);
211     m_caseSensitiveAction->setChecked(false);
212     cmd = am->registerAction(m_caseSensitiveAction, Constants::CASE_SENSITIVE, globalcontext);
213     mfind->addAction(cmd, Constants::G_FIND_FLAGS);
214     connect(m_caseSensitiveAction, SIGNAL(triggered(bool)), this, SLOT(setCaseSensitive(bool)));
215     lineEditMenu->addAction(m_caseSensitiveAction);
216
217     m_wholeWordAction = new QAction(tr("Whole Words Only"), this);
218     m_wholeWordAction->setIcon(QIcon(QLatin1String(":/find/images/wholewords.png")));
219     m_wholeWordAction->setCheckable(true);
220     m_wholeWordAction->setChecked(false);
221     cmd = am->registerAction(m_wholeWordAction, Constants::WHOLE_WORDS, globalcontext);
222     mfind->addAction(cmd, Constants::G_FIND_FLAGS);
223     connect(m_wholeWordAction, SIGNAL(triggered(bool)), this, SLOT(setWholeWord(bool)));
224     lineEditMenu->addAction(m_wholeWordAction);
225
226     m_regularExpressionAction = new QAction(tr("Use Regular Expressions"), this);
227     m_regularExpressionAction->setIcon(QIcon(QLatin1String(":/find/images/regexp.png")));
228     m_regularExpressionAction->setCheckable(true);
229     m_regularExpressionAction->setChecked(false);
230     cmd = am->registerAction(m_regularExpressionAction, Constants::REGULAR_EXPRESSIONS, globalcontext);
231     mfind->addAction(cmd, Constants::G_FIND_FLAGS);
232     connect(m_regularExpressionAction, SIGNAL(triggered(bool)), this, SLOT(setRegularExpressions(bool)));
233     lineEditMenu->addAction(m_regularExpressionAction);
234
235     connect(m_currentDocumentFind, SIGNAL(candidateChanged()), this, SLOT(adaptToCandidate()));
236     connect(m_currentDocumentFind, SIGNAL(changed()), this, SLOT(updateToolBar()));
237     updateToolBar();
238
239     m_findIncrementalTimer.setSingleShot(true);
240     m_findStepTimer.setSingleShot(true);
241     connect(&m_findIncrementalTimer, SIGNAL(timeout()),
242             this, SLOT(invokeFindIncremental()));
243     connect(&m_findStepTimer, SIGNAL(timeout()), this, SLOT(invokeFindStep()));
244 }
245
246 FindToolBar::~FindToolBar()
247 {
248 }
249
250 void FindToolBar::installEventFilters()
251 {
252     if (!m_eventFiltersInstalled) {
253         m_findCompleter->popup()->installEventFilter(this);
254         m_ui.findEdit->installEventFilter(this);
255         m_ui.replaceEdit->installEventFilter(this);
256         this->installEventFilter(this);
257         m_eventFiltersInstalled = true;
258     }
259 }
260
261 bool FindToolBar::eventFilter(QObject *obj, QEvent *event)
262 {
263     if (event->type() == QEvent::KeyPress) {
264         QKeyEvent *ke = static_cast<QKeyEvent *>(event);
265         if (ke->key() == Qt::Key_Down) {
266             if (obj == m_ui.findEdit)
267                 m_findCompleter->complete();
268             else if (obj == m_ui.replaceEdit)
269                 m_replaceCompleter->complete();
270         }
271     }
272
273     if ((obj == m_ui.findEdit || obj == m_findCompleter->popup())
274                && event->type() == QEvent::KeyPress) {
275         QKeyEvent *ke = static_cast<QKeyEvent *>(event);
276 #ifdef Q_WS_MAC
277         if (ke->key() == Qt::Key_Space && (ke->modifiers() & Qt::MetaModifier)) {
278 #else
279         if (ke->key() == Qt::Key_Space && (ke->modifiers() & Qt::ControlModifier)) {
280 #endif
281             QString completedText = m_currentDocumentFind->completedFindString();
282             if (!completedText.isEmpty()) {
283                 setFindText(completedText);
284                 ke->accept();
285                 return true;
286             }
287         }
288     } else if (obj == this && event->type() == QEvent::ShortcutOverride) {
289         QKeyEvent *ke = static_cast<QKeyEvent *>(event);
290         if (ke->key() == Qt::Key_Escape && !ke->modifiers()
291                 && !m_findCompleter->popup()->isVisible()
292                 && !m_replaceCompleter->popup()->isVisible()) {
293             if (setFocusToCurrentFindSupport()) {
294                 event->accept();
295                 return true;
296             }
297 #ifdef Q_WS_MAC
298         } else if (ke->key() == Qt::Key_Space && (ke->modifiers() & Qt::MetaModifier)) {
299 #else
300         } else if (ke->key() == Qt::Key_Space && (ke->modifiers() & Qt::ControlModifier)) {
301 #endif
302             event->accept();
303             return true;
304         }
305     } else if (obj == this && event->type() == QEvent::Hide) {
306         invokeClearResults();
307         if (m_currentDocumentFind->isEnabled()) {
308             m_currentDocumentFind->clearFindScope();
309         }
310     }
311     return Utils::StyledBar::eventFilter(obj, event);
312 }
313
314 void FindToolBar::adaptToCandidate()
315 {
316     updateFindAction();
317     if (findToolBarPlaceHolder() == Core::FindToolBarPlaceHolder::getCurrent()) {
318         m_currentDocumentFind->acceptCandidate();
319     }
320 }
321
322 void FindToolBar::updateFindAction()
323 {
324     m_findInDocumentAction->setEnabled(m_currentDocumentFind->candidateIsEnabled());
325 }
326
327 void FindToolBar::updateToolBar()
328 {
329     bool enabled = m_currentDocumentFind->isEnabled();
330     bool replaceEnabled = enabled && m_currentDocumentFind->supportsReplace();
331     m_findNextAction->setEnabled(enabled);
332     m_findPreviousAction->setEnabled(enabled);
333
334     m_replaceAction->setEnabled(replaceEnabled);
335     m_replaceNextAction->setEnabled(replaceEnabled);
336     m_replacePreviousAction->setEnabled(replaceEnabled);
337     m_replaceAllAction->setEnabled(replaceEnabled);
338
339     m_caseSensitiveAction->setEnabled(enabled);
340     m_wholeWordAction->setEnabled(enabled);
341     m_regularExpressionAction->setEnabled(enabled);
342     if (QApplication::clipboard()->supportsFindBuffer())
343         m_enterFindStringAction->setEnabled(enabled);
344     bool replaceFocus = m_ui.replaceEdit->hasFocus();
345     m_ui.findEdit->setEnabled(enabled);
346     m_ui.findLabel->setEnabled(enabled);
347
348     m_ui.replaceEdit->setEnabled(replaceEnabled);
349     m_ui.replaceLabel->setEnabled(replaceEnabled);
350     m_ui.replaceEdit->setVisible(replaceEnabled);
351     m_ui.replaceLabel->setVisible(replaceEnabled);
352     m_ui.replaceButton->setVisible(replaceEnabled);
353     m_ui.replaceNextButton->setVisible(replaceEnabled);
354     m_ui.replaceAllButton->setVisible(replaceEnabled);
355     m_ui.advancedButton->setVisible(replaceEnabled);
356     layout()->invalidate();
357
358     if (!replaceEnabled && enabled && replaceFocus)
359         m_ui.findEdit->setFocus();
360     updateIcons();
361     updateFlagMenus();
362 }
363
364 void FindToolBar::invokeFindEnter()
365 {
366     if (m_currentDocumentFind->isEnabled()) {
367         if (m_useFakeVim)
368             setFocusToCurrentFindSupport();
369         else
370             invokeFindNext();
371     }
372 }
373
374 void FindToolBar::invokeReplaceEnter()
375 {
376     if (m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace()) {
377         invokeReplaceNext();
378     }
379 }
380
381 void FindToolBar::invokeClearResults()
382 {
383     if (m_currentDocumentFind->isEnabled()) {
384         m_currentDocumentFind->clearResults();
385     }
386 }
387
388
389 void FindToolBar::invokeFindNext()
390 {
391     setFindFlag(Find::FindBackward, false);
392     invokeFindStep();
393 }
394
395 void FindToolBar::invokeFindPrevious()
396 {
397     setFindFlag(Find::FindBackward, true);
398     invokeFindStep();
399 }
400
401 QString FindToolBar::getFindText()
402 {
403     return m_ui.findEdit->text();
404 }
405
406 QString FindToolBar::getReplaceText()
407 {
408     return m_ui.replaceEdit->text();
409 }
410
411 void FindToolBar::setFindText(const QString &text)
412 {
413     disconnect(m_ui.findEdit, SIGNAL(textChanged(const QString&)), this, SLOT(invokeFindIncremental()));
414     if (hasFindFlag(Find::FindRegularExpression))
415         m_ui.findEdit->setText(QRegExp::escape(text));
416     else
417         m_ui.findEdit->setText(text);
418     connect(m_ui.findEdit, SIGNAL(textChanged(const QString&)), this, SLOT(invokeFindIncremental()));
419 }
420
421 void FindToolBar::selectFindText()
422 {
423     m_ui.findEdit->selectAll();
424 }
425
426 void FindToolBar::invokeFindStep()
427 {
428     m_findStepTimer.stop();
429     m_findIncrementalTimer.stop();
430     if (m_currentDocumentFind->isEnabled()) {
431         m_plugin->updateFindCompletion(getFindText());
432         IFindSupport::Result result =
433             m_currentDocumentFind->findStep(getFindText(), effectiveFindFlags());
434         if (result == IFindSupport::NotYetFound)
435             m_findStepTimer.start(50);
436     }
437 }
438
439 void FindToolBar::invokeFindIncremental()
440 {
441     m_findIncrementalTimer.stop();
442     m_findStepTimer.stop();
443     if (m_currentDocumentFind->isEnabled()) {
444         QString text = getFindText();
445         IFindSupport::Result result =
446             m_currentDocumentFind->findIncremental(text, effectiveFindFlags());
447         if (result == IFindSupport::NotYetFound)
448             m_findIncrementalTimer.start(50);
449         if (text.isEmpty())
450             m_currentDocumentFind->clearResults();
451     }
452 }
453
454 void FindToolBar::invokeReplace()
455 {
456     setFindFlag(Find::FindBackward, false);
457     if (m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace()) {
458         m_plugin->updateFindCompletion(getFindText());
459         m_plugin->updateReplaceCompletion(getReplaceText());
460         m_currentDocumentFind->replace(getFindText(), getReplaceText(), effectiveFindFlags());
461     }
462 }
463
464 void FindToolBar::invokeReplaceNext()
465 {
466     setFindFlag(Find::FindBackward, false);
467     invokeReplaceStep();
468 }
469
470 void FindToolBar::invokeReplacePrevious()
471 {
472     setFindFlag(Find::FindBackward, true);
473     invokeReplaceStep();
474 }
475
476 void FindToolBar::invokeReplaceStep()
477 {
478     if (m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace()) {
479         m_plugin->updateFindCompletion(getFindText());
480         m_plugin->updateReplaceCompletion(getReplaceText());
481         m_currentDocumentFind->replaceStep(getFindText(), getReplaceText(), effectiveFindFlags());
482     }
483 }
484
485 void FindToolBar::invokeReplaceAll()
486 {
487     m_plugin->updateFindCompletion(getFindText());
488     m_plugin->updateReplaceCompletion(getReplaceText());
489     if (m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace()) {
490         m_currentDocumentFind->replaceAll(getFindText(), getReplaceText(), effectiveFindFlags());
491     }
492 }
493
494 void FindToolBar::invokeResetIncrementalSearch()
495 {
496     m_findIncrementalTimer.stop();
497     m_findStepTimer.stop();
498     if (m_currentDocumentFind->isEnabled())
499         m_currentDocumentFind->resetIncrementalSearch();
500 }
501
502
503 void FindToolBar::putSelectionToFindClipboard()
504 {
505     const QString text = m_currentDocumentFind->currentFindString();
506     QApplication::clipboard()->setText(text, QClipboard::FindBuffer);
507     setFindText(text);
508 }
509
510
511 void FindToolBar::updateFromFindClipboard()
512 {
513     if (QApplication::clipboard()->supportsFindBuffer()) {
514         const bool blocks = m_ui.findEdit->blockSignals(true);
515         setFindText(QApplication::clipboard()->text(QClipboard::FindBuffer));
516         m_ui.findEdit->blockSignals(blocks);
517     }
518 }
519
520 void FindToolBar::findFlagsChanged()
521 {
522     updateIcons();
523     updateFlagMenus();
524     invokeClearResults();
525     if (isVisible()) {
526         m_currentDocumentFind->highlightAll(getFindText(), effectiveFindFlags());
527     }
528 }
529
530 void FindToolBar::updateIcons()
531 {
532     Find::FindFlags effectiveFlags = effectiveFindFlags();
533     bool casesensitive = effectiveFlags & Find::FindCaseSensitively;
534     bool wholewords = effectiveFlags & Find::FindWholeWords;
535     bool regexp = effectiveFlags & Find::FindRegularExpression;
536     int width = 0;
537     if (casesensitive) width += 6;
538     if (wholewords) width += 6;
539     if (regexp) width += 6;
540     if (width == 0) width = 18;
541     --width;
542     QPixmap pixmap(width, 17);
543     pixmap.fill(Qt::transparent);
544     QPainter painter(&pixmap);
545     int x = 0;
546
547     if (casesensitive) {
548         painter.drawPixmap(x - 6, 0, m_casesensitiveIcon);
549         x += 6;
550     }
551     if (wholewords) {
552         painter.drawPixmap(x - 6, 0, m_wholewordsIcon);
553         x += 6;
554     }
555     if (regexp) {
556         painter.drawPixmap(x - 6, 0, m_regexpIcon);
557     }
558     if (!casesensitive && !wholewords && !regexp) {
559         QPixmap mag(Core::Constants::ICON_MAGNIFIER);
560         painter.drawPixmap(0, (pixmap.height() - mag.height()) / 2, mag);
561     }
562     m_ui.findEdit->setButtonPixmap(Utils::FancyLineEdit::Left, pixmap);
563 }
564
565 Find::FindFlags FindToolBar::effectiveFindFlags()
566 {
567     Find::FindFlags supportedFlags;
568     if (m_currentDocumentFind->isEnabled())
569         supportedFlags = m_currentDocumentFind->supportedFindFlags();
570     else
571         supportedFlags = (Find::FindFlags)0xFFFFFF;
572     return supportedFlags & m_findFlags;
573 }
574
575 void FindToolBar::updateFlagMenus()
576 {
577     bool wholeOnly = ((m_findFlags & Find::FindWholeWords));
578     bool sensitive = ((m_findFlags & Find::FindCaseSensitively));
579     bool regexp = ((m_findFlags & Find::FindRegularExpression));
580     if (m_wholeWordAction->isChecked() != wholeOnly)
581         m_wholeWordAction->setChecked(wholeOnly);
582     if (m_caseSensitiveAction->isChecked() != sensitive)
583         m_caseSensitiveAction->setChecked(sensitive);
584     if (m_regularExpressionAction->isChecked() != regexp)
585         m_regularExpressionAction->setChecked(regexp);
586     Find::FindFlags supportedFlags;
587     if (m_currentDocumentFind->isEnabled())
588         supportedFlags = m_currentDocumentFind->supportedFindFlags();
589     m_wholeWordAction->setEnabled(supportedFlags & Find::FindWholeWords);
590     m_caseSensitiveAction->setEnabled(supportedFlags & Find::FindCaseSensitively);
591     m_regularExpressionAction->setEnabled(supportedFlags & Find::FindRegularExpression);
592 }
593
594 bool FindToolBar::setFocusToCurrentFindSupport()
595 {
596     return m_currentDocumentFind->setFocusToCurrentFindSupport();
597 }
598
599 void FindToolBar::hideAndResetFocus()
600 {
601     m_currentDocumentFind->setFocusToCurrentFindSupport();
602     hide();
603 }
604
605 Core::FindToolBarPlaceHolder *FindToolBar::findToolBarPlaceHolder() const
606 {
607     QList<Core::FindToolBarPlaceHolder*> placeholders = ExtensionSystem::PluginManager::instance()
608                                                         ->getObjects<Core::FindToolBarPlaceHolder>();
609     QWidget *candidate = QApplication::focusWidget();
610     while (candidate) {
611         foreach (Core::FindToolBarPlaceHolder *ph, placeholders) {
612             if (ph->owner() == candidate)
613                 return ph;
614         }
615         candidate = candidate->parentWidget();
616     }
617     return 0;
618 }
619
620 void FindToolBar::openFind()
621 {
622     setBackward(false);
623     openFindToolBar();
624 }
625
626 void FindToolBar::openFindToolBar()
627 {
628     installEventFilters();
629     if (!m_currentDocumentFind->candidateIsEnabled())
630         return;
631     Core::FindToolBarPlaceHolder *holder = findToolBarPlaceHolder();
632     if (!holder)
633         return;
634     Core::FindToolBarPlaceHolder *previousHolder = Core::FindToolBarPlaceHolder::getCurrent();
635     if (previousHolder)
636         previousHolder->setWidget(0);
637     Core::FindToolBarPlaceHolder::setCurrent(holder);
638     m_currentDocumentFind->acceptCandidate();
639     holder->setWidget(this);
640     holder->setVisible(true);
641     setVisible(true);
642     setFocus();
643     QString text = m_currentDocumentFind->currentFindString();
644     if (!text.isEmpty())
645         setFindText(text);
646     m_currentDocumentFind->defineFindScope();
647     m_currentDocumentFind->highlightAll(getFindText(), effectiveFindFlags());
648     selectFindText();
649 }
650
651 bool FindToolBar::focusNextPrevChild(bool next)
652 {
653     // close tab order change
654     if (next && m_ui.replaceAllButton->hasFocus())
655         m_ui.findEdit->setFocus(Qt::TabFocusReason);
656     else if (!next && m_ui.findEdit->hasFocus())
657         m_ui.replaceAllButton->setFocus(Qt::TabFocusReason);
658     else
659         return Utils::StyledBar::focusNextPrevChild(next);
660     return true;
661 }
662
663 void FindToolBar::writeSettings()
664 {
665     QSettings *settings = Core::ICore::instance()->settings();
666     settings->beginGroup("Find");
667     settings->beginGroup("FindToolBar");
668     settings->setValue("Backward", QVariant((m_findFlags & Find::FindBackward) != 0));
669     settings->setValue("CaseSensitively", QVariant((m_findFlags & Find::FindCaseSensitively) != 0));
670     settings->setValue("WholeWords", QVariant((m_findFlags & Find::FindWholeWords) != 0));
671     settings->setValue("RegularExpression", QVariant((m_findFlags & Find::FindRegularExpression) != 0));
672     settings->endGroup();
673     settings->endGroup();
674 }
675
676 void FindToolBar::readSettings()
677 {
678     QSettings *settings = Core::ICore::instance()->settings();
679     settings->beginGroup("Find");
680     settings->beginGroup("FindToolBar");
681     Find::FindFlags flags;
682     if (settings->value("Backward", false).toBool())
683         flags |= Find::FindBackward;
684     if (settings->value("CaseSensitively", false).toBool())
685         flags |= Find::FindCaseSensitively;
686     if (settings->value("WholeWords", false).toBool())
687         flags |= Find::FindWholeWords;
688     if (settings->value("RegularExpression", false).toBool())
689         flags |= Find::FindRegularExpression;
690     settings->endGroup();
691     settings->endGroup();
692     m_findFlags = flags;
693     findFlagsChanged();
694 }
695
696 void FindToolBar::setUseFakeVim(bool on)
697 {
698     m_useFakeVim = on;
699 }
700
701 void FindToolBar::setFindFlag(Find::FindFlag flag, bool enabled)
702 {
703     bool hasFlag = hasFindFlag(flag);
704     if ((hasFlag && enabled) || (!hasFlag && !enabled))
705         return;
706     if (enabled)
707         m_findFlags |= flag;
708     else
709         m_findFlags &= ~flag;
710     if (flag != Find::FindBackward)
711         findFlagsChanged();
712 }
713
714 bool FindToolBar::hasFindFlag(Find::FindFlag flag)
715 {
716     return m_findFlags & flag;
717 }
718
719 void FindToolBar::setCaseSensitive(bool sensitive)
720 {
721     setFindFlag(Find::FindCaseSensitively, sensitive);
722 }
723
724 void FindToolBar::setWholeWord(bool wholeOnly)
725 {
726     setFindFlag(Find::FindWholeWords, wholeOnly);
727 }
728
729 void FindToolBar::setRegularExpressions(bool regexp)
730 {
731     setFindFlag(Find::FindRegularExpression, regexp);
732 }
733
734 void FindToolBar::setBackward(bool backward)
735 {
736     setFindFlag(Find::FindBackward, backward);
737 }