PathChooser: Make use of the environment

* Expand environment arguments
 * Introduce new kind: ExistingCommand
 * Use PATH to look up ExistingCommand

Reviewed-by: dt
This commit is contained in:
Tobias Hunger
2010-09-23 11:06:12 +02:00
parent e851684e9d
commit 656c8691f1
2 changed files with 76 additions and 19 deletions

View File

@@ -30,6 +30,7 @@
#include "pathchooser.h" #include "pathchooser.h"
#include "basevalidatinglineedit.h" #include "basevalidatinglineedit.h"
#include "environment.h"
#include "qtcassert.h" #include "qtcassert.h"
#include <QtCore/QDebug> #include <QtCore/QDebug>
@@ -54,6 +55,7 @@
namespace Utils { namespace Utils {
// ------------------ PathValidatingLineEdit // ------------------ PathValidatingLineEdit
class PathValidatingLineEdit : public BaseValidatingLineEdit class PathValidatingLineEdit : public BaseValidatingLineEdit
{ {
public: public:
@@ -79,10 +81,14 @@ bool PathValidatingLineEdit::validate(const QString &value, QString *errorMessag
} }
// ------------------ PathChooserPrivate // ------------------ PathChooserPrivate
struct PathChooserPrivate
class PathChooserPrivate
{ {
public:
PathChooserPrivate(PathChooser *chooser); PathChooserPrivate(PathChooser *chooser);
QString expandedPath(const QString &path) const;
QHBoxLayout *m_hLayout; QHBoxLayout *m_hLayout;
PathValidatingLineEdit *m_lineEdit; PathValidatingLineEdit *m_lineEdit;
PathChooser::Kind m_acceptingKind; PathChooser::Kind m_acceptingKind;
@@ -90,6 +96,7 @@ struct PathChooserPrivate
QString m_dialogFilter; QString m_dialogFilter;
QString m_initialBrowsePathOverride; QString m_initialBrowsePathOverride;
QString m_baseDirectory; QString m_baseDirectory;
Environment m_environment;
}; };
PathChooserPrivate::PathChooserPrivate(PathChooser *chooser) : PathChooserPrivate::PathChooserPrivate(PathChooser *chooser) :
@@ -99,6 +106,24 @@ PathChooserPrivate::PathChooserPrivate(PathChooser *chooser) :
{ {
} }
QString PathChooserPrivate::expandedPath(const QString &input) const
{
QString path = QDir::fromNativeSeparators(input);
if (m_environment.size() > 0)
return m_environment.expandVariables(path);
if (path.isEmpty() || m_acceptingKind == PathChooser::Command)
return path;
if (m_acceptingKind == PathChooser::ExistingCommand)
return m_environment.searchInPath(path, QStringList() << m_baseDirectory);
if (!m_baseDirectory.isEmpty() && QFileInfo(path).isRelative())
return QFileInfo(m_baseDirectory + QLatin1Char('/') + path).absoluteFilePath();
return path;
}
PathChooser::PathChooser(QWidget *parent) : PathChooser::PathChooser(QWidget *parent) :
QWidget(parent), QWidget(parent),
m_d(new PathChooserPrivate(this)) m_d(new PathChooserPrivate(this))
@@ -119,6 +144,8 @@ PathChooser::PathChooser(QWidget *parent) :
setLayout(m_d->m_hLayout); setLayout(m_d->m_hLayout);
setFocusProxy(m_d->m_lineEdit); setFocusProxy(m_d->m_lineEdit);
setEnvironment(Environment::systemEnvironment());
} }
PathChooser::~PathChooser() PathChooser::~PathChooser()
@@ -153,15 +180,20 @@ void PathChooser::setBaseDirectory(const QString &directory)
m_d->m_baseDirectory = directory; m_d->m_baseDirectory = directory;
} }
void PathChooser::setEnvironment(const Utils::Environment &env)
{
m_d->m_environment = env;
}
QString PathChooser::path() const QString PathChooser::path() const
{ {
const QString path = m_d->m_lineEdit->text(); return m_d->expandedPath(QDir::fromNativeSeparators(m_d->m_lineEdit->text()));
if (!m_d->m_baseDirectory.isEmpty() }
&& QFileInfo(path).isRelative()
&& !path.isEmpty()) QString PathChooser::rawPath() const
return QFileInfo(m_d->m_baseDirectory + QLatin1Char('/') + path).absoluteFilePath(); {
else return QDir::fromNativeSeparators(m_d->m_lineEdit->text());
return QDir::fromNativeSeparators(path);
} }
void PathChooser::setPath(const QString &path) void PathChooser::setPath(const QString &path)
@@ -188,8 +220,13 @@ void PathChooser::slotBrowse()
newPath = QFileDialog::getExistingDirectory(this, newPath = QFileDialog::getExistingDirectory(this,
makeDialogTitle(tr("Choose Directory")), predefined); makeDialogTitle(tr("Choose Directory")), predefined);
break; break;
case PathChooser::File: // fall through case PathChooser::ExistingCommand:
case PathChooser::Command: case PathChooser::Command:
newPath = QFileDialog::getOpenFileName(this,
makeDialogTitle(tr("Choose Executable")), predefined,
m_d->m_dialogFilter);
break;
case PathChooser::File: // fall through
newPath = QFileDialog::getOpenFileName(this, newPath = QFileDialog::getOpenFileName(this,
makeDialogTitle(tr("Choose File")), predefined, makeDialogTitle(tr("Choose File")), predefined,
m_d->m_dialogFilter); m_d->m_dialogFilter);
@@ -239,21 +276,31 @@ QString PathChooser::errorMessage() const
bool PathChooser::validatePath(const QString &path, QString *errorMessage) bool PathChooser::validatePath(const QString &path, QString *errorMessage)
{ {
if (path.isEmpty()) { QString expandedPath = m_d->expandedPath(path);
QString displayPath = expandedPath;
if (expandedPath.isEmpty())
//: Selected path is not valid:
displayPath = tr("<not valid>");
*errorMessage = tr("Full path: <b>%1</b>").arg(QDir::toNativeSeparators(expandedPath));
if (expandedPath.isEmpty()) {
if (errorMessage) if (errorMessage)
*errorMessage = tr("The path must not be empty."); *errorMessage = tr("The path must not be empty.");
return false; return false;
} }
const QFileInfo fi(path); const QFileInfo fi(expandedPath);
// Check if existing // Check if existing
switch (m_d->m_acceptingKind) { switch (m_d->m_acceptingKind) {
case PathChooser::Directory: // fall through case PathChooser::Directory: // fall through
case PathChooser::File: case PathChooser::File: // fall through
case PathChooser::ExistingCommand:
if (!fi.exists()) { if (!fi.exists()) {
if (errorMessage) if (errorMessage)
*errorMessage = tr("The path '%1' does not exist.").arg(path); *errorMessage = tr("The path '%1' does not exist.").arg(QDir::toNativeSeparators(expandedPath));
return false; return false;
} }
break; break;
@@ -268,7 +315,7 @@ bool PathChooser::validatePath(const QString &path, QString *errorMessage)
case PathChooser::Directory: case PathChooser::Directory:
if (!fi.isDir()) { if (!fi.isDir()) {
if (errorMessage) if (errorMessage)
*errorMessage = tr("The path '%1' is not a directory.").arg(path); *errorMessage = tr("The path <b>%1</b> is not a directory.").arg(QDir::toNativeSeparators(expandedPath));
return false; return false;
} }
break; break;
@@ -276,14 +323,19 @@ bool PathChooser::validatePath(const QString &path, QString *errorMessage)
case PathChooser::File: case PathChooser::File:
if (!fi.isFile()) { if (!fi.isFile()) {
if (errorMessage) if (errorMessage)
*errorMessage = tr("The path '%1' is not a file.").arg(path); *errorMessage = tr("The path <b>%1</b> is not a file.").arg(QDir::toNativeSeparators(expandedPath));
return false; return false;
} }
break; break;
case PathChooser::ExistingCommand:
if (!fi.isFile() || !fi.isExecutable()) {
if (errorMessage)
*errorMessage = tr("The path <b>%1</b> is not a executable file.").arg(QDir::toNativeSeparators(expandedPath));
return false;
}
case PathChooser::Command: case PathChooser::Command:
// TODO do proper command validation
// i.e. search $PATH for a matching file
break; break;
case PathChooser::Any: case PathChooser::Any:

View File

@@ -42,7 +42,8 @@ QT_END_NAMESPACE
namespace Utils { namespace Utils {
struct PathChooserPrivate; class Environment;
class PathChooserPrivate;
/** /**
* A control that let's the user choose a path, consisting of a QLineEdit and * A control that let's the user choose a path, consisting of a QLineEdit and
@@ -67,7 +68,8 @@ public:
enum Kind { enum Kind {
Directory, Directory,
File, File,
Command, ExistingCommand, // A command that must exist at the time of selection
Command, // A command that may or may not exist at the time of selection (e.g. result of a build)
Any Any
}; };
@@ -87,10 +89,13 @@ public:
QString errorMessage() const; QString errorMessage() const;
QString path() const; QString path() const;
QString rawPath() const; // The raw unexpanded input.
QString baseDirectory() const; QString baseDirectory() const;
void setBaseDirectory(const QString &directory); void setBaseDirectory(const QString &directory);
void setEnvironment(const Utils::Environment &env);
/** Returns the suggested label title when used in a form layout. */ /** Returns the suggested label title when used in a form layout. */
static QString label(); static QString label();