OSDN Git Service

Update license.
[qt-creator-jp/qt-creator-jp.git] / src / plugins / find / findplugin.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 (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 **
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 **
23 ** Other Usage
24 **
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **************************************************************************/
32
33 #include "findplugin.h"
34
35 #include "textfindconstants.h"
36 #include "currentdocumentfind.h"
37 #include "findtoolbar.h"
38 #include "findtoolwindow.h"
39 #include "searchresultwindow.h"
40 #include "ifindfilter.h"
41
42 #include <coreplugin/actionmanager/actionmanager.h>
43 #include <coreplugin/actionmanager/actioncontainer.h>
44 #include <coreplugin/actionmanager/command.h>
45 #include <coreplugin/coreconstants.h>
46 #include <coreplugin/icore.h>
47 #include <coreplugin/icontext.h>
48 #include <coreplugin/uniqueidmanager.h>
49
50 #include <extensionsystem/pluginmanager.h>
51
52 #include <utils/qtcassert.h>
53
54 #include <QtGui/QMenu>
55 #include <QtGui/QStringListModel>
56 #include <QtGui/QAction>
57
58 #include <QtCore/QtPlugin>
59 #include <QtCore/QSettings>
60
61 /*!
62     \namespace Find
63     The Find namespace provides everything that has to do with search term based searches.
64 */
65
66 /*!
67     \namespace Find::Internal
68     \internal
69 */
70 /*!
71     \namespace Find::Internal::ItemDataRoles
72     \internal
73 */
74
75 Q_DECLARE_METATYPE(Find::IFindFilter*)
76
77 namespace {
78     const int MAX_COMPLETIONS = 50;
79 }
80
81 namespace Find {
82
83 struct FindPluginPrivate {
84     explicit FindPluginPrivate(FindPlugin *q);
85
86     //variables
87     static FindPlugin *m_instance;
88
89     QHash<IFindFilter *, QAction *> m_filterActions;
90
91     Internal::CurrentDocumentFind *m_currentDocumentFind;
92     Internal::FindToolBar *m_findToolBar;
93     Internal::FindToolWindow *m_findDialog;
94     Find::FindFlags m_findFlags;
95     QStringListModel *m_findCompletionModel;
96     QStringListModel *m_replaceCompletionModel;
97     QStringList m_findCompletions;
98     QStringList m_replaceCompletions;
99     QAction *m_openFindDialog;
100 };
101
102 FindPluginPrivate::FindPluginPrivate(FindPlugin *q) :
103     m_currentDocumentFind(0), m_findToolBar(0), m_findDialog(0),
104     m_findCompletionModel(new QStringListModel(q)),
105     m_replaceCompletionModel(new QStringListModel(q))
106 {
107 }
108
109 FindPlugin *FindPluginPrivate::m_instance = 0;
110
111 FindPlugin::FindPlugin() : d(new FindPluginPrivate(this))
112 {
113     QTC_ASSERT(!FindPluginPrivate::m_instance, return);
114     FindPluginPrivate::m_instance = this;
115 }
116
117 FindPlugin::~FindPlugin()
118 {
119     FindPluginPrivate::m_instance = 0;
120     delete d->m_currentDocumentFind;
121     delete d->m_findToolBar;
122     delete d->m_findDialog;
123     delete d;
124 }
125
126 FindPlugin *FindPlugin::instance()
127 {
128     return FindPluginPrivate::m_instance;
129 }
130
131 bool FindPlugin::initialize(const QStringList &, QString *)
132 {
133     setupMenu();
134
135     d->m_currentDocumentFind = new Internal::CurrentDocumentFind;
136
137     d->m_findToolBar = new Internal::FindToolBar(this, d->m_currentDocumentFind);
138     d->m_findDialog = new Internal::FindToolWindow(this);
139     SearchResultWindow *searchResultWindow = new SearchResultWindow;
140     addAutoReleasedObject(searchResultWindow);
141     return true;
142 }
143
144 void FindPlugin::extensionsInitialized()
145 {
146     setupFilterMenuItems();
147     readSettings();
148 }
149
150 ExtensionSystem::IPlugin::ShutdownFlag FindPlugin::aboutToShutdown()
151 {
152     d->m_findToolBar->setVisible(false);
153     d->m_findToolBar->setParent(0);
154     d->m_currentDocumentFind->removeConnections();
155     writeSettings();
156     return SynchronousShutdown;
157 }
158
159 void FindPlugin::filterChanged()
160 {
161     IFindFilter *changedFilter = qobject_cast<IFindFilter *>(sender());
162     QAction *action = d->m_filterActions.value(changedFilter);
163     QTC_ASSERT(changedFilter, return);
164     QTC_ASSERT(action, return);
165     action->setEnabled(changedFilter->isEnabled());
166     bool haveEnabledFilters = false;
167     foreach (IFindFilter *filter, d->m_filterActions.keys()) {
168         if (filter->isEnabled()) {
169             haveEnabledFilters = true;
170             break;
171         }
172     }
173     d->m_openFindDialog->setEnabled(haveEnabledFilters);
174 }
175
176 void FindPlugin::openFindFilter()
177 {
178     QAction *action = qobject_cast<QAction*>(sender());
179     QTC_ASSERT(action, return);
180     IFindFilter *filter = action->data().value<IFindFilter *>();
181     if (d->m_currentDocumentFind->candidateIsEnabled())
182         d->m_currentDocumentFind->acceptCandidate();
183     QString currentFindString = (d->m_currentDocumentFind->isEnabled() ? d->m_currentDocumentFind->currentFindString() : "");
184     if (!currentFindString.isEmpty())
185         d->m_findDialog->setFindText(currentFindString);
186     d->m_findDialog->open(filter);
187 }
188
189 void FindPlugin::setupMenu()
190 {
191     Core::ActionManager *am = Core::ICore::instance()->actionManager();
192     Core::ActionContainer *medit = am->actionContainer(Core::Constants::M_EDIT);
193     Core::ActionContainer *mfind = am->createMenu(Constants::M_FIND);
194     medit->addMenu(mfind, Core::Constants::G_EDIT_FIND);
195     mfind->menu()->setTitle(tr("&Find/Replace"));
196     mfind->appendGroup(Constants::G_FIND_CURRENTDOCUMENT);
197     mfind->appendGroup(Constants::G_FIND_FILTERS);
198     mfind->appendGroup(Constants::G_FIND_FLAGS);
199     mfind->appendGroup(Constants::G_FIND_ACTIONS);
200     Core::Context globalcontext(Core::Constants::C_GLOBAL);
201     Core::Command *cmd;
202     QAction *separator;
203     separator = new QAction(this);
204     separator->setSeparator(true);
205     cmd = am->registerAction(separator, "Find.Sep.Flags", globalcontext);
206     mfind->addAction(cmd, Constants::G_FIND_FLAGS);
207     separator = new QAction(this);
208     separator->setSeparator(true);
209     cmd = am->registerAction(separator, "Find.Sep.Actions", globalcontext);
210     mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
211
212     Core::ActionContainer *mfindadvanced = am->createMenu(Constants::M_FIND_ADVANCED);
213     mfindadvanced->menu()->setTitle(tr("Advanced Find"));
214     mfind->addMenu(mfindadvanced, Constants::G_FIND_FILTERS);
215     d->m_openFindDialog = new QAction(tr("Open Advanced Find..."), this);
216     d->m_openFindDialog->setIconText(tr("Advanced..."));
217     cmd = am->registerAction(d->m_openFindDialog, Constants::ADVANCED_FIND, globalcontext);
218     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F")));
219     mfindadvanced->addAction(cmd);
220     connect(d->m_openFindDialog, SIGNAL(triggered()), this, SLOT(openFindFilter()));
221 }
222
223 void FindPlugin::setupFilterMenuItems()
224 {
225     Core::ActionManager *am = Core::ICore::instance()->actionManager();
226     QList<IFindFilter*> findInterfaces =
227         ExtensionSystem::PluginManager::instance()->getObjects<IFindFilter>();
228     Core::Command *cmd;
229     Core::Context globalcontext(Core::Constants::C_GLOBAL);
230
231     Core::ActionContainer *mfindadvanced = am->actionContainer(Constants::M_FIND_ADVANCED);
232     d->m_filterActions.clear();
233     bool haveEnabledFilters = false;
234     foreach (IFindFilter *filter, findInterfaces) {
235         QAction *action = new QAction(QLatin1String("    ") + filter->displayName(), this);
236         bool isEnabled = filter->isEnabled();
237         if (isEnabled)
238             haveEnabledFilters = true;
239         action->setEnabled(isEnabled);
240         action->setData(qVariantFromValue(filter));
241         cmd = am->registerAction(action, QString(QLatin1String("FindFilter.")+filter->id()), globalcontext);
242         cmd->setDefaultKeySequence(filter->defaultShortcut());
243         mfindadvanced->addAction(cmd);
244         d->m_filterActions.insert(filter, action);
245         connect(action, SIGNAL(triggered(bool)), this, SLOT(openFindFilter()));
246         connect(filter, SIGNAL(changed()), this, SLOT(filterChanged()));
247     }
248     d->m_findDialog->setFindFilters(findInterfaces);
249     d->m_openFindDialog->setEnabled(haveEnabledFilters);
250 }
251
252 Find::FindFlags FindPlugin::findFlags() const
253 {
254     return d->m_findFlags;
255 }
256
257 void FindPlugin::setCaseSensitive(bool sensitive)
258 {
259     setFindFlag(Find::FindCaseSensitively, sensitive);
260 }
261
262 void FindPlugin::setWholeWord(bool wholeOnly)
263 {
264     setFindFlag(Find::FindWholeWords, wholeOnly);
265 }
266
267 void FindPlugin::setBackward(bool backward)
268 {
269     setFindFlag(Find::FindBackward, backward);
270 }
271
272 void FindPlugin::setRegularExpression(bool regExp)
273 {
274     setFindFlag(Find::FindRegularExpression, regExp);
275 }
276
277 void FindPlugin::setFindFlag(Find::FindFlag flag, bool enabled)
278 {
279     bool hasFlag = hasFindFlag(flag);
280     if ((hasFlag && enabled) || (!hasFlag && !enabled))
281         return;
282     if (enabled)
283         d->m_findFlags |= flag;
284     else
285         d->m_findFlags &= ~flag;
286     if (flag != Find::FindBackward)
287         emit findFlagsChanged();
288 }
289
290 bool FindPlugin::hasFindFlag(Find::FindFlag flag)
291 {
292     return d->m_findFlags & flag;
293 }
294
295 void FindPlugin::writeSettings()
296 {
297     QSettings *settings = Core::ICore::instance()->settings();
298     settings->beginGroup("Find");
299     settings->setValue("Backward", hasFindFlag(Find::FindBackward));
300     settings->setValue("CaseSensitively", hasFindFlag(Find::FindCaseSensitively));
301     settings->setValue("WholeWords", hasFindFlag(Find::FindWholeWords));
302     settings->setValue("RegularExpression", hasFindFlag(Find::FindRegularExpression));
303     settings->setValue("FindStrings", d->m_findCompletions);
304     settings->setValue("ReplaceStrings", d->m_replaceCompletions);
305     settings->endGroup();
306     d->m_findToolBar->writeSettings();
307     d->m_findDialog->writeSettings();
308 }
309
310 void FindPlugin::readSettings()
311 {
312     QSettings *settings = Core::ICore::instance()->settings();
313     settings->beginGroup("Find");
314     bool block = blockSignals(true);
315     setBackward(settings->value("Backward", false).toBool());
316     setCaseSensitive(settings->value("CaseSensitively", false).toBool());
317     setWholeWord(settings->value("WholeWords", false).toBool());
318     setRegularExpression(settings->value("RegularExpression", false).toBool());
319     blockSignals(block);
320     d->m_findCompletions = settings->value("FindStrings").toStringList();
321     d->m_replaceCompletions = settings->value("ReplaceStrings").toStringList();
322     d->m_findCompletionModel->setStringList(d->m_findCompletions);
323     d->m_replaceCompletionModel->setStringList(d->m_replaceCompletions);
324     settings->endGroup();
325     d->m_findToolBar->readSettings();
326     d->m_findDialog->readSettings();
327     emit findFlagsChanged(); // would have been done in the setXXX methods above
328 }
329
330 void FindPlugin::updateFindCompletion(const QString &text)
331 {
332     updateCompletion(text, d->m_findCompletions, d->m_findCompletionModel);
333 }
334
335 void FindPlugin::updateReplaceCompletion(const QString &text)
336 {
337     updateCompletion(text, d->m_replaceCompletions, d->m_replaceCompletionModel);
338 }
339
340 void FindPlugin::updateCompletion(const QString &text, QStringList &completions, QStringListModel *model)
341 {
342     if (text.isEmpty())
343         return;
344     completions.removeAll(text);
345     completions.prepend(text);
346     while (completions.size() > MAX_COMPLETIONS)
347         completions.removeLast();
348     model->setStringList(completions);
349 }
350
351 void FindPlugin::setUseFakeVim(bool on)
352 {
353     if (d->m_findToolBar)
354         d->m_findToolBar->setUseFakeVim(on);
355 }
356
357 void FindPlugin::openFindToolBar(FindDirection direction)
358 {
359     if (d->m_findToolBar) {
360         d->m_findToolBar->setBackward(direction == FindBackward);
361         d->m_findToolBar->openFindToolBar();
362     }
363 }
364
365 QStringListModel *FindPlugin::findCompletionModel() const
366 {
367     return d->m_findCompletionModel;
368 }
369
370 QStringListModel *FindPlugin::replaceCompletionModel() const
371 {
372     return d->m_replaceCompletionModel;
373 }
374
375 QKeySequence IFindFilter::defaultShortcut() const
376 {
377     return QKeySequence();
378 }
379
380 } // namespace Find
381
382 // declared in textfindconstants.h
383 QTextDocument::FindFlags Find::textDocumentFlagsForFindFlags(Find::FindFlags flags)
384 {
385     QTextDocument::FindFlags textDocFlags;
386     if (flags & Find::FindBackward)
387         textDocFlags |= QTextDocument::FindBackward;
388     if (flags & Find::FindCaseSensitively)
389         textDocFlags |= QTextDocument::FindCaseSensitively;
390     if (flags & Find::FindWholeWords)
391         textDocFlags |= QTextDocument::FindWholeWords;
392     return textDocFlags;
393 }
394
395 Q_EXPORT_PLUGIN(Find::FindPlugin)