CommandLocator: move some part of the matching code into prepareSearch

We can't call neither Command::isActive() nor QAction->isEnabled()
from inside matchesFor(), as this function is called from non-gui
thread and it may happen, that the gui thread modifies these data
at the same time. Instead we prepare the needed data inside
prepareSearch().

Change-Id: Ie9ddb8eb7df2c39e968ef117caf3ef1d04ed6a80
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Jarek Kobus
2021-01-29 12:36:45 +01:00
parent be1d33299e
commit 069efa9483
2 changed files with 29 additions and 18 deletions

View File

@@ -40,6 +40,7 @@ namespace Core {
struct CommandLocatorPrivate struct CommandLocatorPrivate
{ {
QList<Command *> commands; QList<Command *> commands;
QList<QPair<int, QString>> commandsData;
}; };
/*! /*!
@@ -70,26 +71,36 @@ void CommandLocator::appendCommand(Command *cmd)
d->commands.push_back(cmd); d->commands.push_back(cmd);
} }
void CommandLocator::prepareSearch(const QString &entry)
{
Q_UNUSED(entry)
d->commandsData = {};
const int count = d->commands.size();
// Get active, enabled actions matching text, store in list.
// Reference via index in extraInfo.
for (int i = 0; i < count; ++i) {
Command *command = d->commands.at(i);
if (!command->isActive())
continue;
QAction *action = command->action();
if (action && action->isEnabled())
d->commandsData.append(qMakePair(i, action->text()));
}
}
QList<LocatorFilterEntry> CommandLocator::matchesFor(QFutureInterface<LocatorFilterEntry> &future, const QString &entry) QList<LocatorFilterEntry> CommandLocator::matchesFor(QFutureInterface<LocatorFilterEntry> &future, const QString &entry)
{ {
QList<LocatorFilterEntry> goodEntries; QList<LocatorFilterEntry> goodEntries;
QList<LocatorFilterEntry> betterEntries; QList<LocatorFilterEntry> betterEntries;
// Get active, enabled actions matching text, store in list.
// Reference via index in extraInfo.
const Qt::CaseSensitivity entryCaseSensitivity = caseSensitivity(entry); const Qt::CaseSensitivity entryCaseSensitivity = caseSensitivity(entry);
const int count = d->commands.size(); for (const auto &pair : qAsConst(d->commandsData)) {
for (int i = 0; i < count; i++) {
if (future.isCanceled()) if (future.isCanceled())
break; break;
if (!d->commands.at(i)->isActive())
continue;
QAction *action = d->commands.at(i)->action(); const QString text = Utils::stripAccelerator(pair.second);
if (action && action->isEnabled()) {
const QString text = Utils::stripAccelerator(action->text());
const int index = text.indexOf(entry, 0, entryCaseSensitivity); const int index = text.indexOf(entry, 0, entryCaseSensitivity);
if (index >= 0) { if (index >= 0) {
LocatorFilterEntry filterEntry(this, text, QVariant(i)); LocatorFilterEntry filterEntry(this, text, QVariant(pair.first));
filterEntry.highlightInfo = {index, int(entry.length())}; filterEntry.highlightInfo = {index, int(entry.length())};
if (index == 0) if (index == 0)
@@ -98,7 +109,6 @@ QList<LocatorFilterEntry> CommandLocator::matchesFor(QFutureInterface<LocatorFil
goodEntries.append(filterEntry); goodEntries.append(filterEntry);
} }
} }
}
betterEntries.append(goodEntries); betterEntries.append(goodEntries);
return betterEntries; return betterEntries;
} }

View File

@@ -45,6 +45,7 @@ public:
void appendCommand(Command *cmd); void appendCommand(Command *cmd);
void prepareSearch(const QString &entry) override;
QList<LocatorFilterEntry> matchesFor(QFutureInterface<LocatorFilterEntry> &future, QList<LocatorFilterEntry> matchesFor(QFutureInterface<LocatorFilterEntry> &future,
const QString &entry) override; const QString &entry) override;
void accept(LocatorFilterEntry selection, void accept(LocatorFilterEntry selection,