From 69b0a2cafcd5024dd65432093c4c487da132e53b Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Mon, 16 Mar 2020 10:24:35 +0100 Subject: [PATCH] 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 Reviewed-by: Tobias Hunger --- src/libs/utils/pathchooser.cpp | 67 ++++++++++++++----- src/libs/utils/pathchooser.h | 4 ++ .../cmakebuildconfiguration.cpp | 3 + .../projectconfigurationaspects.cpp | 9 +++ .../projectconfigurationaspects.h | 1 + 5 files changed, 66 insertions(+), 18 deletions(-) diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp index 8d0d78918f3..53de5680dd0 100644 --- a/src/libs/utils/pathchooser.cpp +++ b/src/libs/utils/pathchooser.cpp @@ -175,13 +175,15 @@ public: Environment m_environment; BinaryVersionToolTipEventFilter *m_binaryVersionToolTipEventFilter = nullptr; QList m_buttons; - MacroExpander *m_macroExpander; + MacroExpander *m_macroExpander = globalMacroExpander(); + + bool m_isReadOnly = false; + bool m_isFileDialogOnly = false; }; -PathChooserPrivate::PathChooserPrivate() : - m_hLayout(new QHBoxLayout), - m_lineEdit(new FancyLineEdit), - m_macroExpander(globalMacroExpander()) +PathChooserPrivate::PathChooserPrivate() + : m_hLayout(new QHBoxLayout) + , m_lineEdit(new FancyLineEdit) { } @@ -223,9 +225,13 @@ PathChooser::PathChooser(QWidget *parent) : { 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, &QLineEdit::textChanged, this, [this] { emit rawPathChanged(rawPath()); }); @@ -268,6 +274,7 @@ void PathChooser::insertButton(int index, const QString &text, QObject *context, connect(button, &QAbstractButton::clicked, context, callback); d->m_hLayout->insertWidget(index + 1/*line edit*/, button); d->m_buttons.insert(index, button); + updateReadOnlyStateOfSubwidgets(); } QString PathChooser::browseButtonLabel() @@ -344,15 +351,24 @@ void PathChooser::setFilePath(const FilePath &fn) bool PathChooser::isReadOnly() const { - return d->m_lineEdit->isReadOnly(); + return d->m_isReadOnly; } void PathChooser::setReadOnly(bool b) { - d->m_lineEdit->setReadOnly(b); - const auto buttons = d->m_buttons; - for (QAbstractButton *button : buttons) - button->setEnabled(!b); + d->m_isReadOnly = b; + updateReadOnlyStateOfSubwidgets(); +} + +bool PathChooser::isFileDialogOnly() const +{ + return d->m_isFileDialogOnly; +} + +void PathChooser::setFileDialogOnly(bool b) +{ + d->m_isFileDialogOnly = b; + updateReadOnlyStateOfSubwidgets(); } void PathChooser::slotBrowse() @@ -442,16 +458,31 @@ void PathChooser::slotBrowse() 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); - - if (s_aboutToShowContextMenuHandler) - s_aboutToShowContextMenuHandler(this, menu); - - menu->popup(d->m_lineEdit->mapToGlobal(pos)); + menu->popup(mapToGlobal(pos)); + } else { + delete menu; } } +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 { return d->m_lineEdit->isValid(); diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h index 9fa371fa0e2..ade301b3d0b 100644 --- a/src/libs/utils/pathchooser.h +++ b/src/libs/utils/pathchooser.h @@ -138,6 +138,9 @@ public: bool isReadOnly() const; void setReadOnly(bool b); + bool isFileDialogOnly() const; + void setFileDialogOnly(bool b); + void triggerChanged(); // global handler for adding context menus to ALL pathchooser @@ -156,6 +159,7 @@ private: QString makeDialogTitle(const QString &title); void slotBrowse(); void contextMenuRequested(const QPoint &pos); + void updateReadOnlyStateOfSubwidgets(); signals: void validChanged(bool validState); diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index fef15a3a3e2..18e62ec9366 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -33,6 +33,7 @@ #include "cmakeprojectconstants.h" #include +#include #include #include #include @@ -67,6 +68,8 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Core::Id id) displayName(), BuildConfiguration::Unknown)); + buildDirectoryAspect()->setFileDialogOnly(true); + appendInitialBuildStep(Constants::CMAKE_BUILD_STEP_ID); appendInitialCleanStep(Constants::CMAKE_BUILD_STEP_ID); diff --git a/src/plugins/projectexplorer/projectconfigurationaspects.cpp b/src/plugins/projectexplorer/projectconfigurationaspects.cpp index 3b91f00e137..ea30393eb62 100644 --- a/src/plugins/projectexplorer/projectconfigurationaspects.cpp +++ b/src/plugins/projectexplorer/projectconfigurationaspects.cpp @@ -109,6 +109,7 @@ public: Utils::FilePath m_baseFileName; bool m_readOnly = false; bool m_showToolTipOnLabel = false; + bool m_fileDialogOnly = false; template void updateWidgetFromCheckStatus(Widget *w) { @@ -257,6 +258,13 @@ void BaseStringAspect::setExpectedKind(const PathChooser::Kind 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) { d->m_environment = env; @@ -337,6 +345,7 @@ void BaseStringAspect::addToLayout(LayoutBuilder &builder) connect(d->m_pathChooserDisplay, &PathChooser::pathChanged, this, &BaseStringAspect::setValue); builder.addItem(d->m_pathChooserDisplay.data()); + d->m_pathChooserDisplay->setFileDialogOnly(d->m_fileDialogOnly); break; case LineEditDisplay: d->m_lineEditDisplay = new FancyLineEdit; diff --git a/src/plugins/projectexplorer/projectconfigurationaspects.h b/src/plugins/projectexplorer/projectconfigurationaspects.h index d18ebf5d8b5..71567d493f1 100644 --- a/src/plugins/projectexplorer/projectconfigurationaspects.h +++ b/src/plugins/projectexplorer/projectconfigurationaspects.h @@ -127,6 +127,7 @@ public: void setPlaceHolderText(const QString &placeHolderText); void setHistoryCompleter(const QString &historyCompleterKey); void setExpectedKind(const Utils::PathChooser::Kind expectedKind); + void setFileDialogOnly(bool requireFileDialog); void setEnvironment(const Utils::Environment &env); void setBaseFileName(const Utils::FilePath &baseFileName); void setReadOnly(bool readOnly);