C++ symbols find filter for advanced find.

Required refactoring of the search result window to show real trees of
search results.

The backend is the backend from the Locator filter, which is a bit
outdated now.
This commit is contained in:
con
2010-07-19 14:46:53 +02:00
parent 80d85e2887
commit 2bda8675e5
37 changed files with 926 additions and 474 deletions

View File

@@ -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>

View File

@@ -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);

View File

@@ -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"); }

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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"); }

View File

@@ -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(':')));

View File

@@ -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) {}

View File

@@ -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

View File

@@ -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)

View File

@@ -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);

View File

@@ -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

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;

View File

@@ -48,9 +48,6 @@ 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();
QStyleOptionViewItemV3 opt = setOptions(index, option);
@@ -58,12 +55,22 @@ void SearchResultTreeItemDelegate::paint(QPainter *painter, const QStyleOptionVi
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));
int lineNumberAreaWidth = drawLineNumber(painter, opt, resultRowRect, index);
resultRowRect.adjust(lineNumberAreaWidth, 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);
// 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);
@@ -81,20 +88,37 @@ void SearchResultTreeItemDelegate::paint(QPainter *painter, const QStyleOptionVi
}
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

View File

@@ -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;

View File

@@ -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

View File

@@ -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,16 +97,28 @@ const SearchResultTreeItem *SearchResultTreeItem::parent() const
return m_parent;
}
static bool compareResultFiles(SearchResultTreeItem *a, SearchResultTreeItem *b)
static bool lessThanByText(SearchResultTreeItem *a, const QString &b)
{
return static_cast<SearchResultFile *>(a)->fileName() <
static_cast<SearchResultFile *>(b)->fileName();
return a->item.text < b;
}
int SearchResultTreeItem::insertionIndex(SearchResultFile *child) const
int SearchResultTreeItem::insertionIndex(const QString &text, SearchResultTreeItem **existingItem) const
{
Q_ASSERT(m_type == Root);
return qLowerBound(m_children.begin(), m_children.end(), child, compareResultFiles) - m_children.begin();
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();
}
int SearchResultTreeItem::insertionIndex(const SearchResultItem &item, SearchResultTreeItem **existingItem) const
{
return insertionIndex(item.text, existingItem);
}
void SearchResultTreeItem::insertChild(int index, SearchResultTreeItem *child)
@@ -109,68 +126,17 @@ void SearchResultTreeItem::insertChild(int index, SearchResultTreeItem *child)
m_children.insert(index, child);
}
void SearchResultTreeItem::appendChild(SearchResultTreeItem *child)
void SearchResultTreeItem::insertChild(int index, const SearchResultItem &item)
{
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
{
return m_lineNumber;
}
int SearchResultTextRow::searchTermStart() const
{
return m_searchTermStart;
}
int SearchResultTextRow::searchTermLength() const
{
return m_searchTermLength;
}
SearchResultFile::SearchResultFile(const QString &fileName, const SearchResultTreeItem *parent):
SearchResultTreeItem(ResultFile, parent),
m_fileName(fileName)
{
}
QString SearchResultFile::fileName() const
{
return m_fileName;
}
void SearchResultFile::appendResultLine(int index, int lineNumber, const QString &rowText, int searchTermStart,
int searchTermLength)
{
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);
}

View File

@@ -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

View File

@@ -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:
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();
result = row->item.textMarkLength;
break;
case ItemDataRoles::TypeRole:
result = QLatin1String("row");
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);
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) {
m_lastAddedResultFile->setIsUserCheckable(true);
m_lastAddedResultFile->setCheckState(Qt::Checked);
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());
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_lastAddedResultFile->appendResultLine(item.index,
item.lineNumber,
item.lineText,
item.searchTermStart,
item.searchTermLength);
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();
}
}
}
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);
} 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);
}
if (includeTopLevel)
return nextParent;
return nextParent.child(0, 0);
// 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 {
// We are on a top level item
return idx.child(0,0);
// go up one parent
if (!current.isValid()) {
nextIndex = index(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();
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) {
// Same parent
return index(row - 1, 0, parent);
current = index(row - 1, 0, current.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);
current = current.parent();
checkForChildren = !current.isValid();
}
return prevParent.child(rowCount(prevParent) - 1, 0);
}
} else {
// We are on a top level item
int row = idx.row();
QModelIndex prevParent;
if (row > 0) {
prevParent = index(row - 1, 0);
} else {
// wrap around
prevParent = index(rowCount() -1, 0);
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;

View File

@@ -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;
};

View File

@@ -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;
SearchResultItem item = model()->data(index, ItemDataRoles::ResultItemRole).value<SearchResultItem>();
int position = model()->data(index, ItemDataRoles::ResultIndexRole).toInt();
int checked = model()->data(index, Qt::CheckStateRole).toBool();
emit jumpToSearchResult(position, checked);
emit jumpToSearchResult(item);
}
void SearchResultTreeView::keyPressEvent(QKeyEvent *e)

View File

@@ -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();

View File

@@ -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()) {

View File

@@ -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

View File

@@ -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

View File

@@ -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());

View File

@@ -54,7 +54,6 @@ public:
QString displayName() const;
bool isEnabled() const;
QKeySequence defaultShortcut() const;
QWidget *createConfigWidget();
void writeSettings(QSettings *settings);

View File

@@ -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();

View File

@@ -57,7 +57,6 @@ public:
QString displayName() const;
bool isEnabled() const;
QKeySequence defaultShortcut() const;
QWidget *createConfigWidget();
void writeSettings(QSettings *settings);

View File

@@ -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();

View File

@@ -62,11 +62,6 @@ QString FindInCurrentFile::displayName() const
return tr("Current File");
}
QKeySequence FindInCurrentFile::defaultShortcut() const
{
return QKeySequence();
}
Utils::FileIterator *FindInCurrentFile::files()
{
QStringList fileList;

View File

@@ -55,7 +55,6 @@ public:
QString id() const;
QString displayName() const;
QKeySequence defaultShortcut() const;
bool isEnabled() const;
QWidget *createConfigWidget();
void writeSettings(QSettings *settings);

View File

@@ -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);

View File

@@ -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);