forked from qt-creator/qt-creator
Locator: Add highlighting of the search text
Change-Id: Ia166e9667076e46770a754b626ceb28080139e79 Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -116,6 +116,7 @@ SplitterColor=ff313131
|
||||
TextColorDisabled=textDisabled
|
||||
TextColorError=ffff4040
|
||||
TextColorHighlight=ffff0000
|
||||
TextColorHighlightBackground=555500
|
||||
TextColorLink=textColorLink
|
||||
TextColorLinkVisited=textColorLinkVisited
|
||||
TextColorNormal=text
|
||||
|
@@ -108,6 +108,7 @@ SplitterColor=ff151515
|
||||
TextColorDisabled=ff000000
|
||||
TextColorError=ffff0000
|
||||
TextColorHighlight=ffa0a0a4
|
||||
TextColorHighlightBackground=ffef0b
|
||||
TextColorLink=ff0057ae
|
||||
TextColorLinkVisited=ff644a9b
|
||||
TextColorNormal=ff000000
|
||||
|
@@ -121,6 +121,7 @@ SplitterColor=splitter
|
||||
TextColorDisabled=textDisabled
|
||||
TextColorError=ffff4040
|
||||
TextColorHighlight=ffff0000
|
||||
TextColorHighlightBackground=8a7f2c
|
||||
TextColorLink=textColorLink
|
||||
TextColorLinkVisited=textColorLinkVisited
|
||||
TextColorNormal=text
|
||||
|
@@ -119,6 +119,7 @@ SplitterColor=splitter
|
||||
TextColorDisabled=textDisabled
|
||||
TextColorError=ffff4040
|
||||
TextColorHighlight=ffff0000
|
||||
TextColorHighlightBackground=ffef0b
|
||||
TextColorLink=ff007af4
|
||||
TextColorLinkVisited=ffa57aff
|
||||
TextColorNormal=text
|
||||
|
@@ -117,6 +117,7 @@ SplitterColor=splitter
|
||||
TextColorDisabled=textDisabled
|
||||
TextColorError=ffff4040
|
||||
TextColorHighlight=ffff0000
|
||||
TextColorHighlightBackground=ffef0b
|
||||
TextColorLink=ff007af4
|
||||
TextColorLinkVisited=ffa57aff
|
||||
TextColorNormal=text
|
||||
|
@@ -116,6 +116,7 @@ public:
|
||||
TextColorDisabled,
|
||||
TextColorError,
|
||||
TextColorHighlight,
|
||||
TextColorHighlightBackground,
|
||||
TextColorLink,
|
||||
TextColorLinkVisited,
|
||||
TextColorNormal,
|
||||
|
@@ -65,10 +65,12 @@ void CMakeLocatorFilter::prepareSearch(const QString &entry)
|
||||
if (!cmakeProject)
|
||||
continue;
|
||||
foreach (const QString &title, cmakeProject->buildTargetTitles()) {
|
||||
if (title.contains(entry)) {
|
||||
Core::LocatorFilterEntry entry(this, title, cmakeProject->projectFilePath().toString());
|
||||
entry.extraInfo = FileUtils::shortNativePath(cmakeProject->projectFilePath());
|
||||
m_result.append(entry);
|
||||
const int index = title.indexOf(entry);
|
||||
if (index >= 0) {
|
||||
Core::LocatorFilterEntry filterEntry(this, title, cmakeProject->projectFilePath().toString());
|
||||
filterEntry.extraInfo = FileUtils::shortNativePath(cmakeProject->projectFilePath());
|
||||
filterEntry.highlightInfo = {index, entry.length()};
|
||||
m_result.append(filterEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -98,18 +98,18 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
|
||||
{
|
||||
QList<LocatorFilterEntry> betterEntries;
|
||||
QList<LocatorFilterEntry> goodEntries;
|
||||
const QString trimmed = trimWildcards(QDir::fromNativeSeparators(origEntry));
|
||||
const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(trimmed);
|
||||
QStringMatcher matcher(fp.filePath, Qt::CaseInsensitive);
|
||||
const QChar asterisk = QLatin1Char('*');
|
||||
QRegExp regexp(asterisk + fp.filePath+ asterisk, Qt::CaseInsensitive, QRegExp::Wildcard);
|
||||
const QString entry = QDir::fromNativeSeparators(origEntry);
|
||||
const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(entry);
|
||||
const Qt::CaseSensitivity cs = caseSensitivity(fp.filePath);
|
||||
QStringMatcher matcher(fp.filePath, cs);
|
||||
QRegExp regexp(fp.filePath, cs, QRegExp::Wildcard);
|
||||
if (!regexp.isValid()) {
|
||||
d->m_current.clear(); // free memory
|
||||
return betterEntries;
|
||||
}
|
||||
const QChar pathSeparator(QLatin1Char('/'));
|
||||
const bool hasPathSeparator = fp.filePath.contains(pathSeparator);
|
||||
const bool hasWildcard = fp.filePath.contains(asterisk) || fp.filePath.contains(QLatin1Char('?'));
|
||||
const bool hasWildcard = containsWildcard(fp.filePath);
|
||||
const bool containsPreviousEntry = !d->m_current.previousEntry.isEmpty()
|
||||
&& fp.filePath.contains(d->m_current.previousEntry);
|
||||
const bool pathSeparatorAdded = !d->m_current.previousEntry.contains(pathSeparator)
|
||||
@@ -124,7 +124,6 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
|
||||
d->m_current.previousResultPaths.clear();
|
||||
d->m_current.previousResultNames.clear();
|
||||
d->m_current.previousEntry = fp.filePath;
|
||||
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(fp.filePath);
|
||||
d->m_current.iterator->toFront();
|
||||
bool canceled = false;
|
||||
while (d->m_current.iterator->hasNext()) {
|
||||
@@ -137,16 +136,32 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
|
||||
QString path = d->m_current.iterator->filePath();
|
||||
QString name = d->m_current.iterator->fileName();
|
||||
QString matchText = hasPathSeparator ? path : name;
|
||||
if ((hasWildcard && regexp.exactMatch(matchText))
|
||||
|| (!hasWildcard && matcher.indexIn(matchText) != -1)) {
|
||||
int index = hasWildcard ? regexp.indexIn(matchText) : matcher.indexIn(matchText);
|
||||
|
||||
if (index >= 0) {
|
||||
QFileInfo fi(path);
|
||||
LocatorFilterEntry entry(this, fi.fileName(), QString(path + fp.postfix));
|
||||
entry.extraInfo = FileUtils::shortNativePath(FileName(fi));
|
||||
entry.fileName = path;
|
||||
if (matchText.startsWith(fp.filePath, caseSensitivityForPrefix))
|
||||
betterEntries.append(entry);
|
||||
LocatorFilterEntry filterEntry(this, fi.fileName(), QString(path + fp.postfix));
|
||||
filterEntry.fileName = path;
|
||||
filterEntry.extraInfo = FileUtils::shortNativePath(FileName(fi));
|
||||
|
||||
LocatorFilterEntry::HighlightInfo::DataType hDataType = LocatorFilterEntry::HighlightInfo::DisplayName;
|
||||
int length = hasWildcard ? regexp.matchedLength() : fp.filePath.length();
|
||||
const bool betterMatch = index == 0;
|
||||
if (hasPathSeparator) {
|
||||
const int indexCandidate = index + filterEntry.extraInfo.length() - path.length();
|
||||
const int cutOff = indexCandidate < 0 ? -indexCandidate : 0;
|
||||
index = qMax(indexCandidate, 0);
|
||||
length = qMax(length - cutOff, 1);
|
||||
hDataType = LocatorFilterEntry::HighlightInfo::ExtraInfo;
|
||||
}
|
||||
|
||||
if (index >= 0)
|
||||
filterEntry.highlightInfo = LocatorFilterEntry::HighlightInfo(index, length, hDataType);
|
||||
|
||||
if (betterMatch)
|
||||
betterEntries.append(filterEntry);
|
||||
else
|
||||
goodEntries.append(entry);
|
||||
goodEntries.append(filterEntry);
|
||||
d->m_current.previousResultPaths.append(path);
|
||||
d->m_current.previousResultNames.append(name);
|
||||
}
|
||||
|
@@ -67,20 +67,27 @@ QList<LocatorFilterEntry> CommandLocator::matchesFor(QFutureInterface<LocatorFil
|
||||
// Get active, enabled actions matching text, store in list.
|
||||
// Reference via index in extraInfo.
|
||||
const QChar ampersand = QLatin1Char('&');
|
||||
const Qt::CaseSensitivity caseSensitivity_ = caseSensitivity(entry);
|
||||
const Qt::CaseSensitivity entryCaseSensitivity = caseSensitivity(entry);
|
||||
const int count = d->commands.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (future.isCanceled())
|
||||
break;
|
||||
if (d->commands.at(i)->isActive()) {
|
||||
if (QAction *action = d->commands.at(i)->action())
|
||||
if (action->isEnabled()) {
|
||||
QString text = action->text();
|
||||
text.remove(ampersand);
|
||||
if (text.startsWith(entry, caseSensitivity_))
|
||||
betterEntries.append(LocatorFilterEntry(this, text, QVariant(i)));
|
||||
else if (text.contains(entry, caseSensitivity_))
|
||||
goodEntries.append(LocatorFilterEntry(this, text, QVariant(i)));
|
||||
if (!d->commands.at(i)->isActive())
|
||||
continue;
|
||||
|
||||
QAction *action = d->commands.at(i)->action();
|
||||
if (action && action->isEnabled()) {
|
||||
QString text = action->text();
|
||||
text.remove(ampersand);
|
||||
const int index = text.indexOf(entry, 0, entryCaseSensitivity);
|
||||
if (index >= 0) {
|
||||
LocatorFilterEntry filterEntry(this, text, QVariant(i));
|
||||
filterEntry.highlightInfo = {index, entry.length()};
|
||||
|
||||
if (index == 0)
|
||||
betterEntries.append(filterEntry);
|
||||
else
|
||||
goodEntries.append(filterEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -60,16 +60,20 @@ QList<LocatorFilterEntry> ExecuteFilter::matchesFor(QFutureInterface<LocatorFilt
|
||||
if (!entry.isEmpty()) // avoid empty entry
|
||||
value.append(LocatorFilterEntry(this, entry, QVariant()));
|
||||
QList<LocatorFilterEntry> others;
|
||||
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry);
|
||||
foreach (const QString &i, m_commandHistory) {
|
||||
const Qt::CaseSensitivity entryCaseSensitivity = caseSensitivity(entry);
|
||||
foreach (const QString &cmd, m_commandHistory) {
|
||||
if (future.isCanceled())
|
||||
break;
|
||||
if (i == entry) // avoid repeated entry
|
||||
if (cmd == entry) // avoid repeated entry
|
||||
continue;
|
||||
if (i.startsWith(entry, caseSensitivityForPrefix))
|
||||
value.append(LocatorFilterEntry(this, i, QVariant()));
|
||||
else
|
||||
others.append(LocatorFilterEntry(this, i, QVariant()));
|
||||
LocatorFilterEntry filterEntry(this, cmd, QVariant());
|
||||
const int index = cmd.indexOf(entry, 0, entryCaseSensitivity);
|
||||
if (index >= 0) {
|
||||
filterEntry.highlightInfo = {index, entry.length()};
|
||||
value.append(filterEntry);
|
||||
} else {
|
||||
others.append(filterEntry);
|
||||
}
|
||||
}
|
||||
value.append(others);
|
||||
return value;
|
||||
|
@@ -64,17 +64,23 @@ void ExternalToolsFilter::refresh(QFutureInterface<void> &)
|
||||
void ExternalToolsFilter::prepareSearch(const QString &entry)
|
||||
{
|
||||
m_results.clear();
|
||||
|
||||
Qt::CaseSensitivity useCaseSensitivity = caseSensitivity(entry);
|
||||
const Qt::CaseSensitivity entryCaseSensitivity = caseSensitivity(entry);
|
||||
const QMap<QString, ExternalTool *> externalToolsById = ExternalToolManager::toolsById();
|
||||
auto end = externalToolsById.cend();
|
||||
for (auto it = externalToolsById.cbegin(); it != end; ++it) {
|
||||
ExternalTool *tool = *it;
|
||||
if (tool->description().contains(entry, useCaseSensitivity) ||
|
||||
tool->displayName().contains(entry, useCaseSensitivity)) {
|
||||
|
||||
int index = tool->displayName().indexOf(entry, 0, entryCaseSensitivity);
|
||||
LocatorFilterEntry::HighlightInfo::DataType hDataType = LocatorFilterEntry::HighlightInfo::DisplayName;
|
||||
if (index < 0) {
|
||||
index = tool->description().indexOf(entry, 0, entryCaseSensitivity);
|
||||
hDataType = LocatorFilterEntry::HighlightInfo::ExtraInfo;
|
||||
}
|
||||
|
||||
if (index >= 0) {
|
||||
LocatorFilterEntry filterEntry(this, tool->displayName(), QVariant::fromValue(tool));
|
||||
filterEntry.extraInfo = tool->description();
|
||||
filterEntry.highlightInfo = LocatorFilterEntry::HighlightInfo(index, entry.length(), hDataType);
|
||||
m_results.append(filterEntry);
|
||||
}
|
||||
}
|
||||
|
@@ -41,11 +41,16 @@ namespace {
|
||||
|
||||
QList<LocatorFilterEntry> *categorize(const QString &entry, const QString &candidate,
|
||||
Qt::CaseSensitivity caseSensitivity,
|
||||
QList<LocatorFilterEntry> *betterEntries, QList<LocatorFilterEntry> *goodEntries)
|
||||
QList<LocatorFilterEntry> *betterEntries, QList<LocatorFilterEntry> *goodEntries,
|
||||
int *index)
|
||||
{
|
||||
if (entry.isEmpty() || candidate.startsWith(entry, caseSensitivity))
|
||||
const int position = candidate.indexOf(entry, 0, caseSensitivity);
|
||||
if (index)
|
||||
*index = position;
|
||||
|
||||
if (entry.isEmpty() || position == 0)
|
||||
return betterEntries;
|
||||
else if (candidate.contains(entry, caseSensitivity))
|
||||
else if (position >= 0)
|
||||
return goodEntries;
|
||||
return 0;
|
||||
}
|
||||
@@ -99,11 +104,15 @@ QList<LocatorFilterEntry> FileSystemFilter::matchesFor(QFutureInterface<LocatorF
|
||||
foreach (const QString &dir, dirs) {
|
||||
if (future.isCanceled())
|
||||
break;
|
||||
if (QList<LocatorFilterEntry> *category = categorize(entryFileName, dir, caseSensitivity_, &betterEntries,
|
||||
&goodEntries)) {
|
||||
int index = -1;
|
||||
if (QList<LocatorFilterEntry> *category = categorize(entryFileName, dir, caseSensitivity_,
|
||||
&betterEntries, &goodEntries, &index)) {
|
||||
const QString fullPath = dirInfo.filePath(dir);
|
||||
LocatorFilterEntry filterEntry(this, dir, QVariant());
|
||||
filterEntry.fileName = fullPath;
|
||||
if (index >= 0)
|
||||
filterEntry.highlightInfo = {index, entryFileName.length()};
|
||||
|
||||
category->append(filterEntry);
|
||||
}
|
||||
}
|
||||
@@ -113,11 +122,15 @@ QList<LocatorFilterEntry> FileSystemFilter::matchesFor(QFutureInterface<LocatorF
|
||||
foreach (const QString &file, files) {
|
||||
if (future.isCanceled())
|
||||
break;
|
||||
if (QList<LocatorFilterEntry> *category = categorize(fileName, file, caseSensitivity_, &betterEntries,
|
||||
&goodEntries)) {
|
||||
int index = -1;
|
||||
if (QList<LocatorFilterEntry> *category = categorize(fileName, file, caseSensitivity_,
|
||||
&betterEntries, &goodEntries, &index)) {
|
||||
const QString fullPath = dirInfo.filePath(file);
|
||||
LocatorFilterEntry filterEntry(this, file, QString(fullPath + fp.postfix));
|
||||
filterEntry.fileName = fullPath;
|
||||
if (index >= 0)
|
||||
filterEntry.highlightInfo = {index, fileName.length()};
|
||||
|
||||
category->append(filterEntry);
|
||||
}
|
||||
}
|
||||
|
@@ -118,27 +118,16 @@ bool ILocatorFilter::openConfigDialog(QWidget *parent, bool &needsRefresh)
|
||||
return false;
|
||||
}
|
||||
|
||||
QString ILocatorFilter::trimWildcards(const QString &str)
|
||||
{
|
||||
if (str.isEmpty())
|
||||
return str;
|
||||
int first = 0, last = str.size() - 1;
|
||||
const QChar asterisk = QLatin1Char('*');
|
||||
const QChar question = QLatin1Char('?');
|
||||
while (first < str.size() && (str.at(first) == asterisk || str.at(first) == question))
|
||||
++first;
|
||||
while (last >= 0 && (str.at(last) == asterisk || str.at(last) == question))
|
||||
--last;
|
||||
if (first > last)
|
||||
return QString();
|
||||
return str.mid(first, last - first + 1);
|
||||
}
|
||||
|
||||
Qt::CaseSensitivity ILocatorFilter::caseSensitivity(const QString &str)
|
||||
{
|
||||
return str == str.toLower() ? Qt::CaseInsensitive : Qt::CaseSensitive;
|
||||
}
|
||||
|
||||
bool ILocatorFilter::containsWildcard(const QString &str)
|
||||
{
|
||||
return str.contains(QLatin1Char('*')) || str.contains(QLatin1Char('?'));
|
||||
}
|
||||
|
||||
QString ILocatorFilter::msgConfigureDialogTitle()
|
||||
{
|
||||
return tr("Filter Configuration");
|
||||
|
@@ -37,6 +37,23 @@ class ILocatorFilter;
|
||||
|
||||
struct LocatorFilterEntry
|
||||
{
|
||||
struct HighlightInfo {
|
||||
enum DataType {
|
||||
DisplayName,
|
||||
ExtraInfo
|
||||
};
|
||||
|
||||
HighlightInfo(int startIndex, int length, DataType type = DataType::DisplayName)
|
||||
: startIndex(startIndex)
|
||||
, length(length)
|
||||
, dataType(type)
|
||||
{}
|
||||
|
||||
int startIndex;
|
||||
int length;
|
||||
DataType dataType;
|
||||
};
|
||||
|
||||
LocatorFilterEntry() = default;
|
||||
|
||||
LocatorFilterEntry(ILocatorFilter *fromFilter, const QString &name, const QVariant &data,
|
||||
@@ -67,6 +84,14 @@ struct LocatorFilterEntry
|
||||
QString fileName;
|
||||
/* internal */
|
||||
bool fileIconResolved = false;
|
||||
/* highlighting support */
|
||||
HighlightInfo highlightInfo{0, 0};
|
||||
|
||||
static bool compareLexigraphically(const Core::LocatorFilterEntry &lhs,
|
||||
const Core::LocatorFilterEntry &rhs)
|
||||
{
|
||||
return lhs.displayName < rhs.displayName;
|
||||
}
|
||||
};
|
||||
|
||||
class CORE_EXPORT ILocatorFilter : public QObject
|
||||
@@ -134,8 +159,8 @@ public:
|
||||
/* Returns whether the filter should be enabled and used in menus. */
|
||||
bool isEnabled() const;
|
||||
|
||||
static QString trimWildcards(const QString &str);
|
||||
static Qt::CaseSensitivity caseSensitivity(const QString &str);
|
||||
static bool containsWildcard(const QString &str);
|
||||
|
||||
static QString msgConfigureDialogTitle();
|
||||
static QString msgPrefixLabel();
|
||||
|
@@ -33,6 +33,8 @@
|
||||
#include <coreplugin/modemanager.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
#include <coreplugin/fileiconprovider.h>
|
||||
#include <coreplugin/find/searchresulttreeitemdelegate.h>
|
||||
#include <coreplugin/find/searchresulttreeitemroles.h>
|
||||
#include <coreplugin/icontext.h>
|
||||
#include <coreplugin/mainwindow.h>
|
||||
#include <utils/algorithm.h>
|
||||
@@ -69,8 +71,16 @@ namespace Internal {
|
||||
class LocatorModel : public QAbstractListModel
|
||||
{
|
||||
public:
|
||||
|
||||
enum Columns {
|
||||
DisplayNameColumn,
|
||||
ExtraInfoColumn,
|
||||
ColumnCount
|
||||
};
|
||||
|
||||
LocatorModel(QObject *parent = 0)
|
||||
: QAbstractListModel(parent)
|
||||
, mBackgroundColor(Utils::creatorTheme()->color(Utils::Theme::TextColorHighlightBackground).name())
|
||||
{}
|
||||
|
||||
void clear();
|
||||
@@ -83,6 +93,7 @@ public:
|
||||
private:
|
||||
mutable QList<LocatorFilterEntry> mEntries;
|
||||
bool hasExtraInfo = false;
|
||||
QColor mBackgroundColor;
|
||||
};
|
||||
|
||||
class CompletionList : public QTreeView
|
||||
@@ -144,7 +155,7 @@ int LocatorModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
return hasExtraInfo ? 2 : 1;
|
||||
return hasExtraInfo ? ColumnCount : 1;
|
||||
}
|
||||
|
||||
QVariant LocatorModel::data(const QModelIndex &index, int role) const
|
||||
@@ -154,9 +165,9 @@ QVariant LocatorModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
if (index.column() == 0)
|
||||
if (index.column() == DisplayNameColumn)
|
||||
return mEntries.at(index.row()).displayName;
|
||||
else if (index.column() == 1)
|
||||
else if (index.column() == ExtraInfoColumn)
|
||||
return mEntries.at(index.row()).extraInfo;
|
||||
break;
|
||||
case Qt::ToolTipRole:
|
||||
@@ -167,7 +178,8 @@ QVariant LocatorModel::data(const QModelIndex &index, int role) const
|
||||
+ QLatin1String("\n\n") + mEntries.at(index.row()).extraInfo);
|
||||
break;
|
||||
case Qt::DecorationRole:
|
||||
if (index.column() == 0) {
|
||||
case ItemDataRoles::ResultIconRole:
|
||||
if (index.column() == DisplayNameColumn) {
|
||||
LocatorFilterEntry &entry = mEntries[index.row()];
|
||||
if (!entry.fileIconResolved && !entry.fileName.isEmpty() && entry.displayIcon.isNull()) {
|
||||
entry.fileIconResolved = true;
|
||||
@@ -177,11 +189,25 @@ QVariant LocatorModel::data(const QModelIndex &index, int role) const
|
||||
}
|
||||
break;
|
||||
case Qt::ForegroundRole:
|
||||
if (index.column() == 1)
|
||||
if (index.column() == ExtraInfoColumn)
|
||||
return QColor(Qt::darkGray);
|
||||
break;
|
||||
case Qt::UserRole:
|
||||
case ItemDataRoles::ResultItemRole:
|
||||
return qVariantFromValue(mEntries.at(index.row()));
|
||||
case ItemDataRoles::ResultBeginColumnNumberRole:
|
||||
case ItemDataRoles::SearchTermLengthRole: {
|
||||
LocatorFilterEntry &entry = mEntries[index.row()];
|
||||
const int highlightColumn = entry.highlightInfo.dataType == LocatorFilterEntry::HighlightInfo::DisplayName
|
||||
? DisplayNameColumn
|
||||
: ExtraInfoColumn;
|
||||
if (highlightColumn == index.column()) {
|
||||
const bool startIndexRole = role == ItemDataRoles::ResultBeginColumnNumberRole;
|
||||
return startIndexRole ? entry.highlightInfo.startIndex : entry.highlightInfo.length;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ItemDataRoles::ResultHighlightBackgroundColor:
|
||||
return mBackgroundColor;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
@@ -202,6 +228,7 @@ void LocatorModel::addEntries(const QList<LocatorFilterEntry> &entries)
|
||||
CompletionList::CompletionList(QWidget *parent)
|
||||
: QTreeView(parent)
|
||||
{
|
||||
setItemDelegate(new SearchResultTreeItemDelegate(0, this));
|
||||
setRootIsDecorated(false);
|
||||
setUniformRowHeights(true);
|
||||
header()->hide();
|
||||
@@ -611,9 +638,10 @@ void LocatorWidget::acceptCurrentEntry()
|
||||
const QModelIndex index = m_completionList->currentIndex();
|
||||
if (!index.isValid())
|
||||
return;
|
||||
const LocatorFilterEntry entry = m_locatorModel->data(index, Qt::UserRole).value<LocatorFilterEntry>();
|
||||
const LocatorFilterEntry entry = m_locatorModel->data(index, ItemDataRoles::ResultItemRole).value<LocatorFilterEntry>();
|
||||
m_completionList->hide();
|
||||
m_fileLineEdit->clearFocus();
|
||||
Q_ASSERT(entry.filter != nullptr);
|
||||
entry.filter->accept(entry);
|
||||
}
|
||||
|
||||
|
@@ -55,19 +55,16 @@ OpenDocumentsFilter::OpenDocumentsFilter()
|
||||
this, &OpenDocumentsFilter::refreshInternally);
|
||||
}
|
||||
|
||||
QList<LocatorFilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<LocatorFilterEntry> &future, const QString &entry)
|
||||
QList<LocatorFilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<LocatorFilterEntry> &future,
|
||||
const QString &entry)
|
||||
{
|
||||
QList<LocatorFilterEntry> goodEntries;
|
||||
QList<LocatorFilterEntry> betterEntries;
|
||||
const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(entry);
|
||||
const QChar asterisk = QLatin1Char('*');
|
||||
QString pattern = QString(asterisk);
|
||||
pattern += fp.filePath;
|
||||
pattern += asterisk;
|
||||
QRegExp regexp(pattern, Qt::CaseInsensitive, QRegExp::Wildcard);
|
||||
QRegExp regexp(fp.filePath, caseSensitivity(fp.filePath), QRegExp::Wildcard);
|
||||
if (!regexp.isValid())
|
||||
return goodEntries;
|
||||
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(fp.filePath);
|
||||
|
||||
foreach (const Entry &editorEntry, editors()) {
|
||||
if (future.isCanceled())
|
||||
break;
|
||||
@@ -75,13 +72,16 @@ QList<LocatorFilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<Locat
|
||||
if (fileName.isEmpty())
|
||||
continue;
|
||||
QString displayName = editorEntry.displayName;
|
||||
if (regexp.exactMatch(displayName)) {
|
||||
LocatorFilterEntry fiEntry(this, displayName, QString(fileName + fp.postfix));
|
||||
fiEntry.extraInfo = FileUtils::shortNativePath(FileName::fromString(fileName));
|
||||
fiEntry.fileName = fileName;
|
||||
QList<LocatorFilterEntry> &category = displayName.startsWith(fp.filePath, caseSensitivityForPrefix)
|
||||
? betterEntries : goodEntries;
|
||||
category.append(fiEntry);
|
||||
const int index = regexp.indexIn(displayName);
|
||||
if (index >= 0) {
|
||||
LocatorFilterEntry filterEntry(this, displayName, QString(fileName + fp.postfix));
|
||||
filterEntry.extraInfo = FileUtils::shortNativePath(FileName::fromString(fileName));
|
||||
filterEntry.fileName = fileName;
|
||||
filterEntry.highlightInfo = {index, regexp.matchedLength()};
|
||||
if (index == 0)
|
||||
betterEntries.append(filterEntry);
|
||||
else
|
||||
goodEntries.append(filterEntry);
|
||||
}
|
||||
}
|
||||
betterEntries.append(goodEntries);
|
||||
|
@@ -62,18 +62,16 @@ CppCurrentDocumentFilter::CppCurrentDocumentFilter(CppTools::CppModelManager *ma
|
||||
}
|
||||
|
||||
QList<Core::LocatorFilterEntry> CppCurrentDocumentFilter::matchesFor(
|
||||
QFutureInterface<Core::LocatorFilterEntry> &future, const QString & origEntry)
|
||||
QFutureInterface<Core::LocatorFilterEntry> &future, const QString & entry)
|
||||
{
|
||||
QString entry = trimWildcards(origEntry);
|
||||
QList<Core::LocatorFilterEntry> goodEntries;
|
||||
QList<Core::LocatorFilterEntry> betterEntries;
|
||||
QStringMatcher matcher(entry, Qt::CaseInsensitive);
|
||||
const QChar asterisk = QLatin1Char('*');
|
||||
QRegExp regexp(asterisk + entry + asterisk, Qt::CaseInsensitive, QRegExp::Wildcard);
|
||||
const Qt::CaseSensitivity cs = caseSensitivity(entry);
|
||||
QStringMatcher matcher(entry, cs);
|
||||
QRegExp regexp(entry, cs, QRegExp::Wildcard);
|
||||
if (!regexp.isValid())
|
||||
return goodEntries;
|
||||
bool hasWildcard = (entry.contains(asterisk) || entry.contains(QLatin1Char('?')));
|
||||
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry);
|
||||
bool hasWildcard = containsWildcard(entry);
|
||||
|
||||
foreach (IndexItem::Ptr info, itemsOfCurrentDocument()) {
|
||||
if (future.isCanceled())
|
||||
@@ -85,20 +83,30 @@ QList<Core::LocatorFilterEntry> CppCurrentDocumentFilter::matchesFor(
|
||||
else if (info->type() == IndexItem::Function)
|
||||
matchString += info->symbolType();
|
||||
|
||||
if ((hasWildcard && regexp.exactMatch(matchString))
|
||||
|| (!hasWildcard && matcher.indexIn(matchString) != -1))
|
||||
{
|
||||
int index = hasWildcard ? regexp.indexIn(matchString) : matcher.indexIn(matchString);
|
||||
if (index >= 0) {
|
||||
const bool betterMatch = index == 0;
|
||||
QVariant id = qVariantFromValue(info);
|
||||
QString name = matchString;
|
||||
QString extraInfo = info->symbolScope();
|
||||
if (info->type() == IndexItem::Function) {
|
||||
if (info->unqualifiedNameAndScope(matchString, &name, &extraInfo))
|
||||
if (info->unqualifiedNameAndScope(matchString, &name, &extraInfo)) {
|
||||
name += info->symbolType();
|
||||
index = hasWildcard ? regexp.indexIn(name) : matcher.indexIn(name);
|
||||
}
|
||||
}
|
||||
|
||||
Core::LocatorFilterEntry filterEntry(this, name, id, info->icon());
|
||||
filterEntry.extraInfo = extraInfo;
|
||||
|
||||
if (matchString.startsWith(entry, caseSensitivityForPrefix))
|
||||
if (index < 0) {
|
||||
index = hasWildcard ? regexp.indexIn(extraInfo) : matcher.indexIn(extraInfo);
|
||||
filterEntry.highlightInfo.dataType = Core::LocatorFilterEntry::HighlightInfo::ExtraInfo;
|
||||
}
|
||||
if (index >= 0) {
|
||||
filterEntry.highlightInfo.startIndex = index;
|
||||
filterEntry.highlightInfo.length = hasWildcard ? regexp.matchedLength() : entry.length();
|
||||
}
|
||||
if (betterMatch)
|
||||
betterEntries.append(filterEntry);
|
||||
else
|
||||
goodEntries.append(filterEntry);
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "cppmodelmanager.h"
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <utils/algorithm.h>
|
||||
|
||||
#include <QRegExp>
|
||||
#include <QStringMatcher>
|
||||
@@ -66,26 +67,18 @@ void CppLocatorFilter::refresh(QFutureInterface<void> &future)
|
||||
Q_UNUSED(future)
|
||||
}
|
||||
|
||||
static bool compareLexigraphically(const Core::LocatorFilterEntry &a,
|
||||
const Core::LocatorFilterEntry &b)
|
||||
{
|
||||
return a.displayName < b.displayName;
|
||||
}
|
||||
|
||||
QList<Core::LocatorFilterEntry> CppLocatorFilter::matchesFor(
|
||||
QFutureInterface<Core::LocatorFilterEntry> &future, const QString &origEntry)
|
||||
QFutureInterface<Core::LocatorFilterEntry> &future, const QString &entry)
|
||||
{
|
||||
QString entry = trimWildcards(origEntry);
|
||||
QList<Core::LocatorFilterEntry> goodEntries;
|
||||
QList<Core::LocatorFilterEntry> betterEntries;
|
||||
const QChar asterisk = QLatin1Char('*');
|
||||
QStringMatcher matcher(entry, Qt::CaseInsensitive);
|
||||
QRegExp regexp(asterisk + entry+ asterisk, Qt::CaseInsensitive, QRegExp::Wildcard);
|
||||
const Qt::CaseSensitivity cs = caseSensitivity(entry);
|
||||
QStringMatcher matcher(entry, cs);
|
||||
QRegExp regexp(entry, cs, QRegExp::Wildcard);
|
||||
if (!regexp.isValid())
|
||||
return goodEntries;
|
||||
bool hasWildcard = (entry.contains(asterisk) || entry.contains(QLatin1Char('?')));
|
||||
bool hasWildcard = containsWildcard(entry);
|
||||
bool hasColonColon = entry.contains(QLatin1String("::"));
|
||||
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry);
|
||||
const IndexItem::ItemType wanted = matchTypes();
|
||||
|
||||
m_data->filterAllFiles([&](const IndexItem::Ptr &info) -> IndexItem::VisitorResult {
|
||||
@@ -93,10 +86,20 @@ QList<Core::LocatorFilterEntry> CppLocatorFilter::matchesFor(
|
||||
return IndexItem::Break;
|
||||
if (info->type() & wanted) {
|
||||
const QString matchString = hasColonColon ? info->scopedSymbolName() : info->symbolName();
|
||||
if ((hasWildcard && regexp.exactMatch(matchString)) ||
|
||||
(!hasWildcard && matcher.indexIn(matchString) != -1)) {
|
||||
const Core::LocatorFilterEntry filterEntry = filterEntryFromIndexItem(info);
|
||||
if (matchString.startsWith(entry, caseSensitivityForPrefix))
|
||||
int index = hasWildcard ? regexp.indexIn(matchString) : matcher.indexIn(matchString);
|
||||
if (index >= 0) {
|
||||
const bool betterMatch = index == 0;
|
||||
Core::LocatorFilterEntry filterEntry = filterEntryFromIndexItem(info);
|
||||
|
||||
if (matchString != filterEntry.displayName) {
|
||||
index = hasWildcard ? regexp.indexIn(filterEntry.displayName)
|
||||
: matcher.indexIn(filterEntry.displayName);
|
||||
}
|
||||
|
||||
if (index >= 0)
|
||||
filterEntry.highlightInfo = {index, (hasWildcard ? regexp.matchedLength() : entry.length())};
|
||||
|
||||
if (betterMatch)
|
||||
betterEntries.append(filterEntry);
|
||||
else
|
||||
goodEntries.append(filterEntry);
|
||||
@@ -110,9 +113,9 @@ QList<Core::LocatorFilterEntry> CppLocatorFilter::matchesFor(
|
||||
});
|
||||
|
||||
if (goodEntries.size() < 1000)
|
||||
std::stable_sort(goodEntries.begin(), goodEntries.end(), compareLexigraphically);
|
||||
Utils::sort(goodEntries, Core::LocatorFilterEntry::compareLexigraphically);
|
||||
if (betterEntries.size() < 1000)
|
||||
std::stable_sort(betterEntries.begin(), betterEntries.end(), compareLexigraphically);
|
||||
Utils::sort(betterEntries, Core::LocatorFilterEntry::compareLexigraphically);
|
||||
|
||||
betterEntries += goodEntries;
|
||||
return betterEntries;
|
||||
|
@@ -127,8 +127,12 @@ QList<LocatorFilterEntry> HelpIndexFilter::matchesFor(QFutureInterface<LocatorFi
|
||||
keywords << unsortedKeywords;
|
||||
m_keywordCache = allresults;
|
||||
m_searchTermCache = entry;
|
||||
foreach (const QString &keyword, keywords)
|
||||
entries.append(LocatorFilterEntry(this, keyword, QVariant(), m_icon));
|
||||
foreach (const QString &keyword, keywords) {
|
||||
const int index = keyword.indexOf(entry, 0, cs);
|
||||
LocatorFilterEntry filterEntry(this, keyword, QVariant(), m_icon);
|
||||
filterEntry.highlightInfo = {index, entry.length()};
|
||||
entries.append(filterEntry);
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
@@ -129,15 +129,16 @@ RemoteHelpFilter::~RemoteHelpFilter()
|
||||
{
|
||||
}
|
||||
|
||||
QList<Core::LocatorFilterEntry> RemoteHelpFilter::matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future, const QString &pattern)
|
||||
QList<Core::LocatorFilterEntry> RemoteHelpFilter::matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future, const QString &entry)
|
||||
{
|
||||
QList<Core::LocatorFilterEntry> entries;
|
||||
foreach (const QString &url, remoteUrls()) {
|
||||
if (future.isCanceled())
|
||||
break;
|
||||
|
||||
entries.append(Core::LocatorFilterEntry(this, url.arg(pattern), QVariant(),
|
||||
m_icon));
|
||||
const QString name = url.arg(entry);
|
||||
Core::LocatorFilterEntry filterEntry(this, name, QVariant(), m_icon);
|
||||
filterEntry.highlightInfo = {name.lastIndexOf(entry), entry.length()};
|
||||
entries.append(filterEntry);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
@@ -54,26 +54,32 @@ QList<Core::LocatorFilterEntry> MacroLocatorFilter::matchesFor(QFutureInterface<
|
||||
QList<Core::LocatorFilterEntry> goodEntries;
|
||||
QList<Core::LocatorFilterEntry> betterEntries;
|
||||
|
||||
const Qt::CaseSensitivity caseSensitivity_ = caseSensitivity(entry);
|
||||
const Qt::CaseSensitivity entryCaseSensitivity = caseSensitivity(entry);
|
||||
|
||||
const QMap<QString, Macro*> ¯os = MacroManager::macros();
|
||||
QMapIterator<QString, Macro*> it(macros);
|
||||
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
QString name = it.key();
|
||||
const QString displayName = it.key();
|
||||
const QString description = it.value()->description();
|
||||
|
||||
QList<Core::LocatorFilterEntry> *category = 0;
|
||||
if (name.startsWith(entry, caseSensitivity_))
|
||||
category = &betterEntries;
|
||||
else if (name.contains(entry, caseSensitivity_))
|
||||
category = &goodEntries;
|
||||
int index = displayName.indexOf(entry, 0, entryCaseSensitivity);
|
||||
Core::LocatorFilterEntry::HighlightInfo::DataType hDataType = Core::LocatorFilterEntry::HighlightInfo::DisplayName;
|
||||
if (index < 0) {
|
||||
index = description.indexOf(entry, 0, entryCaseSensitivity);
|
||||
hDataType = Core::LocatorFilterEntry::HighlightInfo::ExtraInfo;
|
||||
}
|
||||
|
||||
if (category) {
|
||||
QVariant id;
|
||||
Core::LocatorFilterEntry entry(this, it.key(), id, m_icon);
|
||||
entry.extraInfo = it.value()->description();
|
||||
category->append(entry);
|
||||
if (index >= 0) {
|
||||
Core::LocatorFilterEntry filterEntry(this, displayName, QVariant(), m_icon);
|
||||
filterEntry.extraInfo = description;
|
||||
filterEntry.highlightInfo = Core::LocatorFilterEntry::HighlightInfo(index, entry.length(), hDataType);
|
||||
|
||||
if (index == 0)
|
||||
betterEntries.append(filterEntry);
|
||||
else
|
||||
goodEntries.append(filterEntry);
|
||||
}
|
||||
}
|
||||
betterEntries.append(goodEntries);
|
||||
|
@@ -53,24 +53,18 @@ void FunctionFilter::refresh(QFutureInterface<void> &)
|
||||
{
|
||||
}
|
||||
|
||||
static bool compareLexigraphically(const Core::LocatorFilterEntry &a,
|
||||
const Core::LocatorFilterEntry &b)
|
||||
QList<Core::LocatorFilterEntry> FunctionFilter::matchesFor(
|
||||
QFutureInterface<Core::LocatorFilterEntry> &future,
|
||||
const QString &entry)
|
||||
{
|
||||
return a.displayName < b.displayName;
|
||||
}
|
||||
|
||||
QList<Core::LocatorFilterEntry> FunctionFilter::matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future, const QString &origEntry)
|
||||
{
|
||||
QString entry = trimWildcards(origEntry);
|
||||
QList<Core::LocatorFilterEntry> goodEntries;
|
||||
QList<Core::LocatorFilterEntry> betterEntries;
|
||||
const QChar asterisk = QLatin1Char('*');
|
||||
QStringMatcher matcher(entry, Qt::CaseInsensitive);
|
||||
QRegExp regexp(asterisk + entry+ asterisk, Qt::CaseInsensitive, QRegExp::Wildcard);
|
||||
const Qt::CaseSensitivity cs = caseSensitivity(entry);
|
||||
QStringMatcher matcher(entry, cs);
|
||||
QRegExp regexp(entry, cs, QRegExp::Wildcard);
|
||||
if (!regexp.isValid())
|
||||
return goodEntries;
|
||||
bool hasWildcard = (entry.contains(asterisk) || entry.contains(QLatin1Char('?')));
|
||||
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry);
|
||||
bool hasWildcard = containsWildcard(entry);
|
||||
|
||||
QHashIterator<QString, QList<LocatorData::Entry> > it(m_data->entries());
|
||||
while (it.hasNext()) {
|
||||
@@ -83,14 +77,17 @@ QList<Core::LocatorFilterEntry> FunctionFilter::matchesFor(QFutureInterface<Core
|
||||
foreach (const LocatorData::Entry &info, items) {
|
||||
if (info.type != LocatorData::Function)
|
||||
continue;
|
||||
if ((hasWildcard && regexp.exactMatch(info.symbolName))
|
||||
|| (!hasWildcard && matcher.indexIn(info.symbolName) != -1)) {
|
||||
|
||||
const int index = hasWildcard ? regexp.indexIn(info.symbolName)
|
||||
: matcher.indexIn(info.symbolName);
|
||||
if (index >= 0) {
|
||||
QVariant id = qVariantFromValue(info);
|
||||
Core::LocatorFilterEntry filterEntry(this, info.displayName, id/*, info.icon*/);
|
||||
filterEntry.extraInfo = info.extraInfo;
|
||||
const int length = hasWildcard ? regexp.matchedLength() : entry.length();
|
||||
filterEntry.highlightInfo = {index, length};
|
||||
|
||||
if (info.symbolName.startsWith(entry, caseSensitivityForPrefix))
|
||||
if (index == 0)
|
||||
betterEntries.append(filterEntry);
|
||||
else
|
||||
goodEntries.append(filterEntry);
|
||||
@@ -99,9 +96,9 @@ QList<Core::LocatorFilterEntry> FunctionFilter::matchesFor(QFutureInterface<Core
|
||||
}
|
||||
|
||||
if (goodEntries.size() < 1000)
|
||||
Utils::sort(goodEntries, compareLexigraphically);
|
||||
Utils::sort(goodEntries, Core::LocatorFilterEntry::compareLexigraphically);
|
||||
if (betterEntries.size() < 1000)
|
||||
Utils::sort(betterEntries, compareLexigraphically);
|
||||
Utils::sort(betterEntries, Core::LocatorFilterEntry::compareLexigraphically);
|
||||
|
||||
betterEntries += goodEntries;
|
||||
return betterEntries;
|
||||
|
Reference in New Issue
Block a user