forked from qt-creator/qt-creator
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:
@@ -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="TextEditor" version="2.1.80"/>
|
||||||
<dependency name="ProjectExplorer" version="2.1.80"/>
|
<dependency name="ProjectExplorer" version="2.1.80"/>
|
||||||
<dependency name="Locator" version="2.1.80"/>
|
<dependency name="Locator" version="2.1.80"/>
|
||||||
|
<dependency name="Find" version="2.1.80"/>
|
||||||
</dependencyList>
|
</dependencyList>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|||||||
@@ -31,8 +31,8 @@
|
|||||||
|
|
||||||
using namespace CppTools::Internal;
|
using namespace CppTools::Internal;
|
||||||
|
|
||||||
CppClassesFilter::CppClassesFilter(CppModelManager *manager, Core::EditorManager *editorManager)
|
CppClassesFilter::CppClassesFilter(CppModelManager *manager)
|
||||||
: CppLocatorFilter(manager, editorManager)
|
: CppLocatorFilter(manager)
|
||||||
{
|
{
|
||||||
setShortcutString("c");
|
setShortcutString("c");
|
||||||
setIncludedByDefault(false);
|
setIncludedByDefault(false);
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class CppClassesFilter : public CppLocatorFilter
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CppClassesFilter(CppModelManager *manager, Core::EditorManager *editorManager);
|
CppClassesFilter(CppModelManager *manager);
|
||||||
~CppClassesFilter();
|
~CppClassesFilter();
|
||||||
|
|
||||||
QString displayName() const { return tr("Classes"); }
|
QString displayName() const { return tr("Classes"); }
|
||||||
|
|||||||
@@ -313,7 +313,11 @@ void CppFindReferences::searchFinished()
|
|||||||
|
|
||||||
void CppFindReferences::openEditor(const Find::SearchResultItem &item)
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,8 @@
|
|||||||
|
|
||||||
using namespace CppTools::Internal;
|
using namespace CppTools::Internal;
|
||||||
|
|
||||||
CppFunctionsFilter::CppFunctionsFilter(CppModelManager *manager, Core::EditorManager *editorManager)
|
CppFunctionsFilter::CppFunctionsFilter(CppModelManager *manager)
|
||||||
: CppLocatorFilter(manager, editorManager)
|
: CppLocatorFilter(manager)
|
||||||
{
|
{
|
||||||
setShortcutString(QString(QLatin1Char('m')));
|
setShortcutString(QString(QLatin1Char('m')));
|
||||||
setIncludedByDefault(false);
|
setIncludedByDefault(false);
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class CppFunctionsFilter : public CppLocatorFilter
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CppFunctionsFilter(CppModelManager *manager, Core::EditorManager *editorManager);
|
CppFunctionsFilter(CppModelManager *manager);
|
||||||
~CppFunctionsFilter();
|
~CppFunctionsFilter();
|
||||||
|
|
||||||
QString displayName() const { return tr("Methods"); }
|
QString displayName() const { return tr("Methods"); }
|
||||||
|
|||||||
@@ -30,8 +30,6 @@
|
|||||||
#include "cpplocatorfilter.h"
|
#include "cpplocatorfilter.h"
|
||||||
#include "cppmodelmanager.h"
|
#include "cppmodelmanager.h"
|
||||||
|
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
|
||||||
#include <coreplugin/editormanager/ieditor.h>
|
|
||||||
#include <texteditor/itexteditor.h>
|
#include <texteditor/itexteditor.h>
|
||||||
#include <texteditor/basetexteditor.h>
|
#include <texteditor/basetexteditor.h>
|
||||||
|
|
||||||
@@ -39,9 +37,8 @@
|
|||||||
|
|
||||||
using namespace CppTools::Internal;
|
using namespace CppTools::Internal;
|
||||||
|
|
||||||
CppLocatorFilter::CppLocatorFilter(CppModelManager *manager, Core::EditorManager *editorManager)
|
CppLocatorFilter::CppLocatorFilter(CppModelManager *manager)
|
||||||
: m_manager(manager),
|
: m_manager(manager),
|
||||||
m_editorManager(editorManager),
|
|
||||||
m_forceNewSearchList(true)
|
m_forceNewSearchList(true)
|
||||||
{
|
{
|
||||||
setShortcutString(QString(QLatin1Char(':')));
|
setShortcutString(QString(QLatin1Char(':')));
|
||||||
|
|||||||
@@ -34,10 +34,6 @@
|
|||||||
|
|
||||||
#include <locator/ilocatorfilter.h>
|
#include <locator/ilocatorfilter.h>
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class EditorManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -47,7 +43,7 @@ class CppLocatorFilter : public Locator::ILocatorFilter
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
CppLocatorFilter(CppModelManager *manager, Core::EditorManager *editorManager);
|
CppLocatorFilter(CppModelManager *manager);
|
||||||
~CppLocatorFilter();
|
~CppLocatorFilter();
|
||||||
|
|
||||||
QString displayName() const { return tr("Classes and Methods"); }
|
QString displayName() const { return tr("Classes and Methods"); }
|
||||||
@@ -66,7 +62,6 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
CppModelManager *m_manager;
|
CppModelManager *m_manager;
|
||||||
Core::EditorManager *m_editorManager;
|
|
||||||
|
|
||||||
struct Info {
|
struct Info {
|
||||||
Info(): dirty(true) {}
|
Info(): dirty(true) {}
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ HEADERS += completionsettingspage.h \
|
|||||||
cppdoxygen.h \
|
cppdoxygen.h \
|
||||||
cppfilesettingspage.h \
|
cppfilesettingspage.h \
|
||||||
cppfindreferences.h \
|
cppfindreferences.h \
|
||||||
cppcodeformatter.h
|
cppcodeformatter.h \
|
||||||
|
symbolsfindfilter.h
|
||||||
|
|
||||||
SOURCES += completionsettingspage.cpp \
|
SOURCES += completionsettingspage.cpp \
|
||||||
cppclassesfilter.cpp \
|
cppclassesfilter.cpp \
|
||||||
@@ -40,7 +41,8 @@ SOURCES += completionsettingspage.cpp \
|
|||||||
cppfilesettingspage.cpp \
|
cppfilesettingspage.cpp \
|
||||||
abstracteditorsupport.cpp \
|
abstracteditorsupport.cpp \
|
||||||
cppfindreferences.cpp \
|
cppfindreferences.cpp \
|
||||||
cppcodeformatter.cpp
|
cppcodeformatter.cpp \
|
||||||
|
symbolsfindfilter.cpp
|
||||||
|
|
||||||
FORMS += completionsettingspage.ui \
|
FORMS += completionsettingspage.ui \
|
||||||
cppfilesettingspage.ui
|
cppfilesettingspage.ui
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
include($$IDE_SOURCE_TREE/src/libs/cplusplus/cplusplus.pri)
|
include($$IDE_SOURCE_TREE/src/libs/cplusplus/cplusplus.pri)
|
||||||
include($$IDE_SOURCE_TREE/src/plugins/projectexplorer/projectexplorer.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/texteditor/texteditor.pri)
|
||||||
|
include($$IDE_SOURCE_TREE/src/plugins/find/find.pri)
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include "cppmodelmanager.h"
|
#include "cppmodelmanager.h"
|
||||||
#include "cpptoolsconstants.h"
|
#include "cpptoolsconstants.h"
|
||||||
#include "cpplocatorfilter.h"
|
#include "cpplocatorfilter.h"
|
||||||
|
#include "symbolsfindfilter.h"
|
||||||
|
|
||||||
#include <extensionsystem/pluginmanager.h>
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
|
||||||
@@ -111,14 +112,13 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error)
|
|||||||
CppCodeCompletion *completion = new CppCodeCompletion(m_modelManager);
|
CppCodeCompletion *completion = new CppCodeCompletion(m_modelManager);
|
||||||
addAutoReleasedObject(completion);
|
addAutoReleasedObject(completion);
|
||||||
|
|
||||||
CppLocatorFilter *locatorFilter = new CppLocatorFilter(m_modelManager,
|
addAutoReleasedObject(new CppLocatorFilter(m_modelManager));
|
||||||
core->editorManager());
|
addAutoReleasedObject(new CppClassesFilter(m_modelManager));
|
||||||
addAutoReleasedObject(locatorFilter);
|
addAutoReleasedObject(new CppFunctionsFilter(m_modelManager));
|
||||||
addAutoReleasedObject(new CppClassesFilter(m_modelManager, core->editorManager()));
|
|
||||||
addAutoReleasedObject(new CppFunctionsFilter(m_modelManager, core->editorManager()));
|
|
||||||
addAutoReleasedObject(new CppCurrentDocumentFilter(m_modelManager, core->editorManager()));
|
addAutoReleasedObject(new CppCurrentDocumentFilter(m_modelManager, core->editorManager()));
|
||||||
addAutoReleasedObject(new CompletionSettingsPage);
|
addAutoReleasedObject(new CompletionSettingsPage);
|
||||||
addAutoReleasedObject(new CppFileSettingsPage(m_fileSettings));
|
addAutoReleasedObject(new CppFileSettingsPage(m_fileSettings));
|
||||||
|
addAutoReleasedObject(new SymbolsFindFilter(m_modelManager));
|
||||||
|
|
||||||
// Menus
|
// Menus
|
||||||
Core::ActionContainer *mtools = am->actionContainer(Core::Constants::M_TOOLS);
|
Core::ActionContainer *mtools = am->actionContainer(Core::Constants::M_TOOLS);
|
||||||
|
|||||||
@@ -32,10 +32,17 @@
|
|||||||
#include <Literals.h>
|
#include <Literals.h>
|
||||||
#include <Scope.h>
|
#include <Scope.h>
|
||||||
#include <Names.h>
|
#include <Names.h>
|
||||||
|
#include <cplusplus/LookupContext.h>
|
||||||
|
|
||||||
using namespace CPlusPlus;
|
using namespace CPlusPlus;
|
||||||
using namespace CppTools::Internal;
|
using namespace CppTools::Internal;
|
||||||
|
|
||||||
|
SearchSymbols::SymbolTypes SearchSymbols::AllTypes =
|
||||||
|
SearchSymbols::Classes
|
||||||
|
| SearchSymbols::Functions
|
||||||
|
| SearchSymbols::Enums
|
||||||
|
| SearchSymbols::Declarations;
|
||||||
|
|
||||||
SearchSymbols::SearchSymbols():
|
SearchSymbols::SearchSymbols():
|
||||||
symbolsToSearchFor(Classes | Functions | Enums),
|
symbolsToSearchFor(Classes | Functions | Enums),
|
||||||
separateScope(false)
|
separateScope(false)
|
||||||
@@ -204,13 +211,17 @@ QString SearchSymbols::symbolName(const Symbol *symbol) const
|
|||||||
void SearchSymbols::appendItem(const QString &name,
|
void SearchSymbols::appendItem(const QString &name,
|
||||||
const QString &info,
|
const QString &info,
|
||||||
ModelItemInfo::ItemType type,
|
ModelItemInfo::ItemType type,
|
||||||
const Symbol *symbol)
|
Symbol *symbol)
|
||||||
{
|
{
|
||||||
if (!symbol->name())
|
if (!symbol->name())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
QStringList fullyQualifiedName;
|
||||||
|
foreach (const Name *name, LookupContext::fullyQualifiedName(symbol))
|
||||||
|
fullyQualifiedName.append(overview.prettyName(name));
|
||||||
const QIcon icon = icons.iconForSymbol(symbol);
|
const QIcon icon = icons.iconForSymbol(symbol);
|
||||||
items.append(ModelItemInfo(name, info, type,
|
items.append(ModelItemInfo(name, info, type,
|
||||||
|
fullyQualifiedName,
|
||||||
QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()),
|
QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()),
|
||||||
symbol->line(),
|
symbol->line(),
|
||||||
symbol->column() - 1, // 1-based vs 0-based column
|
symbol->column() - 1, // 1-based vs 0-based column
|
||||||
|
|||||||
@@ -52,12 +52,14 @@ struct ModelItemInfo
|
|||||||
|
|
||||||
ModelItemInfo()
|
ModelItemInfo()
|
||||||
: type(Declaration),
|
: type(Declaration),
|
||||||
line(0)
|
line(0),
|
||||||
|
column(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
ModelItemInfo(const QString &symbolName,
|
ModelItemInfo(const QString &symbolName,
|
||||||
const QString &symbolType,
|
const QString &symbolType,
|
||||||
ItemType type,
|
ItemType type,
|
||||||
|
QStringList fullyQualifiedName,
|
||||||
const QString &fileName,
|
const QString &fileName,
|
||||||
int line,
|
int line,
|
||||||
int column,
|
int column,
|
||||||
@@ -65,15 +67,28 @@ struct ModelItemInfo
|
|||||||
: symbolName(symbolName),
|
: symbolName(symbolName),
|
||||||
symbolType(symbolType),
|
symbolType(symbolType),
|
||||||
type(type),
|
type(type),
|
||||||
|
fullyQualifiedName(fullyQualifiedName),
|
||||||
fileName(fileName),
|
fileName(fileName),
|
||||||
line(line),
|
line(line),
|
||||||
column(column),
|
column(column),
|
||||||
icon(icon)
|
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 symbolName;
|
||||||
QString symbolType;
|
QString symbolType;
|
||||||
ItemType type;
|
ItemType type;
|
||||||
|
QStringList fullyQualifiedName;
|
||||||
QString fileName;
|
QString fileName;
|
||||||
int line;
|
int line;
|
||||||
int column;
|
int column;
|
||||||
@@ -90,8 +105,11 @@ public:
|
|||||||
Enums = 0x4,
|
Enums = 0x4,
|
||||||
Declarations = 0x8
|
Declarations = 0x8
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_FLAGS(SymbolTypes, SymbolType)
|
Q_DECLARE_FLAGS(SymbolTypes, SymbolType)
|
||||||
|
|
||||||
|
static SymbolTypes AllTypes;
|
||||||
|
|
||||||
SearchSymbols();
|
SearchSymbols();
|
||||||
|
|
||||||
void setSymbolsToSearchFor(SymbolTypes types);
|
void setSymbolsToSearchFor(SymbolTypes types);
|
||||||
@@ -121,7 +139,7 @@ protected:
|
|||||||
void appendItem(const QString &name,
|
void appendItem(const QString &name,
|
||||||
const QString &info,
|
const QString &info,
|
||||||
ModelItemInfo::ItemType type,
|
ModelItemInfo::ItemType type,
|
||||||
const CPlusPlus::Symbol *symbol);
|
CPlusPlus::Symbol *symbol);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString findOrInsert(const QString &s)
|
QString findOrInsert(const QString &s)
|
||||||
|
|||||||
317
src/plugins/cpptools/symbolsfindfilter.cpp
Normal file
317
src/plugins/cpptools/symbolsfindfilter.cpp
Normal 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);
|
||||||
|
}
|
||||||
124
src/plugins/cpptools/symbolsfindfilter.h
Normal file
124
src/plugins/cpptools/symbolsfindfilter.h
Normal 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
|
||||||
@@ -34,9 +34,9 @@
|
|||||||
#include "textfindconstants.h"
|
#include "textfindconstants.h"
|
||||||
|
|
||||||
#include <QtGui/QTextDocument>
|
#include <QtGui/QTextDocument>
|
||||||
|
#include <QtGui/QKeySequence>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QKeySequence;
|
|
||||||
class QWidget;
|
class QWidget;
|
||||||
class QSettings;
|
class QSettings;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
@@ -53,7 +53,7 @@ public:
|
|||||||
virtual QString id() const = 0;
|
virtual QString id() const = 0;
|
||||||
virtual QString displayName() const = 0;
|
virtual QString displayName() const = 0;
|
||||||
virtual bool isEnabled() 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 bool isReplaceSupported() const { return false; }
|
||||||
virtual FindFlags supportedFindFlags() const;
|
virtual FindFlags supportedFindFlags() const;
|
||||||
|
|
||||||
|
|||||||
@@ -48,53 +48,77 @@ SearchResultTreeItemDelegate::SearchResultTreeItemDelegate(QObject *parent)
|
|||||||
|
|
||||||
void SearchResultTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
void SearchResultTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
if (index.model()->data(index, ItemDataRoles::TypeRole).toString().compare(QLatin1String("file")) == 0) {
|
painter->save();
|
||||||
QItemDelegate::paint(painter, option, index);
|
|
||||||
} else {
|
|
||||||
painter->save();
|
|
||||||
|
|
||||||
QStyleOptionViewItemV3 opt = setOptions(index, option);
|
QStyleOptionViewItemV3 opt = setOptions(index, option);
|
||||||
painter->setFont(opt.font);
|
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));
|
int lineNumberAreaWidth = drawLineNumber(painter, opt, resultRowRect, index);
|
||||||
QString displayString = index.model()->data(index, Qt::DisplayRole).toString();
|
resultRowRect.adjust(lineNumberAreaWidth, 0, 0, 0);
|
||||||
drawMarker(painter, index, displayString, resultRowRect);
|
|
||||||
|
|
||||||
// Draw the text and focus/selection
|
QString displayString = index.model()->data(index, Qt::DisplayRole).toString();
|
||||||
QItemDelegate::drawDisplay(painter, opt, resultRowRect, displayString);
|
drawMarker(painter, index, displayString, resultRowRect);
|
||||||
QItemDelegate::drawFocus(painter, opt, opt.rect);
|
|
||||||
|
|
||||||
QVariant value = index.data(Qt::CheckStateRole);
|
// Show number of subresults in displayString
|
||||||
if (value.isValid()) {
|
if (index.model()->hasChildren(index)) {
|
||||||
Qt::CheckState checkState = Qt::Unchecked;
|
displayString += QString::fromLatin1(" (")
|
||||||
checkState = static_cast<Qt::CheckState>(value.toInt());
|
+ QString::number(index.model()->rowCount(index))
|
||||||
QRect checkRect = check(opt, opt.rect, value);
|
+ QLatin1Char(')');
|
||||||
|
|
||||||
QRect emptyRect;
|
|
||||||
doLayout(opt, &checkRect, &emptyRect, &emptyRect, false);
|
|
||||||
|
|
||||||
QItemDelegate::drawCheck(painter, opt, checkRect, checkState);
|
|
||||||
}
|
|
||||||
|
|
||||||
painter->restore();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw the text and focus/selection
|
||||||
|
QItemDelegate::drawDisplay(painter, opt, resultRowRect, displayString);
|
||||||
|
QItemDelegate::drawFocus(painter, opt, opt.rect);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
QRect emptyRect;
|
||||||
|
doLayout(opt, &checkRect, &emptyRect, &emptyRect, false);
|
||||||
|
|
||||||
|
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,
|
int SearchResultTreeItemDelegate::drawLineNumber(QPainter *painter, const QStyleOptionViewItemV3 &option,
|
||||||
|
const QRect &rect,
|
||||||
const QModelIndex &index) const
|
const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
static const int lineNumberAreaHorizontalPadding = 4;
|
static const int lineNumberAreaHorizontalPadding = 4;
|
||||||
const bool isSelected = option.state & QStyle::State_Selected;
|
|
||||||
int lineNumber = index.model()->data(index, ItemDataRoles::ResultLineNumberRole).toInt();
|
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 lineNumberDigits = (int)floor(log10((double)lineNumber)) + 1;
|
||||||
int minimumLineNumberDigits = qMax((int)m_minimumLineNumberDigits, lineNumberDigits);
|
int minimumLineNumberDigits = qMax((int)m_minimumLineNumberDigits, lineNumberDigits);
|
||||||
int fontWidth = painter->fontMetrics().width(QString(minimumLineNumberDigits, QLatin1Char('0')));
|
int fontWidth = painter->fontMetrics().width(QString(minimumLineNumberDigits, QLatin1Char('0')));
|
||||||
int lineNumberAreaWidth = lineNumberAreaHorizontalPadding + fontWidth + lineNumberAreaHorizontalPadding;
|
int lineNumberAreaWidth = lineNumberAreaHorizontalPadding + fontWidth + lineNumberAreaHorizontalPadding;
|
||||||
QRect lineNumberAreaRect(option.rect);
|
QRect lineNumberAreaRect(rect);
|
||||||
lineNumberAreaRect.setWidth(lineNumberAreaWidth);
|
lineNumberAreaRect.setWidth(lineNumberAreaWidth);
|
||||||
|
|
||||||
QPalette::ColorGroup cg = QPalette::Normal;
|
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,
|
void SearchResultTreeItemDelegate::drawMarker(QPainter *painter, const QModelIndex &index, const QString text,
|
||||||
const QRect &rect) const
|
const QRect &rect) const
|
||||||
{
|
{
|
||||||
const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
|
|
||||||
int searchTermStart = index.model()->data(index, ItemDataRoles::SearchTermStartRole).toInt();
|
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();
|
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));
|
int searchTermLengthPixels = painter->fontMetrics().width(text.mid(searchTermStart, searchTermLength));
|
||||||
QRect resultHighlightRect(rect);
|
QRect resultHighlightRect(rect);
|
||||||
resultHighlightRect.setLeft(resultHighlightRect.left() + searchTermStartPixels + textMargin - 1); // -1: Cosmetics
|
resultHighlightRect.setLeft(resultHighlightRect.left() + searchTermStartPixels + textMargin - 1); // -1: Cosmetics
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ public:
|
|||||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||||
|
|
||||||
private:
|
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;
|
void drawMarker(QPainter *painter, const QModelIndex &index, const QString text, const QRect &rect) const;
|
||||||
|
|
||||||
static const int m_minimumLineNumberDigits = 6;
|
static const int m_minimumLineNumberDigits = 6;
|
||||||
|
|||||||
@@ -30,22 +30,21 @@
|
|||||||
#ifndef SEARCHRESULTTREEITEMROLES_H
|
#ifndef SEARCHRESULTTREEITEMROLES_H
|
||||||
#define SEARCHRESULTTREEITEMROLES_H
|
#define SEARCHRESULTTREEITEMROLES_H
|
||||||
|
|
||||||
|
#include <QtGui/QAbstractItemView>
|
||||||
|
|
||||||
namespace Find {
|
namespace Find {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
namespace ItemDataRoles {
|
namespace ItemDataRoles {
|
||||||
|
|
||||||
enum Roles
|
enum Roles
|
||||||
{
|
{
|
||||||
TypeRole = Qt::UserRole,
|
ResultItemRole = Qt::UserRole,
|
||||||
FileNameRole,
|
|
||||||
ResultLinesCountRole,
|
|
||||||
ResultIndexRole,
|
|
||||||
ResultLineRole,
|
ResultLineRole,
|
||||||
ResultLineNumberRole,
|
ResultLineNumberRole,
|
||||||
|
ResultIconRole,
|
||||||
SearchTermStartRole,
|
SearchTermStartRole,
|
||||||
SearchTermLengthRole,
|
SearchTermLengthRole,
|
||||||
RowOfItem, // The ?-th child of its parent is this this item
|
RowOfItem // The ?-th child of its parent is this this item
|
||||||
TextRole // for files == FileNameRole, for results == ResultLineRole
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -31,8 +31,13 @@
|
|||||||
|
|
||||||
using namespace Find::Internal;
|
using namespace Find::Internal;
|
||||||
|
|
||||||
SearchResultTreeItem::SearchResultTreeItem(SearchResultTreeItem::ItemType type, const SearchResultTreeItem *parent)
|
SearchResultTreeItem::SearchResultTreeItem(const SearchResultItem &item,
|
||||||
: m_type(type), m_parent(parent), m_isUserCheckable(false), m_checkState(Qt::Unchecked)
|
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();
|
clearChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SearchResultTreeItem::isLeaf() const
|
||||||
|
{
|
||||||
|
return childrenCount() == 0 && parent() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool SearchResultTreeItem::isUserCheckable() const
|
bool SearchResultTreeItem::isUserCheckable() const
|
||||||
{
|
{
|
||||||
return m_isUserCheckable;
|
return m_isUserCheckable;
|
||||||
@@ -67,11 +77,6 @@ void SearchResultTreeItem::clearChildren()
|
|||||||
m_children.clear();
|
m_children.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchResultTreeItem::ItemType SearchResultTreeItem::itemType() const
|
|
||||||
{
|
|
||||||
return m_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SearchResultTreeItem::childrenCount() const
|
int SearchResultTreeItem::childrenCount() const
|
||||||
{
|
{
|
||||||
return m_children.count();
|
return m_children.count();
|
||||||
@@ -92,16 +97,28 @@ const SearchResultTreeItem *SearchResultTreeItem::parent() const
|
|||||||
return m_parent;
|
return m_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool compareResultFiles(SearchResultTreeItem *a, SearchResultTreeItem *b)
|
static bool lessThanByText(SearchResultTreeItem *a, const QString &b)
|
||||||
{
|
{
|
||||||
return static_cast<SearchResultFile *>(a)->fileName() <
|
return a->item.text < b;
|
||||||
static_cast<SearchResultFile *>(b)->fileName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SearchResultTreeItem::insertionIndex(SearchResultFile *child) const
|
int SearchResultTreeItem::insertionIndex(const QString &text, SearchResultTreeItem **existingItem) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_type == Root);
|
QList<SearchResultTreeItem *>::const_iterator insertionPosition =
|
||||||
return qLowerBound(m_children.begin(), m_children.end(), child, compareResultFiles) - m_children.begin();
|
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)
|
void SearchResultTreeItem::insertChild(int index, SearchResultTreeItem *child)
|
||||||
@@ -109,68 +126,17 @@ void SearchResultTreeItem::insertChild(int index, SearchResultTreeItem *child)
|
|||||||
m_children.insert(index, child);
|
m_children.insert(index, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchResultTreeItem::appendChild(SearchResultTreeItem *child)
|
void SearchResultTreeItem::insertChild(int index, const SearchResultItem &item)
|
||||||
{
|
{
|
||||||
m_children.append(child);
|
SearchResultTreeItem *child = new SearchResultTreeItem(item, this);
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
if (isUserCheckable()) {
|
if (isUserCheckable()) {
|
||||||
child->setIsUserCheckable(true);
|
child->setIsUserCheckable(true);
|
||||||
child->setCheckState(Qt::Checked);
|
child->setCheckState(Qt::Checked);
|
||||||
}
|
}
|
||||||
appendChild(child);
|
insertChild(index, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchResultTreeItem::appendChild(const SearchResultItem &item)
|
||||||
|
{
|
||||||
|
insertChild(m_children.count(), item);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,35 +30,31 @@
|
|||||||
#ifndef SEARCHRESULTTREEITEMS_H
|
#ifndef SEARCHRESULTTREEITEMS_H
|
||||||
#define SEARCHRESULTTREEITEMS_H
|
#define SEARCHRESULTTREEITEMS_H
|
||||||
|
|
||||||
|
#include "searchresultwindow.h"
|
||||||
|
|
||||||
#include <QtCore/QString>
|
#include <QtCore/QString>
|
||||||
#include <QtCore/QList>
|
#include <QtCore/QList>
|
||||||
#include <QtCore/qnamespace.h>
|
#include <QtCore/qnamespace.h>
|
||||||
|
#include <QtGui/QIcon>
|
||||||
|
|
||||||
namespace Find {
|
namespace Find {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class SearchResultTreeItem;
|
|
||||||
class SearchResultFile;
|
|
||||||
|
|
||||||
class SearchResultTreeItem
|
class SearchResultTreeItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum ItemType
|
SearchResultTreeItem(const SearchResultItem &item = SearchResultItem(),
|
||||||
{
|
const SearchResultTreeItem *parent = NULL);
|
||||||
Root,
|
|
||||||
ResultRow,
|
|
||||||
ResultFile
|
|
||||||
};
|
|
||||||
|
|
||||||
SearchResultTreeItem(ItemType type = Root, const SearchResultTreeItem *parent = NULL);
|
|
||||||
virtual ~SearchResultTreeItem();
|
virtual ~SearchResultTreeItem();
|
||||||
|
|
||||||
ItemType itemType() const;
|
bool isLeaf() const;
|
||||||
const SearchResultTreeItem *parent() const;
|
const SearchResultTreeItem *parent() const;
|
||||||
SearchResultTreeItem *childAt(int index) 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 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 childrenCount() const;
|
||||||
int rowOfItem() const;
|
int rowOfItem() const;
|
||||||
void clearChildren();
|
void clearChildren();
|
||||||
@@ -69,43 +65,17 @@ public:
|
|||||||
Qt::CheckState checkState() const;
|
Qt::CheckState checkState() const;
|
||||||
void setCheckState(Qt::CheckState checkState);
|
void setCheckState(Qt::CheckState checkState);
|
||||||
|
|
||||||
|
bool isGenerated() const { return m_isGenerated; }
|
||||||
|
void setGenerated(bool value) { m_isGenerated = value; }
|
||||||
|
|
||||||
|
SearchResultItem item;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ItemType m_type;
|
|
||||||
const SearchResultTreeItem *m_parent;
|
const SearchResultTreeItem *m_parent;
|
||||||
QList<SearchResultTreeItem *> m_children;
|
QList<SearchResultTreeItem *> m_children;
|
||||||
bool m_isUserCheckable;
|
bool m_isUserCheckable;
|
||||||
Qt::CheckState m_checkState;
|
Qt::CheckState m_checkState;
|
||||||
};
|
bool m_isGenerated;
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ using namespace Find::Internal;
|
|||||||
|
|
||||||
SearchResultTreeModel::SearchResultTreeModel(QObject *parent)
|
SearchResultTreeModel::SearchResultTreeModel(QObject *parent)
|
||||||
: QAbstractItemModel(parent)
|
: QAbstractItemModel(parent)
|
||||||
, m_lastAddedResultFile(0)
|
, m_currentParent(0)
|
||||||
, m_showReplaceUI(false)
|
, m_showReplaceUI(false)
|
||||||
{
|
{
|
||||||
m_rootItem = new SearchResultTreeItem;
|
m_rootItem = new SearchResultTreeItem;
|
||||||
@@ -70,13 +70,13 @@ void SearchResultTreeModel::setTextEditorFont(const QFont &font)
|
|||||||
layoutChanged();
|
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 (idx.isValid()) {
|
||||||
if (const SearchResultTreeItem *item = static_cast<const SearchResultTreeItem*>(index.internalPointer())) {
|
if (const SearchResultTreeItem *item = treeItemAtIndex(idx)) {
|
||||||
if (item->itemType() == SearchResultTreeItem::ResultRow && item->isUserCheckable()) {
|
if (item->isLeaf() && item->isUserCheckable()) {
|
||||||
flags |= Qt::ItemIsUserCheckable;
|
flags |= Qt::ItemIsUserCheckable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ QModelIndex SearchResultTreeModel::index(int row, int column,
|
|||||||
if (!parent.isValid())
|
if (!parent.isValid())
|
||||||
parentItem = m_rootItem;
|
parentItem = m_rootItem;
|
||||||
else
|
else
|
||||||
parentItem = static_cast<const SearchResultTreeItem*>(parent.internalPointer());
|
parentItem = treeItemAtIndex(parent);
|
||||||
|
|
||||||
const SearchResultTreeItem *childItem = parentItem->childAt(row);
|
const SearchResultTreeItem *childItem = parentItem->childAt(row);
|
||||||
if (childItem)
|
if (childItem)
|
||||||
@@ -105,12 +105,17 @@ QModelIndex SearchResultTreeModel::index(int row, int column,
|
|||||||
return QModelIndex();
|
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();
|
return QModelIndex();
|
||||||
|
|
||||||
const SearchResultTreeItem *childItem = static_cast<const SearchResultTreeItem*>(index.internalPointer());
|
const SearchResultTreeItem *childItem = treeItemAtIndex(idx);
|
||||||
const SearchResultTreeItem *parentItem = childItem->parent();
|
const SearchResultTreeItem *parentItem = childItem->parent();
|
||||||
|
|
||||||
if (parentItem == m_rootItem)
|
if (parentItem == m_rootItem)
|
||||||
@@ -129,7 +134,7 @@ int SearchResultTreeModel::rowCount(const QModelIndex &parent) const
|
|||||||
if (!parent.isValid())
|
if (!parent.isValid())
|
||||||
parentItem = m_rootItem;
|
parentItem = m_rootItem;
|
||||||
else
|
else
|
||||||
parentItem = static_cast<const SearchResultTreeItem*>(parent.internalPointer());
|
parentItem = treeItemAtIndex(parent);
|
||||||
|
|
||||||
return parentItem->childrenCount();
|
return parentItem->childrenCount();
|
||||||
}
|
}
|
||||||
@@ -140,48 +145,41 @@ int SearchResultTreeModel::columnCount(const QModelIndex &parent) const
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant SearchResultTreeModel::data(const QModelIndex &index, int role) const
|
SearchResultTreeItem *SearchResultTreeModel::treeItemAtIndex(const QModelIndex &idx) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
return static_cast<SearchResultTreeItem*>(idx.internalPointer());
|
||||||
return QVariant();
|
}
|
||||||
|
|
||||||
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;
|
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 appFontHeight = QApplication::fontMetrics().height();
|
||||||
const int editorFontHeight = QFontMetrics(m_textEditorFont).height();
|
const int editorFontHeight = QFontMetrics(m_textEditorFont).height();
|
||||||
result = QSize(0, qMax(appFontHeight, editorFontHeight));
|
result = QSize(0, qMax(appFontHeight, editorFontHeight));
|
||||||
}
|
} else {
|
||||||
else if (item->itemType() == SearchResultTreeItem::ResultRow)
|
result = data(treeItemAtIndex(idx), role);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
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) {
|
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());
|
Qt::CheckState checkState = static_cast<Qt::CheckState>(value.toInt());
|
||||||
row->setCheckState(checkState);
|
treeItemAtIndex(idx)->setCheckState(checkState);
|
||||||
return true;
|
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;
|
QVariant result;
|
||||||
|
|
||||||
@@ -192,39 +190,40 @@ QVariant SearchResultTreeModel::data(const SearchResultTextRow *row, int role) c
|
|||||||
result = row->checkState();
|
result = row->checkState();
|
||||||
break;
|
break;
|
||||||
case Qt::ToolTipRole:
|
case Qt::ToolTipRole:
|
||||||
result = row->rowText().trimmed();
|
result = row->item.text.trimmed();
|
||||||
break;
|
break;
|
||||||
case Qt::FontRole:
|
case Qt::FontRole:
|
||||||
result = m_textEditorFont;
|
if (row->item.useTextEditorFont)
|
||||||
|
result = m_textEditorFont;
|
||||||
|
else
|
||||||
|
result = QVariant();
|
||||||
break;
|
break;
|
||||||
case ItemDataRoles::TextRole:
|
|
||||||
case ItemDataRoles::ResultLineRole:
|
case ItemDataRoles::ResultLineRole:
|
||||||
case Qt::DisplayRole:
|
case Qt::DisplayRole:
|
||||||
result = row->rowText();
|
result = row->item.text;
|
||||||
break;
|
break;
|
||||||
case ItemDataRoles::ResultIndexRole:
|
case ItemDataRoles::ResultItemRole:
|
||||||
result = row->index();
|
result = qVariantFromValue(row->item);
|
||||||
break;
|
break;
|
||||||
case ItemDataRoles::ResultLineNumberRole:
|
case ItemDataRoles::ResultLineNumberRole:
|
||||||
result = row->lineNumber();
|
result = row->item.lineNumber;
|
||||||
|
break;
|
||||||
|
case ItemDataRoles::ResultIconRole:
|
||||||
|
result = row->item.icon;
|
||||||
break;
|
break;
|
||||||
case ItemDataRoles::SearchTermStartRole:
|
case ItemDataRoles::SearchTermStartRole:
|
||||||
result = row->searchTermStart();
|
result = row->item.textMarkPos;
|
||||||
break;
|
break;
|
||||||
case ItemDataRoles::SearchTermLengthRole:
|
case ItemDataRoles::SearchTermLengthRole:
|
||||||
result = row->searchTermLength();
|
result = row->item.textMarkLength;
|
||||||
break;
|
break;
|
||||||
case ItemDataRoles::TypeRole:
|
// TODO this looks stupid in case of symbol tree, is it necessary?
|
||||||
result = QLatin1String("row");
|
// case Qt::BackgroundRole:
|
||||||
break;
|
// if (row->parent() && row->parent()->parent())
|
||||||
case ItemDataRoles::FileNameRole:
|
// result = QVariant();
|
||||||
{
|
// else
|
||||||
if (row->parent()->itemType() == SearchResultTreeItem::ResultFile) {
|
// result = QApplication::palette().base().color().darker(105);
|
||||||
const SearchResultFile *file = static_cast<const SearchResultFile *>(row->parent());
|
// break;
|
||||||
result = file->fileName();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
result = QVariant();
|
result = QVariant();
|
||||||
break;
|
break;
|
||||||
@@ -233,42 +232,6 @@ QVariant SearchResultTreeModel::data(const SearchResultTextRow *row, int role) c
|
|||||||
return result;
|
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,
|
QVariant SearchResultTreeModel::headerData(int section, Qt::Orientation orientation,
|
||||||
int role) const
|
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
|
QSet<SearchResultTreeItem *> pathNodes;
|
||||||
if (fileName.contains(QLatin1Char('\\')))
|
SearchResultTreeItem *currentItem = m_rootItem;
|
||||||
qWarning("SearchResultTreeModel::appendResultFile: File name with native separators added %s.\n", qPrintable(fileName));
|
QModelIndex currentItemIndex = QModelIndex();
|
||||||
#endif
|
SearchResultTreeItem *partItem = 0;
|
||||||
m_lastAddedResultFile = new SearchResultFile(fileName, m_rootItem);
|
QStringList currentPath;
|
||||||
|
foreach (const QString &part, path) {
|
||||||
if (m_showReplaceUI) {
|
const int insertionIndex = currentItem->insertionIndex(part, &partItem);
|
||||||
m_lastAddedResultFile->setIsUserCheckable(true);
|
if (!partItem) {
|
||||||
m_lastAddedResultFile->setCheckState(Qt::Checked);
|
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);
|
m_currentParent = currentItem;
|
||||||
beginInsertRows(QModelIndex(), index, index);
|
m_currentPath = currentPath;
|
||||||
m_rootItem->insertChild(index, m_lastAddedResultFile);
|
m_currentIndex = currentItemIndex;
|
||||||
endInsertRows();
|
return pathNodes;
|
||||||
return index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchResultTreeModel::appendResultLines(const QList<SearchResultItem> &items)
|
void SearchResultTreeModel::addResultsToCurrentParent(const QList<SearchResultItem> &items, SearchResultWindow::AddMode mode)
|
||||||
{
|
{
|
||||||
if (!m_lastAddedResultFile)
|
if (!m_currentParent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QModelIndex lastFile(createIndex(m_lastAddedResultFile->rowOfItem(), 0, m_lastAddedResultFile));
|
if (mode == SearchResultWindow::AddOrdered) {
|
||||||
|
// this is the mode for e.g. text search
|
||||||
beginInsertRows(lastFile, m_lastAddedResultFile->childrenCount(), m_lastAddedResultFile->childrenCount() + items.count());
|
beginInsertRows(m_currentIndex, m_currentParent->childrenCount(), m_currentParent->childrenCount() + items.count());
|
||||||
foreach (const SearchResultItem &item, items) {
|
foreach (const SearchResultItem &item, items) {
|
||||||
m_lastAddedResultFile->appendResultLine(item.index,
|
m_currentParent->appendChild(item);
|
||||||
item.lineNumber,
|
}
|
||||||
item.lineText,
|
endInsertRows();
|
||||||
item.searchTermStart,
|
} else if (mode == SearchResultWindow::AddSorted) {
|
||||||
item.searchTermLength);
|
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
|
* Adds the search result to the list of results, creating nodes for the path when
|
||||||
* necessary. Returns the insertion index when a new file entry was created.
|
* 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;
|
QList<SearchResultItem> itemSet;
|
||||||
foreach (const SearchResultItem &item, items) {
|
foreach (const SearchResultItem &item, sortedItems) {
|
||||||
if (!m_lastAddedResultFile || (m_lastAddedResultFile->fileName() != item.fileName)) {
|
if (!m_currentParent || (m_currentPath != item.path)) {
|
||||||
|
// first add all the items from before
|
||||||
if (!itemSet.isEmpty()) {
|
if (!itemSet.isEmpty()) {
|
||||||
appendResultLines(itemSet);
|
addResultsToCurrentParent(itemSet, mode);
|
||||||
itemSet.clear();
|
itemSet.clear();
|
||||||
}
|
}
|
||||||
insertedFileIndices << addResultFile(item.fileName);
|
// switch parent
|
||||||
|
pathNodes += addPath(item.path);
|
||||||
}
|
}
|
||||||
itemSet << item;
|
itemSet << item;
|
||||||
}
|
}
|
||||||
if (!itemSet.isEmpty()) {
|
if (!itemSet.isEmpty()) {
|
||||||
appendResultLines(itemSet);
|
addResultsToCurrentParent(itemSet, mode);
|
||||||
itemSet.clear();
|
itemSet.clear();
|
||||||
}
|
}
|
||||||
return insertedFileIndices;
|
QList<QModelIndex> pathIndices;
|
||||||
|
foreach (SearchResultTreeItem *item, pathNodes)
|
||||||
|
pathIndices << index(item);
|
||||||
|
return pathIndices;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchResultTreeModel::clear()
|
void SearchResultTreeModel::clear()
|
||||||
{
|
{
|
||||||
m_lastAddedResultFile = NULL;
|
m_currentParent = NULL;
|
||||||
m_rootItem->clearChildren();
|
m_rootItem->clearChildren();
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex SearchResultTreeModel::next(const QModelIndex &idx, bool includeTopLevel) const
|
QModelIndex SearchResultTreeModel::nextIndex(const QModelIndex &idx) const
|
||||||
{
|
{
|
||||||
QModelIndex parent = idx.parent();
|
// pathological
|
||||||
if (parent.isValid()) {
|
if (!idx.isValid())
|
||||||
int row = idx.row();
|
return index(0, 0);
|
||||||
if (row + 1 < rowCount(parent)) {
|
|
||||||
// Same parent
|
if (rowCount(idx) > 0) {
|
||||||
return index(row + 1, 0, parent);
|
// node with children
|
||||||
} else {
|
return idx.child(0, 0);
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We are on a top level item
|
|
||||||
return idx.child(0,0);
|
|
||||||
}
|
}
|
||||||
return QModelIndex();
|
// 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 {
|
||||||
|
// go up one parent
|
||||||
|
if (!current.isValid()) {
|
||||||
|
nextIndex = index(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nextIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex SearchResultTreeModel::prev(const QModelIndex &idx, bool includeTopLevel) const
|
QModelIndex SearchResultTreeModel::next(const QModelIndex &idx, bool includeGenerated) const
|
||||||
{
|
{
|
||||||
QModelIndex parent = idx.parent();
|
QModelIndex value = idx;
|
||||||
if (parent.isValid()) {
|
do {
|
||||||
int row = idx.row();
|
value = nextIndex(value);
|
||||||
if (row > 0) {
|
} while (value != idx && !includeGenerated && treeItemAtIndex(value)->isGenerated());
|
||||||
// Same parent
|
return value;
|
||||||
return index(row - 1, 0, parent);
|
}
|
||||||
} else {
|
|
||||||
if (includeTopLevel)
|
QModelIndex SearchResultTreeModel::prevIndex(const QModelIndex &idx) const
|
||||||
return parent;
|
{
|
||||||
// Prev parent
|
QModelIndex current = idx;
|
||||||
int parentRow = parent.row();
|
bool checkForChildren = true;
|
||||||
QModelIndex prevParent;
|
if (current.isValid()) {
|
||||||
if (parentRow > 0 ) {
|
int row = current.row();
|
||||||
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;
|
|
||||||
if (row > 0) {
|
if (row > 0) {
|
||||||
prevParent = index(row - 1, 0);
|
current = index(row - 1, 0, current.parent());
|
||||||
} else {
|
} else {
|
||||||
// wrap around
|
current = current.parent();
|
||||||
prevParent = index(rowCount() -1, 0);
|
checkForChildren = !current.isValid();
|
||||||
}
|
}
|
||||||
return prevParent.child(rowCount(prevParent) -1,0);
|
|
||||||
}
|
}
|
||||||
return QModelIndex();
|
if (checkForChildren) {
|
||||||
|
// traverse down the hierarchy
|
||||||
|
while (int rc = rowCount(current)) {
|
||||||
|
current = index(rc - 1, 0, current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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)
|
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
|
else
|
||||||
currentIndex = next(currentIndex, true);
|
currentIndex = next(currentIndex, true);
|
||||||
if (currentIndex.isValid()) {
|
if (currentIndex.isValid()) {
|
||||||
const QString &text = data(currentIndex, ItemDataRoles::TextRole).toString();
|
const QString &text = data(currentIndex, ItemDataRoles::ResultLineRole).toString();
|
||||||
if (expr.indexIn(text) != -1)
|
if (expr.indexIn(text) != -1)
|
||||||
resultIndex = currentIndex;
|
resultIndex = currentIndex;
|
||||||
}
|
}
|
||||||
@@ -452,7 +467,7 @@ QModelIndex SearchResultTreeModel::find(const QString &term, const QModelIndex &
|
|||||||
else
|
else
|
||||||
currentIndex = next(currentIndex, true);
|
currentIndex = next(currentIndex, true);
|
||||||
if (currentIndex.isValid()) {
|
if (currentIndex.isValid()) {
|
||||||
const QString &text = data(currentIndex, ItemDataRoles::TextRole).toString();
|
const QString &text = data(currentIndex, ItemDataRoles::ResultLineRole).toString();
|
||||||
QTextDocument doc(text);
|
QTextDocument doc(text);
|
||||||
if (!doc.find(term, 0, flags).isNull())
|
if (!doc.find(term, 0, flags).isNull())
|
||||||
resultIndex = currentIndex;
|
resultIndex = currentIndex;
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ namespace Find {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class SearchResultTreeItem;
|
class SearchResultTreeItem;
|
||||||
class SearchResultTextRow;
|
|
||||||
class SearchResultFile;
|
|
||||||
|
|
||||||
class SearchResultTreeModel : public QAbstractItemModel
|
class SearchResultTreeModel : public QAbstractItemModel
|
||||||
{
|
{
|
||||||
@@ -64,10 +62,10 @@ public:
|
|||||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||||
|
|
||||||
QModelIndex next(const QModelIndex &idx, bool includeTopLevel = false) const;
|
QModelIndex next(const QModelIndex &idx, bool includeGenerated = false) const;
|
||||||
QModelIndex prev(const QModelIndex &idx, bool includeTopLevel = 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 QRegExp &expr, const QModelIndex &index, QTextDocument::FindFlags flags);
|
||||||
QModelIndex find(const QString &term, 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();
|
void clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void appendResultLines(const QList<SearchResultItem> &items);
|
QModelIndex index(SearchResultTreeItem *item) const;
|
||||||
int addResultFile(const QString &fileName);
|
void addResultsToCurrentParent(const QList<SearchResultItem> &items, SearchResultWindow::AddMode mode);
|
||||||
QVariant data(const SearchResultTextRow *row, int role) const;
|
QSet<SearchResultTreeItem *> addPath(const QStringList &path);
|
||||||
QVariant data(const SearchResultFile *file, int role) const;
|
QVariant data(const SearchResultTreeItem *row, int role) const;
|
||||||
void initializeData();
|
QModelIndex nextIndex(const QModelIndex &idx) const;
|
||||||
void disposeData();
|
QModelIndex prevIndex(const QModelIndex &idx) const;
|
||||||
|
SearchResultTreeItem *treeItemAtIndex(const QModelIndex &idx) const;
|
||||||
|
|
||||||
SearchResultTreeItem *m_rootItem;
|
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;
|
QFont m_textEditorFont;
|
||||||
bool m_showReplaceUI;
|
bool m_showReplaceUI;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ SearchResultTreeView::SearchResultTreeView(QWidget *parent)
|
|||||||
setItemDelegate(new SearchResultTreeItemDelegate(this));
|
setItemDelegate(new SearchResultTreeItemDelegate(this));
|
||||||
setIndentation(14);
|
setIndentation(14);
|
||||||
setUniformRowHeights(true);
|
setUniformRowHeights(true);
|
||||||
|
setExpandsOnDoubleClick(false);
|
||||||
header()->hide();
|
header()->hide();
|
||||||
|
|
||||||
connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(emitJumpToSearchResult(QModelIndex)));
|
connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(emitJumpToSearchResult(QModelIndex)));
|
||||||
@@ -66,24 +67,20 @@ void SearchResultTreeView::clear()
|
|||||||
m_model->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);
|
QList<QModelIndex> addedParents = m_model->addResults(items, mode);
|
||||||
if (m_autoExpandResults && !insertedFileIndices.isEmpty()) {
|
if (m_autoExpandResults && !addedParents.isEmpty()) {
|
||||||
foreach (int index, insertedFileIndices)
|
foreach (const QModelIndex &index, addedParents)
|
||||||
setExpanded(model()->index(index, 0), true);
|
setExpanded(index, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchResultTreeView::emitJumpToSearchResult(const QModelIndex &index)
|
void SearchResultTreeView::emitJumpToSearchResult(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
if (model()->data(index, ItemDataRoles::TypeRole).toString().compare(QLatin1String("row")) != 0)
|
SearchResultItem item = model()->data(index, ItemDataRoles::ResultItemRole).value<SearchResultItem>();
|
||||||
return;
|
|
||||||
|
|
||||||
int position = model()->data(index, ItemDataRoles::ResultIndexRole).toInt();
|
emit jumpToSearchResult(item);
|
||||||
int checked = model()->data(index, Qt::CheckStateRole).toBool();
|
|
||||||
|
|
||||||
emit jumpToSearchResult(position, checked);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchResultTreeView::keyPressEvent(QKeyEvent *e)
|
void SearchResultTreeView::keyPressEvent(QKeyEvent *e)
|
||||||
|
|||||||
@@ -50,10 +50,10 @@ public:
|
|||||||
void setTextEditorFont(const QFont &font);
|
void setTextEditorFont(const QFont &font);
|
||||||
|
|
||||||
SearchResultTreeModel *model() const;
|
SearchResultTreeModel *model() const;
|
||||||
void appendResultLines(const QList<Find::SearchResultItem> &items);
|
void addResults(const QList<Find::SearchResultItem> &items, SearchResultWindow::AddMode mode);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void jumpToSearchResult(int index, bool checked);
|
void jumpToSearchResult(const SearchResultItem &item);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void clear();
|
void clear();
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
#include <QtCore/QTextStream>
|
#include <QtCore/QTextStream>
|
||||||
#include <QtCore/QSettings>
|
#include <QtCore/QSettings>
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtCore/QDir>
|
||||||
#include <QtGui/QListWidget>
|
#include <QtGui/QListWidget>
|
||||||
#include <QtGui/QToolButton>
|
#include <QtGui/QToolButton>
|
||||||
#include <QtGui/QLineEdit>
|
#include <QtGui/QLineEdit>
|
||||||
@@ -56,7 +57,6 @@
|
|||||||
static const char SETTINGSKEYSECTIONNAME[] = "SearchResults";
|
static const char SETTINGSKEYSECTIONNAME[] = "SearchResults";
|
||||||
static const char SETTINGSKEYEXPANDRESULTS[] = "ExpandResults";
|
static const char SETTINGSKEYEXPANDRESULTS[] = "ExpandResults";
|
||||||
|
|
||||||
|
|
||||||
namespace Find {
|
namespace Find {
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -204,13 +204,14 @@ namespace Internal {
|
|||||||
static const bool m_initiallyExpand = false;
|
static const bool m_initiallyExpand = false;
|
||||||
QStackedWidget *m_widget;
|
QStackedWidget *m_widget;
|
||||||
SearchResult *m_currentSearch;
|
SearchResult *m_currentSearch;
|
||||||
QList<SearchResultItem> m_items;
|
int m_itemCount;
|
||||||
bool m_isShowingReplaceUI;
|
bool m_isShowingReplaceUI;
|
||||||
bool m_focusReplaceEdit;
|
bool m_focusReplaceEdit;
|
||||||
};
|
};
|
||||||
|
|
||||||
SearchResultWindowPrivate::SearchResultWindowPrivate()
|
SearchResultWindowPrivate::SearchResultWindowPrivate()
|
||||||
: m_currentSearch(0),
|
: m_currentSearch(0),
|
||||||
|
m_itemCount(0),
|
||||||
m_isShowingReplaceUI(false),
|
m_isShowingReplaceUI(false),
|
||||||
m_focusReplaceEdit(false)
|
m_focusReplaceEdit(false)
|
||||||
{
|
{
|
||||||
@@ -338,8 +339,8 @@ SearchResultWindow::SearchResultWindow() : d(new SearchResultWindowPrivate)
|
|||||||
d->m_replaceButton->setAutoRaise(true);
|
d->m_replaceButton->setAutoRaise(true);
|
||||||
d->m_replaceTextEdit->setTabOrder(d->m_replaceTextEdit, d->m_searchResultTreeView);
|
d->m_replaceTextEdit->setTabOrder(d->m_replaceTextEdit, d->m_searchResultTreeView);
|
||||||
|
|
||||||
connect(d->m_searchResultTreeView, SIGNAL(jumpToSearchResult(int,bool)),
|
connect(d->m_searchResultTreeView, SIGNAL(jumpToSearchResult(SearchResultItem)),
|
||||||
this, SLOT(handleJumpToSearchResult(int,bool)));
|
this, SLOT(handleJumpToSearchResult(SearchResultItem)));
|
||||||
connect(d->m_expandCollapseAction, SIGNAL(toggled(bool)), this, SLOT(handleExpandCollapseToolButton(bool)));
|
connect(d->m_expandCollapseAction, SIGNAL(toggled(bool)), this, SLOT(handleExpandCollapseToolButton(bool)));
|
||||||
connect(d->m_replaceTextEdit, SIGNAL(returnPressed()), this, SLOT(handleReplaceButton()));
|
connect(d->m_replaceTextEdit, SIGNAL(returnPressed()), this, SLOT(handleReplaceButton()));
|
||||||
connect(d->m_replaceButton, SIGNAL(clicked()), this, SLOT(handleReplaceButton()));
|
connect(d->m_replaceButton, SIGNAL(clicked()), this, SLOT(handleReplaceButton()));
|
||||||
@@ -359,7 +360,7 @@ SearchResultWindow::~SearchResultWindow()
|
|||||||
d->m_currentSearch = 0;
|
d->m_currentSearch = 0;
|
||||||
delete d->m_widget;
|
delete d->m_widget;
|
||||||
d->m_widget = 0;
|
d->m_widget = 0;
|
||||||
d->m_items.clear();
|
d->m_itemCount = 0;
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,13 +429,13 @@ QList<SearchResultItem> SearchResultWindow::checkedItems() const
|
|||||||
const int fileCount = model->rowCount(QModelIndex());
|
const int fileCount = model->rowCount(QModelIndex());
|
||||||
for (int i = 0; i < fileCount; ++i) {
|
for (int i = 0; i < fileCount; ++i) {
|
||||||
QModelIndex fileIndex = model->index(i, 0, QModelIndex());
|
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);
|
Q_ASSERT(fileItem != 0);
|
||||||
for (int rowIndex = 0; rowIndex < fileItem->childrenCount(); ++rowIndex) {
|
for (int rowIndex = 0; rowIndex < fileItem->childrenCount(); ++rowIndex) {
|
||||||
QModelIndex textIndex = model->index(rowIndex, 0, fileIndex);
|
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())
|
if (rowItem->checkState())
|
||||||
result << d->m_items.at(rowItem->index());
|
result << rowItem->item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -492,7 +493,7 @@ SearchResult *SearchResultWindow::startNewSearch(SearchMode searchOrSearchAndRep
|
|||||||
*/
|
*/
|
||||||
void SearchResultWindow::finishSearch()
|
void SearchResultWindow::finishSearch()
|
||||||
{
|
{
|
||||||
if (d->m_items.count()) {
|
if (d->m_itemCount > 0) {
|
||||||
d->m_replaceButton->setEnabled(true);
|
d->m_replaceButton->setEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
showNoMatchesFound();
|
showNoMatchesFound();
|
||||||
@@ -509,7 +510,7 @@ void SearchResultWindow::clearContents()
|
|||||||
d->m_replaceButton->setEnabled(false);
|
d->m_replaceButton->setEnabled(false);
|
||||||
d->m_replaceTextEdit->clear();
|
d->m_replaceTextEdit->clear();
|
||||||
d->m_searchResultTreeView->clear();
|
d->m_searchResultTreeView->clear();
|
||||||
d->m_items.clear();
|
d->m_itemCount = 0;
|
||||||
d->m_widget->setCurrentWidget(d->m_searchResultTreeView);
|
d->m_widget->setCurrentWidget(d->m_searchResultTreeView);
|
||||||
navigateStateChanged();
|
navigateStateChanged();
|
||||||
}
|
}
|
||||||
@@ -541,7 +542,7 @@ bool SearchResultWindow::isEmpty() const
|
|||||||
*/
|
*/
|
||||||
int SearchResultWindow::numberOfResults() const
|
int SearchResultWindow::numberOfResults() const
|
||||||
{
|
{
|
||||||
return d->m_items.count();
|
return d->m_itemCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -559,7 +560,7 @@ bool SearchResultWindow::hasFocus()
|
|||||||
*/
|
*/
|
||||||
bool SearchResultWindow::canFocus()
|
bool SearchResultWindow::canFocus()
|
||||||
{
|
{
|
||||||
return !d->m_items.isEmpty();
|
return d->m_itemCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -568,7 +569,7 @@ bool SearchResultWindow::canFocus()
|
|||||||
*/
|
*/
|
||||||
void SearchResultWindow::setFocus()
|
void SearchResultWindow::setFocus()
|
||||||
{
|
{
|
||||||
if (!d->m_items.isEmpty()) {
|
if (d->m_itemCount > 0) {
|
||||||
if (!d->m_isShowingReplaceUI) {
|
if (!d->m_isShowingReplaceUI) {
|
||||||
d->m_searchResultTreeView->setFocus();
|
d->m_searchResultTreeView->setFocus();
|
||||||
} else {
|
} else {
|
||||||
@@ -597,10 +598,10 @@ void SearchResultWindow::setTextEditorFont(const QFont &font)
|
|||||||
\fn void SearchResultWindow::handleJumpToSearchResult(int index, bool)
|
\fn void SearchResultWindow::handleJumpToSearchResult(int index, bool)
|
||||||
\internal
|
\internal
|
||||||
*/
|
*/
|
||||||
void SearchResultWindow::handleJumpToSearchResult(int index, bool /* checked */)
|
void SearchResultWindow::handleJumpToSearchResult(const SearchResultItem &item)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(d->m_currentSearch, return);
|
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)
|
int searchTermStart, int searchTermLength, const QVariant &userData)
|
||||||
{
|
{
|
||||||
SearchResultItem item;
|
SearchResultItem item;
|
||||||
item.fileName = fileName;
|
item.path = QStringList() << QDir::toNativeSeparators(fileName);
|
||||||
item.lineNumber = lineNumber;
|
item.lineNumber = lineNumber;
|
||||||
item.lineText = rowText;
|
item.text = rowText;
|
||||||
item.searchTermStart = searchTermStart;
|
item.textMarkPos = searchTermStart;
|
||||||
item.searchTermLength = searchTermLength;
|
item.textMarkLength = searchTermLength;
|
||||||
|
item.useTextEditorFont = true;
|
||||||
item.userData = userData;
|
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()
|
\sa addResult()
|
||||||
*/
|
*/
|
||||||
void SearchResultWindow::addResults(QList<SearchResultItem> &items)
|
void SearchResultWindow::addResults(QList<SearchResultItem> &items, AddMode mode)
|
||||||
{
|
{
|
||||||
int index = d->m_items.size();
|
bool firstItems = (d->m_itemCount == 0);
|
||||||
bool firstItems = (index == 0);
|
d->m_itemCount += items.size();
|
||||||
for (int i = 0; i < items.size(); ++i) {
|
d->m_searchResultTreeView->addResults(items, mode);
|
||||||
items[i].index = index;
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->m_items << items;
|
|
||||||
d->m_searchResultTreeView->appendResultLines(items);
|
|
||||||
if (firstItems) {
|
if (firstItems) {
|
||||||
d->m_replaceTextEdit->setEnabled(true);
|
d->m_replaceTextEdit->setEnabled(true);
|
||||||
// We didn't have an item before, set the focus to the search widget
|
// 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()
|
bool SearchResultWindow::canNext()
|
||||||
{
|
{
|
||||||
return d->m_items.count() > 0;
|
return d->m_itemCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -722,7 +718,7 @@ bool SearchResultWindow::canNext()
|
|||||||
*/
|
*/
|
||||||
bool SearchResultWindow::canPrevious()
|
bool SearchResultWindow::canPrevious()
|
||||||
{
|
{
|
||||||
return d->m_items.count() > 0;
|
return d->m_itemCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -731,7 +727,7 @@ bool SearchResultWindow::canPrevious()
|
|||||||
*/
|
*/
|
||||||
void SearchResultWindow::goToNext()
|
void SearchResultWindow::goToNext()
|
||||||
{
|
{
|
||||||
if (d->m_items.count() == 0)
|
if (d->m_itemCount == 0)
|
||||||
return;
|
return;
|
||||||
QModelIndex idx = d->m_searchResultTreeView->model()->next(d->m_searchResultTreeView->currentIndex());
|
QModelIndex idx = d->m_searchResultTreeView->model()->next(d->m_searchResultTreeView->currentIndex());
|
||||||
if (idx.isValid()) {
|
if (idx.isValid()) {
|
||||||
|
|||||||
@@ -32,10 +32,12 @@
|
|||||||
|
|
||||||
#include "find_global.h"
|
#include "find_global.h"
|
||||||
|
|
||||||
#include <QtCore/QVariant>
|
|
||||||
|
|
||||||
#include <coreplugin/ioutputpane.h>
|
#include <coreplugin/ioutputpane.h>
|
||||||
|
|
||||||
|
#include <QtCore/QVariant>
|
||||||
|
#include <QtCore/QStringList>
|
||||||
|
#include <QtGui/QIcon>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QFont;
|
class QFont;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
@@ -49,14 +51,34 @@ class SearchResultWindow;
|
|||||||
|
|
||||||
struct FIND_EXPORT SearchResultItem
|
struct FIND_EXPORT SearchResultItem
|
||||||
{
|
{
|
||||||
QString fileName;
|
SearchResultItem()
|
||||||
int lineNumber;
|
: textMarkPos(-1),
|
||||||
QString lineText;
|
textMarkLength(0),
|
||||||
int searchTermStart;
|
lineNumber(-1),
|
||||||
int searchTermLength;
|
useTextEditorFont(false)
|
||||||
int index; // SearchResultWindow sets the index
|
{
|
||||||
QVariant userData;
|
}
|
||||||
// whatever information we also need here
|
|
||||||
|
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
|
class FIND_EXPORT SearchResult : public QObject
|
||||||
@@ -80,6 +102,11 @@ public:
|
|||||||
SearchAndReplace
|
SearchAndReplace
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum AddMode {
|
||||||
|
AddSorted,
|
||||||
|
AddOrdered
|
||||||
|
};
|
||||||
|
|
||||||
SearchResultWindow();
|
SearchResultWindow();
|
||||||
virtual ~SearchResultWindow();
|
virtual ~SearchResultWindow();
|
||||||
static SearchResultWindow *instance();
|
static SearchResultWindow *instance();
|
||||||
@@ -110,7 +137,7 @@ public:
|
|||||||
// search result object only lives till next startnewsearch call
|
// search result object only lives till next startnewsearch call
|
||||||
SearchResult *startNewSearch(SearchMode searchOrSearchAndReplace = SearchOnly);
|
SearchResult *startNewSearch(SearchMode searchOrSearchAndReplace = SearchOnly);
|
||||||
|
|
||||||
void addResults(QList<SearchResultItem> &items);
|
void addResults(QList<SearchResultItem> &items, AddMode mode);
|
||||||
public slots:
|
public slots:
|
||||||
void clearContents();
|
void clearContents();
|
||||||
void addResult(const QString &fileName, int lineNumber, const QString &lineText,
|
void addResult(const QString &fileName, int lineNumber, const QString &lineText,
|
||||||
@@ -119,7 +146,7 @@ public slots:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleExpandCollapseToolButton(bool checked);
|
void handleExpandCollapseToolButton(bool checked);
|
||||||
void handleJumpToSearchResult(int index, bool checked);
|
void handleJumpToSearchResult(const SearchResultItem &item);
|
||||||
void handleReplaceButton();
|
void handleReplaceButton();
|
||||||
void showNoMatchesFound();
|
void showNoMatchesFound();
|
||||||
|
|
||||||
@@ -135,4 +162,6 @@ private:
|
|||||||
|
|
||||||
} // namespace Find
|
} // namespace Find
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Find::SearchResultItem)
|
||||||
|
|
||||||
#endif // SEARCHRESULTWINDOW_H
|
#endif // SEARCHRESULTWINDOW_H
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ plugin_cpptools.subdir = cpptools
|
|||||||
plugin_cpptools.depends = plugin_projectexplorer
|
plugin_cpptools.depends = plugin_projectexplorer
|
||||||
plugin_cpptools.depends += plugin_coreplugin
|
plugin_cpptools.depends += plugin_coreplugin
|
||||||
plugin_cpptools.depends += plugin_texteditor
|
plugin_cpptools.depends += plugin_texteditor
|
||||||
|
plugin_cpptools.depends += plugin_find
|
||||||
|
|
||||||
plugin_bookmarks.subdir = bookmarks
|
plugin_bookmarks.subdir = bookmarks
|
||||||
plugin_bookmarks.depends = plugin_projectexplorer
|
plugin_bookmarks.depends = plugin_projectexplorer
|
||||||
|
|||||||
@@ -72,11 +72,6 @@ bool AllProjectsFind::isEnabled() const
|
|||||||
&& m_plugin->session()->projects().count() > 0;
|
&& m_plugin->session()->projects().count() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QKeySequence AllProjectsFind::defaultShortcut() const
|
|
||||||
{
|
|
||||||
return QKeySequence();
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils::FileIterator *AllProjectsFind::files()
|
Utils::FileIterator *AllProjectsFind::files()
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_plugin->session());
|
Q_ASSERT(m_plugin->session());
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ public:
|
|||||||
QString displayName() const;
|
QString displayName() const;
|
||||||
|
|
||||||
bool isEnabled() const;
|
bool isEnabled() const;
|
||||||
QKeySequence defaultShortcut() const;
|
|
||||||
|
|
||||||
QWidget *createConfigWidget();
|
QWidget *createConfigWidget();
|
||||||
void writeSettings(QSettings *settings);
|
void writeSettings(QSettings *settings);
|
||||||
|
|||||||
@@ -70,11 +70,6 @@ bool CurrentProjectFind::isEnabled() const
|
|||||||
return m_plugin->currentProject() != 0 && BaseFileFind::isEnabled();
|
return m_plugin->currentProject() != 0 && BaseFileFind::isEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
QKeySequence CurrentProjectFind::defaultShortcut() const
|
|
||||||
{
|
|
||||||
return QKeySequence();
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils::FileIterator *CurrentProjectFind::files()
|
Utils::FileIterator *CurrentProjectFind::files()
|
||||||
{
|
{
|
||||||
Project *project = m_plugin->currentProject();
|
Project *project = m_plugin->currentProject();
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ public:
|
|||||||
QString displayName() const;
|
QString displayName() const;
|
||||||
|
|
||||||
bool isEnabled() const;
|
bool isEnabled() const;
|
||||||
QKeySequence defaultShortcut() const;
|
|
||||||
|
|
||||||
QWidget *createConfigWidget();
|
QWidget *createConfigWidget();
|
||||||
void writeSettings(QSettings *settings);
|
void writeSettings(QSettings *settings);
|
||||||
|
|||||||
@@ -153,15 +153,16 @@ void BaseFileFind::displayResult(int index) {
|
|||||||
QList<Find::SearchResultItem> items; // this conversion is stupid...
|
QList<Find::SearchResultItem> items; // this conversion is stupid...
|
||||||
foreach (const Utils::FileSearchResult &result, results) {
|
foreach (const Utils::FileSearchResult &result, results) {
|
||||||
Find::SearchResultItem item;
|
Find::SearchResultItem item;
|
||||||
item.fileName = result.fileName;
|
item.path = QStringList() << QDir::toNativeSeparators(result.fileName);
|
||||||
item.lineNumber = result.lineNumber;
|
item.lineNumber = result.lineNumber;
|
||||||
item.lineText = result.matchingLine;
|
item.text = result.matchingLine;
|
||||||
item.searchTermLength = result.matchLength;
|
item.textMarkLength = result.matchLength;
|
||||||
item.searchTermStart = result.matchStart;
|
item.textMarkPos = result.matchStart;
|
||||||
|
item.useTextEditorFont = true;
|
||||||
item.userData = result.regexpCapturedTexts;
|
item.userData = result.regexpCapturedTexts;
|
||||||
items << item;
|
items << item;
|
||||||
}
|
}
|
||||||
m_resultWindow->addResults(items);
|
m_resultWindow->addResults(items, Find::SearchResultWindow::AddOrdered);
|
||||||
if (m_resultLabel)
|
if (m_resultLabel)
|
||||||
m_resultLabel->setText(tr("%1 found").arg(m_resultWindow->numberOfResults()));
|
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)
|
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
|
// #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;
|
const int blockNumber = item.lineNumber - 1;
|
||||||
QTextCursor tc(doc->findBlockByNumber(blockNumber));
|
QTextCursor tc(doc->findBlockByNumber(blockNumber));
|
||||||
|
|
||||||
const int cursorPosition = tc.position() + item.searchTermStart;
|
const int cursorPosition = tc.position() + item.textMarkPos;
|
||||||
|
|
||||||
int cursorIndex = 0;
|
int cursorIndex = 0;
|
||||||
for (; cursorIndex < changes.size(); ++cursorIndex) {
|
for (; cursorIndex < changes.size(); ++cursorIndex) {
|
||||||
@@ -277,7 +282,7 @@ static void applyChanges(QTextDocument *doc, const QString &text, const QList<Fi
|
|||||||
continue; // skip this change.
|
continue; // skip this change.
|
||||||
|
|
||||||
tc.setPosition(cursorPosition);
|
tc.setPosition(cursorPosition);
|
||||||
tc.setPosition(tc.position() + item.searchTermLength,
|
tc.setPosition(tc.position() + item.textMarkLength,
|
||||||
QTextCursor::KeepAnchor);
|
QTextCursor::KeepAnchor);
|
||||||
QString substitutionText;
|
QString substitutionText;
|
||||||
if (item.userData.canConvert<QStringList>() && !item.userData.toStringList().isEmpty())
|
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;
|
QHash<QString, QList<Find::SearchResultItem> > changes;
|
||||||
|
|
||||||
foreach (const Find::SearchResultItem &item, items)
|
foreach (const Find::SearchResultItem &item, items)
|
||||||
changes[item.fileName].append(item);
|
changes[item.path.first()].append(item);
|
||||||
|
|
||||||
Core::EditorManager *editorManager = Core::EditorManager::instance();
|
Core::EditorManager *editorManager = Core::EditorManager::instance();
|
||||||
|
|
||||||
|
|||||||
@@ -62,11 +62,6 @@ QString FindInCurrentFile::displayName() const
|
|||||||
return tr("Current File");
|
return tr("Current File");
|
||||||
}
|
}
|
||||||
|
|
||||||
QKeySequence FindInCurrentFile::defaultShortcut() const
|
|
||||||
{
|
|
||||||
return QKeySequence();
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils::FileIterator *FindInCurrentFile::files()
|
Utils::FileIterator *FindInCurrentFile::files()
|
||||||
{
|
{
|
||||||
QStringList fileList;
|
QStringList fileList;
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ public:
|
|||||||
|
|
||||||
QString id() const;
|
QString id() const;
|
||||||
QString displayName() const;
|
QString displayName() const;
|
||||||
QKeySequence defaultShortcut() const;
|
|
||||||
bool isEnabled() const;
|
bool isEnabled() const;
|
||||||
QWidget *createConfigWidget();
|
QWidget *createConfigWidget();
|
||||||
void writeSettings(QSettings *settings);
|
void writeSettings(QSettings *settings);
|
||||||
|
|||||||
@@ -57,11 +57,6 @@ QString FindInFiles::displayName() const
|
|||||||
return tr("Files on File System");
|
return tr("Files on File System");
|
||||||
}
|
}
|
||||||
|
|
||||||
QKeySequence FindInFiles::defaultShortcut() const
|
|
||||||
{
|
|
||||||
return QKeySequence();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FindInFiles::findAll(const QString &txt, Find::FindFlags findFlags)
|
void FindInFiles::findAll(const QString &txt, Find::FindFlags findFlags)
|
||||||
{
|
{
|
||||||
updateComboEntries(m_directory, true);
|
updateComboEntries(m_directory, true);
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ public:
|
|||||||
|
|
||||||
QString id() const;
|
QString id() const;
|
||||||
QString displayName() const;
|
QString displayName() const;
|
||||||
QKeySequence defaultShortcut() const;
|
|
||||||
void findAll(const QString &txt, Find::FindFlags findFlags);
|
void findAll(const QString &txt, Find::FindFlags findFlags);
|
||||||
QWidget *createConfigWidget();
|
QWidget *createConfigWidget();
|
||||||
void writeSettings(QSettings *settings);
|
void writeSettings(QSettings *settings);
|
||||||
|
|||||||
Reference in New Issue
Block a user