forked from qt-creator/qt-creator
Make commands for File Name Index locator filter configurable
Change-Id: I4a110ed9184345eb6992f4fda59a76fc843b2f1e Reviewed-by: Cristian Adam <cristian.adam@qt.io> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -180,39 +180,7 @@ void ILocatorFilter::restoreState(const QByteArray &state)
|
|||||||
bool ILocatorFilter::openConfigDialog(QWidget *parent, bool &needsRefresh)
|
bool ILocatorFilter::openConfigDialog(QWidget *parent, bool &needsRefresh)
|
||||||
{
|
{
|
||||||
Q_UNUSED(needsRefresh)
|
Q_UNUSED(needsRefresh)
|
||||||
|
return openConfigDialog(parent, nullptr);
|
||||||
QDialog dialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
|
|
||||||
dialog.setWindowTitle(msgConfigureDialogTitle());
|
|
||||||
|
|
||||||
auto vlayout = new QVBoxLayout(&dialog);
|
|
||||||
auto hlayout = new QHBoxLayout;
|
|
||||||
QLineEdit *shortcutEdit = new QLineEdit(shortcutString());
|
|
||||||
QCheckBox *includeByDefault = new QCheckBox(msgIncludeByDefault());
|
|
||||||
includeByDefault->setToolTip(msgIncludeByDefaultToolTip());
|
|
||||||
includeByDefault->setChecked(isIncludedByDefault());
|
|
||||||
|
|
||||||
auto prefixLabel = new QLabel(msgPrefixLabel());
|
|
||||||
prefixLabel->setToolTip(msgPrefixToolTip());
|
|
||||||
hlayout->addWidget(prefixLabel);
|
|
||||||
hlayout->addWidget(shortcutEdit);
|
|
||||||
hlayout->addWidget(includeByDefault);
|
|
||||||
|
|
||||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok |
|
|
||||||
QDialogButtonBox::Cancel);
|
|
||||||
connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
|
||||||
connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
|
|
||||||
|
|
||||||
vlayout->addLayout(hlayout);
|
|
||||||
vlayout->addStretch();
|
|
||||||
vlayout->addWidget(buttonBox);
|
|
||||||
|
|
||||||
if (dialog.exec() == QDialog::Accepted) {
|
|
||||||
setShortcutString(shortcutEdit->text().trimmed());
|
|
||||||
setIncludedByDefault(includeByDefault->isChecked());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -456,6 +424,56 @@ void ILocatorFilter::setConfigurable(bool configurable)
|
|||||||
m_isConfigurable = configurable;
|
m_isConfigurable = configurable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Shows the standard configuration dialog with options for the prefix string
|
||||||
|
and for isIncludedByDefault(). The \a additionalWidget is added at the top.
|
||||||
|
Ownership of \a additionalWidget stays with the caller, but its parent is
|
||||||
|
reset to \c nullptr.
|
||||||
|
|
||||||
|
Returns \c false if the user canceled the dialog.
|
||||||
|
*/
|
||||||
|
bool ILocatorFilter::openConfigDialog(QWidget *parent, QWidget *additionalWidget)
|
||||||
|
{
|
||||||
|
QDialog dialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
|
||||||
|
dialog.setWindowTitle(msgConfigureDialogTitle());
|
||||||
|
|
||||||
|
auto vlayout = new QVBoxLayout(&dialog);
|
||||||
|
auto hlayout = new QHBoxLayout;
|
||||||
|
QLineEdit *shortcutEdit = new QLineEdit(shortcutString());
|
||||||
|
QCheckBox *includeByDefault = new QCheckBox(msgIncludeByDefault());
|
||||||
|
includeByDefault->setToolTip(msgIncludeByDefaultToolTip());
|
||||||
|
includeByDefault->setChecked(isIncludedByDefault());
|
||||||
|
|
||||||
|
auto prefixLabel = new QLabel(msgPrefixLabel());
|
||||||
|
prefixLabel->setToolTip(msgPrefixToolTip());
|
||||||
|
hlayout->addWidget(prefixLabel);
|
||||||
|
hlayout->addWidget(shortcutEdit);
|
||||||
|
hlayout->addWidget(includeByDefault);
|
||||||
|
|
||||||
|
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
|
||||||
|
| QDialogButtonBox::Cancel);
|
||||||
|
connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
||||||
|
connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
|
||||||
|
|
||||||
|
if (additionalWidget)
|
||||||
|
vlayout->addWidget(additionalWidget);
|
||||||
|
vlayout->addLayout(hlayout);
|
||||||
|
vlayout->addStretch();
|
||||||
|
vlayout->addWidget(buttonBox);
|
||||||
|
|
||||||
|
bool accepted = false;
|
||||||
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
|
setShortcutString(shortcutEdit->text().trimmed());
|
||||||
|
setIncludedByDefault(includeByDefault->isChecked());
|
||||||
|
accepted = true;
|
||||||
|
}
|
||||||
|
if (additionalWidget) {
|
||||||
|
additionalWidget->setVisible(false);
|
||||||
|
additionalWidget->setParent(nullptr);
|
||||||
|
}
|
||||||
|
return accepted;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn QList<Core::LocatorFilterEntry> Core::ILocatorFilter::matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future, const QString &entry)
|
\fn QList<Core::LocatorFilterEntry> Core::ILocatorFilter::matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future, const QString &entry)
|
||||||
|
|
||||||
|
@@ -174,6 +174,7 @@ protected:
|
|||||||
void setPriority(Priority priority);
|
void setPriority(Priority priority);
|
||||||
void setDisplayName(const QString &displayString);
|
void setDisplayName(const QString &displayString);
|
||||||
void setConfigurable(bool configurable);
|
void setConfigurable(bool configurable);
|
||||||
|
bool openConfigDialog(QWidget *parent, QWidget *additionalWidget);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Utils::Id m_id;
|
Utils::Id m_id;
|
||||||
|
@@ -31,9 +31,17 @@
|
|||||||
#include <coreplugin/reaper.h>
|
#include <coreplugin/reaper.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
|
#include <utils/fancylineedit.h>
|
||||||
|
#include <utils/macroexpander.h>
|
||||||
|
#include <utils/pathchooser.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
#include <utils/stringutils.h>
|
#include <utils/stringutils.h>
|
||||||
|
#include <utils/variablechooser.h>
|
||||||
|
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QMutexLocker>
|
#include <QMutexLocker>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
@@ -171,37 +179,75 @@ void SpotlightIterator::ensureNext()
|
|||||||
|
|
||||||
// #pragma mark -- SpotlightLocatorFilter
|
// #pragma mark -- SpotlightLocatorFilter
|
||||||
|
|
||||||
|
static QString defaultCommand()
|
||||||
|
{
|
||||||
|
if (HostOsInfo::isMacHost())
|
||||||
|
return "mdfind";
|
||||||
|
if (HostOsInfo::isWindowsHost())
|
||||||
|
return "es.exe";
|
||||||
|
return "locate";
|
||||||
|
}
|
||||||
|
|
||||||
|
static QString defaultArguments()
|
||||||
|
{
|
||||||
|
if (HostOsInfo::isMacHost())
|
||||||
|
return "\"kMDItemFSName = '*%{Query:Escaped}*'c\"";
|
||||||
|
if (HostOsInfo::isWindowsHost())
|
||||||
|
return "-n 10000 -r \"%{Query:Regex}\"";
|
||||||
|
return "-i -l 10000 -r \"%{Query:Regex}\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
static QString defaultCaseSensitiveArguments()
|
||||||
|
{
|
||||||
|
if (HostOsInfo::isMacHost())
|
||||||
|
return "\"kMDItemFSName = '*%{Query:Escaped}*'\"";
|
||||||
|
if (HostOsInfo::isWindowsHost())
|
||||||
|
return "-i -n 10000 -r \"%{Query:Regex}\"";
|
||||||
|
return "-l 10000 -r \"%{Query:Regex}\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char kShortcutStringDefault[] = "md";
|
||||||
|
const bool kIncludedByDefaultDefault = false;
|
||||||
|
|
||||||
|
const char kShortcutStringKey[] = "shortcut";
|
||||||
|
const char kIncludedByDefaultKey[] = "includeByDefault";
|
||||||
|
const char kCommandKey[] = "command";
|
||||||
|
const char kArgumentsKey[] = "arguments";
|
||||||
|
const char kCaseSensitiveKey[] = "caseSensitive";
|
||||||
|
|
||||||
|
static MacroExpander *createMacroExpander(const QString &query)
|
||||||
|
{
|
||||||
|
MacroExpander *expander = new MacroExpander;
|
||||||
|
expander->registerVariable("Query",
|
||||||
|
SpotlightLocatorFilter::tr("Locator query string."),
|
||||||
|
[query] { return query; });
|
||||||
|
expander->registerVariable("Query:Escaped",
|
||||||
|
SpotlightLocatorFilter::tr(
|
||||||
|
"Locator query string with quotes escaped with backslash."),
|
||||||
|
[query] {
|
||||||
|
QString quoted = query;
|
||||||
|
quoted.replace('\\', "\\\\")
|
||||||
|
.replace('\'', "\\\'")
|
||||||
|
.replace('\"', "\\\"");
|
||||||
|
return quoted;
|
||||||
|
});
|
||||||
|
expander->registerVariable("Query:Regex",
|
||||||
|
SpotlightLocatorFilter::tr(
|
||||||
|
"Locator query string as regular expression."),
|
||||||
|
[query] {
|
||||||
|
QString regex = query;
|
||||||
|
regex = regex.replace('*', ".*");
|
||||||
|
return regex;
|
||||||
|
});
|
||||||
|
return expander;
|
||||||
|
}
|
||||||
|
|
||||||
SpotlightLocatorFilter::SpotlightLocatorFilter()
|
SpotlightLocatorFilter::SpotlightLocatorFilter()
|
||||||
{
|
{
|
||||||
if (HostOsInfo::isMacHost()) {
|
|
||||||
command = [](const QString &query, Qt::CaseSensitivity sensitivity) {
|
|
||||||
QString quoted = query;
|
|
||||||
quoted.replace('\\', "\\\\").replace('\'', "\\\'").replace('\"', "\\\"");
|
|
||||||
return QStringList(
|
|
||||||
{"mdfind",
|
|
||||||
QString("kMDItemFSName = '*%1*'%2")
|
|
||||||
.arg(quoted, sensitivity == Qt::CaseInsensitive ? QString("c") : QString())});
|
|
||||||
};
|
|
||||||
} else if (HostOsInfo::isLinuxHost()) {
|
|
||||||
command = [](const QString &query, Qt::CaseSensitivity sensitivity) {
|
|
||||||
QString regex = query;
|
|
||||||
regex = regex.replace('*', ".*");
|
|
||||||
return QStringList({"locate"})
|
|
||||||
+ (sensitivity == Qt::CaseInsensitive ? QStringList({"-i"}) : QStringList())
|
|
||||||
+ QStringList({"-l", "10000", "-r", regex});
|
|
||||||
};
|
|
||||||
} else if (HostOsInfo::isWindowsHost()) {
|
|
||||||
command = [](const QString &query, Qt::CaseSensitivity sensitivity) {
|
|
||||||
QString regex = query;
|
|
||||||
regex = regex.replace('*', ".*");
|
|
||||||
return QStringList({"es.exe"})
|
|
||||||
+ (sensitivity == Qt::CaseSensitive ? QStringList({"-i"}) : QStringList())
|
|
||||||
+ QStringList({"-n", "10000", "-r", regex});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
setId("SpotlightFileNamesLocatorFilter");
|
setId("SpotlightFileNamesLocatorFilter");
|
||||||
setDisplayName(tr("File Name Index"));
|
setDisplayName(tr("File Name Index"));
|
||||||
setShortcutString("md");
|
setConfigurable(true);
|
||||||
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpotlightLocatorFilter::prepareSearch(const QString &entry)
|
void SpotlightLocatorFilter::prepareSearch(const QString &entry)
|
||||||
@@ -213,7 +259,12 @@ void SpotlightLocatorFilter::prepareSearch(const QString &entry)
|
|||||||
// only pass the file name part to allow searches like "somepath/*foo"
|
// only pass the file name part to allow searches like "somepath/*foo"
|
||||||
int lastSlash = fp.filePath.lastIndexOf(QLatin1Char('/'));
|
int lastSlash = fp.filePath.lastIndexOf(QLatin1Char('/'));
|
||||||
const QString query = fp.filePath.mid(lastSlash + 1);
|
const QString query = fp.filePath.mid(lastSlash + 1);
|
||||||
setFileIterator(new SpotlightIterator(command(query, caseSensitivity(fp.filePath))));
|
std::unique_ptr<MacroExpander> expander(createMacroExpander(query));
|
||||||
|
const QString argumentString = expander->expand(
|
||||||
|
caseSensitivity(fp.filePath) == Qt::CaseInsensitive ? m_arguments
|
||||||
|
: m_caseSensitiveArguments);
|
||||||
|
setFileIterator(
|
||||||
|
new SpotlightIterator(QStringList(m_command) + QtcProcess::splitArgs(argumentString)));
|
||||||
}
|
}
|
||||||
BaseFileFilter::prepareSearch(entry);
|
BaseFileFilter::prepareSearch(entry);
|
||||||
}
|
}
|
||||||
@@ -223,5 +274,81 @@ void SpotlightLocatorFilter::refresh(QFutureInterface<void> &future)
|
|||||||
Q_UNUSED(future)
|
Q_UNUSED(future)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SpotlightLocatorFilter::openConfigDialog(QWidget *parent, bool &needsRefresh)
|
||||||
|
{
|
||||||
|
Q_UNUSED(needsRefresh)
|
||||||
|
QWidget configWidget;
|
||||||
|
QFormLayout *layout = new QFormLayout;
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
layout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
||||||
|
configWidget.setLayout(layout);
|
||||||
|
PathChooser *commandEdit = new PathChooser;
|
||||||
|
commandEdit->setExpectedKind(PathChooser::ExistingCommand);
|
||||||
|
commandEdit->lineEdit()->setText(m_command);
|
||||||
|
FancyLineEdit *argumentsEdit = new FancyLineEdit;
|
||||||
|
argumentsEdit->setText(m_arguments);
|
||||||
|
FancyLineEdit *caseSensitiveArgumentsEdit = new FancyLineEdit;
|
||||||
|
caseSensitiveArgumentsEdit->setText(m_caseSensitiveArguments);
|
||||||
|
layout->addRow(tr("Executable:"), commandEdit);
|
||||||
|
layout->addRow(tr("Arguments:"), argumentsEdit);
|
||||||
|
layout->addRow(tr("Case sensitive:"), caseSensitiveArgumentsEdit);
|
||||||
|
std::unique_ptr<MacroExpander> expander(createMacroExpander(""));
|
||||||
|
auto chooser = new VariableChooser(&configWidget);
|
||||||
|
chooser->addMacroExpanderProvider([expander = expander.get()] { return expander; });
|
||||||
|
chooser->addSupportedWidget(argumentsEdit);
|
||||||
|
chooser->addSupportedWidget(caseSensitiveArgumentsEdit);
|
||||||
|
const bool accepted = openConfigDialog(parent, &configWidget);
|
||||||
|
if (accepted) {
|
||||||
|
m_command = commandEdit->rawFilePath().toString();
|
||||||
|
m_arguments = argumentsEdit->text();
|
||||||
|
m_caseSensitiveArguments = caseSensitiveArgumentsEdit->text();
|
||||||
|
}
|
||||||
|
return accepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray SpotlightLocatorFilter::saveState() const
|
||||||
|
{
|
||||||
|
QJsonObject obj;
|
||||||
|
if (shortcutString() != kShortcutStringDefault)
|
||||||
|
obj.insert(kShortcutStringKey, shortcutString());
|
||||||
|
if (isIncludedByDefault() != kIncludedByDefaultDefault)
|
||||||
|
obj.insert(kIncludedByDefaultKey, isIncludedByDefault());
|
||||||
|
if (m_command != defaultCommand())
|
||||||
|
obj.insert(kCommandKey, m_command);
|
||||||
|
if (m_arguments != defaultArguments())
|
||||||
|
obj.insert(kArgumentsKey, m_arguments);
|
||||||
|
if (m_caseSensitiveArguments != defaultCaseSensitiveArguments())
|
||||||
|
obj.insert(kCaseSensitiveKey, m_caseSensitiveArguments);
|
||||||
|
QJsonDocument doc;
|
||||||
|
doc.setObject(obj);
|
||||||
|
return doc.toJson(QJsonDocument::Compact);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpotlightLocatorFilter::restoreState(const QByteArray &state)
|
||||||
|
{
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(state);
|
||||||
|
if (doc.isNull() || !doc.isObject()) {
|
||||||
|
reset();
|
||||||
|
ILocatorFilter::restoreState(state); // legacy settings from Qt Creator < 4.15
|
||||||
|
} else {
|
||||||
|
const QJsonObject obj = doc.object();
|
||||||
|
setShortcutString(obj.value(kShortcutStringKey).toString(kShortcutStringDefault));
|
||||||
|
setIncludedByDefault(obj.value(kIncludedByDefaultKey).toBool(kIncludedByDefaultDefault));
|
||||||
|
m_command = obj.value(kCommandKey).toString(defaultCommand());
|
||||||
|
m_arguments = obj.value(kArgumentsKey).toString(defaultArguments());
|
||||||
|
m_caseSensitiveArguments = obj.value(kCaseSensitiveKey)
|
||||||
|
.toString(defaultCaseSensitiveArguments());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpotlightLocatorFilter::reset()
|
||||||
|
{
|
||||||
|
setShortcutString(kShortcutStringDefault);
|
||||||
|
setIncludedByDefault(kIncludedByDefaultDefault);
|
||||||
|
m_command = defaultCommand();
|
||||||
|
m_arguments = defaultArguments();
|
||||||
|
m_caseSensitiveArguments = defaultCaseSensitiveArguments();
|
||||||
|
}
|
||||||
|
|
||||||
} // Internal
|
} // Internal
|
||||||
} // Core
|
} // Core
|
||||||
|
@@ -41,8 +41,18 @@ public:
|
|||||||
void prepareSearch(const QString &entry) override;
|
void prepareSearch(const QString &entry) override;
|
||||||
void refresh(QFutureInterface<void> &future) override;
|
void refresh(QFutureInterface<void> &future) override;
|
||||||
|
|
||||||
|
using ILocatorFilter::openConfigDialog;
|
||||||
|
bool openConfigDialog(QWidget *parent, bool &needsRefresh) final;
|
||||||
|
|
||||||
|
QByteArray saveState() const final;
|
||||||
|
void restoreState(const QByteArray &state) final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::function<QStringList(QString, Qt::CaseSensitivity)> command;
|
void reset();
|
||||||
|
|
||||||
|
QString m_command;
|
||||||
|
QString m_arguments;
|
||||||
|
QString m_caseSensitiveArguments;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Internal
|
} // Internal
|
||||||
|
Reference in New Issue
Block a user