Commit ef018ddd authored by Nikolai Kosjar's avatar Nikolai Kosjar

Locator: Case sensitivity of input affects prioritizing

So far candidates were prefix matched case sensitive which led to
an unfavorable results order.

With this patch, if the input is lower case, the prioritizing happens by
a case insensitive prefix match. Otherwise the match happens case
sensitive (just like before).

Example:

    Search for e.g. "m cppmodelmanager"
    Top result before: AbstractEditorSupport (match at parameter type)
    Top result now: CppModelManager

Change-Id: Ic27042cfe717be812a2237a3437399597c98dd74
Reviewed-by: Orgad Shaneh's avatarOrgad Shaneh <orgads@gmail.com>
Reviewed-by: default avatarDavid Schulz <david.schulz@digia.com>
parent 541a7179
......@@ -222,7 +222,8 @@ QMap<QString, QUrl> HelpManager::linksForIdentifier(const QString &id) const
}
// This should go into Qt 4.8 once we start using it for Qt Creator
QStringList HelpManager::findKeywords(const QString &key, int maxHits) const
QStringList HelpManager::findKeywords(const QString &key, Qt::CaseSensitivity caseSensitivity,
int maxHits) const
{
if (d->m_needsSetup)
return QStringList();
......@@ -251,7 +252,7 @@ QStringList HelpManager::findKeywords(const QString &key, int maxHits) const
while (query.next()) {
const QString &keyValue = query.value(0).toString();
if (!keyValue.isEmpty()) {
if (keyValue.startsWith(key, Qt::CaseInsensitive))
if (keyValue.startsWith(key, caseSensitivity))
keywordsToSort.insert(keyValue);
else
keywords.insert(keyValue);
......
......@@ -63,7 +63,9 @@ public:
QMap<QString, QUrl> linksForKeyword(const QString &key) const;
QMap<QString, QUrl> linksForIdentifier(const QString &id) const;
QStringList findKeywords(const QString &key, int maxHits = INT_MAX) const;
QStringList findKeywords(const QString &key,
Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive,
int maxHits = INT_MAX) const;
QUrl findFile(const QUrl &url) const;
QByteArray fileData(const QUrl &url) const;
......
......@@ -81,6 +81,8 @@ QList<Locator::FilterEntry> CppCurrentDocumentFilter::matchesFor(QFutureInterfac
m_itemsOfCurrentDoc = search(thisDocument);
}
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry);
foreach (const ModelItemInfo & info, m_itemsOfCurrentDoc)
{
if (future.isCanceled())
......@@ -94,7 +96,7 @@ QList<Locator::FilterEntry> CppCurrentDocumentFilter::matchesFor(QFutureInterfac
Locator::FilterEntry filterEntry(this, symbolName, id, info.icon);
filterEntry.extraInfo = info.symbolType;
if (info.symbolName.startsWith(entry))
if (info.symbolName.startsWith(entry, caseSensitivityForPrefix))
betterEntries.append(filterEntry);
else
goodEntries.append(filterEntry);
......
......@@ -135,6 +135,7 @@ QList<Locator::FilterEntry> CppLocatorFilter::matchesFor(QFutureInterface<Locato
if (!regexp.isValid())
return goodEntries;
bool hasWildcard = (entry.contains(asterisk) || entry.contains(QLatin1Char('?')));
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry);
QHashIterator<QString, QList<ModelItemInfo> > it(m_searchList);
while (it.hasNext()) {
......@@ -157,7 +158,7 @@ QList<Locator::FilterEntry> CppLocatorFilter::matchesFor(QFutureInterface<Locato
FileName::fromString(info.fileName));
}
if (info.symbolName.startsWith(entry))
if (info.symbolName.startsWith(entry, caseSensitivityForPrefix))
betterEntries.append(filterEntry);
else
goodEntries.append(filterEntry);
......
......@@ -195,12 +195,12 @@ void CppToolsPlugin::test_cpplocatorfilters_CppLocatorFilter_data()
<< cppLocatorFilter
<< _("myclass")
<< (QList<ResultData>()
<< ResultData(_("<anonymous namespace>::MyClass"), testFileShort)
<< ResultData(_("<anonymous namespace>::MyClass::MyClass"), _("()"))
<< ResultData(_("<anonymous namespace>::MyClass::function2"), _("(bool, int)"))
<< ResultData(_("MyClass"), testFileShort)
<< ResultData(_("MyClass::MyClass"), _("()"))
<< ResultData(_("MyClass::function2"), _("(bool, int)"))
<< ResultData(_("<anonymous namespace>::MyClass"), testFileShort)
<< ResultData(_("<anonymous namespace>::MyClass::MyClass"), _("()"))
<< ResultData(_("<anonymous namespace>::MyClass::function2"), _("(bool, int)"))
<< ResultData(_("MyNamespace::MyClass"), testFileShort)
<< ResultData(_("MyNamespace::MyClass::MyClass"), _("()"))
<< ResultData(_("MyNamespace::MyClass::function2"), _("(bool, int)"))
......
......@@ -62,9 +62,9 @@ QList<FilterEntry> HelpIndexFilter::matchesFor(QFutureInterface<Locator::FilterE
{
QStringList keywords;
if (entry.length() < 2)
keywords = Core::HelpManager::instance()->findKeywords(entry, 200);
keywords = Core::HelpManager::instance()->findKeywords(entry, caseSensitivity(entry), 200);
else
keywords = Core::HelpManager::instance()->findKeywords(entry);
keywords = Core::HelpManager::instance()->findKeywords(entry, caseSensitivity(entry));
QList<FilterEntry> entries;
foreach (const QString &keyword, keywords) {
......
......@@ -70,6 +70,7 @@ QList<FilterEntry> BaseFileFilter::matchesFor(QFutureInterface<Locator::FilterEn
m_previousResultNames.clear();
m_forceNewSearchList = false;
m_previousEntry = needle;
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(needle);
QStringListIterator paths(searchListPaths);
QStringListIterator names(searchListNames);
while (paths.hasNext() && names.hasNext()) {
......@@ -84,7 +85,7 @@ QList<FilterEntry> BaseFileFilter::matchesFor(QFutureInterface<Locator::FilterEn
FilterEntry entry(this, fi.fileName(), QString(path + lineNoSuffix));
entry.extraInfo = FileUtils::shortNativePath(FileName(fi));
entry.fileName = path;
if (name.startsWith(needle))
if (name.startsWith(needle, caseSensitivityForPrefix))
matches.append(entry);
else
badMatches.append(entry);
......
......@@ -71,6 +71,7 @@ QList<Locator::FilterEntry> CommandLocator::matchesFor(QFutureInterface<Locator:
// 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 int count = d->commands.size();
for (int i = 0; i < count; i++) {
if (future.isCanceled())
......@@ -80,9 +81,9 @@ QList<Locator::FilterEntry> CommandLocator::matchesFor(QFutureInterface<Locator:
if (action->isEnabled()) {
QString text = action->text();
text.remove(ampersand);
if (text.startsWith(entry, Qt::CaseInsensitive))
if (text.startsWith(entry, caseSensitivity_))
betterEntries.append(FilterEntry(this, text, QVariant(i)));
else if (text.contains(entry, Qt::CaseInsensitive))
else if (text.contains(entry, caseSensitivity_))
goodEntries.append(FilterEntry(this, text, QVariant(i)));
}
}
......
......@@ -64,12 +64,13 @@ QList<FilterEntry> ExecuteFilter::matchesFor(QFutureInterface<Locator::FilterEnt
if (!entry.isEmpty()) // avoid empty entry
value.append(FilterEntry(this, entry, QVariant()));
QList<FilterEntry> others;
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry);
foreach (const QString& i, m_commandHistory) {
if (future.isCanceled())
break;
if (i == entry) // avoid repeated entry
continue;
if (i.startsWith(entry))
if (i.startsWith(entry, caseSensitivityForPrefix))
value.append(FilterEntry(this, i, QVariant()));
else
others.append(FilterEntry(this, i, QVariant()));
......
......@@ -38,6 +38,21 @@ using namespace Core;
using namespace Locator;
using namespace Locator::Internal;
namespace {
QList<FilterEntry> *categorize(const QString &entry, const QString &candidate,
Qt::CaseSensitivity caseSensitivity,
QList<FilterEntry> *betterEntries, QList<FilterEntry> *goodEntries)
{
if (entry.isEmpty() || candidate.startsWith(entry, caseSensitivity))
return betterEntries;
else if (candidate.contains(entry, caseSensitivity))
return goodEntries;
return 0;
}
} // anynoumous namespace
FileSystemFilter::FileSystemFilter(EditorManager *editorManager, LocatorWidget *locatorWidget)
: m_editorManager(editorManager), m_locatorWidget(locatorWidget), m_includeHidden(true)
{
......@@ -49,7 +64,8 @@ FileSystemFilter::FileSystemFilter(EditorManager *editorManager, LocatorWidget *
QList<FilterEntry> FileSystemFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry)
{
QList<FilterEntry> value;
QList<FilterEntry> goodEntries;
QList<FilterEntry> betterEntries;
QFileInfo entryInfo(entry);
QString name = entryInfo.fileName();
QString directory = entryInfo.path();
......@@ -72,6 +88,7 @@ QList<FilterEntry> FileSystemFilter::matchesFor(QFutureInterface<Locator::Filter
dirFilter |= QDir::Hidden;
fileFilter |= QDir::Hidden;
}
const Qt::CaseSensitivity caseSensitivity_ = caseSensitivity(entry);
QStringList dirs = dirInfo.entryList(dirFilter,
QDir::Name|QDir::IgnoreCase|QDir::LocaleAware);
QStringList files = dirInfo.entryList(fileFilter,
......@@ -79,11 +96,12 @@ QList<FilterEntry> FileSystemFilter::matchesFor(QFutureInterface<Locator::Filter
foreach (const QString &dir, dirs) {
if (future.isCanceled())
break;
if (name.isEmpty() || dir.startsWith(name, Qt::CaseInsensitive)) {
if (QList<FilterEntry> *category = categorize(name, dir, caseSensitivity_, &betterEntries,
&goodEntries)) {
const QString fullPath = dirInfo.filePath(dir);
FilterEntry filterEntry(this, dir, QVariant());
filterEntry.fileName = fullPath;
value.append(filterEntry);
category->append(filterEntry);
}
}
// file names can match with +linenumber or :linenumber
......@@ -93,14 +111,16 @@ QList<FilterEntry> FileSystemFilter::matchesFor(QFutureInterface<Locator::Filter
foreach (const QString &file, files) {
if (future.isCanceled())
break;
if (name.isEmpty() || file.startsWith(name, Qt::CaseInsensitive)) {
if (QList<FilterEntry> *category = categorize(name, file, caseSensitivity_, &betterEntries,
&goodEntries)) {
const QString fullPath = dirInfo.filePath(file);
FilterEntry filterEntry(this, file, QString(fullPath + lineNoSuffix));
filterEntry.fileName = fullPath;
value.append(filterEntry);
category->append(filterEntry);
}
}
return value;
betterEntries.append(goodEntries);
return betterEntries;
}
void FileSystemFilter::accept(FilterEntry selection) const
......
......@@ -132,6 +132,11 @@ QString ILocatorFilter::trimWildcards(const QString &str)
return str.mid(first, last-first+1);
}
Qt::CaseSensitivity ILocatorFilter::caseSensitivity(const QString &str)
{
return str == str.toLower() ? Qt::CaseInsensitive : Qt::CaseSensitive;
}
bool ILocatorFilter::isConfigurable() const
{
return m_isConfigurable;
......
......@@ -138,6 +138,7 @@ public:
bool isEnabled() const;
static QString trimWildcards(const QString &str);
static Qt::CaseSensitivity caseSensitivity(const QString &str);
public slots:
/* Enable or disable the filter. */
......
......@@ -56,7 +56,8 @@ OpenDocumentsFilter::OpenDocumentsFilter(EditorManager *editorManager) :
QList<FilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry_)
{
QList<FilterEntry> value;
QList<FilterEntry> goodEntries;
QList<FilterEntry> betterEntries;
QString entry = entry_;
const QString lineNoSuffix = EditorManager::splitLineNumber(&entry);
const QChar asterisk = QLatin1Char('*');
......@@ -65,23 +66,27 @@ QList<FilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<Locator::Fil
pattern += asterisk;
QRegExp regexp(pattern, Qt::CaseInsensitive, QRegExp::Wildcard);
if (!regexp.isValid())
return value;
return goodEntries;
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry);
foreach (const DocumentModel::Entry &editorEntry, m_editors) {
if (future.isCanceled())
break;
QString fileName = editorEntry.fileName();
if (fileName.isEmpty())
continue;
QString displayName = editorEntry.displayName();
if (regexp.exactMatch(displayName)) {
if (!fileName.isEmpty()) {
QFileInfo fi(fileName);
FilterEntry fiEntry(this, fi.fileName(), QString(fileName + lineNoSuffix));
fiEntry.extraInfo = FileUtils::shortNativePath(FileName(fi));
fiEntry.fileName = fileName;
value.append(fiEntry);
}
QFileInfo fi(fileName);
FilterEntry fiEntry(this, fi.fileName(), QString(fileName + lineNoSuffix));
fiEntry.extraInfo = FileUtils::shortNativePath(FileName(fi));
fiEntry.fileName = fileName;
QList<FilterEntry> &category = displayName.startsWith(entry, caseSensitivityForPrefix)
? betterEntries : goodEntries;
category.append(fiEntry);
}
}
return value;
betterEntries.append(goodEntries);
return betterEntries;
}
void OpenDocumentsFilter::refreshInternally()
......
......@@ -55,7 +55,10 @@ MacroLocatorFilter::~MacroLocatorFilter()
QList<Locator::FilterEntry> MacroLocatorFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry)
{
Q_UNUSED(future)
QList<Locator::FilterEntry> result;
QList<Locator::FilterEntry> goodEntries;
QList<Locator::FilterEntry> betterEntries;
const Qt::CaseSensitivity caseSensitivity_ = caseSensitivity(entry);
const QMap<QString, Macro*> &macros = MacroManager::macros();
QMapIterator<QString, Macro*> it(macros);
......@@ -64,14 +67,21 @@ QList<Locator::FilterEntry> MacroLocatorFilter::matchesFor(QFutureInterface<Loca
it.next();
QString name = it.key();
if (name.contains(entry)) {
QList<Locator::FilterEntry> *category = 0;
if (name.startsWith(entry, caseSensitivity_))
category = &betterEntries;
else if (name.contains(entry, caseSensitivity_))
category = &goodEntries;
if (category) {
QVariant id;
Locator::FilterEntry entry(this, it.key(), id, m_icon);
entry.extraInfo = it.value()->description();
result.append(entry);
category->append(entry);
}
}
return result;
betterEntries.append(goodEntries);
return betterEntries;
}
void MacroLocatorFilter::accept(Locator::FilterEntry selection) const
......
......@@ -72,6 +72,7 @@ QList<Locator::FilterEntry> FunctionFilter::matchesFor(QFutureInterface<Locator:
if (!regexp.isValid())
return goodEntries;
bool hasWildcard = (entry.contains(asterisk) || entry.contains(QLatin1Char('?')));
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry);
QHashIterator<QString, QList<LocatorData::Entry> > it(m_data->entries());
while (it.hasNext()) {
......@@ -91,7 +92,7 @@ QList<Locator::FilterEntry> FunctionFilter::matchesFor(QFutureInterface<Locator:
Locator::FilterEntry filterEntry(this, info.displayName, id/*, info.icon*/);
filterEntry.extraInfo = info.extraInfo;
if (info.symbolName.startsWith(entry))
if (info.symbolName.startsWith(entry, caseSensitivityForPrefix))
betterEntries.append(filterEntry);
else
goodEntries.append(filterEntry);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment