findtoolbar.cpp 39.2 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8
9
10
11
12
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
Eike Ziller's avatar
Eike Ziller committed
13
14
** conditions see http://www.qt.io/licensing.  For further information
** use the contact form at http://www.qt.io/contact-us.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
** Alternatively, this file may be used under the terms of the GNU Lesser
Eike Ziller's avatar
Eike Ziller committed
18
19
20
21
22
23
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24
**
hjk's avatar
hjk committed
25
26
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
27
28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
29
****************************************************************************/
hjk's avatar
hjk committed
30

con's avatar
con committed
31
#include "findtoolbar.h"
32
#include "ifindfilter.h"
33
#include "findplugin.h"
con's avatar
con committed
34
35

#include <coreplugin/coreconstants.h>
36
#include <coreplugin/coreplugin.h>
37
#include <coreplugin/icore.h>
38
#include <coreplugin/actionmanager/actionmanager.h>
39
#include <coreplugin/actionmanager/actioncontainer.h>
40
41
#include <coreplugin/findplaceholder.h>

42
#include <extensionsystem/pluginmanager.h>
43

44
#include <utils/hostosinfo.h>
45
#include <utils/qtcassert.h>
46
#include <utils/stylehelper.h>
47

48
49
#include <QDebug>
#include <QSettings>
50

51
#include <QCheckBox>
52
53
54
55
56
57
#include <QClipboard>
#include <QCompleter>
#include <QKeyEvent>
#include <QMenu>
#include <QPainter>
#include <QStringListModel>
con's avatar
con committed
58
59

Q_DECLARE_METATYPE(QStringList)
60
Q_DECLARE_METATYPE(Core::IFindFilter*)
con's avatar
con committed
61

62
63
64
static const int MINIMUM_WIDTH_FOR_COMPLEX_LAYOUT = 150;
static const int FINDBUTTON_SPACER_WIDTH = 20;

65
66
using namespace Core;
using namespace Core::Internal;
con's avatar
con committed
67
68
69
70
71
72
73
74
75

FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumentFind)
    : m_plugin(plugin),
      m_currentDocumentFind(currentDocumentFind),
      m_findCompleter(new QCompleter(this)),
      m_replaceCompleter(new QCompleter(this)),
      m_enterFindStringAction(0),
      m_findNextAction(0),
      m_findPreviousAction(0),
76
      m_replaceAction(0),
con's avatar
con committed
77
      m_replaceNextAction(0),
78
      m_replacePreviousAction(0),
79
      m_findIncrementalTimer(this), m_findStepTimer(this),
80
81
      m_useFakeVim(false),
      m_eventFiltersInstalled(false)
con's avatar
con committed
82
83
{
    //setup ui
84
    m_ui.setupUi(this);
85
86
    // compensate for a vertically expanding spacer below the label
    m_ui.replaceLabel->setMinimumHeight(m_ui.replaceEdit->sizeHint().height());
87
88
    m_ui.mainLayout->setColumnStretch(1, 10);

con's avatar
con committed
89
    setFocusProxy(m_ui.findEdit);
con's avatar
con committed
90
    setProperty("topBorder", true);
con's avatar
con committed
91
    setSingleRow(false);
92
93
    m_ui.findEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
    m_ui.replaceEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
con's avatar
con committed
94
95
96

    connect(m_ui.findEdit, SIGNAL(editingFinished()), this, SLOT(invokeResetIncrementalSearch()));

97
    setLightColoredIcon(false);
98
    connect(m_ui.close, SIGNAL(clicked()), this, SLOT(hideAndResetFocus()));
con's avatar
con committed
99
100
101

    m_findCompleter->setModel(m_plugin->findCompletionModel());
    m_replaceCompleter->setModel(m_plugin->replaceCompletionModel());
102
103
    m_ui.findEdit->setSpecialCompleter(m_findCompleter);
    m_ui.replaceEdit->setSpecialCompleter(m_replaceCompleter);
con's avatar
con committed
104

105
    m_ui.findEdit->setButtonVisible(Utils::FancyLineEdit::Left, true);
106
    m_ui.findEdit->setFiltering(true);
107
    m_ui.findEdit->setPlaceholderText(QString());
108
    m_ui.findEdit->button(Utils::FancyLineEdit::Left)->setFocusPolicy(Qt::TabFocus);
109
    m_ui.replaceEdit->setPlaceholderText(QString());
con's avatar
con committed
110

Robert Loehning's avatar
Robert Loehning committed
111
    connect(m_ui.findEdit, SIGNAL(textChanged(QString)), this, SLOT(invokeFindIncremental()));
112
113
    connect(m_ui.findEdit, SIGNAL(leftButtonClicked()),
            this, SLOT(findEditButtonClicked()));
114
115
116
117
118

    // invoke{Find,Replace}Helper change the completion model. QueuedConnection is used to perform these
    // changes only after the completer's activated() signal is handled (QTCREATORBUG-8408)
    connect(m_ui.findEdit, SIGNAL(returnPressed()), this, SLOT(invokeFindEnter()), Qt::QueuedConnection);
    connect(m_ui.replaceEdit, SIGNAL(returnPressed()), this, SLOT(invokeReplaceEnter()), Qt::QueuedConnection);
con's avatar
con committed
119
120

    QAction *shiftEnterAction = new QAction(m_ui.findEdit);
121
    shiftEnterAction->setShortcut(QKeySequence(tr("Shift+Enter")));
con's avatar
con committed
122
123
124
125
    shiftEnterAction->setShortcutContext(Qt::WidgetShortcut);
    connect(shiftEnterAction, SIGNAL(triggered()), this, SLOT(invokeFindPrevious()));
    m_ui.findEdit->addAction(shiftEnterAction);
    QAction *shiftReturnAction = new QAction(m_ui.findEdit);
126
    shiftReturnAction->setShortcut(QKeySequence(tr("Shift+Return")));
con's avatar
con committed
127
128
129
130
131
    shiftReturnAction->setShortcutContext(Qt::WidgetShortcut);
    connect(shiftReturnAction, SIGNAL(triggered()), this, SLOT(invokeFindPrevious()));
    m_ui.findEdit->addAction(shiftReturnAction);

    QAction *shiftEnterReplaceAction = new QAction(m_ui.replaceEdit);
132
    shiftEnterReplaceAction->setShortcut(QKeySequence(tr("Shift+Enter")));
con's avatar
con committed
133
134
135
136
    shiftEnterReplaceAction->setShortcutContext(Qt::WidgetShortcut);
    connect(shiftEnterReplaceAction, SIGNAL(triggered()), this, SLOT(invokeReplacePrevious()));
    m_ui.replaceEdit->addAction(shiftEnterReplaceAction);
    QAction *shiftReturnReplaceAction = new QAction(m_ui.replaceEdit);
137
    shiftReturnReplaceAction->setShortcut(QKeySequence(tr("Shift+Return")));
con's avatar
con committed
138
139
140
141
142
143
144
    shiftReturnReplaceAction->setShortcutContext(Qt::WidgetShortcut);
    connect(shiftReturnReplaceAction, SIGNAL(triggered()), this, SLOT(invokeReplacePrevious()));
    m_ui.replaceEdit->addAction(shiftReturnReplaceAction);

    // need to make sure QStringList is registered as metatype
    QMetaTypeId<QStringList>::qt_metatype_id();

145
    // register actions
146
    Core::Context globalcontext(Core::Constants::C_GLOBAL);
147
    Core::Context findcontext(Constants::C_FINDTOOLBAR);
Eike Ziller's avatar
Eike Ziller committed
148
    Core::ActionContainer *mfind = Core::ActionManager::actionContainer(Constants::M_FIND);
con's avatar
con committed
149
    Core::Command *cmd;
con's avatar
con committed
150

Eike Ziller's avatar
Eike Ziller committed
151
    m_ui.advancedButton->setDefaultAction(Core::ActionManager::command(Constants::ADVANCED_FIND)->action());
152

153
    m_goToCurrentFindAction = new QAction(this);
Orgad Shaneh's avatar
Orgad Shaneh committed
154
    Core::ActionManager::registerAction(m_goToCurrentFindAction, Constants::S_RETURNTOEDITOR,
155
                                        findcontext);
156
157
    connect(m_goToCurrentFindAction, SIGNAL(triggered()), this, SLOT(setFocusToCurrentFindSupport()));

158
159
    QIcon icon = QIcon::fromTheme(QLatin1String("edit-find-replace"));
    m_findInDocumentAction = new QAction(icon, tr("Find/Replace"), this);
Eike Ziller's avatar
Eike Ziller committed
160
    cmd = Core::ActionManager::registerAction(m_findInDocumentAction, Constants::FIND_IN_DOCUMENT, globalcontext);
con's avatar
con committed
161
    cmd->setDefaultKeySequence(QKeySequence::Find);
162
    mfind->addAction(cmd, Constants::G_FIND_CURRENTDOCUMENT);
con's avatar
con committed
163
164
    connect(m_findInDocumentAction, SIGNAL(triggered()), this, SLOT(openFind()));

165
166
167
    // Pressing the find shortcut while focus is in the tool bar should not change the search text,
    // so register a different find action for the tool bar
    auto localFindAction = new QAction(this);
168
    cmd = ActionManager::registerAction(localFindAction, Constants::FIND_IN_DOCUMENT, findcontext);
169
    connect(localFindAction, &QAction::triggered, this, [this]() {
Orgad Shaneh's avatar
Orgad Shaneh committed
170
        openFindToolBar(FindToolBar::OpenFlags(UpdateAll & ~UpdateFindText));
171
172
    });

con's avatar
con committed
173
174
    if (QApplication::clipboard()->supportsFindBuffer()) {
        m_enterFindStringAction = new QAction(tr("Enter Find String"), this);
Eike Ziller's avatar
Eike Ziller committed
175
        cmd = Core::ActionManager::registerAction(m_enterFindStringAction, "Find.EnterFindString", globalcontext);
con's avatar
con committed
176
177
178
179
180
181
182
        cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E")));
        mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
        connect(m_enterFindStringAction, SIGNAL(triggered()), this, SLOT(putSelectionToFindClipboard()));
        connect(QApplication::clipboard(), SIGNAL(findBufferChanged()), this, SLOT(updateFromFindClipboard()));
    }

    m_findNextAction = new QAction(tr("Find Next"), this);
Eike Ziller's avatar
Eike Ziller committed
183
    cmd = Core::ActionManager::registerAction(m_findNextAction, Constants::FIND_NEXT, globalcontext);
con's avatar
con committed
184
185
    cmd->setDefaultKeySequence(QKeySequence::FindNext);
    mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
186
    connect(m_findNextAction, SIGNAL(triggered()), this, SLOT(invokeGlobalFindNext()));
187
188
189
190
191
    m_localFindNextAction = new QAction(m_findNextAction->text(), this);
    cmd = ActionManager::registerAction(m_localFindNextAction, Constants::FIND_NEXT, findcontext);
    cmd->augmentActionWithShortcutToolTip(m_localFindNextAction);
    connect(m_localFindNextAction, &QAction::triggered, this, &FindToolBar::invokeFindNext);
    m_ui.findNextButton->setDefaultAction(m_localFindNextAction);
con's avatar
con committed
192
193

    m_findPreviousAction = new QAction(tr("Find Previous"), this);
Eike Ziller's avatar
Eike Ziller committed
194
    cmd = Core::ActionManager::registerAction(m_findPreviousAction, Constants::FIND_PREVIOUS, globalcontext);
con's avatar
con committed
195
196
    cmd->setDefaultKeySequence(QKeySequence::FindPrevious);
    mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
197
    connect(m_findPreviousAction, SIGNAL(triggered()), this, SLOT(invokeGlobalFindPrevious()));
198
199
200
201
202
    m_localFindPreviousAction = new QAction(m_findPreviousAction->text(), this);
    cmd = ActionManager::registerAction(m_localFindPreviousAction, Constants::FIND_PREVIOUS, findcontext);
    cmd->augmentActionWithShortcutToolTip(m_localFindPreviousAction);
    connect(m_localFindPreviousAction, &QAction::triggered, this, &FindToolBar::invokeFindPrevious);
    m_ui.findPreviousButton->setDefaultAction(m_localFindPreviousAction);
con's avatar
con committed
203

204
    m_findNextSelectedAction = new QAction(tr("Find Next (Selected)"), this);
Eike Ziller's avatar
Eike Ziller committed
205
    cmd = Core::ActionManager::registerAction(m_findNextSelectedAction, Constants::FIND_NEXT_SELECTED, globalcontext);
206
207
208
209
210
    cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+F3")));
    mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
    connect(m_findNextSelectedAction, SIGNAL(triggered()), this, SLOT(findNextSelected()));

    m_findPreviousSelectedAction = new QAction(tr("Find Previous (Selected)"), this);
Eike Ziller's avatar
Eike Ziller committed
211
    cmd = Core::ActionManager::registerAction(m_findPreviousSelectedAction, Constants::FIND_PREV_SELECTED, globalcontext);
212
213
214
215
    cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F3")));
    mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
    connect(m_findPreviousSelectedAction, SIGNAL(triggered()), this, SLOT(findPreviousSelected()));

216
    m_replaceAction = new QAction(tr("Replace"), this);
Eike Ziller's avatar
Eike Ziller committed
217
    cmd = Core::ActionManager::registerAction(m_replaceAction, Constants::REPLACE, globalcontext);
218
219
    cmd->setDefaultKeySequence(QKeySequence());
    mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
220
    connect(m_replaceAction, SIGNAL(triggered()), this, SLOT(invokeGlobalReplace()));
221
222
223
224
225
    m_localReplaceAction = new QAction(m_replaceAction->text(), this);
    cmd = ActionManager::registerAction(m_localReplaceAction, Constants::REPLACE, findcontext);
    cmd->augmentActionWithShortcutToolTip(m_localReplaceAction);
    connect(m_localReplaceAction, &QAction::triggered, this, &FindToolBar::invokeReplace);
    m_ui.replaceButton->setDefaultAction(m_localReplaceAction);
226
227

    m_replaceNextAction = new QAction(tr("Replace && Find"), this);
Eike Ziller's avatar
Eike Ziller committed
228
    cmd = Core::ActionManager::registerAction(m_replaceNextAction, Constants::REPLACE_NEXT, globalcontext);
con's avatar
con committed
229
230
    cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+=")));
    mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
231
    connect(m_replaceNextAction, SIGNAL(triggered()), this, SLOT(invokeGlobalReplaceNext()));
232
    m_localReplaceNextAction = new QAction(m_replaceNextAction->text(), this);
233
    m_localReplaceNextAction->setIconText(m_replaceNextAction->text()); // Workaround QTBUG-23396
234
235
236
237
    cmd = ActionManager::registerAction(m_localReplaceNextAction, Constants::REPLACE_NEXT, findcontext);
    cmd->augmentActionWithShortcutToolTip(m_localReplaceNextAction);
    connect(m_localReplaceNextAction, &QAction::triggered, this, &FindToolBar::invokeReplaceNext);
    m_ui.replaceNextButton->setDefaultAction(m_localReplaceNextAction);
con's avatar
con committed
238
239

    m_replacePreviousAction = new QAction(tr("Replace && Find Previous"), this);
Eike Ziller's avatar
Eike Ziller committed
240
    cmd = Core::ActionManager::registerAction(m_replacePreviousAction, Constants::REPLACE_PREVIOUS, globalcontext);
con's avatar
con committed
241
    mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
242
    connect(m_replacePreviousAction, SIGNAL(triggered()), this, SLOT(invokeGlobalReplacePrevious()));
243
244
245
246
    m_localReplacePreviousAction = new QAction(m_replacePreviousAction->text(), this);
    cmd = ActionManager::registerAction(m_localReplacePreviousAction, Constants::REPLACE_PREVIOUS, findcontext);
    cmd->augmentActionWithShortcutToolTip(m_localReplacePreviousAction);
    connect(m_localReplacePreviousAction, &QAction::triggered, this, &FindToolBar::invokeReplacePrevious);
con's avatar
con committed
247
248

    m_replaceAllAction = new QAction(tr("Replace All"), this);
Eike Ziller's avatar
Eike Ziller committed
249
    cmd = Core::ActionManager::registerAction(m_replaceAllAction, Constants::REPLACE_ALL, globalcontext);
con's avatar
con committed
250
    mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
251
    connect(m_replaceAllAction, SIGNAL(triggered()), this, SLOT(invokeGlobalReplaceAll()));
252
253
254
255
256
    m_localReplaceAllAction = new QAction(m_replaceAllAction->text(), this);
    cmd = ActionManager::registerAction(m_localReplaceAllAction, Constants::REPLACE_ALL, findcontext);
    cmd->augmentActionWithShortcutToolTip(m_localReplaceAllAction);
    connect(m_localReplaceAllAction, &QAction::triggered, this, &FindToolBar::invokeReplaceAll);
    m_ui.replaceAllButton->setDefaultAction(m_localReplaceAllAction);
con's avatar
con committed
257
258

    m_caseSensitiveAction = new QAction(tr("Case Sensitive"), this);
259
    m_caseSensitiveAction->setIcon(QIcon(QLatin1String(":/find/images/casesensitively.png")));
con's avatar
con committed
260
261
    m_caseSensitiveAction->setCheckable(true);
    m_caseSensitiveAction->setChecked(false);
Eike Ziller's avatar
Eike Ziller committed
262
    cmd = Core::ActionManager::registerAction(m_caseSensitiveAction, Constants::CASE_SENSITIVE, globalcontext);
con's avatar
con committed
263
    mfind->addAction(cmd, Constants::G_FIND_FLAGS);
264
    connect(m_caseSensitiveAction, SIGNAL(toggled(bool)), this, SLOT(setCaseSensitive(bool)));
con's avatar
con committed
265
266

    m_wholeWordAction = new QAction(tr("Whole Words Only"), this);
267
    m_wholeWordAction->setIcon(QIcon(QLatin1String(":/find/images/wholewords.png")));
con's avatar
con committed
268
269
    m_wholeWordAction->setCheckable(true);
    m_wholeWordAction->setChecked(false);
Eike Ziller's avatar
Eike Ziller committed
270
    cmd = Core::ActionManager::registerAction(m_wholeWordAction, Constants::WHOLE_WORDS, globalcontext);
con's avatar
con committed
271
    mfind->addAction(cmd, Constants::G_FIND_FLAGS);
272
    connect(m_wholeWordAction, SIGNAL(toggled(bool)), this, SLOT(setWholeWord(bool)));
con's avatar
con committed
273

274
    m_regularExpressionAction = new QAction(tr("Use Regular Expressions"), this);
275
    m_regularExpressionAction->setIcon(QIcon(QLatin1String(":/find/images/regexp.png")));
276
277
    m_regularExpressionAction->setCheckable(true);
    m_regularExpressionAction->setChecked(false);
Eike Ziller's avatar
Eike Ziller committed
278
    cmd = Core::ActionManager::registerAction(m_regularExpressionAction, Constants::REGULAR_EXPRESSIONS, globalcontext);
279
    mfind->addAction(cmd, Constants::G_FIND_FLAGS);
280
    connect(m_regularExpressionAction, SIGNAL(toggled(bool)), this, SLOT(setRegularExpressions(bool)));
281

282
283
284
285
286
287
    m_preserveCaseAction = new QAction(tr("Preserve Case when Replacing"), this);
    m_preserveCaseAction->setIcon(QPixmap(QLatin1String(":/find/images/preservecase.png")));
    m_preserveCaseAction->setCheckable(true);
    m_preserveCaseAction->setChecked(false);
    cmd = Core::ActionManager::registerAction(m_preserveCaseAction, Constants::PRESERVE_CASE, globalcontext);
    mfind->addAction(cmd, Constants::G_FIND_FLAGS);
288
    connect(m_preserveCaseAction, SIGNAL(toggled(bool)), this, SLOT(setPreserveCase(bool)));
289

290
291
292
293
294
295
296
    connect(m_currentDocumentFind, &CurrentDocumentFind::candidateChanged,
            this, &FindToolBar::adaptToCandidate);
    connect(m_currentDocumentFind, &CurrentDocumentFind::changed,
            this, &FindToolBar::updateGlobalActions);
    connect(m_currentDocumentFind, &CurrentDocumentFind::changed,
            this, &FindToolBar::updateToolBar);
    updateGlobalActions();
297
    updateToolBar();
ck's avatar
ck committed
298
299
300
301
302
303

    m_findIncrementalTimer.setSingleShot(true);
    m_findStepTimer.setSingleShot(true);
    connect(&m_findIncrementalTimer, SIGNAL(timeout()),
            this, SLOT(invokeFindIncremental()));
    connect(&m_findStepTimer, SIGNAL(timeout()), this, SLOT(invokeFindStep()));
con's avatar
con committed
304
305
306
307
308
309
}

FindToolBar::~FindToolBar()
{
}

310
311
312
313
314
315
316
317
318
319
320
void FindToolBar::installEventFilters()
{
    if (!m_eventFiltersInstalled) {
        m_findCompleter->popup()->installEventFilter(this);
        m_ui.findEdit->installEventFilter(this);
        m_ui.replaceEdit->installEventFilter(this);
        this->installEventFilter(this);
        m_eventFiltersInstalled = true;
    }
}

con's avatar
con committed
321
322
bool FindToolBar::eventFilter(QObject *obj, QEvent *event)
{
323
324
325
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent *ke = static_cast<QKeyEvent *>(event);
        if (ke->key() == Qt::Key_Down) {
326
327
328
            if (obj == m_ui.findEdit) {
                if (m_ui.findEdit->text().isEmpty())
                    m_findCompleter->setCompletionPrefix(QString());
329
                m_findCompleter->complete();
330
331
332
            } else if (obj == m_ui.replaceEdit) {
                if (m_ui.replaceEdit->text().isEmpty())
                    m_replaceCompleter->setCompletionPrefix(QString());
333
                m_replaceCompleter->complete();
334
            }
335
336
337
        }
    }

con's avatar
con committed
338
339
340
    if ((obj == m_ui.findEdit || obj == m_findCompleter->popup())
               && event->type() == QEvent::KeyPress) {
        QKeyEvent *ke = static_cast<QKeyEvent *>(event);
341
        if (ke->key() == Qt::Key_Space && (ke->modifiers() & Utils::HostOsInfo::controlModifier())) {
con's avatar
con committed
342
343
344
345
346
347
348
            QString completedText = m_currentDocumentFind->completedFindString();
            if (!completedText.isEmpty()) {
                setFindText(completedText);
                ke->accept();
                return true;
            }
        }
349
    } else if (obj == this && event->type() == QEvent::ShortcutOverride) {
con's avatar
con committed
350
        QKeyEvent *ke = static_cast<QKeyEvent *>(event);
351
        if (ke->key() == Qt::Key_Space && (ke->modifiers() & Utils::HostOsInfo::controlModifier())) {
con's avatar
con committed
352
353
354
            event->accept();
            return true;
        }
355
    } else if (obj == this && event->type() == QEvent::Hide) {
con's avatar
con committed
356
        invokeClearResults();
357
        if (m_currentDocumentFind->isEnabled())
con's avatar
con committed
358
359
            m_currentDocumentFind->clearFindScope();
    }
360
    return Utils::StyledBar::eventFilter(obj, event);
con's avatar
con committed
361
362
}

363
364
void FindToolBar::adaptToCandidate()
{
365
    updateGlobalActions();
366
    if (findToolBarPlaceHolder() == Core::FindToolBarPlaceHolder::getCurrent()) {
367
        m_currentDocumentFind->acceptCandidate();
368
369
370
        if (isVisible())
            m_currentDocumentFind->highlightAll(getFindText(), effectiveFindFlags());
    }
371
372
}

373
void FindToolBar::updateGlobalActions()
374
{
375
376
377
378
    IFindSupport *candidate = m_currentDocumentFind->candidate();
    bool enabled = (candidate != 0);
    bool replaceEnabled = enabled && candidate->supportsReplace();
    m_findInDocumentAction->setEnabled(enabled || (toolBarHasFocus() && isEnabled()));
379
380
    m_findNextSelectedAction->setEnabled(enabled);
    m_findPreviousSelectedAction->setEnabled(enabled);
381
382
    if (QApplication::clipboard()->supportsFindBuffer())
        m_enterFindStringAction->setEnabled(enabled);
383
384
385
386
387
388
    m_findNextAction->setEnabled(enabled);
    m_findPreviousAction->setEnabled(enabled);
    m_replaceAction->setEnabled(replaceEnabled);
    m_replaceNextAction->setEnabled(replaceEnabled);
    m_replacePreviousAction->setEnabled(replaceEnabled);
    m_replaceAllAction->setEnabled(replaceEnabled);
389
390
391
}

void FindToolBar::updateToolBar()
con's avatar
con committed
392
393
394
{
    bool enabled = m_currentDocumentFind->isEnabled();
    bool replaceEnabled = enabled && m_currentDocumentFind->supportsReplace();
395
    bool showAllControls = canShowAllControls(replaceEnabled);
396

397
398
    m_localFindNextAction->setEnabled(enabled);
    m_localFindPreviousAction->setEnabled(enabled);
399

400
401
402
403
    m_localReplaceAction->setEnabled(replaceEnabled);
    m_localReplacePreviousAction->setEnabled(replaceEnabled);
    m_localReplaceNextAction->setEnabled(replaceEnabled);
    m_localReplaceAllAction->setEnabled(replaceEnabled);
404

con's avatar
con committed
405
406
    m_caseSensitiveAction->setEnabled(enabled);
    m_wholeWordAction->setEnabled(enabled);
407
    m_regularExpressionAction->setEnabled(enabled);
408
    m_preserveCaseAction->setEnabled(replaceEnabled && !hasFindFlag(FindRegularExpression));
con's avatar
con committed
409
    bool replaceFocus = m_ui.replaceEdit->hasFocus();
410

con's avatar
con committed
411
    m_ui.findLabel->setEnabled(enabled);
412
413
414
415
416
417
418
419
    m_ui.findLabel->setVisible(showAllControls);
    m_ui.findEdit->setEnabled(enabled);
    m_ui.findEdit->setPlaceholderText(showAllControls ? QString() : tr("Search for..."));
    m_ui.findPreviousButton->setVisible(showAllControls);
    m_ui.findNextButton->setVisible(showAllControls);
    m_ui.horizontalSpacer->changeSize((showAllControls ? FINDBUTTON_SPACER_WIDTH : 0), 0,
                                      QSizePolicy::Expanding, QSizePolicy::Ignored);
    m_ui.findButtonLayout->invalidate(); // apply spacer change
420

con's avatar
con committed
421
    m_ui.replaceLabel->setEnabled(replaceEnabled);
422
423
424
    m_ui.replaceLabel->setVisible(replaceEnabled && showAllControls);
    m_ui.replaceEdit->setEnabled(replaceEnabled);
    m_ui.replaceEdit->setPlaceholderText(showAllControls ? QString() : tr("Replace with..."));
425
    m_ui.replaceEdit->setVisible(replaceEnabled);
426
427
428
    m_ui.replaceButtonsWidget->setVisible(replaceEnabled && showAllControls);
    m_ui.advancedButton->setVisible(replaceEnabled && showAllControls);

429
430
    layout()->invalidate();

con's avatar
con committed
431
432
    if (!replaceEnabled && enabled && replaceFocus)
        m_ui.findEdit->setFocus();
433
434
    updateIcons();
    updateFlagMenus();
con's avatar
con committed
435
436
437
438
439
}

void FindToolBar::invokeFindEnter()
{
    if (m_currentDocumentFind->isEnabled()) {
440
441
442
443
        if (m_useFakeVim)
            setFocusToCurrentFindSupport();
        else
            invokeFindNext();
con's avatar
con committed
444
445
446
447
448
    }
}

void FindToolBar::invokeReplaceEnter()
{
449
    if (m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace())
con's avatar
con committed
450
451
452
453
454
        invokeReplaceNext();
}

void FindToolBar::invokeClearResults()
{
455
    if (m_currentDocumentFind->isEnabled())
456
        m_currentDocumentFind->clearHighlights();
con's avatar
con committed
457
458
459
460
461
}


void FindToolBar::invokeFindNext()
{
462
    setFindFlag(FindBackward, false);
con's avatar
con committed
463
464
465
    invokeFindStep();
}

466
467
468
469
470
471
void FindToolBar::invokeGlobalFindNext()
{
    acceptCandidateAndMoveToolBar();
    invokeFindNext();
}

con's avatar
con committed
472
473
void FindToolBar::invokeFindPrevious()
{
474
    setFindFlag(FindBackward, true);
con's avatar
con committed
475
476
477
    invokeFindStep();
}

478
479
480
481
482
483
void FindToolBar::invokeGlobalFindPrevious()
{
    acceptCandidateAndMoveToolBar();
    invokeFindPrevious();
}

con's avatar
con committed
484
485
486
487
488
489
490
491
492
493
494
495
QString FindToolBar::getFindText()
{
    return m_ui.findEdit->text();
}

QString FindToolBar::getReplaceText()
{
    return m_ui.replaceEdit->text();
}

void FindToolBar::setFindText(const QString &text)
{
Robert Loehning's avatar
Robert Loehning committed
496
    disconnect(m_ui.findEdit, SIGNAL(textChanged(QString)), this, SLOT(invokeFindIncremental()));
497
    if (hasFindFlag(FindRegularExpression))
498
499
500
        m_ui.findEdit->setText(QRegExp::escape(text));
    else
        m_ui.findEdit->setText(text);
Robert Loehning's avatar
Robert Loehning committed
501
    connect(m_ui.findEdit, SIGNAL(textChanged(QString)), this, SLOT(invokeFindIncremental()));
con's avatar
con committed
502
503
504
505
506
507
508
509
510
}

void FindToolBar::selectFindText()
{
    m_ui.findEdit->selectAll();
}

void FindToolBar::invokeFindStep()
{
ck's avatar
ck committed
511
512
    m_findStepTimer.stop();
    m_findIncrementalTimer.stop();
con's avatar
con committed
513
514
    if (m_currentDocumentFind->isEnabled()) {
        m_plugin->updateFindCompletion(getFindText());
ck's avatar
ck committed
515
516
517
518
        IFindSupport::Result result =
            m_currentDocumentFind->findStep(getFindText(), effectiveFindFlags());
        if (result == IFindSupport::NotYetFound)
            m_findStepTimer.start(50);
con's avatar
con committed
519
520
521
522
523
    }
}

void FindToolBar::invokeFindIncremental()
{
ck's avatar
ck committed
524
525
    m_findIncrementalTimer.stop();
    m_findStepTimer.stop();
con's avatar
con committed
526
527
    if (m_currentDocumentFind->isEnabled()) {
        QString text = getFindText();
ck's avatar
ck committed
528
529
530
531
        IFindSupport::Result result =
            m_currentDocumentFind->findIncremental(text, effectiveFindFlags());
        if (result == IFindSupport::NotYetFound)
            m_findIncrementalTimer.start(50);
con's avatar
con committed
532
        if (text.isEmpty())
533
            m_currentDocumentFind->clearHighlights();
con's avatar
con committed
534
535
536
    }
}

537
538
void FindToolBar::invokeReplace()
{
539
    setFindFlag(FindBackward, false);
540
541
542
543
544
545
546
    if (m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace()) {
        m_plugin->updateFindCompletion(getFindText());
        m_plugin->updateReplaceCompletion(getReplaceText());
        m_currentDocumentFind->replace(getFindText(), getReplaceText(), effectiveFindFlags());
    }
}

547
548
549
550
551
552
void FindToolBar::invokeGlobalReplace()
{
    acceptCandidateAndMoveToolBar();
    invokeReplace();
}

con's avatar
con committed
553
554
void FindToolBar::invokeReplaceNext()
{
555
    setFindFlag(FindBackward, false);
con's avatar
con committed
556
557
558
    invokeReplaceStep();
}

559
560
561
562
563
564
void FindToolBar::invokeGlobalReplaceNext()
{
    acceptCandidateAndMoveToolBar();
    invokeReplaceNext();
}

con's avatar
con committed
565
566
void FindToolBar::invokeReplacePrevious()
{
567
    setFindFlag(FindBackward, true);
con's avatar
con committed
568
569
570
    invokeReplaceStep();
}

571
572
573
574
575
576
void FindToolBar::invokeGlobalReplacePrevious()
{
    acceptCandidateAndMoveToolBar();
    invokeReplacePrevious();
}

con's avatar
con committed
577
578
579
580
581
void FindToolBar::invokeReplaceStep()
{
    if (m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace()) {
        m_plugin->updateFindCompletion(getFindText());
        m_plugin->updateReplaceCompletion(getReplaceText());
582
        m_currentDocumentFind->replaceStep(getFindText(), getReplaceText(), effectiveFindFlags());
con's avatar
con committed
583
584
585
586
587
588
589
    }
}

void FindToolBar::invokeReplaceAll()
{
    m_plugin->updateFindCompletion(getFindText());
    m_plugin->updateReplaceCompletion(getReplaceText());
590
    if (m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace())
591
        m_currentDocumentFind->replaceAll(getFindText(), getReplaceText(), effectiveFindFlags());
con's avatar
con committed
592
593
}

594
595
596
597
598
599
void FindToolBar::invokeGlobalReplaceAll()
{
    acceptCandidateAndMoveToolBar();
    invokeReplaceAll();
}

con's avatar
con committed
600
601
void FindToolBar::invokeResetIncrementalSearch()
{
ck's avatar
ck committed
602
603
    m_findIncrementalTimer.stop();
    m_findStepTimer.stop();
con's avatar
con committed
604
605
606
607
608
609
610
    if (m_currentDocumentFind->isEnabled())
        m_currentDocumentFind->resetIncrementalSearch();
}


void FindToolBar::putSelectionToFindClipboard()
{
611
    openFind(false);
con's avatar
con committed
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
    const QString text = m_currentDocumentFind->currentFindString();
    QApplication::clipboard()->setText(text, QClipboard::FindBuffer);
}


void FindToolBar::updateFromFindClipboard()
{
    if (QApplication::clipboard()->supportsFindBuffer()) {
        const bool blocks = m_ui.findEdit->blockSignals(true);
        setFindText(QApplication::clipboard()->text(QClipboard::FindBuffer));
        m_ui.findEdit->blockSignals(blocks);
    }
}

void FindToolBar::findFlagsChanged()
{
    updateIcons();
    updateFlagMenus();
    invokeClearResults();
631
    if (isVisible())
con's avatar
con committed
632
        m_currentDocumentFind->highlightAll(getFindText(), effectiveFindFlags());
con's avatar
con committed
633
634
}

635
636
637
638
639
640
void FindToolBar::findEditButtonClicked()
{
    OptionsPopup *popup = new OptionsPopup(m_ui.findEdit);
    popup->show();
}

con's avatar
con committed
641
642
void FindToolBar::updateIcons()
{
643
644
645
646
647
    FindFlags effectiveFlags = effectiveFindFlags();
    bool casesensitive = effectiveFlags & FindCaseSensitively;
    bool wholewords = effectiveFlags & FindWholeWords;
    bool regexp = effectiveFlags & FindRegularExpression;
    bool preserveCase = effectiveFlags & FindPreserveCase;
648
    if (!casesensitive && !wholewords && !regexp && !preserveCase) {
649
        m_ui.findEdit->setButtonPixmap(Utils::FancyLineEdit::Left,
650
                                       Utils::StyleHelper::dpiSpecificImageFile(QLatin1Literal(Core::Constants::ICON_MAGNIFIER)));
651
652
653
    } else {
        m_ui.findEdit->setButtonPixmap(Utils::FancyLineEdit::Left,
                                       IFindFilter::pixmapForFindFlags(effectiveFlags));
654
    }
con's avatar
con committed
655
656
}

657
FindFlags FindToolBar::effectiveFindFlags()
658
{
659
    FindFlags supportedFlags;
660
661
    bool supportsReplace = true;
    if (m_currentDocumentFind->isEnabled()) {
662
        supportedFlags = m_currentDocumentFind->supportedFindFlags();
663
664
        supportsReplace = m_currentDocumentFind->supportsReplace();
    } else {
665
        supportedFlags = (FindFlags)0xFFFFFF;
666
    }
667
668
    if (!supportsReplace || m_findFlags & FindRegularExpression)
        supportedFlags &= ~FindPreserveCase;
669
670
671
    return supportedFlags & m_findFlags;
}

con's avatar
con committed
672
673
void FindToolBar::updateFlagMenus()
{
674
675
676
677
    bool wholeOnly = ((m_findFlags & FindWholeWords));
    bool sensitive = ((m_findFlags & FindCaseSensitively));
    bool regexp = ((m_findFlags & FindRegularExpression));
    bool preserveCase = ((m_findFlags & FindPreserveCase));
con's avatar
con committed
678
679
680
681
    if (m_wholeWordAction->isChecked() != wholeOnly)
        m_wholeWordAction->setChecked(wholeOnly);
    if (m_caseSensitiveAction->isChecked() != sensitive)
        m_caseSensitiveAction->setChecked(sensitive);
682
683
    if (m_regularExpressionAction->isChecked() != regexp)
        m_regularExpressionAction->setChecked(regexp);
684
685
    if (m_preserveCaseAction->isChecked() != preserveCase)
        m_preserveCaseAction->setChecked(preserveCase);
686
    FindFlags supportedFlags;
687
688
    if (m_currentDocumentFind->isEnabled())
        supportedFlags = m_currentDocumentFind->supportedFindFlags();
689
690
691
    m_wholeWordAction->setEnabled(supportedFlags & FindWholeWords);
    m_caseSensitiveAction->setEnabled(supportedFlags & FindCaseSensitively);
    m_regularExpressionAction->setEnabled(supportedFlags & FindRegularExpression);
692
    bool replaceEnabled = m_currentDocumentFind->isEnabled() && m_currentDocumentFind->supportsReplace();
693
    m_preserveCaseAction->setEnabled((supportedFlags & FindPreserveCase) && !regexp && replaceEnabled);
con's avatar
con committed
694
695
}

696
void FindToolBar::setFocusToCurrentFindSupport()
con's avatar
con committed
697
{
698
699
700
    if (!m_currentDocumentFind->setFocusToCurrentFindSupport())
        if (QWidget *w = focusWidget())
            w->clearFocus();
con's avatar
con committed
701
702
703
704
705
706
707
708
}

void FindToolBar::hideAndResetFocus()
{
    m_currentDocumentFind->setFocusToCurrentFindSupport();
    hide();
}

709
710
Core::FindToolBarPlaceHolder *FindToolBar::findToolBarPlaceHolder() const
{
711
    QList<Core::FindToolBarPlaceHolder*> placeholders = ExtensionSystem::PluginManager::getObjects<Core::FindToolBarPlaceHolder>();
712
713
714
    QWidget *candidate = QApplication::focusWidget();
    while (candidate) {
        foreach (Core::FindToolBarPlaceHolder *ph, placeholders) {
715
            if (ph->owner() == candidate)
716
717
718
719
720
721
722
                return ph;
        }
        candidate = candidate->parentWidget();
    }
    return 0;
}

723
724
725
726
727
bool FindToolBar::toolBarHasFocus() const
{
    return qApp->focusWidget() == focusWidget();
}

728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
bool FindToolBar::canShowAllControls(bool replaceIsVisible) const
{
    int fullWidth = width();
    int findFixedWidth = m_ui.findLabel->sizeHint().width()
            + m_ui.findNextButton->sizeHint().width()
            + m_ui.findPreviousButton->sizeHint().width()
            + FINDBUTTON_SPACER_WIDTH
            + m_ui.close->sizeHint().width();
    if (fullWidth - findFixedWidth < MINIMUM_WIDTH_FOR_COMPLEX_LAYOUT)
        return false;
    if (!replaceIsVisible)
        return true;
    int replaceFixedWidth = m_ui.replaceLabel->sizeHint().width()
            + m_ui.replaceButton->sizeHint().width()
            + m_ui.replaceNextButton->sizeHint().width()
            + m_ui.replaceAllButton->sizeHint().width()
            + m_ui.advancedButton->sizeHint().width();
    return fullWidth - replaceFixedWidth >= MINIMUM_WIDTH_FOR_COMPLEX_LAYOUT;
}

748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
/*!
    Accepts the candidate find of the current focus widget (if any), and moves the tool bar
    there, if it was visible before.
*/
void FindToolBar::acceptCandidateAndMoveToolBar()
{
    if (!m_currentDocumentFind->candidate())
        return;
    if (isVisible()) {
        openFindToolBar(UpdateHighlight);
    } else {
        // Make sure we are really hidden, and not just because our parent was hidden.
        // Otherwise when the tool bar gets visible again, it will be in a different widget than
        // the current document find it acts on.
        // Test case: Open find in navigation side bar, hide side bar, click into editor,
        // trigger find next, show side bar
        hide();
        m_currentDocumentFind->acceptCandidate();
    }
}

769
void FindToolBar::openFind(bool focus)
770
771
{
    setBackward(false);
772
773
774
775
    OpenFlags flags = UpdateAll;
    if (!focus) // remove focus flag
        flags = flags & ~UpdateFocusAndSelect;
    openFindToolBar(flags);
776
777
}

778
void FindToolBar::openFindToolBar(OpenFlags flags)
con's avatar
con committed
779
{
780
    installEventFilters();
781
782
783
784
    Core::FindToolBarPlaceHolder *holder = findToolBarPlaceHolder();
    if (!holder)
        return;
    Core::FindToolBarPlaceHolder *previousHolder = Core::FindToolBarPlaceHolder::getCurrent();
785
786
787
788
789
790
    if (previousHolder != holder) {
        if (previousHolder)
            previousHolder->setWidget(0);
        holder->setWidget(this);
        Core::FindToolBarPlaceHolder::setCurrent(holder);
    }
791
792
793
    m_currentDocumentFind->acceptCandidate();
    holder->setVisible(true);
    setVisible(true);
794
795
796
797
//     We do not want to change the text when we currently have the focus and user presses the
//     find shortcut
//    if (!focus || !toolBarHasFocus()) {
    if (flags & UpdateFindText) {
798
799
800
801
        QString text = m_currentDocumentFind->currentFindString();
        if (!text.isEmpty())
            setFindText(text);
    }
802
    if (flags & UpdateFocusAndSelect)
803
        setFocus();
804
805
806
807
808
    if (flags & UpdateFindScope)
        m_currentDocumentFind->defineFindScope();
    if (flags & UpdateHighlight)
        m_currentDocumentFind->highlightAll(getFindText(), effectiveFindFlags());
    if (flags & UpdateFocusAndSelect)
809
810
811
812
813
        selectFindText();
}

void FindToolBar::findNextSelected()
{
814
    openFindToolBar(OpenFlags(UpdateAll & ~UpdateFocusAndSelect));
815
816
817
818
819
    invokeFindNext();
}

void FindToolBar::findPreviousSelected()
{
820
    openFindToolBar(OpenFlags(UpdateAll & ~UpdateFocusAndSelect));
821
    invokeFindPrevious();
con's avatar
con committed
822
}
823
824
825

bool FindToolBar::focusNextPrevChild(bool next)
{
826
827
    QAbstractButton *optionsButton = m_ui.findEdit->button(Utils::FancyLineEdit::Left);
    // close tab order
828
    if (next && m_ui.advancedButton->hasFocus())
829
830
        optionsButton->setFocus(Qt::TabFocusReason);
    else if (next && optionsButton->hasFocus())
831
        m_ui.findEdit->setFocus(Qt::TabFocusReason);
832
    else if (!next && optionsButton->hasFocus())
833
        m_ui.advancedButton->setFocus(Qt::TabFocusReason);
834
835
    else if (!next && m_ui.findEdit->hasFocus())
        optionsButton->setFocus(Qt::TabFocusReason);
836
    else
837
        return Utils::StyledBar::focusNextPrevChild(next);
838
839
    return true;
}
840

841
842
843
844
845
846
void FindToolBar::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event)
    QTimer::singleShot(0, this, SLOT(updateToolBar()));
}

847
848
void FindToolBar::writeSettings()
{
hjk's avatar
hjk committed
849
    QSettings *settings = Core::ICore::settings();
850
851
    settings->beginGroup(QLatin1String("Find"));
    settings->beginGroup(QLatin1String("FindToolBar"));
852
853
854
855
856
    settings->setValue(QLatin1String("Backward"), QVariant((m_findFlags & FindBackward) != 0));
    settings->setValue(QLatin1String("CaseSensitively"), QVariant((m_findFlags & FindCaseSensitively) != 0));
    settings->setValue(QLatin1String("WholeWords"), QVariant((m_findFlags & FindWholeWords) != 0));
    settings->setValue(QLatin1String("RegularExpression"), QVariant((m_findFlags & FindRegularExpression) != 0));
    settings->setValue(QLatin1String("PreserveCase"), QVariant((m_findFlags & FindPreserveCase) != 0));
857
858
859
860
861
862
    settings->endGroup();
    settings->endGroup();
}

void FindToolBar::readSettings()
{
hjk's avatar
hjk committed
863
    QSettings *settings = Core::ICore::settings();
864
865
    settings->beginGroup(QLatin1String("Find"));
    settings->beginGroup(QLatin1String("FindToolBar"));
866
    FindFlags flags;
867
    if (settings->value(QLatin1String("Backward"), false).toBool())
868
        flags |= FindBackward;
869
    if (settings->value(QLatin1String("CaseSensitively"), false).toBool())
870
        flags |= FindCaseSensitively;
871
    if (settings->value(QLatin1String("WholeWords"), false).toBool())
872
        flags |= FindWholeWords;
873
    if (settings->value(QLatin1String("RegularExpression"), false).toBool())
874
        flags |= FindRegularExpression;
875
    if (settings->value(QLatin1String("PreserveCase"), false).toBool())
876
        flags |= FindPreserveCase;
877
878
879
880
881
882
    settings->endGroup();
    settings->endGroup();
    m_findFlags = flags;
    findFlagsChanged();
}

883
884
885
886
887
void FindToolBar::setUseFakeVim(bool on)
{
    m_useFakeVim = on;
}

888
void FindToolBar::setFindFlag(FindFlag flag, bool enabled)
889
890
891
892
893
894
895
896
{
    bool hasFlag = hasFindFlag(flag);
    if ((hasFlag && enabled) || (!hasFlag && !enabled))
        return;
    if (enabled)
        m_findFlags |= flag;
    else
        m_findFlags &= ~flag;
897
    if (flag != FindBackward)
898
899
900
        findFlagsChanged();
}

901
bool FindToolBar::hasFindFlag(FindFlag flag)
902
903
904
905
906
907
{
    return m_findFlags & flag;
}

void FindToolBar::setCaseSensitive(bool sensitive)
{
908
    setFindFlag(FindCaseSensitively, sensitive);
909
910
911
912
}

void FindToolBar::setWholeWord(bool wholeOnly)
{
913
    setFindFlag(FindWholeWords, wholeOnly);
914
}
915
916
917

void FindToolBar::setRegularExpressions(bool regexp)
{
918
    setFindFlag(FindRegularExpression, regexp);
919
}
920

921
922
void FindToolBar::setPreserveCase(bool preserveCase)
{
923
    setFindFlag(FindPreserveCase, preserveCase);
924
925
}

926
927
void FindToolBar::setBackward(bool backward)
{
928
    setFindFlag(FindBackward, backward);
929
}
930

931
932
933
934
935
936
void FindToolBar::setLightColoredIcon(bool lightColored)
{
    m_ui.close->setIcon(lightColored ? QIcon(QLatin1String(Core::Constants::ICON_DARK_CLOSE))
                                     : QIcon(QLatin1String(Core::Constants::ICON_BUTTON_CLOSE)));
}

937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
OptionsPopup::OptionsPopup(QWidget *parent)
    : QWidget(parent, Qt::Popup)
{
    setAttribute(Qt::WA_DeleteOnClose);
    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->setContentsMargins(2, 2, 2, 2);
    layout->setSpacing(2);
    setLayout(layout);
    QCheckBox *firstCheckBox = createCheckboxForCommand(Constants::CASE_SENSITIVE);
    layout->addWidget(firstCheckBox);
    layout->addWidget(createCheckboxForCommand(Constants::WHOLE_WORDS));
    layout->addWidget(createCheckboxForCommand(Constants::REGULAR_EXPRESSIONS));
    layout->addWidget(createCheckboxForCommand(Constants::PRESERVE_CASE));
    firstCheckBox->setFocus();
    move(parent->mapToGlobal(QPoint(0, -sizeHint().height())));
}

bool OptionsPopup::event(QEvent *ev)
{
    if (ev->type() == QEvent::ShortcutOverride) {
        QKeyEvent *ke = static_cast<QKeyEvent *>(ev);
        if (ke->key() == Qt::Key_Escape && !ke->modifiers()) {
            ev->accept();
            return true;
        }
    }
    return QWidget::event(ev);
}

bool OptionsPopup::eventFilter(QObject *obj, QEvent *ev)
{
    QCheckBox *checkbox = qobject_cast<QCheckBox *>(obj);
    if (ev->type() == QEvent::KeyPress && checkbox) {
        QKeyEvent *ke = static_cast<QKeyEvent *>(ev);
        if (!ke->modifiers() && (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return)) {
            checkbox->click();
            ev->accept();
            return true;
        }
    }
    return QWidget::eventFilter(obj, ev);
}

void OptionsPopup::actionChanged()
{
    QAction *action = qobject_cast<QAction *>(sender());
    QTC_ASSERT(action, return);
    QCheckBox *checkbox = m_checkboxMap.value(action);
    QTC_ASSERT(checkbox, return);
    checkbox->setEnabled(action->isEnabled());
}

QCheckBox *OptionsPopup::createCheckboxForCommand(Id id)
{
    QAction *action = ActionManager::command(id)->action();
    QCheckBox *checkbox = new QCheckBox(action->text());
    checkbox->setToolTip(action->toolTip());
    checkbox->setChecked(action->isChecked());
    checkbox->setEnabled(action->isEnabled());
    checkbox->installEventFilter(this); // enter key handling
    QObject::connect(checkbox, SIGNAL(clicked(bool)), action, SLOT(setChecked(bool)));
    QObject::connect(action, SIGNAL(changed()), this, SLOT(actionChanged()));
    m_checkboxMap.insert(action, checkbox);
    return checkbox;
}