forked from qt-creator/qt-creator
Utils: Change browse button to OptionPushButton
Allows the user to choose whether he wants to browse local files, or remote files. Change-Id: I0d262034a5c2df56bea2efca876c9019099e3da9 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: David Schulz <david.schulz@qt.io> Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -481,15 +481,29 @@ FilePath firstOrEmpty(const FilePaths &filePaths)
|
|||||||
return filePaths.isEmpty() ? FilePath() : filePaths.first();
|
return filePaths.isEmpty() ? FilePath() : filePaths.first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FileUtils::hasNativeFileDialog()
|
||||||
|
{
|
||||||
|
static std::optional<bool> hasNative;
|
||||||
|
if (!hasNative.has_value()) {
|
||||||
|
// Checking QFileDialog::itemDelegate() seems to be the only way to determine
|
||||||
|
// whether the dialog is native or not.
|
||||||
|
QFileDialog dialog;
|
||||||
|
hasNative = dialog.itemDelegate() == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *hasNative;
|
||||||
|
}
|
||||||
|
|
||||||
FilePath FileUtils::getOpenFilePath(QWidget *parent,
|
FilePath FileUtils::getOpenFilePath(QWidget *parent,
|
||||||
const QString &caption,
|
const QString &caption,
|
||||||
const FilePath &dir,
|
const FilePath &dir,
|
||||||
const QString &filter,
|
const QString &filter,
|
||||||
QString *selectedFilter,
|
QString *selectedFilter,
|
||||||
QFileDialog::Options options,
|
QFileDialog::Options options,
|
||||||
bool fromDeviceIfShiftIsPressed)
|
bool fromDeviceIfShiftIsPressed,
|
||||||
|
bool forceNonNativeDialog)
|
||||||
{
|
{
|
||||||
bool forceNonNativeDialog = dir.needsDevice();
|
forceNonNativeDialog = forceNonNativeDialog || dir.needsDevice();
|
||||||
#ifdef QT_GUI_LIB
|
#ifdef QT_GUI_LIB
|
||||||
if (fromDeviceIfShiftIsPressed && qApp->queryKeyboardModifiers() & Qt::ShiftModifier) {
|
if (fromDeviceIfShiftIsPressed && qApp->queryKeyboardModifiers() & Qt::ShiftModifier) {
|
||||||
forceNonNativeDialog = true;
|
forceNonNativeDialog = true;
|
||||||
@@ -514,9 +528,10 @@ FilePath FileUtils::getSaveFilePath(QWidget *parent,
|
|||||||
const FilePath &dir,
|
const FilePath &dir,
|
||||||
const QString &filter,
|
const QString &filter,
|
||||||
QString *selectedFilter,
|
QString *selectedFilter,
|
||||||
QFileDialog::Options options)
|
QFileDialog::Options options,
|
||||||
|
bool forceNonNativeDialog)
|
||||||
{
|
{
|
||||||
bool forceNonNativeDialog = dir.needsDevice();
|
forceNonNativeDialog = forceNonNativeDialog || dir.needsDevice();
|
||||||
|
|
||||||
const QStringList schemes = QStringList(QStringLiteral("file"));
|
const QStringList schemes = QStringList(QStringLiteral("file"));
|
||||||
return firstOrEmpty(getFilePaths(dialogParent(parent),
|
return firstOrEmpty(getFilePaths(dialogParent(parent),
|
||||||
@@ -535,9 +550,10 @@ FilePath FileUtils::getExistingDirectory(QWidget *parent,
|
|||||||
const QString &caption,
|
const QString &caption,
|
||||||
const FilePath &dir,
|
const FilePath &dir,
|
||||||
QFileDialog::Options options,
|
QFileDialog::Options options,
|
||||||
bool fromDeviceIfShiftIsPressed)
|
bool fromDeviceIfShiftIsPressed,
|
||||||
|
bool forceNonNativeDialog)
|
||||||
{
|
{
|
||||||
bool forceNonNativeDialog = dir.needsDevice();
|
forceNonNativeDialog = forceNonNativeDialog || dir.needsDevice();
|
||||||
|
|
||||||
#ifdef QT_GUI_LIB
|
#ifdef QT_GUI_LIB
|
||||||
if (fromDeviceIfShiftIsPressed && qApp->queryKeyboardModifiers() & Qt::ShiftModifier) {
|
if (fromDeviceIfShiftIsPressed && qApp->queryKeyboardModifiers() & Qt::ShiftModifier) {
|
||||||
|
@@ -90,26 +90,31 @@ public:
|
|||||||
#ifdef QT_WIDGETS_LIB
|
#ifdef QT_WIDGETS_LIB
|
||||||
static void setDialogParentGetter(const std::function<QWidget *()> &getter);
|
static void setDialogParentGetter(const std::function<QWidget *()> &getter);
|
||||||
|
|
||||||
|
static bool hasNativeFileDialog();
|
||||||
|
|
||||||
static FilePath getOpenFilePath(QWidget *parent,
|
static FilePath getOpenFilePath(QWidget *parent,
|
||||||
const QString &caption,
|
const QString &caption,
|
||||||
const FilePath &dir = {},
|
const FilePath &dir = {},
|
||||||
const QString &filter = {},
|
const QString &filter = {},
|
||||||
QString *selectedFilter = nullptr,
|
QString *selectedFilter = nullptr,
|
||||||
QFileDialog::Options options = {},
|
QFileDialog::Options options = {},
|
||||||
bool fromDeviceIfShiftIsPressed = false);
|
bool fromDeviceIfShiftIsPressed = false,
|
||||||
|
bool forceNonNativeDialog = false);
|
||||||
|
|
||||||
static FilePath getSaveFilePath(QWidget *parent,
|
static FilePath getSaveFilePath(QWidget *parent,
|
||||||
const QString &caption,
|
const QString &caption,
|
||||||
const FilePath &dir = {},
|
const FilePath &dir = {},
|
||||||
const QString &filter = {},
|
const QString &filter = {},
|
||||||
QString *selectedFilter = nullptr,
|
QString *selectedFilter = nullptr,
|
||||||
QFileDialog::Options options = {});
|
QFileDialog::Options options = {},
|
||||||
|
bool forceNonNativeDialog = false);
|
||||||
|
|
||||||
static FilePath getExistingDirectory(QWidget *parent,
|
static FilePath getExistingDirectory(QWidget *parent,
|
||||||
const QString &caption,
|
const QString &caption,
|
||||||
const FilePath &dir = {},
|
const FilePath &dir = {},
|
||||||
QFileDialog::Options options = QFileDialog::ShowDirsOnly,
|
QFileDialog::Options options = QFileDialog::ShowDirsOnly,
|
||||||
bool fromDeviceIfShiftIsPressed = false);
|
bool fromDeviceIfShiftIsPressed = false,
|
||||||
|
bool forceNonNativeDialog = false);
|
||||||
|
|
||||||
static FilePaths getOpenFilePaths(QWidget *parent,
|
static FilePaths getOpenFilePaths(QWidget *parent,
|
||||||
const QString &caption,
|
const QString &caption,
|
||||||
|
@@ -8,11 +8,13 @@
|
|||||||
#include "fileutils.h"
|
#include "fileutils.h"
|
||||||
#include "hostosinfo.h"
|
#include "hostosinfo.h"
|
||||||
#include "macroexpander.h"
|
#include "macroexpander.h"
|
||||||
|
#include "optionpushbutton.h"
|
||||||
#include "qtcassert.h"
|
#include "qtcassert.h"
|
||||||
#include "qtcprocess.h"
|
#include "qtcprocess.h"
|
||||||
|
#include "utilstr.h"
|
||||||
|
|
||||||
#include <QGuiApplication>
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QGuiApplication>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
@@ -174,6 +176,9 @@ public:
|
|||||||
const MacroExpander *m_macroExpander = globalMacroExpander();
|
const MacroExpander *m_macroExpander = globalMacroExpander();
|
||||||
std::function<void()> m_openTerminal;
|
std::function<void()> m_openTerminal;
|
||||||
bool m_allowPathFromDevice = false;
|
bool m_allowPathFromDevice = false;
|
||||||
|
|
||||||
|
QMenu *m_contextMenu = nullptr;
|
||||||
|
OptionPushButton *m_browseButton = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
PathChooserPrivate::PathChooserPrivate()
|
PathChooserPrivate::PathChooserPrivate()
|
||||||
@@ -254,7 +259,15 @@ PathChooser::PathChooser(QWidget *parent) :
|
|||||||
d->m_hLayout->addWidget(d->m_lineEdit);
|
d->m_hLayout->addWidget(d->m_lineEdit);
|
||||||
d->m_hLayout->setSizeConstraint(QLayout::SetMinimumSize);
|
d->m_hLayout->setSizeConstraint(QLayout::SetMinimumSize);
|
||||||
|
|
||||||
addButton(browseButtonLabel(), this, [this] { slotBrowse(); });
|
d->m_contextMenu = new QMenu(d->m_browseButton);
|
||||||
|
d->m_contextMenu->addAction(Tr::tr("Local"), this, [this] { slotBrowse(false); });
|
||||||
|
d->m_contextMenu->addAction(Tr::tr("Remote"), this, [this] { slotBrowse(true); });
|
||||||
|
|
||||||
|
d->m_browseButton = new OptionPushButton();
|
||||||
|
d->m_browseButton->setText(browseButtonLabel());
|
||||||
|
connect(d->m_browseButton, &OptionPushButton::clicked, this, [this] { slotBrowse(false); });
|
||||||
|
|
||||||
|
insertButton(d->m_buttons.count(), d->m_browseButton);
|
||||||
|
|
||||||
setLayout(d->m_hLayout);
|
setLayout(d->m_hLayout);
|
||||||
setFocusProxy(d->m_lineEdit);
|
setFocusProxy(d->m_lineEdit);
|
||||||
@@ -277,13 +290,18 @@ void PathChooser::addButton(const QString &text, QObject *context, const std::fu
|
|||||||
insertButton(d->m_buttons.count(), text, context, callback);
|
insertButton(d->m_buttons.count(), text, context, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PathChooser::insertButton(int index, QAbstractButton *button)
|
||||||
|
{
|
||||||
|
d->m_hLayout->insertWidget(index + 1 /*line edit*/, button);
|
||||||
|
d->m_buttons.insert(index, button);
|
||||||
|
}
|
||||||
|
|
||||||
void PathChooser::insertButton(int index, const QString &text, QObject *context, const std::function<void ()> &callback)
|
void PathChooser::insertButton(int index, const QString &text, QObject *context, const std::function<void ()> &callback)
|
||||||
{
|
{
|
||||||
auto button = new QPushButton;
|
auto button = new QPushButton;
|
||||||
button->setText(text);
|
button->setText(text);
|
||||||
connect(button, &QAbstractButton::clicked, context, callback);
|
connect(button, &QAbstractButton::clicked, context, callback);
|
||||||
d->m_hLayout->insertWidget(index + 1/*line edit*/, button);
|
insertButton(index, button);
|
||||||
d->m_buttons.insert(index, button);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PathChooser::browseButtonLabel()
|
QString PathChooser::browseButtonLabel()
|
||||||
@@ -371,7 +389,7 @@ void PathChooser::setReadOnly(bool b)
|
|||||||
button->setEnabled(!b);
|
button->setEnabled(!b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathChooser::slotBrowse()
|
void PathChooser::slotBrowse(bool remote)
|
||||||
{
|
{
|
||||||
emit beforeBrowsing();
|
emit beforeBrowsing();
|
||||||
|
|
||||||
@@ -387,6 +405,8 @@ void PathChooser::slotBrowse()
|
|||||||
predefined.clear();
|
predefined.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remote = remote || filePath().needsDevice();
|
||||||
|
|
||||||
// Prompt for a file/dir
|
// Prompt for a file/dir
|
||||||
FilePath newPath;
|
FilePath newPath;
|
||||||
switch (d->m_acceptingKind) {
|
switch (d->m_acceptingKind) {
|
||||||
@@ -394,7 +414,10 @@ void PathChooser::slotBrowse()
|
|||||||
case PathChooser::ExistingDirectory:
|
case PathChooser::ExistingDirectory:
|
||||||
newPath = FileUtils::getExistingDirectory(this,
|
newPath = FileUtils::getExistingDirectory(this,
|
||||||
makeDialogTitle(tr("Choose Directory")),
|
makeDialogTitle(tr("Choose Directory")),
|
||||||
predefined, {}, d->m_allowPathFromDevice);
|
predefined,
|
||||||
|
{},
|
||||||
|
d->m_allowPathFromDevice,
|
||||||
|
remote);
|
||||||
break;
|
break;
|
||||||
case PathChooser::ExistingCommand:
|
case PathChooser::ExistingCommand:
|
||||||
case PathChooser::Command:
|
case PathChooser::Command:
|
||||||
@@ -404,7 +427,8 @@ void PathChooser::slotBrowse()
|
|||||||
d->m_dialogFilter,
|
d->m_dialogFilter,
|
||||||
nullptr,
|
nullptr,
|
||||||
{},
|
{},
|
||||||
d->m_allowPathFromDevice);
|
d->m_allowPathFromDevice,
|
||||||
|
remote);
|
||||||
newPath = appBundleExpandedPath(newPath);
|
newPath = appBundleExpandedPath(newPath);
|
||||||
break;
|
break;
|
||||||
case PathChooser::File: // fall through
|
case PathChooser::File: // fall through
|
||||||
@@ -414,14 +438,18 @@ void PathChooser::slotBrowse()
|
|||||||
d->m_dialogFilter,
|
d->m_dialogFilter,
|
||||||
nullptr,
|
nullptr,
|
||||||
{},
|
{},
|
||||||
d->m_allowPathFromDevice);
|
d->m_allowPathFromDevice,
|
||||||
|
remote);
|
||||||
newPath = appBundleExpandedPath(newPath);
|
newPath = appBundleExpandedPath(newPath);
|
||||||
break;
|
break;
|
||||||
case PathChooser::SaveFile:
|
case PathChooser::SaveFile:
|
||||||
newPath = FileUtils::getSaveFilePath(this,
|
newPath = FileUtils::getSaveFilePath(this,
|
||||||
makeDialogTitle(tr("Choose File")),
|
makeDialogTitle(tr("Choose File")),
|
||||||
predefined,
|
predefined,
|
||||||
d->m_dialogFilter);
|
d->m_dialogFilter,
|
||||||
|
nullptr,
|
||||||
|
{},
|
||||||
|
remote);
|
||||||
break;
|
break;
|
||||||
case PathChooser::Any: {
|
case PathChooser::Any: {
|
||||||
newPath = FileUtils::getOpenFilePath(this,
|
newPath = FileUtils::getOpenFilePath(this,
|
||||||
@@ -430,7 +458,8 @@ void PathChooser::slotBrowse()
|
|||||||
d->m_dialogFilter,
|
d->m_dialogFilter,
|
||||||
nullptr,
|
nullptr,
|
||||||
{},
|
{},
|
||||||
d->m_allowPathFromDevice);
|
d->m_allowPathFromDevice,
|
||||||
|
remote);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -740,6 +769,11 @@ void PathChooser::setCommandVersionArguments(const QStringList &arguments)
|
|||||||
void PathChooser::setAllowPathFromDevice(bool allow)
|
void PathChooser::setAllowPathFromDevice(bool allow)
|
||||||
{
|
{
|
||||||
d->m_allowPathFromDevice = allow;
|
d->m_allowPathFromDevice = allow;
|
||||||
|
|
||||||
|
if (allow && FileUtils::hasNativeFileDialog())
|
||||||
|
d->m_browseButton->setOptionalMenu(d->m_contextMenu);
|
||||||
|
else
|
||||||
|
d->m_browseButton->setOptionalMenu(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PathChooser::allowPathFromDevice() const
|
bool PathChooser::allowPathFromDevice() const
|
||||||
|
@@ -91,6 +91,7 @@ public:
|
|||||||
static FilePath homePath();
|
static FilePath homePath();
|
||||||
|
|
||||||
void addButton(const QString &text, QObject *context, const std::function<void()> &callback);
|
void addButton(const QString &text, QObject *context, const std::function<void()> &callback);
|
||||||
|
void insertButton(int index, QAbstractButton *button);
|
||||||
void insertButton(int index, const QString &text, QObject *context, const std::function<void()> &callback);
|
void insertButton(int index, const QString &text, QObject *context, const std::function<void()> &callback);
|
||||||
QAbstractButton *buttonAtIndex(int index) const;
|
QAbstractButton *buttonAtIndex(int index) const;
|
||||||
|
|
||||||
@@ -157,7 +158,7 @@ private:
|
|||||||
bool validatePath(FancyLineEdit *edit, QString *errorMessage) const;
|
bool validatePath(FancyLineEdit *edit, QString *errorMessage) const;
|
||||||
// Returns overridden title or the one from <title>
|
// Returns overridden title or the one from <title>
|
||||||
QString makeDialogTitle(const QString &title);
|
QString makeDialogTitle(const QString &title);
|
||||||
void slotBrowse();
|
void slotBrowse(bool remote);
|
||||||
void contextMenuRequested(const QPoint &pos);
|
void contextMenuRequested(const QPoint &pos);
|
||||||
|
|
||||||
PathChooserPrivate *d = nullptr;
|
PathChooserPrivate *d = nullptr;
|
||||||
|
@@ -417,6 +417,7 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model)
|
|||||||
m_binaryChooser->setMinimumWidth(400);
|
m_binaryChooser->setMinimumWidth(400);
|
||||||
m_binaryChooser->setHistoryCompleter(QLatin1String("Cmake.Command.History"));
|
m_binaryChooser->setHistoryCompleter(QLatin1String("Cmake.Command.History"));
|
||||||
m_binaryChooser->setCommandVersionArguments({"--version"});
|
m_binaryChooser->setCommandVersionArguments({"--version"});
|
||||||
|
m_binaryChooser->setAllowPathFromDevice(true);
|
||||||
|
|
||||||
m_qchFileChooser = new PathChooser(this);
|
m_qchFileChooser = new PathChooser(this);
|
||||||
m_qchFileChooser->setExpectedKind(PathChooser::File);
|
m_qchFileChooser->setExpectedKind(PathChooser::File);
|
||||||
|
Reference in New Issue
Block a user