diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp index ac9c2daf38a5615a40b976f83d090284fb82d1cf..1d7049c90f59205b2062d05baf6211caba89ef6a 100644 --- a/src/libs/utils/pathchooser.cpp +++ b/src/libs/utils/pathchooser.cpp @@ -37,11 +37,15 @@ #include "environment.h" #include "qtcassert.h" +#include "synchronousprocess.h" + #include <QtCore/QDebug> #include <QtCore/QDir> #include <QtCore/QFileInfo> #include <QtCore/QSettings> +#include <QtCore/QProcess> +#include <QtGui/qevent.h> #include <QtGui/QDesktopServices> #include <QtGui/QFileDialog> #include <QtGui/QHBoxLayout> @@ -84,6 +88,95 @@ bool PathValidatingLineEdit::validate(const QString &value, QString *errorMessag return m_chooser->validatePath(value, errorMessage); } +// ------------------ BinaryVersionToolTipEventFilter +// Event filter to be installed on a lineedit used for entering +// executables, taking the arguments to print the version ('--version'). +// On a tooltip event, the version is obtained by running the binary and +// setting its stdout as tooltip. + +class BinaryVersionToolTipEventFilter : public QObject +{ +public: + explicit BinaryVersionToolTipEventFilter(QLineEdit *le); + + virtual bool eventFilter(QObject *, QEvent *); + + QStringList arguments() const { return m_arguments; } + void setArguments(const QStringList &arguments) { m_arguments = arguments; } + + static QString toolVersion(const QString &binary, const QStringList &arguments); + +private: + // Extension point for concatenating existing tooltips. + virtual QString defaultToolTip() const { return QString(); } + + QStringList m_arguments; +}; + +BinaryVersionToolTipEventFilter::BinaryVersionToolTipEventFilter(QLineEdit *le) : + QObject(le) +{ + le->installEventFilter(this); +} + +bool BinaryVersionToolTipEventFilter::eventFilter(QObject *o, QEvent *e) +{ + if (e->type() != QEvent::ToolTip) + return false; + QLineEdit *le = qobject_cast<QLineEdit *>(o); + QTC_ASSERT(le, return false; ) + + const QString binary = le->text(); + if (!binary.isEmpty()) { + const QString version = BinaryVersionToolTipEventFilter::toolVersion(QDir::cleanPath(binary), m_arguments); + if (!version.isEmpty()) { + // Concatenate tooltips. + QString tooltip = QLatin1String("<html><head/><body>"); + const QString defaultValue = defaultToolTip(); + if (!defaultValue.isEmpty()) { + tooltip += QLatin1String("<p>"); + tooltip += defaultValue; + tooltip += QLatin1String("</p>"); + } + tooltip += QLatin1String("<pre>"); + tooltip += version; + tooltip += QLatin1String("</pre><body></html>"); + le->setToolTip(tooltip); + } + } + return false; +} + +QString BinaryVersionToolTipEventFilter::toolVersion(const QString &binary, const QStringList &arguments) +{ + if (binary.isEmpty()) + return QString(); + QProcess proc; + proc.start(binary, arguments); + if (!proc.waitForStarted()) + return QString(); + if (!proc.waitForFinished()) { + Utils::SynchronousProcess::stopProcess(proc); + return QString(); + } + return QString::fromLocal8Bit(proc.readAllStandardOutput()); +} + +// Extends BinaryVersionToolTipEventFilter to prepend the existing pathchooser +// tooltip to display the full path. +class PathChooserBinaryVersionToolTipEventFilter : public BinaryVersionToolTipEventFilter +{ +public: + explicit PathChooserBinaryVersionToolTipEventFilter(PathChooser *pe) : + BinaryVersionToolTipEventFilter(pe->lineEdit()), m_pathChooser(pe) {} + +private: + virtual QString defaultToolTip() const + { return m_pathChooser->errorMessage(); } + + const PathChooser *m_pathChooser; +}; + // ------------------ PathChooserPrivate class PathChooserPrivate @@ -101,12 +194,14 @@ public: QString m_initialBrowsePathOverride; QString m_baseDirectory; Environment m_environment; + BinaryVersionToolTipEventFilter *m_binaryVersionToolTipEventFilter; }; PathChooserPrivate::PathChooserPrivate(PathChooser *chooser) : m_hLayout(new QHBoxLayout), m_lineEdit(new PathValidatingLineEdit(chooser)), - m_acceptingKind(PathChooser::Directory) + m_acceptingKind(PathChooser::Directory), + m_binaryVersionToolTipEventFilter(0) { } @@ -428,4 +523,36 @@ QLineEdit *PathChooser::lineEdit() const return m_d->m_lineEdit; } +QString PathChooser::toolVersion(const QString &binary, const QStringList &arguments) +{ + return BinaryVersionToolTipEventFilter::toolVersion(binary, arguments); +} + +void PathChooser::installLineEditVersionToolTip(QLineEdit *le, const QStringList &arguments) +{ + BinaryVersionToolTipEventFilter *ef = new BinaryVersionToolTipEventFilter(le); + ef->setArguments(arguments); +} + +QStringList PathChooser::commandVersionArguments() const +{ + return m_d->m_binaryVersionToolTipEventFilter ? + m_d->m_binaryVersionToolTipEventFilter->arguments() : + QStringList(); +} + +void PathChooser::setCommandVersionArguments(const QStringList &arguments) +{ + if (arguments.isEmpty()) { + if (m_d->m_binaryVersionToolTipEventFilter) { + delete m_d->m_binaryVersionToolTipEventFilter; + m_d->m_binaryVersionToolTipEventFilter = 0; + } + } else { + if (!m_d->m_binaryVersionToolTipEventFilter) + m_d->m_binaryVersionToolTipEventFilter = new PathChooserBinaryVersionToolTipEventFilter(this); + m_d->m_binaryVersionToolTipEventFilter->setArguments(arguments); + } +} + } // namespace Utils diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h index 23be035adfcd1416e48973321b1f6ac087529f32..1c90142d386fa90d161767c4763f6832c880c609 100644 --- a/src/libs/utils/pathchooser.h +++ b/src/libs/utils/pathchooser.h @@ -62,6 +62,7 @@ class QTCREATOR_UTILS_EXPORT PathChooser : public QWidget Q_PROPERTY(QString promptDialogTitle READ promptDialogTitle WRITE setPromptDialogTitle DESIGNABLE true) Q_PROPERTY(Kind expectedKind READ expectedKind WRITE setExpectedKind DESIGNABLE true) Q_PROPERTY(QString baseDirectory READ baseDirectory WRITE setBaseDirectory DESIGNABLE true) + Q_PROPERTY(QStringList commandVersionArguments READ commandVersionArguments WRITE setCommandVersionArguments) public: static const char * const browseButtonLabel; @@ -113,6 +114,17 @@ public: QLineEdit *lineEdit() const; + // For PathChoosers of 'Command' type, this property specifies the arguments + // required to obtain the tool version (commonly, '--version'). Setting them + // causes the version to be displayed as a tooltip. + QStringList commandVersionArguments() const; + void setCommandVersionArguments(const QStringList &arguments); + + // Utility to run a tool and return its stdout. + static QString toolVersion(const QString &binary, const QStringList &arguments); + // Install a tooltip on lineedits used for binaries showing the version. + static void installLineEditVersionToolTip(QLineEdit *le, const QStringList &arguments); + private: // Returns overridden title or the one from <title> QString makeDialogTitle(const QString &title); diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index cffc2bb3f9053151251e4275fea91be2aaa35196..6d3df290fcb478a7bb9d7fd19a3f290c4c4b5078 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -504,25 +504,22 @@ QList<ToolChain *> Internal::GccToolChainFactory::autoDetectCompiler(const QStri // -------------------------------------------------------------------------- Internal::GccToolChainConfigWidget::GccToolChainConfigWidget(GccToolChain *tc) : - ToolChainConfigWidget(tc) + ToolChainConfigWidget(tc), + m_compilerPath(new Utils::PathChooser), + m_force32BitCheckBox(new QCheckBox) { Q_ASSERT(tc); QGridLayout *layout = new QGridLayout(this); - QLabel *label = new QLabel(this); - label->setText(tr("Compiler path:")); - layout->addWidget(label, 0, 0); + layout->addWidget(new QLabel(tr("Compiler path:")), 0, 0); - m_compilerPath = new Utils::PathChooser(this); m_compilerPath->setExpectedKind(Utils::PathChooser::ExistingCommand); + m_compilerPath->setCommandVersionArguments(QStringList(QLatin1String("--version"))); layout->addWidget(m_compilerPath, 0, 1); connect(m_compilerPath, SIGNAL(changed(QString)), this, SLOT(handlePathChange())); - label = new QLabel(this); - label->setText(tr("Force 32bit compilation:")); - layout->addWidget(label, 1, 0); + layout->addWidget(new QLabel(tr("Force 32bit compilation:")), 1, 0); - m_force32BitCheckBox = new QCheckBox(this); layout->addWidget(m_force32BitCheckBox, 1, 1); connect(m_force32BitCheckBox, SIGNAL(toggled(bool)), this, SLOT(handle32BitChange()));