Keep multiple search results in history.

Change-Id: I7350c78479343e85b1ca4957e08bccefb5756d20
Reviewed-on: http://codereview.qt-project.org/4556
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Leandro T. C. Melo <leandro.melo@nokia.com>
This commit is contained in:
Eike Ziller
2011-09-09 16:10:57 +02:00
parent c5c94206ba
commit fdeb7620f1
12 changed files with 205 additions and 107 deletions

View File

@@ -161,8 +161,7 @@ public:
CppFindReferences::CppFindReferences(CppModelManagerInterface *modelManager) CppFindReferences::CppFindReferences(CppModelManagerInterface *modelManager)
: QObject(modelManager), : QObject(modelManager),
_modelManager(modelManager), _modelManager(modelManager)
m_currentSearch(0)
{ {
m_watcher.setPendingResultsLimit(1); m_watcher.setPendingResultsLimit(1);
connect(&m_watcher, SIGNAL(resultsReadyAt(int,int)), this, SLOT(displayResults(int,int))); connect(&m_watcher, SIGNAL(resultsReadyAt(int,int)), this, SLOT(displayResults(int,int)));
@@ -227,9 +226,11 @@ static void find_helper(QFutureInterface<Usage> &future,
void CppFindReferences::findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context) void CppFindReferences::findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context)
{ {
m_currentSearch = Find::SearchResultWindow::instance()->startNewSearch(Find::SearchResultWindow::SearchOnly);
Overview overview; Overview overview;
m_currentSearch->setInfo(tr("C++ Usages:"), QString(), overview(context.fullyQualifiedName(symbol))); m_currentSearch = Find::SearchResultWindow::instance()->startNewSearch(tr("C++ Usages:"),
QString(),
overview(context.fullyQualifiedName(symbol)),
Find::SearchResultWindow::SearchOnly);
connect(m_currentSearch, SIGNAL(activated(Find::SearchResultItem)), connect(m_currentSearch, SIGNAL(activated(Find::SearchResultItem)),
this, SLOT(openEditor(Find::SearchResultItem))); this, SLOT(openEditor(Find::SearchResultItem)));
@@ -243,10 +244,12 @@ void CppFindReferences::renameUsages(CPlusPlus::Symbol *symbol, const CPlusPlus:
const QString textToReplace = replacement.isEmpty() const QString textToReplace = replacement.isEmpty()
? QString::fromUtf8(id->chars(), id->size()) : replacement; ? QString::fromUtf8(id->chars(), id->size()) : replacement;
m_currentSearch = Find::SearchResultWindow::instance()->startNewSearch(
Find::SearchResultWindow::SearchAndReplace, QLatin1String("CppEditor"));
Overview overview; Overview overview;
m_currentSearch->setInfo(tr("C++ Usages:"), QString(), overview(context.fullyQualifiedName(symbol))); m_currentSearch = Find::SearchResultWindow::instance()->startNewSearch(
tr("C++ Usages:"),
QString(),
overview(context.fullyQualifiedName(symbol)),
Find::SearchResultWindow::SearchAndReplace, QLatin1String("CppEditor"));
m_currentSearch->setTextToReplace(textToReplace); m_currentSearch->setTextToReplace(textToReplace);
connect(m_currentSearch, SIGNAL(activated(Find::SearchResultItem)), connect(m_currentSearch, SIGNAL(activated(Find::SearchResultItem)),
@@ -293,6 +296,10 @@ void CppFindReferences::onReplaceButtonClicked(const QString &text,
void CppFindReferences::displayResults(int first, int last) void CppFindReferences::displayResults(int first, int last)
{ {
if (!m_currentSearch) {
m_watcher.cancel();
return;
}
for (int index = first; index != last; ++index) { for (int index = first; index != last; ++index) {
Usage result = m_watcher.future().resultAt(index); Usage result = m_watcher.future().resultAt(index);
m_currentSearch->addResult(result.path, m_currentSearch->addResult(result.path,
@@ -305,6 +312,7 @@ void CppFindReferences::displayResults(int first, int last)
void CppFindReferences::searchFinished() void CppFindReferences::searchFinished()
{ {
if (m_currentSearch)
m_currentSearch->finishSearch(); m_currentSearch->finishSearch();
m_currentSearch = 0; m_currentSearch = 0;
emit changed(); emit changed();
@@ -422,8 +430,11 @@ static void findMacroUses_helper(QFutureInterface<Usage> &future,
void CppFindReferences::findMacroUses(const Macro &macro) void CppFindReferences::findMacroUses(const Macro &macro)
{ {
m_currentSearch = Find::SearchResultWindow::instance()->startNewSearch(Find::SearchResultWindow::SearchOnly); m_currentSearch = Find::SearchResultWindow::instance()->startNewSearch(
m_currentSearch->setInfo(tr("C++ Macro Usages:"), QString(), QString::fromLocal8Bit(macro.name())); tr("C++ Macro Usages:"),
QString(),
macro.name(),
Find::SearchResultWindow::SearchOnly);
Find::SearchResultWindow::instance()->popup(true); Find::SearchResultWindow::instance()->popup(true);

View File

@@ -94,7 +94,7 @@ private:
private: private:
QPointer<CPlusPlus::CppModelManagerInterface> _modelManager; QPointer<CPlusPlus::CppModelManagerInterface> _modelManager;
Find::SearchResult *m_currentSearch; QPointer<Find::SearchResult> m_currentSearch;
QFutureWatcher<CPlusPlus::Usage> m_watcher; QFutureWatcher<CPlusPlus::Usage> m_watcher;
mutable QMutex m_depsLock; mutable QMutex m_depsLock;

View File

@@ -104,7 +104,6 @@ SymbolsFindFilter::SymbolsFindFilter(CppModelManager *manager)
: m_manager(manager), : m_manager(manager),
m_isRunning(false), m_isRunning(false),
m_enabled(true), m_enabled(true),
m_currentSearch(0),
m_symbolsToSearch(SearchSymbols::AllTypes), m_symbolsToSearch(SearchSymbols::AllTypes),
m_scope(SearchProjectsOnly) m_scope(SearchProjectsOnly)
{ {
@@ -150,8 +149,7 @@ void SymbolsFindFilter::findAll(const QString &txt, Find::FindFlags findFlags)
m_isRunning = true; m_isRunning = true;
emit changed(); emit changed();
Find::SearchResultWindow *window = Find::SearchResultWindow::instance(); Find::SearchResultWindow *window = Find::SearchResultWindow::instance();
m_currentSearch = window->startNewSearch(); m_currentSearch = window->startNewSearch(label(), toolTip(findFlags), txt);
m_currentSearch->setInfo(label(), toolTip(findFlags), txt);
connect(m_currentSearch, SIGNAL(activated(Find::SearchResultItem)), this, SLOT(openEditor(Find::SearchResultItem))); connect(m_currentSearch, SIGNAL(activated(Find::SearchResultItem)), this, SLOT(openEditor(Find::SearchResultItem)));
window->popup(true); window->popup(true);
@@ -177,6 +175,10 @@ void SymbolsFindFilter::findAll(const QString &txt, Find::FindFlags findFlags)
void SymbolsFindFilter::addResults(int begin, int end) void SymbolsFindFilter::addResults(int begin, int end)
{ {
if (!m_currentSearch) {
m_watcher.cancel();
return;
}
QList<Find::SearchResultItem> items; QList<Find::SearchResultItem> items;
for (int i = begin; i < end; ++i) for (int i = begin; i < end; ++i)
items << m_watcher.resultAt(i); items << m_watcher.resultAt(i);
@@ -185,6 +187,7 @@ void SymbolsFindFilter::addResults(int begin, int end)
void SymbolsFindFilter::finish() void SymbolsFindFilter::finish()
{ {
if (m_currentSearch)
m_currentSearch->finishSearch(); m_currentSearch->finishSearch();
m_currentSearch = 0; m_currentSearch = 0;
m_isRunning = false; m_isRunning = false;

View File

@@ -40,6 +40,7 @@
#include <QtCore/QFutureInterface> #include <QtCore/QFutureInterface>
#include <QtCore/QFutureWatcher> #include <QtCore/QFutureWatcher>
#include <QtCore/QPointer>
#include <QtGui/QWidget> #include <QtGui/QWidget>
#include <QtGui/QCheckBox> #include <QtGui/QCheckBox>
#include <QtGui/QRadioButton> #include <QtGui/QRadioButton>
@@ -97,7 +98,7 @@ private:
bool m_isRunning; bool m_isRunning;
bool m_enabled; bool m_enabled;
QFutureWatcher<Find::SearchResultItem> m_watcher; QFutureWatcher<Find::SearchResultItem> m_watcher;
Find::SearchResult *m_currentSearch; QPointer<Find::SearchResult> m_currentSearch;
SearchSymbols::SymbolTypes m_symbolsToSearch; SearchSymbols::SymbolTypes m_symbolsToSearch;
SearchSymbols m_search; SearchSymbols m_search;
SearchScope m_scope; SearchScope m_scope;

View File

@@ -254,7 +254,6 @@ SearchResultWidget::SearchResultWidget(QWidget *parent) :
m_cancelButton->setText(tr("Cancel")); m_cancelButton->setText(tr("Cancel"));
m_cancelButton->setToolButtonStyle(Qt::ToolButtonTextOnly); m_cancelButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(cancel())); connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(cancel()));
m_cancelButton->setVisible(false);
m_replaceLabel = new QLabel(tr("Replace with:"), topWidget); m_replaceLabel = new QLabel(tr("Replace with:"), topWidget);
m_replaceTextEdit = new WideEnoughLineEdit(topWidget); m_replaceTextEdit = new WideEnoughLineEdit(topWidget);
@@ -285,11 +284,6 @@ SearchResultWidget::SearchResultWidget(QWidget *parent) :
connect(m_replaceButton, SIGNAL(clicked()), this, SLOT(handleReplaceButton())); connect(m_replaceButton, SIGNAL(clicked()), this, SLOT(handleReplaceButton()));
} }
void SearchResultWidget::startSearch()
{
m_cancelButton->setVisible(true);
}
void SearchResultWidget::setInfo(const QString &label, const QString &toolTip, const QString &term) void SearchResultWidget::setInfo(const QString &label, const QString &toolTip, const QString &term)
{ {
m_label->setText(label); m_label->setText(label);
@@ -319,7 +313,7 @@ void SearchResultWidget::addResults(const QList<SearchResultItem> &items, Search
m_count += items.size(); m_count += items.size();
m_searchResultTreeView->addResults(items, mode); m_searchResultTreeView->addResults(items, mode);
if (firstItems) { if (firstItems) {
if (!m_dontAskAgainGroup.isEmpty() && showWarningMessage()) { if (showWarningMessage()) {
Core::InfoBarEntry info("warninglabel", tr("This change cannot be undone.")); Core::InfoBarEntry info("warninglabel", tr("This change cannot be undone."));
info.setCustomButtonInfo(tr("Do not warn again"), this, SLOT(hideNoUndoWarning())); info.setCustomButtonInfo(tr("Do not warn again"), this, SLOT(hideNoUndoWarning()));
m_infoBar.addInfo(info); m_infoBar.addInfo(info);
@@ -497,6 +491,8 @@ void SearchResultWidget::cancel()
bool SearchResultWidget::showWarningMessage() const bool SearchResultWidget::showWarningMessage() const
{ {
if (m_dontAskAgainGroup.isEmpty())
return false;
// read settings // read settings
QSettings *settings = Core::ICore::instance()->settings(); QSettings *settings = Core::ICore::instance()->settings();
settings->beginGroup(m_dontAskAgainGroup); settings->beginGroup(m_dontAskAgainGroup);

View File

@@ -53,7 +53,6 @@ class SearchResultWidget : public QWidget
public: public:
explicit SearchResultWidget(QWidget *parent = 0); explicit SearchResultWidget(QWidget *parent = 0);
void startSearch();
void setInfo(const QString &label, const QString &toolTip, const QString &term); void setInfo(const QString &label, const QString &toolTip, const QString &term);
void addResult(const QString &fileName, int lineNumber, const QString &lineText, void addResult(const QString &fileName, int lineNumber, const QString &lineText,

View File

@@ -47,6 +47,7 @@
#include <QtGui/QVBoxLayout> #include <QtGui/QVBoxLayout>
#include <QtGui/QFont> #include <QtGui/QFont>
#include <QtGui/QAction> #include <QtGui/QAction>
#include <QtGui/QComboBox>
#include <QtGui/QStackedWidget> #include <QtGui/QStackedWidget>
static const char SETTINGSKEYSECTIONNAME[] = "SearchResults"; static const char SETTINGSKEYSECTIONNAME[] = "SearchResults";
@@ -56,21 +57,60 @@ namespace Find {
namespace Internal { namespace Internal {
struct SearchResultWindowPrivate { class SearchResultWindowPrivate : public QObject {
SearchResultWindowPrivate(); Q_OBJECT
public:
SearchResultWindowPrivate(SearchResultWindow *window);
bool isSearchVisible() const;
int visibleSearchIndex() const;
Internal::SearchResultWidget *m_searchResultWidget; SearchResultWindow *q;
QList<Internal::SearchResultWidget *> m_searchResultWidgets;
QToolButton *m_expandCollapseButton; QToolButton *m_expandCollapseButton;
QAction *m_expandCollapseAction; QAction *m_expandCollapseAction;
static const bool m_initiallyExpand = false; static const bool m_initiallyExpand = false;
QWidget *m_spacer;
QComboBox *m_recentSearchesBox;
QStackedWidget *m_widget; QStackedWidget *m_widget;
SearchResult *m_currentSearch; QList<SearchResult *> m_searchResults;
int m_currentIndex;
public slots:
void setCurrentIndex(int index);
}; };
SearchResultWindowPrivate::SearchResultWindowPrivate() SearchResultWindowPrivate::SearchResultWindowPrivate(SearchResultWindow *window)
: m_currentSearch(0) : q(window)
{ {
} }
bool SearchResultWindowPrivate::isSearchVisible() const
{
return m_currentIndex > 0;
}
int SearchResultWindowPrivate::visibleSearchIndex() const
{
return m_currentIndex - 1;
}
void SearchResultWindowPrivate::setCurrentIndex(int index)
{
if (isSearchVisible())
m_searchResultWidgets.at(visibleSearchIndex())->notifyVisibilityChanged(false);
m_currentIndex = index;
m_widget->setCurrentIndex(index);
m_recentSearchesBox->setCurrentIndex(index);
if (!isSearchVisible()) {
m_widget->currentWidget()->setFocus();
m_expandCollapseButton->setEnabled(false);
} else {
m_searchResultWidgets.at(visibleSearchIndex())->setFocusInternally();
m_searchResultWidgets.at(visibleSearchIndex())->notifyVisibilityChanged(true);
m_expandCollapseButton->setEnabled(true);
}
q->navigateStateChanged();
}
} }
using namespace Find::Internal; using namespace Find::Internal;
@@ -155,16 +195,21 @@ SearchResultWindow *SearchResultWindow::m_instance = 0;
\internal \internal
*/ */
SearchResultWindow::SearchResultWindow(QWidget *newSearchPanel) SearchResultWindow::SearchResultWindow(QWidget *newSearchPanel)
: d(new SearchResultWindowPrivate) : d(new SearchResultWindowPrivate(this))
{ {
m_instance = this; m_instance = this;
d->m_spacer = new QWidget;
d->m_spacer->setMinimumWidth(30);
d->m_recentSearchesBox = new QComboBox;
d->m_recentSearchesBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
d->m_recentSearchesBox->addItem(tr("New Search"));
connect(d->m_recentSearchesBox, SIGNAL(activated(int)), d, SLOT(setCurrentIndex(int)));
d->m_widget = new QStackedWidget; d->m_widget = new QStackedWidget;
d->m_widget->setWindowTitle(displayName()); d->m_widget->setWindowTitle(displayName());
d->m_widget->addWidget(newSearchPanel); d->m_widget->addWidget(newSearchPanel);
d->m_currentIndex = 0;
d->m_searchResultWidget = new Internal::SearchResultWidget(d->m_widget);
d->m_widget->addWidget(d->m_searchResultWidget);
d->m_expandCollapseButton = new QToolButton(d->m_widget); d->m_expandCollapseButton = new QToolButton(d->m_widget);
d->m_expandCollapseButton->setAutoRaise(true); d->m_expandCollapseButton->setAutoRaise(true);
@@ -179,7 +224,6 @@ SearchResultWindow::SearchResultWindow(QWidget *newSearchPanel)
d->m_expandCollapseButton->setDefaultAction(cmd->action()); d->m_expandCollapseButton->setDefaultAction(cmd->action());
connect(d->m_expandCollapseAction, SIGNAL(toggled(bool)), this, SLOT(handleExpandCollapseToolButton(bool))); connect(d->m_expandCollapseAction, SIGNAL(toggled(bool)), this, SLOT(handleExpandCollapseToolButton(bool)));
connect(d->m_searchResultWidget, SIGNAL(navigateStateChanged()), this, SLOT(navigateStateChanged()));
readSettings(); readSettings();
} }
@@ -190,8 +234,7 @@ SearchResultWindow::SearchResultWindow(QWidget *newSearchPanel)
SearchResultWindow::~SearchResultWindow() SearchResultWindow::~SearchResultWindow()
{ {
writeSettings(); writeSettings();
delete d->m_currentSearch; qDeleteAll(d->m_searchResults);
d->m_currentSearch = 0;
delete d->m_widget; delete d->m_widget;
d->m_widget = 0; d->m_widget = 0;
delete d; delete d;
@@ -212,7 +255,8 @@ SearchResultWindow *SearchResultWindow::instance()
*/ */
void SearchResultWindow::visibilityChanged(bool visible) void SearchResultWindow::visibilityChanged(bool visible)
{ {
d->m_searchResultWidget->notifyVisibilityChanged(visible); if (d->isSearchVisible())
d->m_searchResultWidgets.at(d->visibleSearchIndex())->notifyVisibilityChanged(visible);
} }
/*! /*!
@@ -230,31 +274,56 @@ QWidget *SearchResultWindow::outputWidget(QWidget *)
*/ */
QList<QWidget*> SearchResultWindow::toolBarWidgets() const QList<QWidget*> SearchResultWindow::toolBarWidgets() const
{ {
return QList<QWidget*>() << d->m_expandCollapseButton; return QList<QWidget*>() << d->m_expandCollapseButton << d->m_spacer << d->m_recentSearchesBox;
} }
/*! /*!
\brief Tells the search results window to start a new search. \brief Tells the search results window to start a new search.
This will clear the contents of the previous search and initialize the UI The \a label should be a string that shortly describes the type of
with regard to showing the replace UI or not (depending on the search mode search, i.e. search filter and possibly a most relevant search option, followed by a colon ':'.
in \a searchOrSearchAndReplace). E.g. \code{Project 'myproject':}
The \a searchTerm will be shown behind the colon.
The \a toolTip should elaborate on the search parameters, like file patterns that are searched and
find flags.
If \a cfgGroup is not empty, it will be used for storing the "do not ask again" If \a cfgGroup is not empty, it will be used for storing the "do not ask again"
setting of a "this change cannot be undone" warning (which is implicitly requested setting of a "this change cannot be undone" warning (which is implicitly requested
by passing a non-empty group). by passing a non-empty group).
Returns a SearchResult object that is used for signaling user interaction Returns a SearchResult object that is used for signaling user interaction
with the results of this search. with the results of this search.
The search result window owns the returned SearchResult
and might delete it any time, even while the search is running
(e.g. when the user clears the search result pane, or if the user opens so many other searches
that this search falls out of the history).
*/ */
SearchResult *SearchResultWindow::startNewSearch(SearchMode searchOrSearchAndReplace, const QString &cfgGroup) SearchResult *SearchResultWindow::startNewSearch(const QString &label,
const QString &toolTip,
const QString &searchTerm,
SearchMode searchOrSearchAndReplace,
const QString &cfgGroup)
{ {
clearContents(); if (d->m_searchResults.size() >= 5) {
d->m_searchResultWidget->setShowReplaceUI(searchOrSearchAndReplace != SearchOnly); d->m_searchResultWidgets.last()->notifyVisibilityChanged(false);
d->m_searchResultWidget->setDontAskAgainGroup(cfgGroup); delete d->m_searchResults.takeLast();
d->m_searchResultWidget->startSearch(); delete d->m_searchResultWidgets.takeLast();
d->m_widget->setCurrentWidget(d->m_searchResultWidget); d->m_recentSearchesBox->removeItem(d->m_recentSearchesBox->count()-1);
delete d->m_currentSearch; }
d->m_currentSearch = new SearchResult(d->m_searchResultWidget); Internal::SearchResultWidget *widget = new Internal::SearchResultWidget;
return d->m_currentSearch; d->m_searchResultWidgets.prepend(widget);
d->m_widget->insertWidget(1, widget);
connect(widget, SIGNAL(navigateStateChanged()), this, SLOT(navigateStateChanged()));
widget->setShowReplaceUI(searchOrSearchAndReplace != SearchOnly);
widget->setInfo(label, toolTip, searchTerm);
if (searchOrSearchAndReplace == SearchAndReplace)
widget->setDontAskAgainGroup(cfgGroup);
SearchResult *result = new SearchResult(widget);
d->m_searchResults.prepend(result);
d->m_recentSearchesBox->insertItem(1, tr("%1 %2").arg(label, searchTerm));
if (d->m_currentIndex > 0)
++d->m_currentIndex; // so setCurrentIndex still knows about the right "currentIndex" and its widget
d->setCurrentIndex(1);
return result;
} }
/*! /*!
@@ -263,7 +332,18 @@ SearchResult *SearchResultWindow::startNewSearch(SearchMode searchOrSearchAndRep
*/ */
void SearchResultWindow::clearContents() void SearchResultWindow::clearContents()
{ {
d->m_searchResultWidget->clear(); for (int i = d->m_recentSearchesBox->count() - 1; i > 0 /* don't want i==0 */; --i)
d->m_recentSearchesBox->removeItem(i);
foreach (Internal::SearchResultWidget *widget, d->m_searchResultWidgets)
widget->notifyVisibilityChanged(false);
qDeleteAll(d->m_searchResultWidgets);
d->m_searchResultWidgets.clear();
qDeleteAll(d->m_searchResults);
d->m_searchResults.clear();
d->m_currentIndex = 0;
d->m_widget->currentWidget()->setFocus();
d->m_expandCollapseButton->setEnabled(false);
navigateStateChanged(); navigateStateChanged();
} }
@@ -273,7 +353,7 @@ void SearchResultWindow::clearContents()
*/ */
bool SearchResultWindow::hasFocus() bool SearchResultWindow::hasFocus()
{ {
return d->m_searchResultWidget->hasFocusInternally(); return d->m_widget->focusWidget() && d->m_widget->focusWidget()->hasFocus();
} }
/*! /*!
@@ -282,7 +362,9 @@ bool SearchResultWindow::hasFocus()
*/ */
bool SearchResultWindow::canFocus() bool SearchResultWindow::canFocus()
{ {
return d->m_searchResultWidget->canFocusInternally(); if (d->isSearchVisible())
return d->m_searchResultWidgets.at(d->visibleSearchIndex())->canFocusInternally();
return true;
} }
/*! /*!
@@ -291,11 +373,10 @@ bool SearchResultWindow::canFocus()
*/ */
void SearchResultWindow::setFocus() void SearchResultWindow::setFocus()
{ {
int stackIndex = d->m_widget->currentIndex(); if (!d->isSearchVisible())
if (stackIndex == 0)
d->m_widget->currentWidget()->setFocus(); d->m_widget->currentWidget()->setFocus();
else else
d->m_searchResultWidget->setFocusInternally(); d->m_searchResultWidgets.at(d->visibleSearchIndex())->setFocusInternally();
} }
/*! /*!
@@ -304,12 +385,13 @@ void SearchResultWindow::setFocus()
*/ */
void SearchResultWindow::setTextEditorFont(const QFont &font) void SearchResultWindow::setTextEditorFont(const QFont &font)
{ {
d->m_searchResultWidget->setTextEditorFont(font); foreach (Internal::SearchResultWidget *widget, d->m_searchResultWidgets)
widget->setTextEditorFont(font);
} }
void SearchResultWindow::openNewSearchPanel() void SearchResultWindow::openNewSearchPanel()
{ {
d->m_widget->setCurrentIndex(0); d->setCurrentIndex(0);
popup(); popup();
} }
@@ -319,13 +401,15 @@ void SearchResultWindow::openNewSearchPanel()
*/ */
void SearchResultWindow::handleExpandCollapseToolButton(bool checked) void SearchResultWindow::handleExpandCollapseToolButton(bool checked)
{ {
d->m_searchResultWidget->setAutoExpandResults(checked); if (!d->isSearchVisible())
return;
d->m_searchResultWidgets.at(d->visibleSearchIndex())->setAutoExpandResults(checked);
if (checked) { if (checked) {
d->m_expandCollapseAction->setText(tr("Collapse All")); d->m_expandCollapseAction->setText(tr("Collapse All"));
d->m_searchResultWidget->expandAll(); d->m_searchResultWidgets.at(d->visibleSearchIndex())->expandAll();
} else { } else {
d->m_expandCollapseAction->setText(tr("Expand All")); d->m_expandCollapseAction->setText(tr("Expand All"));
d->m_searchResultWidget->collapseAll(); d->m_searchResultWidgets.at(d->visibleSearchIndex())->collapseAll();
} }
} }
@@ -372,7 +456,9 @@ int SearchResultWindow::priorityInStatusBar() const
*/ */
bool SearchResultWindow::canNext() bool SearchResultWindow::canNext()
{ {
return d->m_searchResultWidget->count() > 0; if (d->isSearchVisible())
return d->m_searchResultWidgets.at(d->visibleSearchIndex())->count() > 0;
return false;
} }
/*! /*!
@@ -381,7 +467,7 @@ bool SearchResultWindow::canNext()
*/ */
bool SearchResultWindow::canPrevious() bool SearchResultWindow::canPrevious()
{ {
return d->m_searchResultWidget->count() > 0; return canNext();
} }
/*! /*!
@@ -390,7 +476,9 @@ bool SearchResultWindow::canPrevious()
*/ */
void SearchResultWindow::goToNext() void SearchResultWindow::goToNext()
{ {
d->m_searchResultWidget->goToNext(); int index = d->m_widget->currentIndex();
if (index != 0)
d->m_searchResultWidgets.at(index-1)->goToNext();
} }
/*! /*!
@@ -399,7 +487,9 @@ void SearchResultWindow::goToNext()
*/ */
void SearchResultWindow::goToPrev() void SearchResultWindow::goToPrev()
{ {
d->m_searchResultWidget->goToPrevious(); int index = d->m_widget->currentIndex();
if (index != 0)
d->m_searchResultWidgets.at(index-1)->goToPrevious();
} }
/*! /*!
@@ -459,23 +549,6 @@ QString SearchResult::textToReplace() const
return m_widget->textToReplace(); return m_widget->textToReplace();
} }
/*!
\fn void SearchResult::setInfo(const QString &label, const QString &toolTip, const QString &term)
\brief Set the information about the search that is show in the top-left corner of
the search result window.
The \a label should be a string that shortly describes the
search, i.e. search filter and a most relevant search options, followed by a colon ':'.
E.g. \code{Project 'myproject':}
The search \a term will be shown behind the colon.
The \a toolTip should elaborate on the search parameters, like file patterns that are searched and
find flags.
*/
void SearchResult::setInfo(const QString &label, const QString &toolTip, const QString &term)
{
m_widget->setInfo(label, toolTip, term);
}
/*! /*!
\fn void SearchResult::addResult(const QString &fileName, int lineNumber, const QString &rowText, int searchTermStart, int searchTermLength, const QVariant &userData) \fn void SearchResult::addResult(const QString &fileName, int lineNumber, const QString &rowText, int searchTermStart, int searchTermLength, const QVariant &userData)
\brief Adds a single result line to the search results. \brief Adds a single result line to the search results.
@@ -528,3 +601,5 @@ void SearchResult::setTextToReplace(const QString &textToReplace)
} }
} // namespace Find } // namespace Find
#include "searchresultwindow.moc"

View File

@@ -48,7 +48,7 @@ QT_END_NAMESPACE
namespace Find { namespace Find {
namespace Internal { namespace Internal {
class SearchResultTreeView; class SearchResultTreeView;
struct SearchResultWindowPrivate; class SearchResultWindowPrivate;
class SearchResultWidget; class SearchResultWidget;
} }
class SearchResultWindow; class SearchResultWindow;
@@ -98,7 +98,6 @@ public:
void setUserData(const QVariant &data); void setUserData(const QVariant &data);
QVariant userData() const; QVariant userData() const;
QString textToReplace() const; QString textToReplace() const;
void setInfo(const QString &label, const QString &toolTip, const QString &term);
public slots: public slots:
void addResult(const QString &fileName, int lineNumber, const QString &lineText, void addResult(const QString &fileName, int lineNumber, const QString &lineText,
@@ -156,8 +155,14 @@ public:
void setTextEditorFont(const QFont &font); void setTextEditorFont(const QFont &font);
void openNewSearchPanel(); void openNewSearchPanel();
// search result object is guaranteed to live till its finishSearch method is called // The search result window owns the returned SearchResult
SearchResult *startNewSearch(SearchMode searchOrSearchAndReplace = SearchOnly, // and might delete it any time, even while the search is running
// (e.g. when the user clears the search result pane, or if the user opens so many other searches
// that this search falls out of the history).
SearchResult *startNewSearch(const QString &label,
const QString &toolTip,
const QString &searchTerm,
SearchMode searchOrSearchAndReplace = SearchOnly,
const QString &cfgGroup = QString()); const QString &cfgGroup = QString());
public slots: public slots:

View File

@@ -776,8 +776,7 @@ public:
} // end of anonymous namespace } // end of anonymous namespace
FindReferences::FindReferences(QObject *parent) FindReferences::FindReferences(QObject *parent)
: QObject(parent), : QObject(parent)
m_currentSearch(0)
{ {
m_watcher.setPendingResultsLimit(1); m_watcher.setPendingResultsLimit(1);
connect(&m_watcher, SIGNAL(resultsReadyAt(int,int)), this, SLOT(displayResults(int,int))); connect(&m_watcher, SIGNAL(resultsReadyAt(int,int)), this, SLOT(displayResults(int,int)));
@@ -914,18 +913,20 @@ void FindReferences::displayResults(int first, int last)
// the first usage is always a dummy to indicate we now start searching // the first usage is always a dummy to indicate we now start searching
if (first == 0) { if (first == 0) {
Usage dummy = m_watcher.future().resultAt(0); Usage dummy = m_watcher.future().resultAt(0);
QString replacement = dummy.path; const QString replacement = dummy.path;
QString symbolName = dummy.lineText; const QString symbolName = dummy.lineText;
const QString label = tr("QML/JS Usages:");
if (replacement.isEmpty()) { if (replacement.isEmpty()) {
m_currentSearch = Find::SearchResultWindow::instance()->startNewSearch(Find::SearchResultWindow::SearchOnly); m_currentSearch = Find::SearchResultWindow::instance()->startNewSearch(
label, QString(), symbolName, Find::SearchResultWindow::SearchOnly);
} else { } else {
m_currentSearch = Find::SearchResultWindow::instance()->startNewSearch(Find::SearchResultWindow::SearchAndReplace); m_currentSearch = Find::SearchResultWindow::instance()->startNewSearch(
label, QString(), symbolName, Find::SearchResultWindow::SearchAndReplace);
m_currentSearch->setTextToReplace(replacement); m_currentSearch->setTextToReplace(replacement);
connect(m_currentSearch, SIGNAL(replaceButtonClicked(QString,QList<Find::SearchResultItem>)), connect(m_currentSearch, SIGNAL(replaceButtonClicked(QString,QList<Find::SearchResultItem>)),
SLOT(onReplaceButtonClicked(QString,QList<Find::SearchResultItem>))); SLOT(onReplaceButtonClicked(QString,QList<Find::SearchResultItem>)));
} }
m_currentSearch->setInfo(tr("Usages:"), QString(), symbolName);
connect(m_currentSearch, SIGNAL(activated(Find::SearchResultItem)), connect(m_currentSearch, SIGNAL(activated(Find::SearchResultItem)),
this, SLOT(openEditor(Find::SearchResultItem))); this, SLOT(openEditor(Find::SearchResultItem)));
connect(m_currentSearch, SIGNAL(cancelled()), this, SLOT(cancel())); connect(m_currentSearch, SIGNAL(cancelled()), this, SLOT(cancel()));
@@ -940,6 +941,10 @@ void FindReferences::displayResults(int first, int last)
++first; ++first;
} }
if (!m_currentSearch) {
m_watcher.cancel();
return;
}
for (int index = first; index != last; ++index) { for (int index = first; index != last; ++index) {
Usage result = m_watcher.future().resultAt(index); Usage result = m_watcher.future().resultAt(index);
m_currentSearch->addResult(result.path, m_currentSearch->addResult(result.path,
@@ -952,6 +957,7 @@ void FindReferences::displayResults(int first, int last)
void FindReferences::searchFinished() void FindReferences::searchFinished()
{ {
if (m_currentSearch)
m_currentSearch->finishSearch(); m_currentSearch->finishSearch();
m_currentSearch = 0; m_currentSearch = 0;
emit changed(); emit changed();

View File

@@ -37,6 +37,7 @@
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QFuture> #include <QtCore/QFuture>
#include <QtCore/QFutureWatcher> #include <QtCore/QFutureWatcher>
#include <QtCore/QPointer>
#include <utils/filesearch.h> #include <utils/filesearch.h>
#include <qmljs/qmljsdocument.h> #include <qmljs/qmljsdocument.h>
@@ -90,7 +91,7 @@ private Q_SLOTS:
void onReplaceButtonClicked(const QString &text, const QList<Find::SearchResultItem> &items); void onReplaceButtonClicked(const QString &text, const QList<Find::SearchResultItem> &items);
private: private:
Find::SearchResult *m_currentSearch; QPointer<Find::SearchResult> m_currentSearch;
QFutureWatcher<Usage> m_watcher; QFutureWatcher<Usage> m_watcher;
}; };

View File

@@ -113,14 +113,10 @@ void BaseFileFind::runNewSearch(const QString &txt, Find::FindFlags findFlags,
updateComboEntries(m_filterCombo, true); updateComboEntries(m_filterCombo, true);
m_watcher.setFuture(QFuture<FileSearchResultList>()); m_watcher.setFuture(QFuture<FileSearchResultList>());
m_currentSearchCount = 0; m_currentSearchCount = 0;
m_currentSearch = Find::SearchResultWindow::instance()->startNewSearch(searchMode, m_currentSearch = Find::SearchResultWindow::instance()->startNewSearch(label(),
searchMode == SearchResultWindow::SearchAndReplace
? QString::fromLatin1("TextEditor")
: QString());
m_currentSearch->setTextToReplace(txt);
m_currentSearch->setInfo(label(),
toolTip().arg(Find::IFindFilter::descriptionForFindFlags(findFlags)), toolTip().arg(Find::IFindFilter::descriptionForFindFlags(findFlags)),
txt); txt, searchMode, QString::fromLatin1("TextEditor"));
m_currentSearch->setTextToReplace(txt);
QVariantList searchParameters; QVariantList searchParameters;
searchParameters << qVariantFromValue(txt) << qVariantFromValue(findFlags); searchParameters << qVariantFromValue(txt) << qVariantFromValue(findFlags);
m_currentSearch->setUserData(searchParameters); m_currentSearch->setUserData(searchParameters);
@@ -169,6 +165,10 @@ void BaseFileFind::doReplace(const QString &text,
} }
void BaseFileFind::displayResult(int index) { void BaseFileFind::displayResult(int index) {
if (!m_currentSearch) {
m_watcher.cancel();
return;
}
Utils::FileSearchResultList results = m_watcher.future().resultAt(index); Utils::FileSearchResultList results = m_watcher.future().resultAt(index);
QList<Find::SearchResultItem> items; QList<Find::SearchResultItem> items;
foreach (const Utils::FileSearchResult &result, results) { foreach (const Utils::FileSearchResult &result, results) {
@@ -190,6 +190,7 @@ void BaseFileFind::displayResult(int index) {
void BaseFileFind::searchFinished() void BaseFileFind::searchFinished()
{ {
if (m_currentSearch)
m_currentSearch->finishSearch(); m_currentSearch->finishSearch();
m_currentSearch = 0; m_currentSearch = 0;
m_isSearching = false; m_isSearching = false;

View File

@@ -78,8 +78,8 @@ public:
protected: protected:
virtual Utils::FileIterator *files() const = 0; virtual Utils::FileIterator *files() const = 0;
virtual QString label() const = 0; // see Find::SearchResult::setInfo virtual QString label() const = 0; // see Find::SearchResultWindow::startNewSearch
virtual QString toolTip() const = 0; // see Find::SearchResult::setInfo, virtual QString toolTip() const = 0; // see Find::SearchResultWindow::startNewSearch,
// add %1 placeholder where the find flags should be put // add %1 placeholder where the find flags should be put
void writeCommonSettings(QSettings *settings); void writeCommonSettings(QSettings *settings);
@@ -103,7 +103,7 @@ private:
void runNewSearch(const QString &txt, Find::FindFlags findFlags, void runNewSearch(const QString &txt, Find::FindFlags findFlags,
Find::SearchResultWindow::SearchMode searchMode); Find::SearchResultWindow::SearchMode searchMode);
Find::SearchResult *m_currentSearch; QPointer<Find::SearchResult> m_currentSearch;
int m_currentSearchCount; int m_currentSearchCount;
QFutureWatcher<Utils::FileSearchResultList> m_watcher; QFutureWatcher<Utils::FileSearchResultList> m_watcher;