forked from qt-creator/qt-creator
Utils: Add push button with menu and default click action
QPushButton has the functionality of setting a menu, but that replaces the normal "click" functionality, and always opens the menu on click. QToolButton can have a menu and the user can still click on it to just click. But, QToolButton looks very different, and in combination with other, normal push buttons very alien. Create a push button that only shows the menu when clicking on/near the menu indicator, and otherwise just sends the clicked() signal like a non-menu push button. Change-Id: Id6ba367e40c370275f67f0fbf77521c2e974b3b8 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -106,6 +106,8 @@ add_qtc_library(Utils
|
|||||||
namevaluevalidator.cpp namevaluevalidator.h
|
namevaluevalidator.cpp namevaluevalidator.h
|
||||||
navigationtreeview.cpp navigationtreeview.h
|
navigationtreeview.cpp navigationtreeview.h
|
||||||
networkaccessmanager.cpp networkaccessmanager.h
|
networkaccessmanager.cpp networkaccessmanager.h
|
||||||
|
optionpushbutton.h
|
||||||
|
optionpushbutton.cpp
|
||||||
osspecificaspects.h
|
osspecificaspects.h
|
||||||
outputformat.h
|
outputformat.h
|
||||||
outputformatter.cpp outputformatter.h
|
outputformatter.cpp outputformatter.h
|
||||||
|
87
src/libs/utils/optionpushbutton.cpp
Normal file
87
src/libs/utils/optionpushbutton.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// Copyright (C) 2022 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "optionpushbutton.h"
|
||||||
|
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QStyleOptionButton>
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class Utils::OptionPushButton
|
||||||
|
|
||||||
|
\brief The OptionPushButton class implements a QPushButton for which the menu is only opened
|
||||||
|
if the user presses the menu indicator.
|
||||||
|
|
||||||
|
Use OptionPushButton::setOptionalMenu() to set the menu and its actions.
|
||||||
|
If the users clicks on the menu indicator of the push button, this menu is opened, and
|
||||||
|
its actions are triggered when the user selects them.
|
||||||
|
|
||||||
|
If the user clicks anywhere else on the button, the QAbstractButton::clicked() signal is
|
||||||
|
sent, as if the button didn't have a menu.
|
||||||
|
|
||||||
|
Note: You may not call QPushButton::setMenu(). Use OptionPushButton::setOptionalMenu() instead.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs an option push button with parent \a parent.
|
||||||
|
*/
|
||||||
|
OptionPushButton::OptionPushButton(QWidget *parent)
|
||||||
|
: QPushButton(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs an option push button with text \a text and parent \a parent.
|
||||||
|
*/
|
||||||
|
OptionPushButton::OptionPushButton(const QString &text, QWidget *parent)
|
||||||
|
: QPushButton(text, parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Associates the popup menu \a menu with this push button.
|
||||||
|
This menu is shown if the user clicks on the menu indicator that is shown.
|
||||||
|
If the user clicks anywhere else on the button, QAbstractButton::clicked() is sent instead.
|
||||||
|
|
||||||
|
Ownership of the menu is not transferred to the push button.
|
||||||
|
*/
|
||||||
|
void OptionPushButton::setOptionalMenu(QMenu *menu)
|
||||||
|
{
|
||||||
|
setMenu(menu);
|
||||||
|
// hack away that QPushButton opens the menu on "pressed"
|
||||||
|
disconnect(this, SIGNAL(pressed()), this, SLOT(_q_popupPressed()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
void OptionPushButton::mouseReleaseEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (!menu() || event->button() != Qt::LeftButton)
|
||||||
|
return QPushButton::mouseReleaseEvent(event);
|
||||||
|
setDown(false);
|
||||||
|
const QRect r = rect();
|
||||||
|
if (!r.contains(event->position().toPoint()))
|
||||||
|
return;
|
||||||
|
QStyleOptionButton option;
|
||||||
|
initStyleOption(&option);
|
||||||
|
// for Mac style
|
||||||
|
const QRect contentRect = style()->subElementRect(QStyle::SE_PushButtonContents, &option, this);
|
||||||
|
// for Common style
|
||||||
|
const int menuButtonSize = style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &option, this);
|
||||||
|
// see: newBtn.rect = QRect(ir.right() - mbi - 2, ir.height()/2 - mbi/2 + 3, mbi - 6, mbi - 6);
|
||||||
|
// in QCommonStyle::drawControl, CE_PushButtonBevel, QStyleOptionButton::HasMenu
|
||||||
|
static const int magicBorder = 4;
|
||||||
|
const int clickX = event->position().toPoint().x();
|
||||||
|
if ((option.direction == Qt::LeftToRight
|
||||||
|
&& clickX <= std::min(contentRect.right(), r.right() - menuButtonSize - magicBorder))
|
||||||
|
|| (option.direction == Qt::RightToLeft
|
||||||
|
&& clickX >= std::max(contentRect.left(), r.left() + menuButtonSize + magicBorder))) {
|
||||||
|
click();
|
||||||
|
} else {
|
||||||
|
showMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Utils
|
31
src/libs/utils/optionpushbutton.h
Normal file
31
src/libs/utils/optionpushbutton.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (C) 2022 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "utils_global.h"
|
||||||
|
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QMenu;
|
||||||
|
class QMouseEvent;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
|
||||||
|
class QTCREATOR_UTILS_EXPORT OptionPushButton : public QPushButton
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
OptionPushButton(QWidget *parent = nullptr);
|
||||||
|
OptionPushButton(const QString &text, QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
void setOptionalMenu(QMenu *menu);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Utils
|
@@ -208,6 +208,8 @@ Project {
|
|||||||
"navigationtreeview.h",
|
"navigationtreeview.h",
|
||||||
"networkaccessmanager.cpp",
|
"networkaccessmanager.cpp",
|
||||||
"networkaccessmanager.h",
|
"networkaccessmanager.h",
|
||||||
|
"optionpushbutton.h",
|
||||||
|
"optionpushbutton.cpp",
|
||||||
"osspecificaspects.h",
|
"osspecificaspects.h",
|
||||||
"outputformat.h",
|
"outputformat.h",
|
||||||
"outputformatter.cpp",
|
"outputformatter.cpp",
|
||||||
|
Reference in New Issue
Block a user