PathChooser: Allow for chooser-only selection of files/directories

Makes the line edit disabled and read-only in that case.
We also need to change the custom context menu from the line edit to the
path chooser itself, because disabled widgets do not show a context
menu, but we still want to see the select & copy, and the special
items for opening explorer or terminal.

Task-number: QTCREATORBUG-23798
Change-Id: Ib653b4eaaedfbe54c614377795ddc52d21ac12c0
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
Tobias Hunger
2020-03-16 10:24:35 +01:00
committed by Eike Ziller
parent 5838b40c6d
commit 69b0a2cafc
5 changed files with 66 additions and 18 deletions

View File

@@ -175,13 +175,15 @@ public:
Environment m_environment; Environment m_environment;
BinaryVersionToolTipEventFilter *m_binaryVersionToolTipEventFilter = nullptr; BinaryVersionToolTipEventFilter *m_binaryVersionToolTipEventFilter = nullptr;
QList<QAbstractButton *> m_buttons; QList<QAbstractButton *> m_buttons;
MacroExpander *m_macroExpander; MacroExpander *m_macroExpander = globalMacroExpander();
bool m_isReadOnly = false;
bool m_isFileDialogOnly = false;
}; };
PathChooserPrivate::PathChooserPrivate() : PathChooserPrivate::PathChooserPrivate()
m_hLayout(new QHBoxLayout), : m_hLayout(new QHBoxLayout)
m_lineEdit(new FancyLineEdit), , m_lineEdit(new FancyLineEdit)
m_macroExpander(globalMacroExpander())
{ {
} }
@@ -223,9 +225,13 @@ PathChooser::PathChooser(QWidget *parent) :
{ {
d->m_hLayout->setContentsMargins(0, 0, 0, 0); d->m_hLayout->setContentsMargins(0, 0, 0, 0);
d->m_lineEdit->setContextMenuPolicy(Qt::CustomContextMenu); setContextMenuPolicy(Qt::CustomContextMenu);
d->m_lineEdit->setContextMenuPolicy(Qt::NoContextMenu);
connect(d->m_lineEdit, &FancyLineEdit::customContextMenuRequested, this, &PathChooser::contextMenuRequested); connect(this,
&FancyLineEdit::customContextMenuRequested,
this,
&PathChooser::contextMenuRequested);
connect(d->m_lineEdit, &FancyLineEdit::validReturnPressed, this, &PathChooser::returnPressed); connect(d->m_lineEdit, &FancyLineEdit::validReturnPressed, this, &PathChooser::returnPressed);
connect(d->m_lineEdit, &QLineEdit::textChanged, this, connect(d->m_lineEdit, &QLineEdit::textChanged, this,
[this] { emit rawPathChanged(rawPath()); }); [this] { emit rawPathChanged(rawPath()); });
@@ -268,6 +274,7 @@ void PathChooser::insertButton(int index, const QString &text, QObject *context,
connect(button, &QAbstractButton::clicked, context, callback); connect(button, &QAbstractButton::clicked, context, callback);
d->m_hLayout->insertWidget(index + 1/*line edit*/, button); d->m_hLayout->insertWidget(index + 1/*line edit*/, button);
d->m_buttons.insert(index, button); d->m_buttons.insert(index, button);
updateReadOnlyStateOfSubwidgets();
} }
QString PathChooser::browseButtonLabel() QString PathChooser::browseButtonLabel()
@@ -344,15 +351,24 @@ void PathChooser::setFilePath(const FilePath &fn)
bool PathChooser::isReadOnly() const bool PathChooser::isReadOnly() const
{ {
return d->m_lineEdit->isReadOnly(); return d->m_isReadOnly;
} }
void PathChooser::setReadOnly(bool b) void PathChooser::setReadOnly(bool b)
{ {
d->m_lineEdit->setReadOnly(b); d->m_isReadOnly = b;
const auto buttons = d->m_buttons; updateReadOnlyStateOfSubwidgets();
for (QAbstractButton *button : buttons) }
button->setEnabled(!b);
bool PathChooser::isFileDialogOnly() const
{
return d->m_isFileDialogOnly;
}
void PathChooser::setFileDialogOnly(bool b)
{
d->m_isFileDialogOnly = b;
updateReadOnlyStateOfSubwidgets();
} }
void PathChooser::slotBrowse() void PathChooser::slotBrowse()
@@ -442,16 +458,31 @@ void PathChooser::slotBrowse()
void PathChooser::contextMenuRequested(const QPoint &pos) void PathChooser::contextMenuRequested(const QPoint &pos)
{ {
if (QMenu *menu = d->m_lineEdit->createStandardContextMenu()) { if (!d->m_lineEdit->rect().contains(pos))
return;
QMenu *menu = d->m_lineEdit->createStandardContextMenu();
if (!menu)
menu = new QMenu;
if (s_aboutToShowContextMenuHandler)
s_aboutToShowContextMenuHandler(this, menu);
if (!menu->actions().isEmpty()) {
menu->setAttribute(Qt::WA_DeleteOnClose); menu->setAttribute(Qt::WA_DeleteOnClose);
menu->popup(mapToGlobal(pos));
if (s_aboutToShowContextMenuHandler) } else {
s_aboutToShowContextMenuHandler(this, menu); delete menu;
menu->popup(d->m_lineEdit->mapToGlobal(pos));
} }
} }
void PathChooser::updateReadOnlyStateOfSubwidgets()
{
const bool readOnlyLineEdit = d->m_isReadOnly || d->m_isFileDialogOnly;
d->m_lineEdit->setEnabled(!readOnlyLineEdit);
d->m_lineEdit->setReadOnly(readOnlyLineEdit);
setFocusPolicy(d->m_lineEdit->focusPolicy());
for (QAbstractButton *button : qAsConst(d->m_buttons))
button->setEnabled(!d->m_isReadOnly);
}
bool PathChooser::isValid() const bool PathChooser::isValid() const
{ {
return d->m_lineEdit->isValid(); return d->m_lineEdit->isValid();

View File

@@ -138,6 +138,9 @@ public:
bool isReadOnly() const; bool isReadOnly() const;
void setReadOnly(bool b); void setReadOnly(bool b);
bool isFileDialogOnly() const;
void setFileDialogOnly(bool b);
void triggerChanged(); void triggerChanged();
// global handler for adding context menus to ALL pathchooser // global handler for adding context menus to ALL pathchooser
@@ -156,6 +159,7 @@ private:
QString makeDialogTitle(const QString &title); QString makeDialogTitle(const QString &title);
void slotBrowse(); void slotBrowse();
void contextMenuRequested(const QPoint &pos); void contextMenuRequested(const QPoint &pos);
void updateReadOnlyStateOfSubwidgets();
signals: signals:
void validChanged(bool validState); void validChanged(bool validState);

View File

@@ -33,6 +33,7 @@
#include "cmakeprojectconstants.h" #include "cmakeprojectconstants.h"
#include <android/androidconstants.h> #include <android/androidconstants.h>
#include <projectexplorer/buildaspects.h>
#include <projectexplorer/buildinfo.h> #include <projectexplorer/buildinfo.h>
#include <projectexplorer/buildmanager.h> #include <projectexplorer/buildmanager.h>
#include <projectexplorer/buildsteplist.h> #include <projectexplorer/buildsteplist.h>
@@ -67,6 +68,8 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Core::Id id)
displayName(), displayName(),
BuildConfiguration::Unknown)); BuildConfiguration::Unknown));
buildDirectoryAspect()->setFileDialogOnly(true);
appendInitialBuildStep(Constants::CMAKE_BUILD_STEP_ID); appendInitialBuildStep(Constants::CMAKE_BUILD_STEP_ID);
appendInitialCleanStep(Constants::CMAKE_BUILD_STEP_ID); appendInitialCleanStep(Constants::CMAKE_BUILD_STEP_ID);

View File

@@ -109,6 +109,7 @@ public:
Utils::FilePath m_baseFileName; Utils::FilePath m_baseFileName;
bool m_readOnly = false; bool m_readOnly = false;
bool m_showToolTipOnLabel = false; bool m_showToolTipOnLabel = false;
bool m_fileDialogOnly = false;
template<class Widget> void updateWidgetFromCheckStatus(Widget *w) template<class Widget> void updateWidgetFromCheckStatus(Widget *w)
{ {
@@ -257,6 +258,13 @@ void BaseStringAspect::setExpectedKind(const PathChooser::Kind expectedKind)
d->m_pathChooserDisplay->setExpectedKind(expectedKind); d->m_pathChooserDisplay->setExpectedKind(expectedKind);
} }
void BaseStringAspect::setFileDialogOnly(bool requireFileDialog)
{
d->m_fileDialogOnly = requireFileDialog;
if (d->m_pathChooserDisplay)
d->m_pathChooserDisplay->setFileDialogOnly(requireFileDialog);
}
void BaseStringAspect::setEnvironment(const Environment &env) void BaseStringAspect::setEnvironment(const Environment &env)
{ {
d->m_environment = env; d->m_environment = env;
@@ -337,6 +345,7 @@ void BaseStringAspect::addToLayout(LayoutBuilder &builder)
connect(d->m_pathChooserDisplay, &PathChooser::pathChanged, connect(d->m_pathChooserDisplay, &PathChooser::pathChanged,
this, &BaseStringAspect::setValue); this, &BaseStringAspect::setValue);
builder.addItem(d->m_pathChooserDisplay.data()); builder.addItem(d->m_pathChooserDisplay.data());
d->m_pathChooserDisplay->setFileDialogOnly(d->m_fileDialogOnly);
break; break;
case LineEditDisplay: case LineEditDisplay:
d->m_lineEditDisplay = new FancyLineEdit; d->m_lineEditDisplay = new FancyLineEdit;

View File

@@ -127,6 +127,7 @@ public:
void setPlaceHolderText(const QString &placeHolderText); void setPlaceHolderText(const QString &placeHolderText);
void setHistoryCompleter(const QString &historyCompleterKey); void setHistoryCompleter(const QString &historyCompleterKey);
void setExpectedKind(const Utils::PathChooser::Kind expectedKind); void setExpectedKind(const Utils::PathChooser::Kind expectedKind);
void setFileDialogOnly(bool requireFileDialog);
void setEnvironment(const Utils::Environment &env); void setEnvironment(const Utils::Environment &env);
void setBaseFileName(const Utils::FilePath &baseFileName); void setBaseFileName(const Utils::FilePath &baseFileName);
void setReadOnly(bool readOnly); void setReadOnly(bool readOnly);