Utils: Add effective binary getter to FilePathAspect

It is quite common to provide a single command as default value
for commands to be executed.
In several cases we fail to handle this correctly when trying
to validate or using the executable although it is validated
correctly inside the underlying path chooser.
This patch provides a method to explicitly get the effective
binary, means either the configured path or if it just had been
a single command it retrieves the full path information by
looking up the command in PATH.
This functionality is limited to non-device file paths which
are expected to be an (optionally existing) command.

Change-Id: I17db69f546f5fb9fec8809db91232f212d21e9a6
Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
Christian Stenger
2024-06-03 09:42:33 +02:00
parent 3d828123be
commit a6fabc48a3
2 changed files with 33 additions and 3 deletions

View File

@@ -1410,6 +1410,7 @@ public:
FilePath m_baseFileName; FilePath m_baseFileName;
StringAspect::ValueAcceptor m_valueAcceptor; StringAspect::ValueAcceptor m_valueAcceptor;
std::optional<FancyLineEdit::ValidationFunction> m_validator; std::optional<FancyLineEdit::ValidationFunction> m_validator;
std::optional<FilePath> m_effectiveBinary;
std::function<void()> m_openTerminal; std::function<void()> m_openTerminal;
CheckableAspectImplementation m_checkerImpl; CheckableAspectImplementation m_checkerImpl;
@@ -1430,6 +1431,8 @@ FilePathAspect::FilePathAspect(AspectContainer *container)
addDataExtractor(this, &FilePathAspect::value, &Data::value); addDataExtractor(this, &FilePathAspect::value, &Data::value);
addDataExtractor(this, &FilePathAspect::operator(), &Data::filePath); addDataExtractor(this, &FilePathAspect::operator(), &Data::filePath);
connect(this, &BaseAspect::changed, this, [this] { d->m_effectiveBinary.reset(); });
} }
FilePathAspect::~FilePathAspect() = default; FilePathAspect::~FilePathAspect() = default;
@@ -1455,6 +1458,29 @@ FilePath FilePathAspect::expandedValue() const
return FilePath::fromUserInput(value); return FilePath::fromUserInput(value);
} }
/*!
Returns the full path of the set command. Only makes a difference if
expected kind is \c Command or \c ExistingCommand and the current
file path is an executable provided without its path.
Performs a lookup in PATH if necessary.
*/
FilePath FilePathAspect::effectiveBinary() const
{
if (d->m_effectiveBinary)
return *d->m_effectiveBinary;
const FilePath current = expandedValue();
const PathChooser::Kind kind = d->m_expectedKind;
if (kind != PathChooser::ExistingCommand && kind != PathChooser::Command)
return current;
if (current.needsDevice())
return current;
d->m_effectiveBinary.emplace(current.searchInPath());
return *d->m_effectiveBinary;
}
QString FilePathAspect::value() const QString FilePathAspect::value() const
{ {
return TypedAspect::value(); return TypedAspect::value();
@@ -1693,10 +1719,13 @@ void FilePathAspect::setAutoApplyOnEditingFinished(bool applyOnEditingFinished)
*/ */
void FilePathAspect::setExpectedKind(const PathChooser::Kind expectedKind) void FilePathAspect::setExpectedKind(const PathChooser::Kind expectedKind)
{ {
if (d->m_expectedKind != expectedKind) {
d->m_expectedKind = expectedKind; d->m_expectedKind = expectedKind;
d->m_effectiveBinary.reset();
if (d->m_pathChooserDisplay) if (d->m_pathChooserDisplay)
d->m_pathChooserDisplay->setExpectedKind(expectedKind); d->m_pathChooserDisplay->setExpectedKind(expectedKind);
} }
}
void FilePathAspect::setEnvironment(const Environment &env) void FilePathAspect::setEnvironment(const Environment &env)
{ {

View File

@@ -663,6 +663,7 @@ public:
}; };
FilePath operator()() const; FilePath operator()() const;
FilePath effectiveBinary() const;
FilePath expandedValue() const; FilePath expandedValue() const;
QString value() const; QString value() const;
void setValue(const FilePath &filePath, Announcement howToAnnounce = DoEmit); void setValue(const FilePath &filePath, Announcement howToAnnounce = DoEmit);