Files
RedBear-OS/local/recipes/kde/kf6-kwidgetsaddons/source/src/kcontextualhelpbutton.cpp
T
2026-04-14 10:51:06 +01:00

153 lines
5.4 KiB
C++

/*
This file is part of the KDE project
SPDX-FileCopyrightText: 2024 Felix Ernst <felixernst@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "kcontextualhelpbutton.h"
#include <QLabel>
#include <QPointer>
#include <QTextDocumentFragment>
#include <QWidgetAction>
/**
* The private class of KContextualHelpButton used for the PIMPL idiom.
* \internal
*/
class KContextualHelpButtonPrivate
{
public:
/** @see KContextualHelpButton::KContextualHelpButton() */
explicit KContextualHelpButtonPrivate(KContextualHelpButton *q, const QString &contextualHelpText, const QWidget *heightHintWidget);
/** @see KContextualHelButton::setContextualHelpText() */
void setContextualHelpText(const QString &contextualHelpText);
/** @see KContextualHelButton::contextualHelpText() */
QString contextualHelpText() const;
/** @see KContextualHelpButton::setHeightHintWidget() */
void setHeightHintWidget(const QWidget *heightHintWidget);
/** @see KContextualHelpButton::setHeightHintWidget() */
const QWidget *heightHintWidget() const;
/**
* A helper method called from KContextualHelpButton::sizeHint().
*
* @returns the preferredSize based on m_heightHintWidget and fallbackSize.
* @param fallbackSize Used as the width. Also used as the height if there is no m_heightHintWidget.
*
* @see QWidget::sizeHint()
* @see KContextualHelpButton::setHeightHintWidget()
*/
QSize preferredSize(const QSize &fallbackSize) const;
private:
KContextualHelpButton *const q_ptr;
/** The popup showing the contextualHelpText. */
QLabel *m_popupLabel = nullptr;
/** @see KContextualHelpButton::setHeightHintWidget() */
QPointer<const QWidget> m_heightHintWidget;
};
KContextualHelpButton::KContextualHelpButton(const QString &contextualHelpText, const QWidget *heightHintWidget, QWidget *parent)
: QToolButton{parent}
, d_ptr(std::make_unique<KContextualHelpButtonPrivate>(this, contextualHelpText, heightHintWidget))
{
}
KContextualHelpButton::KContextualHelpButton(QWidget *parent)
: KContextualHelpButton{QString{}, nullptr, parent}
{
}
KContextualHelpButtonPrivate::KContextualHelpButtonPrivate(KContextualHelpButton *q, const QString &contextualHelpText, const QWidget *heightHintWidget)
: q_ptr{q}
, m_heightHintWidget{heightHintWidget}
{
q_ptr->setIcon(QIcon::fromTheme(QStringLiteral("help-contextual")));
q_ptr->setAutoRaise(true);
q_ptr->setCursor(Qt::WhatsThisCursor);
// i18n: This text will only ever be read by assistive technology like screen readers for visually-impaired. It shows up nowhere on the visible user
// interface. Usually we start button labels with a verb, however the help text contained within this button will automatically be read by the screen
// reader without requiring additional user input. In this sense the label here is more of an announcement that the text read afterwards is help relevant
// to the current context.
q_ptr->setAccessibleName(QObject::tr("Contextual Help", "@action:button accessible name"));
q_ptr->setAttribute(Qt::WidgetAttribute::WA_CustomWhatsThis); // Makes sure clicking this button in whatsThisMode triggers it instead of doing nothing.
auto popup = new QWidgetAction{q_ptr};
q_ptr->addAction(popup);
q_ptr->setPopupMode(QToolButton::InstantPopup);
m_popupLabel = new QLabel{q_ptr};
m_popupLabel->setWordWrap(true);
m_popupLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); // Makes the label and links within it keyboard-accessible.
m_popupLabel->setOpenExternalLinks(true);
popup->setDefaultWidget(m_popupLabel);
setContextualHelpText(contextualHelpText);
}
KContextualHelpButton::~KContextualHelpButton() = default;
void KContextualHelpButton::setContextualHelpText(const QString &contextualHelpText)
{
d_ptr->setContextualHelpText(contextualHelpText);
}
void KContextualHelpButtonPrivate::setContextualHelpText(const QString &contextualHelpText)
{
if (contextualHelpText == q_ptr->toolTip() && contextualHelpText == m_popupLabel->text()) {
return;
}
q_ptr->setToolTip(contextualHelpText);
q_ptr->setAccessibleDescription(QTextDocumentFragment::fromHtml(contextualHelpText).toPlainText()); // Makes sure html tags aren't read out.
m_popupLabel->setText(contextualHelpText);
Q_EMIT q_ptr->contextualHelpTextChanged(contextualHelpText);
}
QString KContextualHelpButton::contextualHelpText() const
{
return d_ptr->contextualHelpText();
}
QString KContextualHelpButtonPrivate::contextualHelpText() const
{
return m_popupLabel->text();
}
void KContextualHelpButton::setHeightHintWidget(const QWidget *heightHintWidget)
{
d_ptr->setHeightHintWidget(heightHintWidget);
}
void KContextualHelpButtonPrivate::setHeightHintWidget(const QWidget *heightHintWidget)
{
m_heightHintWidget = heightHintWidget;
}
const QWidget *KContextualHelpButton::heightHintWidget() const
{
return d_ptr->heightHintWidget();
}
const QWidget *KContextualHelpButtonPrivate::heightHintWidget() const
{
return m_heightHintWidget;
}
QSize KContextualHelpButton::sizeHint() const
{
return d_ptr->preferredSize(QToolButton::sizeHint());
}
QSize KContextualHelpButtonPrivate::preferredSize(const QSize &fallbackSize) const
{
return {fallbackSize.width(), m_heightHintWidget ? m_heightHintWidget->sizeHint().height() : fallbackSize.height()};
}