summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/plugins/cpptools/CppTools.pluginspec1
-rw-r--r--src/plugins/cpptools/cppclassesfilter.cpp4
-rw-r--r--src/plugins/cpptools/cppclassesfilter.h2
-rw-r--r--src/plugins/cpptools/cppfindreferences.cpp6
-rw-r--r--src/plugins/cpptools/cppfunctionsfilter.cpp4
-rw-r--r--src/plugins/cpptools/cppfunctionsfilter.h2
-rw-r--r--src/plugins/cpptools/cpplocatorfilter.cpp5
-rw-r--r--src/plugins/cpptools/cpplocatorfilter.h7
-rw-r--r--src/plugins/cpptools/cpptools.pro6
-rw-r--r--src/plugins/cpptools/cpptools_dependencies.pri1
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.cpp10
-rw-r--r--src/plugins/cpptools/searchsymbols.cpp13
-rw-r--r--src/plugins/cpptools/searchsymbols.h22
-rw-r--r--src/plugins/cpptools/symbolsfindfilter.cpp317
-rw-r--r--src/plugins/cpptools/symbolsfindfilter.h124
-rw-r--r--src/plugins/find/ifindfilter.h4
-rw-r--r--src/plugins/find/searchresulttreeitemdelegate.cpp82
-rw-r--r--src/plugins/find/searchresulttreeitemdelegate.h3
-rw-r--r--src/plugins/find/searchresulttreeitemroles.h11
-rw-r--r--src/plugins/find/searchresulttreeitems.cpp108
-rw-r--r--src/plugins/find/searchresulttreeitems.h62
-rw-r--r--src/plugins/find/searchresulttreemodel.cpp381
-rw-r--r--src/plugins/find/searchresulttreemodel.h25
-rw-r--r--src/plugins/find/searchresulttreeview.cpp19
-rw-r--r--src/plugins/find/searchresulttreeview.h4
-rw-r--r--src/plugins/find/searchresultwindow.cpp62
-rw-r--r--src/plugins/find/searchresultwindow.h53
-rw-r--r--src/plugins/plugins.pro1
-rw-r--r--src/plugins/projectexplorer/allprojectsfind.cpp5
-rw-r--r--src/plugins/projectexplorer/allprojectsfind.h1
-rw-r--r--src/plugins/projectexplorer/currentprojectfind.cpp5
-rw-r--r--src/plugins/projectexplorer/currentprojectfind.h1
-rw-r--r--src/plugins/texteditor/basefilefind.cpp23
-rw-r--r--src/plugins/texteditor/findincurrentfile.cpp5
-rw-r--r--src/plugins/texteditor/findincurrentfile.h1
-rw-r--r--src/plugins/texteditor/findinfiles.cpp5
-rw-r--r--src/plugins/texteditor/findinfiles.h1
37 files changed, 919 insertions, 467 deletions
diff --git a/src/plugins/cpptools/CppTools.pluginspec b/src/plugins/cpptools/CppTools.pluginspec
index bc76520f15..35492513f3 100644
--- a/src/plugins/cpptools/CppTools.pluginspec
+++ b/src/plugins/cpptools/CppTools.pluginspec
@@ -17,5 +17,6 @@ Alternatively, this plugin may be used under the terms of the GNU Lesser General
<dependency name="TextEditor" version="2.1.80"/>
<dependency name="ProjectExplorer" version="2.1.80"/>
<dependency name="Locator" version="2.1.80"/>
+ <dependency name="Find" version="2.1.80"/>
</dependencyList>
</plugin>
diff --git a/src/plugins/cpptools/cppclassesfilter.cpp b/src/plugins/cpptools/cppclassesfilter.cpp
index d15901c120..7609949a74 100644
--- a/src/plugins/cpptools/cppclassesfilter.cpp
+++ b/src/plugins/cpptools/cppclassesfilter.cpp
@@ -31,8 +31,8 @@
using namespace CppTools::Internal;
-CppClassesFilter::CppClassesFilter(CppModelManager *manager, Core::EditorManager *editorManager)
- : CppLocatorFilter(manager, editorManager)
+CppClassesFilter::CppClassesFilter(CppModelManager *manager)
+ : CppLocatorFilter(manager)
{
setShortcutString("c");
setIncludedByDefault(false);
diff --git a/src/plugins/cpptools/cppclassesfilter.h b/src/plugins/cpptools/cppclassesfilter.h
index 7fbbe475b0..417997ada0 100644
--- a/src/plugins/cpptools/cppclassesfilter.h
+++ b/src/plugins/cpptools/cppclassesfilter.h
@@ -40,7 +40,7 @@ class CppClassesFilter : public CppLocatorFilter
Q_OBJECT
public:
- CppClassesFilter(CppModelManager *manager, Core::EditorManager *editorManager);
+ CppClassesFilter(CppModelManager *manager);
~CppClassesFilter();
QString displayName() const { return tr("Classes"); }
diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp
index c3c36dcb2e..451aef4261 100644
--- a/src/plugins/cpptools/cppfindreferences.cpp
+++ b/src/plugins/cpptools/cppfindreferences.cpp
@@ -313,7 +313,11 @@ void CppFindReferences::searchFinished()
void CppFindReferences::openEditor(const Find::SearchResultItem &item)
{
- TextEditor::BaseTextEditor::openEditorAt(item.fileName, item.lineNumber, item.searchTermStart);
+ if (item.path.size() > 0) {
+ TextEditor::BaseTextEditor::openEditorAt(item.path.first(), item.lineNumber, item.textMarkPos);
+ } else {
+ Core::EditorManager::instance()->openEditor(item.text);
+ }
}
diff --git a/src/plugins/cpptools/cppfunctionsfilter.cpp b/src/plugins/cpptools/cppfunctionsfilter.cpp
index 300a9f065c..bc8f46e6b5 100644
--- a/src/plugins/cpptools/cppfunctionsfilter.cpp
+++ b/src/plugins/cpptools/cppfunctionsfilter.cpp
@@ -31,8 +31,8 @@
using namespace CppTools::Internal;
-CppFunctionsFilter::CppFunctionsFilter(CppModelManager *manager, Core::EditorManager *editorManager)
- : CppLocatorFilter(manager, editorManager)
+CppFunctionsFilter::CppFunctionsFilter(CppModelManager *manager)
+ : CppLocatorFilter(manager)
{
setShortcutString(QString(QLatin1Char('m')));
setIncludedByDefault(false);
diff --git a/src/plugins/cpptools/cppfunctionsfilter.h b/src/plugins/cpptools/cppfunctionsfilter.h
index 35bf55e39c..becae07b03 100644
--- a/src/plugins/cpptools/cppfunctionsfilter.h
+++ b/src/plugins/cpptools/cppfunctionsfilter.h
@@ -40,7 +40,7 @@ class CppFunctionsFilter : public CppLocatorFilter
Q_OBJECT
public:
- CppFunctionsFilter(CppModelManager *manager, Core::EditorManager *editorManager);
+ CppFunctionsFilter(CppModelManager *manager);
~CppFunctionsFilter();
QString displayName() const { return tr("Methods"); }
diff --git a/src/plugins/cpptools/cpplocatorfilter.cpp b/src/plugins/cpptools/cpplocatorfilter.cpp
index 913a411a7f..34c696a15d 100644
--- a/src/plugins/cpptools/cpplocatorfilter.cpp
+++ b/src/plugins/cpptools/cpplocatorfilter.cpp
@@ -30,8 +30,6 @@
#include "cpplocatorfilter.h"
#include "cppmodelmanager.h"
-#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/editormanager/ieditor.h>
#include <texteditor/itexteditor.h>
#include <texteditor/basetexteditor.h>
@@ -39,9 +37,8 @@
using namespace CppTools::Internal;
-CppLocatorFilter::CppLocatorFilter(CppModelManager *manager, Core::EditorManager *editorManager)
+CppLocatorFilter::CppLocatorFilter(CppModelManager *manager)
: m_manager(manager),
- m_editorManager(editorManager),
m_forceNewSearchList(true)
{
setShortcutString(QString(QLatin1Char(':')));
diff --git a/src/plugins/cpptools/cpplocatorfilter.h b/src/plugins/cpptools/cpplocatorfilter.h
index 7176f7a054..4c4df83a23 100644
--- a/src/plugins/cpptools/cpplocatorfilter.h
+++ b/src/plugins/cpptools/cpplocatorfilter.h
@@ -34,10 +34,6 @@
#include <locator/ilocatorfilter.h>
-namespace Core {
-class EditorManager;
-}
-
namespace CppTools {
namespace Internal {
@@ -47,7 +43,7 @@ class CppLocatorFilter : public Locator::ILocatorFilter
{
Q_OBJECT
public:
- CppLocatorFilter(CppModelManager *manager, Core::EditorManager *editorManager);
+ CppLocatorFilter(CppModelManager *manager);
~CppLocatorFilter();
QString displayName() const { return tr("Classes and Methods"); }
@@ -66,7 +62,6 @@ private slots:
private:
CppModelManager *m_manager;
- Core::EditorManager *m_editorManager;
struct Info {
Info(): dirty(true) {}
diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro
index 9382bcb5cf..346d10f86c 100644
--- a/src/plugins/cpptools/cpptools.pro
+++ b/src/plugins/cpptools/cpptools.pro
@@ -24,7 +24,8 @@ HEADERS += completionsettingspage.h \
cppdoxygen.h \
cppfilesettingspage.h \
cppfindreferences.h \
- cppcodeformatter.h
+ cppcodeformatter.h \
+ symbolsfindfilter.h
SOURCES += completionsettingspage.cpp \
cppclassesfilter.cpp \
@@ -40,7 +41,8 @@ SOURCES += completionsettingspage.cpp \
cppfilesettingspage.cpp \
abstracteditorsupport.cpp \
cppfindreferences.cpp \
- cppcodeformatter.cpp
+ cppcodeformatter.cpp \
+ symbolsfindfilter.cpp
FORMS += completionsettingspage.ui \
cppfilesettingspage.ui
diff --git a/src/plugins/cpptools/cpptools_dependencies.pri b/src/plugins/cpptools/cpptools_dependencies.pri
index 7ac540da28..84e655797d 100644
--- a/src/plugins/cpptools/cpptools_dependencies.pri
+++ b/src/plugins/cpptools/cpptools_dependencies.pri
@@ -1,3 +1,4 @@
include($$IDE_SOURCE_TREE/src/libs/cplusplus/cplusplus.pri)
include($$IDE_SOURCE_TREE/src/plugins/projectexplorer/projectexplorer.pri)
include($$IDE_SOURCE_TREE/src/plugins/texteditor/texteditor.pri)
+include($$IDE_SOURCE_TREE/src/plugins/find/find.pri)
diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp
index 9b84e8012b..1595fd231c 100644
--- a/src/plugins/cpptools/cpptoolsplugin.cpp
+++ b/src/plugins/cpptools/cpptoolsplugin.cpp
@@ -37,6 +37,7 @@
#include "cppmodelmanager.h"
#include "cpptoolsconstants.h"
#include "cpplocatorfilter.h"
+#include "symbolsfindfilter.h"
#include <extensionsystem/pluginmanager.h>
@@ -111,14 +112,13 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error)
CppCodeCompletion *completion = new CppCodeCompletion(m_modelManager);
addAutoReleasedObject(completion);
- CppLocatorFilter *locatorFilter = new CppLocatorFilter(m_modelManager,
- core->editorManager());
- addAutoReleasedObject(locatorFilter);
- addAutoReleasedObject(new CppClassesFilter(m_modelManager, core->editorManager()));
- addAutoReleasedObject(new CppFunctionsFilter(m_modelManager, core->editorManager()));
+ addAutoReleasedObject(new CppLocatorFilter(m_modelManager));
+ addAutoReleasedObject(new CppClassesFilter(m_modelManager));
+ addAutoReleasedObject(new CppFunctionsFilter(m_modelManager));
addAutoReleasedObject(new CppCurrentDocumentFilter(m_modelManager, core->editorManager()));
addAutoReleasedObject(new CompletionSettingsPage);
addAutoReleasedObject(new CppFileSettingsPage(m_fileSettings));
+ addAutoReleasedObject(new SymbolsFindFilter(m_modelManager));
// Menus
Core::ActionContainer *mtools = am->actionContainer(Core::Constants::M_TOOLS);
diff --git a/src/plugins/cpptools/searchsymbols.cpp b/src/plugins/cpptools/searchsymbols.cpp
index ac13d4fd81..70cd1452bd 100644
--- a/src/plugins/cpptools/searchsymbols.cpp
+++ b/src/plugins/cpptools/searchsymbols.cpp
@@ -32,10 +32,17 @@
#include <Literals.h>
#include <Scope.h>
#include <Names.h>
+#include <cplusplus/LookupContext.h>
using namespace CPlusPlus;
using namespace CppTools::Internal;
+SearchSymbols::SymbolTypes SearchSymbols::AllTypes =
+ SearchSymbols::Classes
+ | SearchSymbols::Functions
+ | SearchSymbols::Enums
+ | SearchSymbols::Declarations;
+
SearchSymbols::SearchSymbols():
symbolsToSearchFor(Classes | Functions | Enums),
separateScope(false)
@@ -204,13 +211,17 @@ QString SearchSymbols::symbolName(const Symbol *symbol) const
void SearchSymbols::appendItem(const QString &name,
const QString &info,
ModelItemInfo::ItemType type,
- const Symbol *symbol)
+ Symbol *symbol)
{
if (!symbol->name())
return;
+ QStringList fullyQualifiedName;
+ foreach (const Name *name, LookupContext::fullyQualifiedName(symbol))
+ fullyQualifiedName.append(overview.prettyName(name));
const QIcon icon = icons.iconForSymbol(symbol);
items.append(ModelItemInfo(name, info, type,
+ fullyQualifiedName,
QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()),
symbol->line(),
symbol->column() - 1, // 1-based vs 0-based column
diff --git a/src/plugins/cpptools/searchsymbols.h b/src/plugins/cpptools/searchsymbols.h
index 7c3c379e68..9a08b4dced 100644
--- a/src/plugins/cpptools/searchsymbols.h
+++ b/src/plugins/cpptools/searchsymbols.h
@@ -52,12 +52,14 @@ struct ModelItemInfo
ModelItemInfo()
: type(Declaration),
- line(0)
+ line(0),
+ column(0)
{ }
ModelItemInfo(const QString &symbolName,
const QString &symbolType,
ItemType type,
+ QStringList fullyQualifiedName,
const QString &fileName,
int line,
int column,
@@ -65,15 +67,28 @@ struct ModelItemInfo
: symbolName(symbolName),
symbolType(symbolType),
type(type),
+ fullyQualifiedName(fullyQualifiedName),
fileName(fileName),
line(line),
column(column),
icon(icon)
{ }
+ ModelItemInfo(const ModelItemInfo &otherInfo)
+ : symbolName(otherInfo.symbolName),
+ symbolType(otherInfo.symbolType),
+ type(otherInfo.type),
+ fullyQualifiedName(otherInfo.fullyQualifiedName),
+ fileName(otherInfo.fileName),
+ line(otherInfo.line),
+ column(otherInfo.column),
+ icon(otherInfo.icon)
+ { }
+
QString symbolName;
QString symbolType;
ItemType type;
+ QStringList fullyQualifiedName;
QString fileName;
int line;
int column;
@@ -90,8 +105,11 @@ public:
Enums = 0x4,
Declarations = 0x8
};
+
Q_DECLARE_FLAGS(SymbolTypes, SymbolType)
+ static SymbolTypes AllTypes;
+
SearchSymbols();
void setSymbolsToSearchFor(SymbolTypes types);
@@ -121,7 +139,7 @@ protected:
void appendItem(const QString &name,
const QString &info,
ModelItemInfo::ItemType type,
- const CPlusPlus::Symbol *symbol);
+ CPlusPlus::Symbol *symbol);
private:
QString findOrInsert(const QString &s)
diff --git a/src/plugins/cpptools/symbolsfindfilter.cpp b/src/plugins/cpptools/symbolsfindfilter.cpp
new file mode 100644
index 0000000000..f133831a25
--- /dev/null
+++ b/src/plugins/cpptools/symbolsfindfilter.cpp
@@ -0,0 +1,317 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "symbolsfindfilter.h"
+
+#include "cppmodelmanager.h"
+#include "cpptoolsconstants.h"
+
+#include <coreplugin/progressmanager/progressmanager.h>
+#include <coreplugin/icore.h>
+#include <find/textfindconstants.h>
+#include <qtconcurrent/runextensions.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/session.h>
+#include <projectexplorer/project.h>
+
+#include <QtCore/QSet>
+#include <QtCore/QRegExp>
+#include <QtGui/QGridLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QButtonGroup>
+
+using namespace CppTools;
+using namespace CppTools::Internal;
+
+namespace {
+ const char * const SETTINGS_GROUP = "CppSymbols";
+ const char * const SETTINGS_SYMBOLTYPES = "SymbolsToSearchFor";
+ const char * const SETTINGS_SEARCHSCOPE = "SearchScope";
+
+ void runSearch(QFutureInterface<Find::SearchResultItem> &future,
+ QString txt, Find::FindFlags findFlags, CPlusPlus::Snapshot snapshot,
+ SearchSymbols *search, QSet<QString> fileNames)
+ {
+ future.setProgressRange(0, snapshot.size());
+ future.setProgressValue(0);
+ int progress = 0;
+
+ CPlusPlus::Snapshot::const_iterator it = snapshot.begin();
+
+ QString findString = (findFlags & Find::FindRegularExpression ? txt : QRegExp::escape(txt));
+ if (findFlags & Find::FindWholeWords)
+ findString = QString::fromLatin1("\\b%1\\b").arg(findString);
+ QRegExp matcher(findString, (findFlags & Find::FindCaseSensitively ? Qt::CaseSensitive : Qt::CaseInsensitive));
+ while (it != snapshot.end() && !future.isCanceled()) {
+ if (fileNames.isEmpty() || fileNames.contains(it.value()->fileName())) {
+ QVector<Find::SearchResultItem> resultItems;
+ QList<ModelItemInfo> modelInfos = (*search)(it.value());
+ foreach (const ModelItemInfo &info, modelInfos) {
+ int index = matcher.indexIn(info.symbolName);
+ if (index != -1) {
+ QStringList path = info.fullyQualifiedName.mid(0, info.fullyQualifiedName.size() - 1);
+ Find::SearchResultItem item;
+ item.path = path;
+ item.text = info.symbolName;
+ item.textMarkPos = -1;
+ item.textMarkLength = 0;
+ item.icon = info.icon;
+ item.lineNumber = -1;
+ item.userData = qVariantFromValue(info);
+ resultItems << item;
+ }
+ }
+ if (!resultItems.isEmpty())
+ future.reportResults(resultItems);
+ }
+ ++it;
+ ++progress;
+ future.setProgressValue(progress);
+ }
+ }
+} //namespace
+
+SymbolsFindFilter::SymbolsFindFilter(CppModelManager *manager)
+ : m_manager(manager),
+ m_isRunning(false),
+ m_enabled(true),
+ m_symbolsToSearch(SearchSymbols::AllTypes),
+ m_scope(SearchProjectsOnly)
+{
+ // for disabling while parser is running
+ connect(Core::ICore::instance()->progressManager(), SIGNAL(taskStarted(QString)),
+ this, SLOT(onTaskStarted(QString)));
+ connect(Core::ICore::instance()->progressManager(), SIGNAL(allTasksFinished(QString)),
+ this, SLOT(onAllTasksFinished(QString)));
+
+ connect(&m_watcher, SIGNAL(finished()),
+ this, SLOT(finish()));
+ connect(&m_watcher, SIGNAL(resultsReadyAt(int,int)),
+ this, SLOT(addResults(int, int)));
+}
+
+QString SymbolsFindFilter::id() const
+{
+ return QLatin1String("CppSymbols");
+}
+
+QString SymbolsFindFilter::displayName() const
+{
+ return tr("C++ Symbols");
+}
+
+bool SymbolsFindFilter::isEnabled() const
+{
+ return !m_isRunning && m_enabled;
+}
+
+Find::FindFlags SymbolsFindFilter::supportedFindFlags() const
+{
+ return Find::FindCaseSensitively | Find::FindRegularExpression | Find::FindWholeWords;
+}
+
+void SymbolsFindFilter::findAll(const QString &txt, Find::FindFlags findFlags)
+{
+ m_isRunning = true;
+ emit changed();
+ Find::SearchResultWindow *window = Find::SearchResultWindow::instance();
+ Find::SearchResult *result = window->startNewSearch();
+ connect(result, SIGNAL(activated(Find::SearchResultItem)), this, SLOT(openEditor(Find::SearchResultItem)));
+ window->popup(true);
+
+ m_search.setSymbolsToSearchFor(m_symbolsToSearch);
+ m_search.setSeparateScope(true);
+ QSet<QString> projectFileNames;
+ if (m_scope == SymbolsFindFilter::SearchProjectsOnly) {
+ foreach (ProjectExplorer::Project *project,
+ ProjectExplorer::ProjectExplorerPlugin::instance()->session()->projects()) {
+ projectFileNames += project->files(ProjectExplorer::Project::AllFiles).toSet();
+ }
+ }
+
+ m_watcher.setFuture(QtConcurrent::run<Find::SearchResultItem, QString,
+ Find::FindFlags, CPlusPlus::Snapshot,
+ SearchSymbols *, QSet<QString> >(runSearch, txt, findFlags, m_manager->snapshot(),
+ &m_search, projectFileNames));
+ Core::ICore::instance()->progressManager()->addTask(m_watcher.future(),
+ tr("Searching"),
+ Find::Constants::TASK_SEARCH);
+}
+
+void SymbolsFindFilter::addResults(int begin, int end)
+{
+ Find::SearchResultWindow *window = Find::SearchResultWindow::instance();
+ QList<Find::SearchResultItem> items;
+ for (int i = begin; i < end; ++i)
+ items << m_watcher.resultAt(i);
+ window->addResults(items, Find::SearchResultWindow::AddSorted);
+}
+
+void SymbolsFindFilter::finish()
+{
+ Find::SearchResultWindow *window = Find::SearchResultWindow::instance();
+ window->finishSearch();
+ m_isRunning = false;
+ emit changed();
+}
+
+void SymbolsFindFilter::openEditor(const Find::SearchResultItem &item)
+{
+ if (!item.userData.canConvert<ModelItemInfo>())
+ return;
+ ModelItemInfo info = item.userData.value<ModelItemInfo>();
+ TextEditor::BaseTextEditor::openEditorAt(info.fileName,
+ info.line,
+ info.column);
+}
+
+QWidget *SymbolsFindFilter::createConfigWidget()
+{
+ return new SymbolsFindFilterConfigWidget(this);
+}
+
+void SymbolsFindFilter::writeSettings(QSettings *settings)
+{
+ settings->beginGroup(QLatin1String(SETTINGS_GROUP));
+ settings->setValue(SETTINGS_SYMBOLTYPES, (int)m_symbolsToSearch);
+ settings->setValue(SETTINGS_SEARCHSCOPE, (int)m_scope);
+ settings->endGroup();
+}
+
+void SymbolsFindFilter::readSettings(QSettings *settings)
+{
+ settings->beginGroup(QLatin1String(SETTINGS_GROUP));
+ m_symbolsToSearch = (SearchSymbols::SymbolTypes)settings->value(SETTINGS_SYMBOLTYPES,
+ (int)SearchSymbols::AllTypes).toInt();
+ m_scope = (SearchScope)settings->value(SETTINGS_SEARCHSCOPE,
+ (int)SearchProjectsOnly).toInt();
+ settings->endGroup();
+ emit symbolsToSearchChanged();
+}
+
+void SymbolsFindFilter::onTaskStarted(const QString &type)
+{
+ if (type == CppTools::Constants::TASK_INDEX) {
+ m_enabled = false;
+ emit changed();
+ }
+}
+
+void SymbolsFindFilter::onAllTasksFinished(const QString &type)
+{
+ if (type == CppTools::Constants::TASK_INDEX) {
+ m_enabled = true;
+ emit changed();
+ }
+}
+
+// #pragma mark -- SymbolsFindFilterConfigWidget
+
+SymbolsFindFilterConfigWidget::SymbolsFindFilterConfigWidget(SymbolsFindFilter *filter)
+ : m_filter(filter)
+{
+ connect(m_filter, SIGNAL(symbolsToSearchChanged()), this, SLOT(getState()));
+
+ QGridLayout *layout = new QGridLayout(this);
+ setLayout(layout);
+ layout->setMargin(0);
+
+ QLabel *typeLabel = new QLabel(tr("Types:"));
+ layout->addWidget(typeLabel, 0, 0);
+
+ m_typeClasses = new QCheckBox(tr("Classes"));
+ layout->addWidget(m_typeClasses, 0, 1);
+
+ m_typeMethods = new QCheckBox(tr("Methods"));
+ layout->addWidget(m_typeMethods, 0, 2);
+
+ m_typeEnums = new QCheckBox(tr("Enums"));
+ layout->addWidget(m_typeEnums, 1, 1);
+
+ m_typeDeclarations = new QCheckBox(tr("Declarations"));
+ layout->addWidget(m_typeDeclarations, 1, 2);
+
+ // hacks to fix layouting:
+ typeLabel->setMinimumWidth(80);
+ typeLabel->setAlignment(Qt::AlignRight);
+ m_typeClasses->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ m_typeMethods->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+
+ connect(m_typeClasses, SIGNAL(clicked(bool)), this, SLOT(setState()));
+ connect(m_typeMethods, SIGNAL(clicked(bool)), this, SLOT(setState()));
+ connect(m_typeEnums, SIGNAL(clicked(bool)), this, SLOT(setState()));
+ connect(m_typeDeclarations, SIGNAL(clicked(bool)), this, SLOT(setState()));
+
+ m_searchProjectsOnly = new QRadioButton(tr("Projects Only"));
+ layout->addWidget(m_searchProjectsOnly, 2, 1);
+
+ m_searchGlobal = new QRadioButton(tr("Global"));
+ layout->addWidget(m_searchGlobal, 2, 2);
+
+ m_searchGroup = new QButtonGroup(this);
+ m_searchGroup->addButton(m_searchProjectsOnly);
+ m_searchGroup->addButton(m_searchGlobal);
+
+ connect(m_searchProjectsOnly, SIGNAL(clicked(bool)),
+ this, SLOT(setState()));
+ connect(m_searchGlobal, SIGNAL(clicked(bool)),
+ this, SLOT(setState()));
+}
+
+void SymbolsFindFilterConfigWidget::getState()
+{
+ SearchSymbols::SymbolTypes symbols = m_filter->symbolsToSearch();
+ m_typeClasses->setChecked(symbols & SearchSymbols::Classes);
+ m_typeMethods->setChecked(symbols & SearchSymbols::Functions);
+ m_typeEnums->setChecked(symbols & SearchSymbols::Enums);
+ m_typeDeclarations->setChecked(symbols & SearchSymbols::Declarations);
+
+ SymbolsFindFilter::SearchScope scope = m_filter->searchScope();
+ m_searchProjectsOnly->setChecked(scope == SymbolsFindFilter::SearchProjectsOnly);
+ m_searchGlobal->setChecked(scope == SymbolsFindFilter::SearchGlobal);
+}
+
+void SymbolsFindFilterConfigWidget::setState() const
+{
+ SearchSymbols::SymbolTypes symbols;
+ if (m_typeClasses->isChecked())
+ symbols |= SearchSymbols::Classes;
+ if (m_typeMethods->isChecked())
+ symbols |= SearchSymbols::Functions;
+ if (m_typeEnums->isChecked())
+ symbols |= SearchSymbols::Enums;
+ if (m_typeDeclarations->isChecked())
+ symbols |= SearchSymbols::Declarations;
+ m_filter->setSymbolsToSearch(symbols);
+
+ if (m_searchProjectsOnly->isChecked())
+ m_filter->setSearchScope(SymbolsFindFilter::SearchProjectsOnly);
+ else
+ m_filter->setSearchScope(SymbolsFindFilter::SearchGlobal);
+}
diff --git a/src/plugins/cpptools/symbolsfindfilter.h b/src/plugins/cpptools/symbolsfindfilter.h
new file mode 100644
index 0000000000..420420dc4a
--- /dev/null
+++ b/src/plugins/cpptools/symbolsfindfilter.h
@@ -0,0 +1,124 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SYMBOLSFINDFILTER_H
+#define SYMBOLSFINDFILTER_H
+
+#include "searchsymbols.h"
+
+#include <find/ifindfilter.h>
+#include <find/searchresultwindow.h>
+
+#include <QtCore/QFutureInterface>
+#include <QtCore/QFutureWatcher>
+#include <QtGui/QWidget>
+#include <QtGui/QCheckBox>
+#include <QtGui/QRadioButton>
+
+namespace CppTools {
+namespace Internal {
+
+class CppModelManager;
+
+class SymbolsFindFilter : public Find::IFindFilter
+{
+ Q_OBJECT
+public:
+ enum SearchScope {
+ SearchProjectsOnly,
+ SearchGlobal
+ };
+
+ explicit SymbolsFindFilter(CppModelManager *manager);
+
+ QString id() const;
+ QString displayName() const;
+ bool isEnabled() const;
+ Find::FindFlags supportedFindFlags() const;
+
+ void findAll(const QString &txt, Find::FindFlags findFlags);
+
+ QWidget *createConfigWidget();
+ void writeSettings(QSettings *settings);
+ void readSettings(QSettings *settings);
+
+ void setSymbolsToSearch(SearchSymbols::SymbolTypes types) { m_symbolsToSearch = types; }
+ SearchSymbols::SymbolTypes symbolsToSearch() const { return m_symbolsToSearch; }
+
+ void setSearchScope(SearchScope scope) { m_scope = scope; }
+ SearchScope searchScope() const { return m_scope; }
+
+signals:
+ void symbolsToSearchChanged();
+
+private slots:
+ void openEditor(const Find::SearchResultItem &item);
+
+ void addResults(int begin, int end);
+ void finish();
+ void onTaskStarted(const QString &type);
+ void onAllTasksFinished(const QString &type);
+
+private:
+ CppModelManager *m_manager;
+ bool m_isRunning;
+ bool m_enabled;
+ QFutureWatcher<Find::SearchResultItem> m_watcher;
+ SearchSymbols::SymbolTypes m_symbolsToSearch;
+ SearchSymbols m_search;
+ SearchScope m_scope;
+};
+
+class SymbolsFindFilterConfigWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ SymbolsFindFilterConfigWidget(SymbolsFindFilter *filter);
+
+private slots:
+ void setState() const;
+ void getState();
+
+private:
+ SymbolsFindFilter *m_filter;
+
+ QCheckBox *m_typeClasses;
+ QCheckBox *m_typeMethods;
+ QCheckBox *m_typeEnums;
+ QCheckBox *m_typeDeclarations;
+
+ QRadioButton *m_searchGlobal;
+ QRadioButton *m_searchProjectsOnly;
+ QButtonGroup *m_searchGroup;
+};
+
+} // Internal
+} // CppTools
+
+#endif // SYMBOLSFINDFILTER_H
diff --git a/src/plugins/find/ifindfilter.h b/src/plugins/find/ifindfilter.h
index 72d8cacdec..d45dc83a7c 100644
--- a/src/plugins/find/ifindfilter.h
+++ b/src/plugins/find/ifindfilter.h
@@ -34,9 +34,9 @@
#include "textfindconstants.h"
#include <QtGui/QTextDocument>
+#include <QtGui/QKeySequence>
QT_BEGIN_NAMESPACE
-class QKeySequence;
class QWidget;
class QSettings;
QT_END_NAMESPACE
@@ -53,7 +53,7 @@ public:
virtual QString id() const = 0;
virtual QString displayName() const = 0;
virtual bool isEnabled() const = 0;
- virtual QKeySequence defaultShortcut() const = 0;
+ virtual QKeySequence defaultShortcut() const { return QKeySequence(); }
virtual bool isReplaceSupported() const { return false; }
virtual FindFlags supportedFindFlags() const;
diff --git a/src/plugins/find/searchresulttreeitemdelegate.cpp b/src/plugins/find/searchresulttreeitemdelegate.cpp
index d7b1972bc9..379db290b1 100644
--- a/src/plugins/find/searchresulttreeitemdelegate.cpp
+++ b/src/plugins/find/searchresulttreeitemdelegate.cpp
@@ -48,53 +48,77 @@ SearchResultTreeItemDelegate::SearchResultTreeItemDelegate(QObject *parent)
void SearchResultTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
- if (index.model()->data(index, ItemDataRoles::TypeRole).toString().compare(QLatin1String("file")) == 0) {
- QItemDelegate::paint(painter, option, index);
- } else {
- painter->save();
+ painter->save();
- QStyleOptionViewItemV3 opt = setOptions(index, option);
- painter->setFont(opt.font);
+ QStyleOptionViewItemV3 opt = setOptions(index, option);
+ painter->setFont(opt.font);
- QItemDelegate::drawBackground(painter, opt, index);
+ QItemDelegate::drawBackground(painter, opt, index);
- int lineNumberAreaWidth = drawLineNumber(painter, opt, index);
+ int iconAreaWidth = drawIcon(painter, opt, opt.rect, index);
+ QRect resultRowRect(opt.rect.adjusted(iconAreaWidth, 0, 0, 0));
- QRect resultRowRect(opt.rect.adjusted(lineNumberAreaWidth, 0, 0, 0));
- QString displayString = index.model()->data(index, Qt::DisplayRole).toString();
- drawMarker(painter, index, displayString, resultRowRect);
+ int lineNumberAreaWidth = drawLineNumber(painter, opt, resultRowRect, index);
+ resultRowRect.adjust(lineNumberAreaWidth, 0, 0, 0);
- // Draw the text and focus/selection
- QItemDelegate::drawDisplay(painter, opt, resultRowRect, displayString);
- QItemDelegate::drawFocus(painter, opt, opt.rect);
+ QString displayString = index.model()->data(index, Qt::DisplayRole).toString();
+ drawMarker(painter, index, displayString, resultRowRect);
- QVariant value = index.data(Qt::CheckStateRole);
- if (value.isValid()) {
- Qt::CheckState checkState = Qt::Unchecked;
- checkState = static_cast<Qt::CheckState>(value.toInt());
- QRect checkRect = check(opt, opt.rect, value);
+ // Show number of subresults in displayString
+ if (index.model()->hasChildren(index)) {
+ displayString += QString::fromLatin1(" (")
+ + QString::number(index.model()->rowCount(index))
+ + QLatin1Char(')');
+ }
+
+ // Draw the text and focus/selection
+ QItemDelegate::drawDisplay(painter, opt, resultRowRect, displayString);
+ QItemDelegate::drawFocus(painter, opt, opt.rect);
- QRect emptyRect;
- doLayout(opt, &checkRect, &emptyRect, &emptyRect, false);
+ QVariant value = index.data(Qt::CheckStateRole);
+ if (value.isValid()) {
+ Qt::CheckState checkState = Qt::Unchecked;
+ checkState = static_cast<Qt::CheckState>(value.toInt());
+ QRect checkRect = check(opt, opt.rect, value);
- QItemDelegate::drawCheck(painter, opt, checkRect, checkState);
- }
+ QRect emptyRect;
+ doLayout(opt, &checkRect, &emptyRect, &emptyRect, false);
- painter->restore();
+ QItemDelegate::drawCheck(painter, opt, checkRect, checkState);
}
+
+ painter->restore();
+}
+
+int SearchResultTreeItemDelegate::drawIcon(QPainter *painter, const QStyleOptionViewItemV3 &option,
+ const QRect &rect,
+ const QModelIndex &index) const
+{
+ static const int iconWidth = 16;
+ static const int iconPadding = 4;
+ QIcon icon = index.model()->data(index, ItemDataRoles::ResultIconRole).value<QIcon>();
+ if (icon.isNull())
+ return 0;
+ QRect iconRect = rect.adjusted(iconPadding, 0, /*is set below anyhow*/0, 0);
+ iconRect.setWidth(iconWidth);
+ QItemDelegate::drawDecoration(painter, option, iconRect, icon.pixmap(iconWidth));
+ return iconWidth + iconPadding;
}
int SearchResultTreeItemDelegate::drawLineNumber(QPainter *painter, const QStyleOptionViewItemV3 &option,
+ const QRect &rect,
const QModelIndex &index) const
{
static const int lineNumberAreaHorizontalPadding = 4;
- const bool isSelected = option.state & QStyle::State_Selected;
int lineNumber = index.model()->data(index, ItemDataRoles::ResultLineNumberRole).toInt();
+ if (lineNumber < 1)
+ return 0;
+ const bool isSelected = option.state & QStyle::State_Selected;
int lineNumberDigits = (int)floor(log10((double)lineNumber)) + 1;
int minimumLineNumberDigits = qMax((int)m_minimumLineNumberDigits, lineNumberDigits);
int fontWidth = painter->fontMetrics().width(QString(minimumLineNumberDigits, QLatin1Char('0')));
int lineNumberAreaWidth = lineNumberAreaHorizontalPadding + fontWidth + lineNumberAreaHorizontalPadding;
- QRect lineNumberAreaRect(option.rect);
+ QRect lineNumberAreaRect(rect);
lineNumberAreaRect.setWidth(lineNumberAreaWidth);
QPalette::ColorGroup cg = QPalette::Normal;
@@ -123,10 +147,12 @@ int SearchResultTreeItemDelegate::drawLineNumber(QPainter *painter, const QStyle
void SearchResultTreeItemDelegate::drawMarker(QPainter *painter, const QModelIndex &index, const QString text,
const QRect &rect) const
{
- const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
int searchTermStart = index.model()->data(index, ItemDataRoles::SearchTermStartRole).toInt();
- int searchTermStartPixels = painter->fontMetrics().width(text.left(searchTermStart));
int searchTermLength = index.model()->data(index, ItemDataRoles::SearchTermLengthRole).toInt();
+ if (searchTermStart < 0 || searchTermLength < 1)
+ return;
+ const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
+ int searchTermStartPixels = painter->fontMetrics().width(text.left(searchTermStart));
int searchTermLengthPixels = painter->fontMetrics().width(text.mid(searchTermStart, searchTermLength));
QRect resultHighlightRect(rect);
resultHighlightRect.setLeft(resultHighlightRect.left() + searchTermStartPixels + textMargin - 1); // -1: Cosmetics
diff --git a/src/plugins/find/searchresulttreeitemdelegate.h b/src/plugins/find/searchresulttreeitemdelegate.h
index f751d33632..d9fe62cc7f 100644
--- a/src/plugins/find/searchresulttreeitemdelegate.h
+++ b/src/plugins/find/searchresulttreeitemdelegate.h
@@ -42,7 +42,8 @@ public:
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
private:
- int drawLineNumber(QPainter *painter, const QStyleOptionViewItemV3 &option, const QModelIndex &index) const;
+ int drawIcon(QPainter *painter, const QStyleOptionViewItemV3 &option, const QRect &rect, const QModelIndex &index) const;
+ int drawLineNumber(QPainter *painter, const QStyleOptionViewItemV3 &option, const QRect &rect, const QModelIndex &index) const;
void drawMarker(QPainter *painter, const QModelIndex &index, const QString text, const QRect &rect) const;
static const int m_minimumLineNumberDigits = 6;
diff --git a/src/plugins/find/searchresulttreeitemroles.h b/src/plugins/find/searchresulttreeitemroles.h
index eae775192b..d79877e8de 100644
--- a/src/plugins/find/searchresulttreeitemroles.h
+++ b/src/plugins/find/searchresulttreeitemroles.h
@@ -30,22 +30,21 @@
#ifndef SEARCHRESULTTREEITEMROLES_H
#define SEARCHRESULTTREEITEMROLES_H
+#include <QtGui/QAbstractItemView>
+
namespace Find {
namespace Internal {
namespace ItemDataRoles {
enum Roles
{
- TypeRole = Qt::UserRole,
- FileNameRole,
- ResultLinesCountRole,
- ResultIndexRole,
+ ResultItemRole = Qt::UserRole,
ResultLineRole,
ResultLineNumberRole,
+ ResultIconRole,
SearchTermStartRole,
SearchTermLengthRole,
- RowOfItem, // The ?-th child of its parent is this this item
- TextRole // for files == FileNameRole, for results == ResultLineRole
+ RowOfItem // The ?-th child of its parent is this this item
};
} // namespace Internal
diff --git a/src/plugins/find/searchresulttreeitems.cpp b/src/plugins/find/searchresulttreeitems.cpp
index e31a83a982..0738e37082 100644
--- a/src/plugins/find/searchresulttreeitems.cpp
+++ b/src/plugins/find/searchresulttreeitems.cpp
@@ -31,8 +31,13 @@
using namespace Find::Internal;
-SearchResultTreeItem::SearchResultTreeItem(SearchResultTreeItem::ItemType type, const SearchResultTreeItem *parent)
- : m_type(type), m_parent(parent), m_isUserCheckable(false), m_checkState(Qt::Unchecked)
+SearchResultTreeItem::SearchResultTreeItem(const SearchResultItem &item,
+ const SearchResultTreeItem *parent)
+ : item(item),
+ m_parent(parent),
+ m_isUserCheckable(false),
+ m_checkState(Qt::Unchecked),
+ m_isGenerated(false)
{
}
@@ -41,6 +46,11 @@ SearchResultTreeItem::~SearchResultTreeItem()
clearChildren();
}
+bool SearchResultTreeItem::isLeaf() const
+{
+ return childrenCount() == 0 && parent() != 0;
+}
+
bool SearchResultTreeItem::isUserCheckable() const
{
return m_isUserCheckable;
@@ -67,11 +77,6 @@ void SearchResultTreeItem::clearChildren()
m_children.clear();
}
-SearchResultTreeItem::ItemType SearchResultTreeItem::itemType() const
-{
- return m_type;
-}
-
int SearchResultTreeItem::childrenCount() const
{
return m_children.count();
@@ -92,85 +97,46 @@ const SearchResultTreeItem *SearchResultTreeItem::parent() const
return m_parent;
}
-static bool compareResultFiles(SearchResultTreeItem *a, SearchResultTreeItem *b)
-{
- return static_cast<SearchResultFile *>(a)->fileName() <
- static_cast<SearchResultFile *>(b)->fileName();
-}
-
-int SearchResultTreeItem::insertionIndex(SearchResultFile *child) const
-{
- Q_ASSERT(m_type == Root);
- return qLowerBound(m_children.begin(), m_children.end(), child, compareResultFiles) - m_children.begin();
-}
-
-void SearchResultTreeItem::insertChild(int index, SearchResultTreeItem *child)
-{
- m_children.insert(index, child);
-}
-
-void SearchResultTreeItem::appendChild(SearchResultTreeItem *child)
-{
- m_children.append(child);
-}
-
-SearchResultTextRow::SearchResultTextRow(int index, int lineNumber,
- const QString &rowText,
- int searchTermStart, int searchTermLength,
- const SearchResultTreeItem *parent):
- SearchResultTreeItem(ResultRow, parent),
- m_index(index),
- m_lineNumber(lineNumber),
- m_rowText(rowText),
- m_searchTermStart(searchTermStart),
- m_searchTermLength(searchTermLength)
-{
-}
-
-int SearchResultTextRow::index() const
-{
- return m_index;
-}
-
-QString SearchResultTextRow::rowText() const
-{
- return m_rowText;
-}
-
-int SearchResultTextRow::lineNumber() const
+static bool lessThanByText(SearchResultTreeItem *a, const QString &b)
{
- return m_lineNumber;
+ return a->item.text < b;
}
-int SearchResultTextRow::searchTermStart() const
+int SearchResultTreeItem::insertionIndex(const QString &text, SearchResultTreeItem **existingItem) const
{
- return m_searchTermStart;
-}
-
-int SearchResultTextRow::searchTermLength() const
-{
- return m_searchTermLength;
+ QList<SearchResultTreeItem *>::const_iterator insertionPosition =
+ qLowerBound(m_children.begin(), m_children.end(), text, lessThanByText);
+ if (existingItem) {
+ if (insertionPosition != m_children.end() && (*insertionPosition)->item.text == text) {
+ (*existingItem) = (*insertionPosition);
+ } else {
+ *existingItem = 0;
+ }
+ }
+ return insertionPosition - m_children.begin();
}
-SearchResultFile::SearchResultFile(const QString &fileName, const SearchResultTreeItem *parent):
- SearchResultTreeItem(ResultFile, parent),
- m_fileName(fileName)
+int SearchResultTreeItem::insertionIndex(const SearchResultItem &item, SearchResultTreeItem **existingItem) const
{
+ return insertionIndex(item.text, existingItem);
}
-QString SearchResultFile::fileName() const
+void SearchResultTreeItem::insertChild(int index, SearchResultTreeItem *child)
{
- return m_fileName;
+ m_children.insert(index, child);
}
-void SearchResultFile::appendResultLine(int index, int lineNumber, const QString &rowText, int searchTermStart,
- int searchTermLength)
+void SearchResultTreeItem::insertChild(int index, const SearchResultItem &item)
{
- SearchResultTreeItem *child = new SearchResultTextRow(index, lineNumber, rowText,
- searchTermStart, searchTermLength, this);
+ SearchResultTreeItem *child = new SearchResultTreeItem(item, this);
if (isUserCheckable()) {
child->setIsUserCheckable(true);
child->setCheckState(Qt::Checked);
}
- appendChild(child);
+ insertChild(index, child);
+}
+
+void SearchResultTreeItem::appendChild(const SearchResultItem &item)
+{
+ insertChild(m_children.count(), item);
}
diff --git a/src/plugins/find/searchresulttreeitems.h b/src/plugins/find/searchresulttreeitems.h
index 18ff329a0e..ac7fab03d1 100644
--- a/src/plugins/find/searchresulttreeitems.h
+++ b/src/plugins/find/searchresulttreeitems.h
@@ -30,35 +30,31 @@
#ifndef SEARCHRESULTTREEITEMS_H
#define SEARCHRESULTTREEITEMS_H
+#include "searchresultwindow.h"
+
#include <QtCore/QString>
#include <QtCore/QList>
#include <QtCore/qnamespace.h>
+#include <QtGui/QIcon>
namespace Find {
namespace Internal {
-class SearchResultTreeItem;
-class SearchResultFile;
-
class SearchResultTreeItem
{
public:
- enum ItemType
- {
- Root,
- ResultRow,
- ResultFile
- };
-
- SearchResultTreeItem(ItemType type = Root, const SearchResultTreeItem *parent = NULL);
+ SearchResultTreeItem(const SearchResultItem &item = SearchResultItem(),
+ const SearchResultTreeItem *parent = NULL);
virtual ~SearchResultTreeItem();
- ItemType itemType() const;
+ bool isLeaf() const;
const SearchResultTreeItem *parent() const;
SearchResultTreeItem *childAt(int index) const;
- int insertionIndex(SearchResultFile *child) const;
+ int insertionIndex(const QString &text, SearchResultTreeItem **existingItem) const;
+ int insertionIndex(const SearchResultItem &item, SearchResultTreeItem **existingItem) const;
void insertChild(int index, SearchResultTreeItem *child);
- void appendChild(SearchResultTreeItem *child);
+ void insertChild(int index, const SearchResultItem &item);
+ void appendChild(const SearchResultItem &item);
int childrenCount() const;
int rowOfItem() const;
void clearChildren();
@@ -69,43 +65,17 @@ public:
Qt::CheckState checkState() const;
void setCheckState(Qt::CheckState checkState);
+ bool isGenerated() const { return m_isGenerated; }
+ void setGenerated(bool value) { m_isGenerated = value; }
+
+ SearchResultItem item;
+
private:
- ItemType m_type;
const SearchResultTreeItem *m_parent;
QList<SearchResultTreeItem *> m_children;
bool m_isUserCheckable;
Qt::CheckState m_checkState;
-};
-
-class SearchResultTextRow : public SearchResultTreeItem
-{
-public:
- SearchResultTextRow(int index, int lineNumber, const QString &rowText, int searchTermStart,
- int searchTermLength, const SearchResultTreeItem *parent);
- int index() const;
- QString rowText() const;
- int lineNumber() const;
- int searchTermStart() const;
- int searchTermLength() const;
-
-private:
- int m_index;
- int m_lineNumber;
- QString m_rowText;
- int m_searchTermStart;
- int m_searchTermLength;
-};
-
-class SearchResultFile : public SearchResultTreeItem
-{
-public:
- SearchResultFile(const QString &fileName, const SearchResultTreeItem *parent);
- QString fileName() const;
- void appendResultLine(int index, int lineNumber, const QString &rowText, int searchTermStart,
- int searchTermLength);
-
-private:
- QString m_fileName;
+ bool m_isGenerated;
};
} // namespace Internal
diff --git a/src/plugins/find/searchresulttreemodel.cpp b/src/plugins/find/searchresulttreemodel.cpp
index 080edd5c58..705dedcf4e 100644
--- a/src/plugins/find/searchresulttreemodel.cpp
+++ b/src/plugins/find/searchresulttreemodel.cpp
@@ -46,7 +46,7 @@ using namespace Find::Internal;
SearchResultTreeModel::SearchResultTreeModel(QObject *parent)
: QAbstractItemModel(parent)
- , m_lastAddedResultFile(0)
+ , m_currentParent(0)
, m_showReplaceUI(false)
{
m_rootItem = new SearchResultTreeItem;
@@ -70,13 +70,13 @@ void SearchResultTreeModel::setTextEditorFont(const QFont &font)
layoutChanged();
}
-Qt::ItemFlags SearchResultTreeModel::flags(const QModelIndex &index) const
+Qt::ItemFlags SearchResultTreeModel::flags(const QModelIndex &idx) const
{
- Qt::ItemFlags flags = QAbstractItemModel::flags(index);
+ Qt::ItemFlags flags = QAbstractItemModel::flags(idx);
- if (index.isValid()) {
- if (const SearchResultTreeItem *item = static_cast<const SearchResultTreeItem*>(index.internalPointer())) {
- if (item->itemType() == SearchResultTreeItem::ResultRow && item->isUserCheckable()) {
+ if (idx.isValid()) {
+ if (const SearchResultTreeItem *item = treeItemAtIndex(idx)) {
+ if (item->isLeaf() && item->isUserCheckable()) {
flags |= Qt::ItemIsUserCheckable;
}
}
@@ -96,7 +96,7 @@ QModelIndex SearchResultTreeModel::index(int row, int column,
if (!parent.isValid())
parentItem = m_rootItem;
else
- parentItem = static_cast<const SearchResultTreeItem*>(parent.internalPointer());
+ parentItem = treeItemAtIndex(parent);
const SearchResultTreeItem *childItem = parentItem->childAt(row);
if (childItem)
@@ -105,12 +105,17 @@ QModelIndex SearchResultTreeModel::index(int row, int column,
return QModelIndex();
}
-QModelIndex SearchResultTreeModel::parent(const QModelIndex &index) const
+QModelIndex SearchResultTreeModel::index(SearchResultTreeItem *item) const
{
- if (!index.isValid())
+ return createIndex(item->rowOfItem(), 0, (void *)item);
+}
+
+QModelIndex SearchResultTreeModel::parent(const QModelIndex &idx) const
+{
+ if (!idx.isValid())
return QModelIndex();
- const SearchResultTreeItem *childItem = static_cast<const SearchResultTreeItem*>(index.internalPointer());
+ const SearchResultTreeItem *childItem = treeItemAtIndex(idx);
const SearchResultTreeItem *parentItem = childItem->parent();
if (parentItem == m_rootItem)
@@ -129,7 +134,7 @@ int SearchResultTreeModel::rowCount(const QModelIndex &parent) const
if (!parent.isValid())
parentItem = m_rootItem;
else
- parentItem = static_cast<const SearchResultTreeItem*>(parent.internalPointer());
+ parentItem = treeItemAtIndex(parent);
return parentItem->childrenCount();
}
@@ -140,48 +145,41 @@ int SearchResultTreeModel::columnCount(const QModelIndex &parent) const
return 1;
}
-QVariant SearchResultTreeModel::data(const QModelIndex &index, int role) const
+SearchResultTreeItem *SearchResultTreeModel::treeItemAtIndex(const QModelIndex &idx) const
{
- if (!index.isValid())
- return QVariant();
+ return static_cast<SearchResultTreeItem*>(idx.internalPointer());
+}
- const SearchResultTreeItem *item = static_cast<const SearchResultTreeItem*>(index.internalPointer());
+QVariant SearchResultTreeModel::data(const QModelIndex &idx, int role) const
+{
+ if (!idx.isValid())
+ return QVariant();
QVariant result;
- if (role == Qt::SizeHintRole)
- {
+ if (role == Qt::SizeHintRole) {
+ // TODO we should not use editor font height if that is not used by any item
const int appFontHeight = QApplication::fontMetrics().height();
const int editorFontHeight = QFontMetrics(m_textEditorFont).height();
result = QSize(0, qMax(appFontHeight, editorFontHeight));
- }
- else if (item->itemType() == SearchResultTreeItem::ResultRow)
- {
- const SearchResultTextRow *row = static_cast<const SearchResultTextRow *>(item);
- result = data(row, role);
- }
- else if (item->itemType() == SearchResultTreeItem::ResultFile)
- {
- const SearchResultFile *file = static_cast<const SearchResultFile *>(item);
- result = data(file, role);
+ } else {
+ result = data(treeItemAtIndex(idx), role);
}
return result;
}
-bool SearchResultTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
+bool SearchResultTreeModel::setData(const QModelIndex &idx, const QVariant &value, int role)
{
if (role == Qt::CheckStateRole) {
- SearchResultTreeItem *item = static_cast<SearchResultTreeItem*>(index.internalPointer());
- SearchResultTextRow *row = static_cast<SearchResultTextRow *>(item);
Qt::CheckState checkState = static_cast<Qt::CheckState>(value.toInt());
- row->setCheckState(checkState);
+ treeItemAtIndex(idx)->setCheckState(checkState);
return true;
}
- return QAbstractItemModel::setData(index, value, role);
+ return QAbstractItemModel::setData(idx, value, role);
}
-QVariant SearchResultTreeModel::data(const SearchResultTextRow *row, int role) const
+QVariant SearchResultTreeModel::data(const SearchResultTreeItem *row, int role) const
{
QVariant result;
@@ -192,39 +190,40 @@ QVariant SearchResultTreeModel::data(const SearchResultTextRow *row, int role) c
result = row->checkState();
break;
case Qt::ToolTipRole:
- result = row->rowText().trimmed();
+ result = row->item.text.trimmed();
break;
case Qt::FontRole:
- result = m_textEditorFont;
+ if (row->item.useTextEditorFont)
+ result = m_textEditorFont;
+ else
+ result = QVariant();
break;
- case ItemDataRoles::TextRole:
case ItemDataRoles::ResultLineRole:
case Qt::DisplayRole:
- result = row->rowText();
+ result = row->item.text;
break;
- case ItemDataRoles::ResultIndexRole:
- result = row->index();
+ case ItemDataRoles::ResultItemRole:
+ result = qVariantFromValue(row->item);
break;
case ItemDataRoles::ResultLineNumberRole:
- result = row->lineNumber();
+ result = row->item.lineNumber;
+ break;
+ case ItemDataRoles::ResultIconRole:
+ result = row->item.icon;
break;
case ItemDataRoles::SearchTermStartRole:
- result = row->searchTermStart();
+ result = row->item.textMarkPos;
break;
case ItemDataRoles::SearchTermLengthRole:
- result = row->searchTermLength();
- break;
- case ItemDataRoles::TypeRole:
- result = QLatin1String("row");
+ result = row->item.textMarkLength;
break;
- case ItemDataRoles::FileNameRole:
- {
- if (row->parent()->itemType() == SearchResultTreeItem::ResultFile) {
- const SearchResultFile *file = static_cast<const SearchResultFile *>(row->parent());
- result = file->fileName();
- }
- break;
- }
+// TODO this looks stupid in case of symbol tree, is it necessary?
+// case Qt::BackgroundRole:
+// if (row->parent() && row->parent()->parent())
+// result = QVariant();
+// else
+// result = QApplication::palette().base().color().darker(105);
+// break;
default:
result = QVariant();
break;
@@ -233,42 +232,6 @@ QVariant SearchResultTreeModel::data(const SearchResultTextRow *row, int role) c
return result;
}
-QVariant SearchResultTreeModel::data(const SearchResultFile *file, int role) const
-{
- switch (role)
- {
-#if 0
- case Qt::CheckStateRole:
- if (file->isUserCheckable())
- return QVariant(file->checkState());
-#endif
- case Qt::BackgroundRole: {
- const QColor baseColor = QApplication::palette().base().color();
- return QVariant(baseColor.darker(105));
- break;
- }
- case Qt::DisplayRole: {
- const QString result =
- QDir::toNativeSeparators(file->fileName())
- + QString::fromLatin1(" (")
- + QString::number(file->childrenCount())
- + QLatin1Char(')');
- return QVariant(result);
- }
- case ItemDataRoles::TextRole:
- case ItemDataRoles::FileNameRole:
- case Qt::ToolTipRole:
- return QVariant(QDir::toNativeSeparators(file->fileName()));
- case ItemDataRoles::ResultLinesCountRole:
- return QVariant(file->childrenCount());
- case ItemDataRoles::TypeRole:
- return QVariant(QLatin1String("file"));
- default:
- break;
- }
- return QVariant();
-}
-
QVariant SearchResultTreeModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
@@ -279,144 +242,196 @@ QVariant SearchResultTreeModel::headerData(int section, Qt::Orientation orientat
}
/**
- * Adds a file to the list of results and returns the index at which it was inserted.
+ * Makes sure that the nodes for a specific path exist and sets
+ * m_currentParent to the last final
*/
-int SearchResultTreeModel::addResultFile(const QString &fileName)
+QSet<SearchResultTreeItem *> SearchResultTreeModel::addPath(const QStringList &path)
{
-#ifdef Q_OS_WIN
- if (fileName.contains(QLatin1Char('\\')))
- qWarning("SearchResultTreeModel::appendResultFile: File name with native separators added %s.\n", qPrintable(fileName));
-#endif
- m_lastAddedResultFile = new SearchResultFile(fileName, m_rootItem);
-
- if (m_showReplaceUI) {
- m_lastAddedResultFile->setIsUserCheckable(true);
- m_lastAddedResultFile->setCheckState(Qt::Checked);
+ QSet<SearchResultTreeItem *> pathNodes;
+ SearchResultTreeItem *currentItem = m_rootItem;
+ QModelIndex currentItemIndex = QModelIndex();
+ SearchResultTreeItem *partItem = 0;
+ QStringList currentPath;
+ foreach (const QString &part, path) {
+ const int insertionIndex = currentItem->insertionIndex(part, &partItem);
+ if (!partItem) {
+ SearchResultItem item;
+ item.path = currentPath;
+ item.text = part;
+ partItem = new SearchResultTreeItem(item, currentItem);
+ if (m_showReplaceUI) {
+ partItem->setIsUserCheckable(true);
+ partItem->setCheckState(Qt::Checked);
+ }
+ partItem->setGenerated(true);
+ beginInsertRows(currentItemIndex, insertionIndex, insertionIndex);
+ currentItem->insertChild(insertionIndex, partItem);
+ endInsertRows();
+ }
+ pathNodes << partItem;
+ currentItemIndex = index(insertionIndex, 0, currentItemIndex);
+ currentItem = partItem;
+ currentPath << part;
}
- const int index = m_rootItem->insertionIndex(m_lastAddedResultFile);
- beginInsertRows(QModelIndex(), index, index);
- m_rootItem->insertChild(index, m_lastAddedResultFile);
- endInsertRows();
- return index;
+ m_currentParent = currentItem;
+ m_currentPath = currentPath;
+ m_currentIndex = currentItemIndex;
+ return pathNodes;
}
-void SearchResultTreeModel::appendResultLines(const QList<SearchResultItem> &items)
+void SearchResultTreeModel::addResultsToCurrentParent(const QList<SearchResultItem> &items, SearchResultWindow::AddMode mode)
{
- if (!m_lastAddedResultFile)
+ if (!m_currentParent)
return;
- QModelIndex lastFile(createIndex(m_lastAddedResultFile->rowOfItem(), 0, m_lastAddedResultFile));
-
- beginInsertRows(lastFile, m_lastAddedResultFile->childrenCount(), m_lastAddedResultFile->childrenCount() + items.count());
- foreach (const SearchResultItem &item, items) {
- m_lastAddedResultFile->appendResultLine(item.index,
- item.lineNumber,
- item.lineText,
- item.searchTermStart,
- item.searchTermLength);
+ if (mode == SearchResultWindow::AddOrdered) {
+ // this is the mode for e.g. text search
+ beginInsertRows(m_currentIndex, m_currentParent->childrenCount(), m_currentParent->childrenCount() + items.count());
+ foreach (const SearchResultItem &item, items) {
+ m_currentParent->appendChild(item);
+ }
+ endInsertRows();
+ } else if (mode == SearchResultWindow::AddSorted) {
+ foreach (const SearchResultItem &item, items) {
+ SearchResultTreeItem *existingItem;
+ const int insertionIndex = m_currentParent->insertionIndex(item, &existingItem);
+ if (existingItem) {
+ existingItem->setGenerated(false);
+ existingItem->item = item;
+ QModelIndex itemIndex = m_currentIndex.child(insertionIndex, 0);
+ dataChanged(itemIndex, itemIndex);
+ } else {
+ beginInsertRows(m_currentIndex, insertionIndex, insertionIndex);
+ m_currentParent->insertChild(insertionIndex, item);
+ endInsertRows();
+ }
+ }
}
- endInsertRows();
+ dataChanged(m_currentIndex, m_currentIndex); // Make sure that the number after the file name gets updated
+}
- dataChanged(lastFile, lastFile); // Make sure that the number after the file name gets updated
+static bool lessThanByPath(const SearchResultItem &a, const SearchResultItem &b)
+{
+ if (a.path.size() < b.path.size())
+ return true;
+ if (a.path.size() > b.path.size())
+ return false;
+ for (int i = 0; i < a.path.size(); ++i) {
+ if (a.path.at(i) < b.path.at(i))
+ return true;
+ if (a.path.at(i) > b.path.at(i))
+ return false;
+ }
+ return false;
}
/**
- * Adds the search result to the list of results, creating a new file entry when
- * necessary. Returns the insertion index when a new file entry was created.
+ * Adds the search result to the list of results, creating nodes for the path when
+ * necessary.
*/
-QList<int> SearchResultTreeModel::addResultLines(const QList<SearchResultItem> &items)
+QList<QModelIndex> SearchResultTreeModel::addResults(const QList<SearchResultItem> &items, SearchResultWindow::AddMode mode)
{
- QList<int> insertedFileIndices;
+ QSet<SearchResultTreeItem *> pathNodes;
+ QList<SearchResultItem> sortedItems = items;
+ qStableSort(sortedItems.begin(), sortedItems.end(), lessThanByPath);
QList<SearchResultItem> itemSet;
- foreach (const SearchResultItem &item, items) {
- if (!m_lastAddedResultFile || (m_lastAddedResultFile->fileName() != item.fileName)) {
+ foreach (const SearchResultItem &item, sortedItems) {
+ if (!m_currentParent || (m_currentPath != item.path)) {
+ // first add all the items from before
if (!itemSet.isEmpty()) {
- appendResultLines(itemSet);
+ addResultsToCurrentParent(itemSet, mode);
itemSet.clear();
}
- insertedFileIndices << addResultFile(item.fileName);
+ // switch parent
+ pathNodes += addPath(item.path);
}
itemSet << item;
}
if (!itemSet.isEmpty()) {
- appendResultLines(itemSet);
+ addResultsToCurrentParent(itemSet, mode);
itemSet.clear();
}
- return insertedFileIndices;
+ QList<QModelIndex> pathIndices;
+ foreach (SearchResultTreeItem *item, pathNodes)
+ pathIndices << index(item);
+ return pathIndices;
}
void SearchResultTreeModel::clear()
{
- m_lastAddedResultFile = NULL;
+ m_currentParent = NULL;
m_rootItem->clearChildren();
reset();
}
-QModelIndex SearchResultTreeModel::next(const QModelIndex &idx, bool includeTopLevel) const
+QModelIndex SearchResultTreeModel::nextIndex(const QModelIndex &idx) const
{
- QModelIndex parent = idx.parent();
- if (parent.isValid()) {
- int row = idx.row();
- if (row + 1 < rowCount(parent)) {
- // Same parent
- return index(row + 1, 0, parent);
+ // pathological
+ if (!idx.isValid())
+ return index(0, 0);
+
+ if (rowCount(idx) > 0) {
+ // node with children
+ return idx.child(0, 0);
+ }
+ // leaf node
+ QModelIndex nextIndex;
+ QModelIndex current = idx;
+ while (!nextIndex.isValid()) {
+ int row = current.row();
+ current = current.parent();
+ if (row + 1 < rowCount(current)) {
+ // Same parent has another child
+ nextIndex = index(row + 1, 0, current);
} else {
- // Next parent
- int parentRow = parent.row();
- QModelIndex nextParent;
- if (parentRow + 1 < rowCount()) {
- nextParent = index(parentRow + 1, 0);
- } else {
- // Wrap around
- nextParent = index(0,0);
+ // go up one parent
+ if (!current.isValid()) {
+ nextIndex = index(0, 0);
}
- if (includeTopLevel)
- return nextParent;
- return nextParent.child(0, 0);
}
- } else {
- // We are on a top level item
- return idx.child(0,0);
}
- return QModelIndex();
+ return nextIndex;
}
-QModelIndex SearchResultTreeModel::prev(const QModelIndex &idx, bool includeTopLevel) const
+QModelIndex SearchResultTreeModel::next(const QModelIndex &idx, bool includeGenerated) const
{
- QModelIndex parent = idx.parent();
- if (parent.isValid()) {
- int row = idx.row();
- if (row > 0) {
- // Same parent
- return index(row - 1, 0, parent);
- } else {
- if (includeTopLevel)
- return parent;
- // Prev parent
- int parentRow = parent.row();
- QModelIndex prevParent;
- if (parentRow > 0 ) {
- prevParent = index(parentRow - 1, 0);
- } else {
- // Wrap around
- prevParent = index(rowCount() - 1, 0);
- }
- return prevParent.child(rowCount(prevParent) - 1, 0);
- }
- } else {
- // We are on a top level item
- int row = idx.row();
- QModelIndex prevParent;
+ QModelIndex value = idx;
+ do {
+ value = nextIndex(value);
+ } while (value != idx && !includeGenerated && treeItemAtIndex(value)->isGenerated());
+ return value;
+}
+
+QModelIndex SearchResultTreeModel::prevIndex(const QModelIndex &idx) const
+{
+ QModelIndex current = idx;
+ bool checkForChildren = true;
+ if (current.isValid()) {
+ int row = current.row();
if (row > 0) {
- prevParent = index(row - 1, 0);
+ current = index(row - 1, 0, current.parent());
} else {
- // wrap around
- prevParent = index(rowCount() -1, 0);
+ current = current.parent();
+ checkForChildren = !current.isValid();
+ }
+ }
+ if (checkForChildren) {
+ // traverse down the hierarchy
+ while (int rc = rowCount(current)) {
+ current = index(rc - 1, 0, current);
}
- return prevParent.child(rowCount(prevParent) -1,0);
}
- return QModelIndex();
+ return current;
+}
+
+QModelIndex SearchResultTreeModel::prev(const QModelIndex &idx, bool includeGenerated) const
+{
+ QModelIndex value = idx;
+ do {
+ value = prevIndex(value);
+ } while (value != idx && !includeGenerated && treeItemAtIndex(value)->isGenerated());
+ return value;
}
QModelIndex SearchResultTreeModel::find(const QRegExp &expr, const QModelIndex &index, QTextDocument::FindFlags flags)
@@ -431,7 +446,7 @@ QModelIndex SearchResultTreeModel::find(const QRegExp &expr, const QModelIndex &
else
currentIndex = next(currentIndex, true);
if (currentIndex.isValid()) {
- const QString &text = data(currentIndex, ItemDataRoles::TextRole).toString();
+ const QString &text = data(currentIndex, ItemDataRoles::ResultLineRole).toString();
if (expr.indexIn(text) != -1)
resultIndex = currentIndex;
}
@@ -452,7 +467,7 @@ QModelIndex SearchResultTreeModel::find(const QString &term, const QModelIndex &
else
currentIndex = next(currentIndex, true);
if (currentIndex.isValid()) {
- const QString &text = data(currentIndex, ItemDataRoles::TextRole).toString();
+ const QString &text = data(currentIndex, ItemDataRoles::ResultLineRole).toString();
QTextDocument doc(text);
if (!doc.find(term, 0, flags).isNull())
resultIndex = currentIndex;
diff --git a/src/plugins/find/searchresulttreemodel.h b/src/plugins/find/searchresulttreemodel.h
index d143c1213a..ef0cfefce8 100644
--- a/src/plugins/find/searchresulttreemodel.h
+++ b/src/plugins/find/searchresulttreemodel.h
@@ -41,8 +41,6 @@ namespace Find {
namespace Internal {
class SearchResultTreeItem;
-class SearchResultTextRow;
-class SearchResultFile;
class SearchResultTreeModel : public QAbstractItemModel
{
@@ -64,10 +62,10 @@ public:
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
- QModelIndex next(const QModelIndex &idx, bool includeTopLevel = false) const;
- QModelIndex prev(const QModelIndex &idx, bool includeTopLevel = false) const;
+ QModelIndex next(const QModelIndex &idx, bool includeGenerated = false) const;
+ QModelIndex prev(const QModelIndex &idx, bool includeGenerated = false) const;
- QList<int> addResultLines(const QList<SearchResultItem> &items);
+ QList<QModelIndex> addResults(const QList<SearchResultItem> &items, SearchResultWindow::AddMode mode);
QModelIndex find(const QRegExp &expr, const QModelIndex &index, QTextDocument::FindFlags flags);
QModelIndex find(const QString &term, const QModelIndex &index, QTextDocument::FindFlags flags);
@@ -80,15 +78,18 @@ public slots:
void clear();
private:
- void appendResultLines(const QList<SearchResultItem> &items);
- int addResultFile(const QString &fileName);
- QVariant data(const SearchResultTextRow *row, int role) const;
- QVariant data(const SearchResultFile *file, int role) const;
- void initializeData();
- void disposeData();
+ QModelIndex index(SearchResultTreeItem *item) const;
+ void addResultsToCurrentParent(const QList<SearchResultItem> &items, SearchResultWindow::AddMode mode);
+ QSet<SearchResultTreeItem *> addPath(const QStringList &path);
+ QVariant data(const SearchResultTreeItem *row, int role) const;
+ QModelIndex nextIndex(const QModelIndex &idx) const;
+ QModelIndex prevIndex(const QModelIndex &idx) const;
+ SearchResultTreeItem *treeItemAtIndex(const QModelIndex &idx) const;
SearchResultTreeItem *m_rootItem;
- SearchResultFile *m_lastAddedResultFile;
+ SearchResultTreeItem *m_currentParent;
+ QModelIndex m_currentIndex;
+ QStringList m_currentPath; // the path that belongs to the current parent
QFont m_textEditorFont;
bool m_showReplaceUI;
};
diff --git a/src/plugins/find/searchresulttreeview.cpp b/src/plugins/find/searchresulttreeview.cpp
index 650cfe0b1a..d97451d1f7 100644
--- a/src/plugins/find/searchresulttreeview.cpp
+++ b/src/plugins/find/searchresulttreeview.cpp
@@ -46,6 +46,7 @@ SearchResultTreeView::SearchResultTreeView(QWidget *parent)
setItemDelegate(new SearchResultTreeItemDelegate(this));
setIndentation(14);
setUniformRowHeights(true);
+ setExpandsOnDoubleClick(false);
header()->hide();
connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(emitJumpToSearchResult(QModelIndex)));
@@ -66,24 +67,20 @@ void SearchResultTreeView::clear()
m_model->clear();
}
-void SearchResultTreeView::appendResultLines(const QList<Find::SearchResultItem> &items)
+void SearchResultTreeView::addResults(const QList<Find::SearchResultItem> &items, SearchResultWindow::AddMode mode)
{
- const QList<int> &insertedFileIndices = m_model->addResultLines(items);
- if (m_autoExpandResults && !insertedFileIndices.isEmpty()) {
- foreach (int index, insertedFileIndices)
- setExpanded(model()->index(index, 0), true);
+ QList<QModelIndex> addedParents = m_model->addResults(items, mode);
+ if (m_autoExpandResults && !addedParents.isEmpty()) {
+ foreach (const QModelIndex &index, addedParents)
+ setExpanded(index, true);
}
}
void SearchResultTreeView::emitJumpToSearchResult(const QModelIndex &index)
{
- if (model()->data(index, ItemDataRoles::TypeRole).toString().compare(QLatin1String("row")) != 0)
- return;
-
- int position = model()->data(index, ItemDataRoles::ResultIndexRole).toInt();
- int checked = model()->data(index, Qt::CheckStateRole).toBool();
+ SearchResultItem item = model()->data(index, ItemDataRoles::ResultItemRole).value<SearchResultItem>();
- emit jumpToSearchResult(position, checked);
+ emit jumpToSearchResult(item);
}
void SearchResultTreeView::keyPressEvent(QKeyEvent *e)
diff --git a/src/plugins/find/searchresulttreeview.h b/src/plugins/find/searchresulttreeview.h
index ff9f9984e5..64e8ecc86c 100644
--- a/src/plugins/find/searchresulttreeview.h
+++ b/src/plugins/find/searchresulttreeview.h
@@ -50,10 +50,10 @@ public:
void setTextEditorFont(const QFont &font);
SearchResultTreeModel *model() const;
- void appendResultLines(const QList<Find::SearchResultItem> &items);
+ void addResults(const QList<Find::SearchResultItem> &items, SearchResultWindow::AddMode mode);
signals:
- void jumpToSearchResult(int index, bool checked);
+ void jumpToSearchResult(const SearchResultItem &item);
public slots:
void clear();
diff --git a/src/plugins/find/searchresultwindow.cpp b/src/plugins/find/searchresultwindow.cpp
index 90b1cc7563..2dd2cd6228 100644
--- a/src/plugins/find/searchresultwindow.cpp
+++ b/src/plugins/find/searchresultwindow.cpp
@@ -45,6 +45,7 @@
#include <QtCore/QTextStream>
#include <QtCore/QSettings>
#include <QtCore/QDebug>
+#include <QtCore/QDir>
#include <QtGui/QListWidget>
#include <QtGui/QToolButton>
#include <QtGui/QLineEdit>
@@ -56,7 +57,6 @@
static const char SETTINGSKEYSECTIONNAME[] = "SearchResults";
static const char SETTINGSKEYEXPANDRESULTS[] = "ExpandResults";
-
namespace Find {
namespace Internal {
@@ -204,13 +204,14 @@ namespace Internal {
static const bool m_initiallyExpand = false;
QStackedWidget *m_widget;
SearchResult *m_currentSearch;
- QList<SearchResultItem> m_items;
+ int m_itemCount;
bool m_isShowingReplaceUI;
bool m_focusReplaceEdit;
};
SearchResultWindowPrivate::SearchResultWindowPrivate()
: m_currentSearch(0),
+ m_itemCount(0),
m_isShowingReplaceUI(false),
m_focusReplaceEdit(false)
{
@@ -338,8 +339,8 @@ SearchResultWindow::SearchResultWindow() : d(new SearchResultWindowPrivate)
d->m_replaceButton->setAutoRaise(true);
d->m_replaceTextEdit->setTabOrder(d->m_replaceTextEdit, d->m_searchResultTreeView);
- connect(d->m_searchResultTreeView, SIGNAL(jumpToSearchResult(int,bool)),
- this, SLOT(handleJumpToSearchResult(int,bool)));
+ connect(d->m_searchResultTreeView, SIGNAL(jumpToSearchResult(SearchResultItem)),
+ this, SLOT(handleJumpToSearchResult(SearchResultItem)));
connect(d->m_expandCollapseAction, SIGNAL(toggled(bool)), this, SLOT(handleExpandCollapseToolButton(bool)));
connect(d->m_replaceTextEdit, SIGNAL(returnPressed()), this, SLOT(handleReplaceButton()));
connect(d->m_replaceButton, SIGNAL(clicked()), this, SLOT(handleReplaceButton()));
@@ -359,7 +360,7 @@ SearchResultWindow::~SearchResultWindow()
d->m_currentSearch = 0;
delete d->m_widget;
d->m_widget = 0;
- d->m_items.clear();
+ d->m_itemCount = 0;
delete d;
}
@@ -428,13 +429,13 @@ QList<SearchResultItem> SearchResultWindow::checkedItems() const
const int fileCount = model->rowCount(QModelIndex());
for (int i = 0; i < fileCount; ++i) {
QModelIndex fileIndex = model->index(i, 0, QModelIndex());
- Internal::SearchResultFile *fileItem = static_cast<Internal::SearchResultFile *>(fileIndex.internalPointer());
+ Internal::SearchResultTreeItem *fileItem = static_cast<Internal::SearchResultTreeItem *>(fileIndex.internalPointer());
Q_ASSERT(fileItem != 0);
for (int rowIndex = 0; rowIndex < fileItem->childrenCount(); ++rowIndex) {
QModelIndex textIndex = model->index(rowIndex, 0, fileIndex);
- Internal::SearchResultTextRow *rowItem = static_cast<Internal::SearchResultTextRow *>(textIndex.internalPointer());
+ Internal::SearchResultTreeItem *rowItem = static_cast<Internal::SearchResultTreeItem *>(textIndex.internalPointer());
if (rowItem->checkState())
- result << d->m_items.at(rowItem->index());
+ result << rowItem->item;
}
}
return result;
@@ -492,7 +493,7 @@ SearchResult *SearchResultWindow::startNewSearch(SearchMode searchOrSearchAndRep
*/
void SearchResultWindow::finishSearch()
{
- if (d->m_items.count()) {
+ if (d->m_itemCount > 0) {
d->m_replaceButton->setEnabled(true);
} else {
showNoMatchesFound();
@@ -509,7 +510,7 @@ void SearchResultWindow::clearContents()
d->m_replaceButton->setEnabled(false);
d->m_replaceTextEdit->clear();
d->m_searchResultTreeView->clear();
- d->m_items.clear();
+ d->m_itemCount = 0;
d->m_widget->setCurrentWidget(d->m_searchResultTreeView);
navigateStateChanged();
}
@@ -541,7 +542,7 @@ bool SearchResultWindow::isEmpty() const
*/
int SearchResultWindow::numberOfResults() const
{
- return d->m_items.count();
+ return d->m_itemCount;
}
/*!
@@ -559,7 +560,7 @@ bool SearchResultWindow::hasFocus()
*/
bool SearchResultWindow::canFocus()
{
- return !d->m_items.isEmpty();
+ return d->m_itemCount > 0;
}
/*!
@@ -568,7 +569,7 @@ bool SearchResultWindow::canFocus()
*/
void SearchResultWindow::setFocus()
{
- if (!d->m_items.isEmpty()) {
+ if (d->m_itemCount > 0) {
if (!d->m_isShowingReplaceUI) {
d->m_searchResultTreeView->setFocus();
} else {
@@ -597,10 +598,10 @@ void SearchResultWindow::setTextEditorFont(const QFont &font)
\fn void SearchResultWindow::handleJumpToSearchResult(int index, bool)
\internal
*/
-void SearchResultWindow::handleJumpToSearchResult(int index, bool /* checked */)
+void SearchResultWindow::handleJumpToSearchResult(const SearchResultItem &item)
{
QTC_ASSERT(d->m_currentSearch, return);
- d->m_currentSearch->activated(d->m_items.at(index));
+ d->m_currentSearch->activated(item);
}
/*!
@@ -619,13 +620,14 @@ void SearchResultWindow::addResult(const QString &fileName, int lineNumber, cons
int searchTermStart, int searchTermLength, const QVariant &userData)
{
SearchResultItem item;
- item.fileName = fileName;
+ item.path = QStringList() << QDir::toNativeSeparators(fileName);
item.lineNumber = lineNumber;
- item.lineText = rowText;
- item.searchTermStart = searchTermStart;
- item.searchTermLength = searchTermLength;
+ item.text = rowText;
+ item.textMarkPos = searchTermStart;
+ item.textMarkLength = searchTermLength;
+ item.useTextEditorFont = true;
item.userData = userData;
- addResults(QList<SearchResultItem>() << item);
+ addResults(QList<SearchResultItem>() << item, AddOrdered);
}
/*!
@@ -635,17 +637,11 @@ void SearchResultWindow::addResult(const QString &fileName, int lineNumber, cons
\sa addResult()
*/
-void SearchResultWindow::addResults(QList<SearchResultItem> &items)
+void SearchResultWindow::addResults(QList<SearchResultItem> &items, AddMode mode)
{
- int index = d->m_items.size();
- bool firstItems = (index == 0);
- for (int i = 0; i < items.size(); ++i) {
- items[i].index = index;
- ++index;
- }
-
- d->m_items << items;
- d->m_searchResultTreeView->appendResultLines(items);
+ bool firstItems = (d->m_itemCount == 0);
+ d->m_itemCount += items.size();
+ d->m_searchResultTreeView->addResults(items, mode);
if (firstItems) {
d->m_replaceTextEdit->setEnabled(true);
// We didn't have an item before, set the focus to the search widget
@@ -713,7 +709,7 @@ int SearchResultWindow::priorityInStatusBar() const
*/
bool SearchResultWindow::canNext()
{
- return d->m_items.count() > 0;
+ return d->m_itemCount > 0;
}
/*!
@@ -722,7 +718,7 @@ bool SearchResultWindow::canNext()
*/
bool SearchResultWindow::canPrevious()
{
- return d->m_items.count() > 0;
+ return d->m_itemCount > 0;
}
/*!
@@ -731,7 +727,7 @@ bool SearchResultWindow::canPrevious()
*/
void SearchResultWindow::goToNext()
{
- if (d->m_items.count() == 0)
+ if (d->m_itemCount == 0)
return;
QModelIndex idx = d->m_searchResultTreeView->model()->next(d->m_searchResultTreeView->currentIndex());
if (idx.isValid()) {
diff --git a/src/plugins/find/searchresultwindow.h b/src/plugins/find/searchresultwindow.h
index 92e58cebbb..b085f15f1c 100644
--- a/src/plugins/find/searchresultwindow.h
+++ b/src/plugins/find/searchresultwindow.h
@@ -32,10 +32,12 @@
#include "find_global.h"
-#include <QtCore/QVariant>
-
#include <coreplugin/ioutputpane.h>
+#include <QtCore/QVariant>
+#include <QtCore/QStringList>
+#include <QtGui/QIcon>
+
QT_BEGIN_NAMESPACE
class QFont;
QT_END_NAMESPACE
@@ -49,14 +51,34 @@ class SearchResultWindow;
struct FIND_EXPORT SearchResultItem
{
- QString fileName;
- int lineNumber;
- QString lineText;
- int searchTermStart;
- int searchTermLength;
- int index; // SearchResultWindow sets the index
- QVariant userData;
- // whatever information we also need here
+ SearchResultItem()
+ : textMarkPos(-1),
+ textMarkLength(0),
+ lineNumber(-1),
+ useTextEditorFont(false)
+ {
+ }
+
+ SearchResultItem(const SearchResultItem &other)
+ : path(other.path),
+ text(other.text),
+ textMarkPos(other.textMarkPos),
+ textMarkLength(other.textMarkLength),
+ icon(other.icon),
+ lineNumber(other.lineNumber),
+ useTextEditorFont(other.useTextEditorFont),
+ userData(other.userData)
+ {
+ }
+
+ QStringList path; // hierarchy to the parent item of this item
+ QString text; // text to show for the item itself
+ int textMarkPos; // 0-based starting position for a mark (-1 for no mark)
+ int textMarkLength; // length of the mark (0 for no mark)
+ QIcon icon; // icon to show in front of the item (by be null icon to hide)
+ int lineNumber; // (0 or -1 for no line number)
+ bool useTextEditorFont;
+ QVariant userData; // user data for identification of the item
};
class FIND_EXPORT SearchResult : public QObject
@@ -80,6 +102,11 @@ public:
SearchAndReplace
};
+ enum AddMode {
+ AddSorted,
+ AddOrdered
+ };
+
SearchResultWindow();
virtual ~SearchResultWindow();
static SearchResultWindow *instance();
@@ -110,7 +137,7 @@ public:
// search result object only lives till next startnewsearch call
SearchResult *startNewSearch(SearchMode searchOrSearchAndReplace = SearchOnly);
- void addResults(QList<SearchResultItem> &items);
+ void addResults(QList<SearchResultItem> &items, AddMode mode);
public slots:
void clearContents();
void addResult(const QString &fileName, int lineNumber, const QString &lineText,
@@ -119,7 +146,7 @@ public slots:
private slots:
void handleExpandCollapseToolButton(bool checked);
- void handleJumpToSearchResult(int index, bool checked);
+ void handleJumpToSearchResult(const SearchResultItem &item);
void handleReplaceButton();
void showNoMatchesFound();
@@ -135,4 +162,6 @@ private:
} // namespace Find
+Q_DECLARE_METATYPE(Find::SearchResultItem)
+
#endif // SEARCHRESULTWINDOW_H
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 094668d4c0..86df657bf1 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -128,6 +128,7 @@ plugin_cpptools.subdir = cpptools
plugin_cpptools.depends = plugin_projectexplorer
plugin_cpptools.depends += plugin_coreplugin
plugin_cpptools.depends += plugin_texteditor
+plugin_cpptools.depends += plugin_find
plugin_bookmarks.subdir = bookmarks
plugin_bookmarks.depends = plugin_projectexplorer
diff --git a/src/plugins/projectexplorer/allprojectsfind.cpp b/src/plugins/projectexplorer/allprojectsfind.cpp
index 9bf1c99579..89ae73506c 100644
--- a/src/plugins/projectexplorer/allprojectsfind.cpp
+++ b/src/plugins/projectexplorer/allprojectsfind.cpp
@@ -72,11 +72,6 @@ bool AllProjectsFind::isEnabled() const
&& m_plugin->session()->projects().count() > 0;
}
-QKeySequence AllProjectsFind::defaultShortcut() const
-{
- return QKeySequence();
-}
-
Utils::FileIterator *AllProjectsFind::files()
{
Q_ASSERT(m_plugin->session());
diff --git a/src/plugins/projectexplorer/allprojectsfind.h b/src/plugins/projectexplorer/allprojectsfind.h
index d4710a7381..d6484e5d60 100644
--- a/src/plugins/projectexplorer/allprojectsfind.h
+++ b/src/plugins/projectexplorer/allprojectsfind.h
@@ -54,7 +54,6 @@ public:
QString displayName() const;
bool isEnabled() const;
- QKeySequence defaultShortcut() const;
QWidget *createConfigWidget();
void writeSettings(QSettings *settings);
diff --git a/src/plugins/projectexplorer/currentprojectfind.cpp b/src/plugins/projectexplorer/currentprojectfind.cpp
index 55a2ba6950..2e929c5cbe 100644
--- a/src/plugins/projectexplorer/currentprojectfind.cpp
+++ b/src/plugins/projectexplorer/currentprojectfind.cpp
@@ -70,11 +70,6 @@ bool CurrentProjectFind::isEnabled() const
return m_plugin->currentProject() != 0 && BaseFileFind::isEnabled();
}
-QKeySequence CurrentProjectFind::defaultShortcut() const
-{
- return QKeySequence();
-}
-
Utils::FileIterator *CurrentProjectFind::files()
{
Project *project = m_plugin->currentProject();
diff --git a/src/plugins/projectexplorer/currentprojectfind.h b/src/plugins/projectexplorer/currentprojectfind.h
index 5ee35a83c8..8066189595 100644
--- a/src/plugins/projectexplorer/currentprojectfind.h
+++ b/src/plugins/projectexplorer/currentprojectfind.h
@@ -57,7 +57,6 @@ public:
QString displayName() const;
bool isEnabled() const;
- QKeySequence defaultShortcut() const;
QWidget *createConfigWidget();
void writeSettings(QSettings *settings);
diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp
index 9006e11a73..7360ade771 100644
--- a/src/plugins/texteditor/basefilefind.cpp
+++ b/src/plugins/texteditor/basefilefind.cpp
@@ -153,15 +153,16 @@ void BaseFileFind::displayResult(int index) {
QList<Find::SearchResultItem> items; // this conversion is stupid...
foreach (const Utils::FileSearchResult &result, results) {
Find::SearchResultItem item;
- item.fileName = result.fileName;
+ item.path = QStringList() << QDir::toNativeSeparators(result.fileName);
item.lineNumber = result.lineNumber;
- item.lineText = result.matchingLine;
- item.searchTermLength = result.matchLength;
- item.searchTermStart = result.matchStart;
+ item.text = result.matchingLine;
+ item.textMarkLength = result.matchLength;
+ item.textMarkPos = result.matchStart;
+ item.useTextEditorFont = true;
item.userData = result.regexpCapturedTexts;
items << item;
}
- m_resultWindow->addResults(items);
+ m_resultWindow->addResults(items, Find::SearchResultWindow::AddOrdered);
if (m_resultLabel)
m_resultLabel->setText(tr("%1 found").arg(m_resultWindow->numberOfResults()));
}
@@ -250,7 +251,11 @@ void BaseFileFind::updateComboEntries(QComboBox *combo, bool onTop)
void BaseFileFind::openEditor(const Find::SearchResultItem &item)
{
- TextEditor::BaseTextEditor::openEditorAt(item.fileName, item.lineNumber, item.searchTermStart);
+ if (item.path.size() > 0) {
+ TextEditor::BaseTextEditor::openEditorAt(item.path.first(), item.lineNumber, item.textMarkPos);
+ } else {
+ Core::EditorManager::instance()->openEditor(item.text);
+ }
}
// #pragma mark Static methods
@@ -263,7 +268,7 @@ static void applyChanges(QTextDocument *doc, const QString &text, const QList<Fi
const int blockNumber = item.lineNumber - 1;
QTextCursor tc(doc->findBlockByNumber(blockNumber));
- const int cursorPosition = tc.position() + item.searchTermStart;
+ const int cursorPosition = tc.position() + item.textMarkPos;
int cursorIndex = 0;
for (; cursorIndex < changes.size(); ++cursorIndex) {
@@ -277,7 +282,7 @@ static void applyChanges(QTextDocument *doc, const QString &text, const QList<Fi
continue; // skip this change.
tc.setPosition(cursorPosition);
- tc.setPosition(tc.position() + item.searchTermLength,
+ tc.setPosition(tc.position() + item.textMarkLength,
QTextCursor::KeepAnchor);
QString substitutionText;
if (item.userData.canConvert<QStringList>() && !item.userData.toStringList().isEmpty())
@@ -302,7 +307,7 @@ QStringList BaseFileFind::replaceAll(const QString &text,
QHash<QString, QList<Find::SearchResultItem> > changes;
foreach (const Find::SearchResultItem &item, items)
- changes[item.fileName].append(item);
+ changes[item.path.first()].append(item);
Core::EditorManager *editorManager = Core::EditorManager::instance();
diff --git a/src/plugins/texteditor/findincurrentfile.cpp b/src/plugins/texteditor/findincurrentfile.cpp
index cad56dd7a4..01c060133f 100644
--- a/src/plugins/texteditor/findincurrentfile.cpp
+++ b/src/plugins/texteditor/findincurrentfile.cpp
@@ -62,11 +62,6 @@ QString FindInCurrentFile::displayName() const
return tr("Current File");
}
-QKeySequence FindInCurrentFile::defaultShortcut() const
-{
- return QKeySequence();
-}
-
Utils::FileIterator *FindInCurrentFile::files()
{
QStringList fileList;
diff --git a/src/plugins/texteditor/findincurrentfile.h b/src/plugins/texteditor/findincurrentfile.h
index b532e4cfa7..b42064d99c 100644
--- a/src/plugins/texteditor/findincurrentfile.h
+++ b/src/plugins/texteditor/findincurrentfile.h
@@ -55,7 +55,6 @@ public:
QString id() const;
QString displayName() const;
- QKeySequence defaultShortcut() const;
bool isEnabled() const;
QWidget *createConfigWidget();
void writeSettings(QSettings *settings);
diff --git a/src/plugins/texteditor/findinfiles.cpp b/src/plugins/texteditor/findinfiles.cpp
index f2bbc54300..b6b02ef31b 100644
--- a/src/plugins/texteditor/findinfiles.cpp
+++ b/src/plugins/texteditor/findinfiles.cpp
@@ -57,11 +57,6 @@ QString FindInFiles::displayName() const
return tr("Files on File System");
}
-QKeySequence FindInFiles::defaultShortcut() const
-{
- return QKeySequence();
-}
-
void FindInFiles::findAll(const QString &txt, Find::FindFlags findFlags)
{
updateComboEntries(m_directory, true);
diff --git a/src/plugins/texteditor/findinfiles.h b/src/plugins/texteditor/findinfiles.h
index 49172f13b7..569e5ce781 100644
--- a/src/plugins/texteditor/findinfiles.h
+++ b/src/plugins/texteditor/findinfiles.h
@@ -53,7 +53,6 @@ public:
QString id() const;
QString displayName() const;
- QKeySequence defaultShortcut() const;
void findAll(const QString &txt, Find::FindFlags findFlags);
QWidget *createConfigWidget();
void writeSettings(QSettings *settings);