mumble-voip_mumble/src/mumble/Accessibility.cpp

218 lines
5.9 KiB
C++

// Copyright 2024 The Mumble Developers. All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file at the root of the
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
#include "Accessibility.h"
#include "ChannelFilterMode.h"
#include "Global.h"
#include <QAbstractButton>
#include <QAccessible>
#include <QAccessibleEvent>
#include <QObject>
#include <QWidget>
#include <queue>
namespace Mumble {
namespace Accessibility {
QString removeHTMLTags(QString value) { return value.remove(QRegExp("<[^>]*>")); }
void setDescriptionFromLabel(QWidget *widget, const QLabel *label) {
widget->setAccessibleDescription(removeHTMLTags(label->text()));
}
void fixWizardButtonLabels(QWizard *wizard) {
wizard->button(QWizard::NextButton)->setAccessibleName(QObject::tr("Next"));
wizard->button(QWizard::BackButton)->setAccessibleName(QObject::tr("Back"));
}
QString userToText(const ClientUser *user) {
if (Global::get().uiSession != 0) {
const ClientUser *self = ClientUser::get(Global::get().uiSession);
if (self == user) {
return QString("%1, %2").arg(QObject::tr("This is you")).arg(user->qsName);
}
}
QString name;
QString prefix;
if (!user->qsFriendName.isEmpty()) {
prefix = QObject::tr("friend");
name = user->qsFriendName;
} else if (!user->getLocalNickname().isEmpty()) {
prefix = QObject::tr("user");
name = user->getLocalNickname();
} else {
prefix = QObject::tr("user");
name = user->qsName;
}
return QString("%1 %2").arg(prefix).arg(name);
}
QString userToDescription(const ClientUser *user) {
QString description;
if (user->bMute || user->bSuppress || user->bSelfMute) {
if (user->bDeaf || user->bSelfDeaf) {
description = QString("%1 %2,").arg(QObject::tr("status")).arg(QObject::tr("muted and deafened"));
} else {
description = QString("%1 %2,").arg(QObject::tr("status")).arg(QObject::tr("muted"));
}
} else if (user->bLocalMute) {
description = QString("%1 %2,").arg(QObject::tr("status")).arg(QObject::tr("locally muted"));
} else {
description = QString("%1 %2,").arg(QObject::tr("status")).arg(QObject::tr("unmuted"));
}
if (user->bRecording) {
description += QString("%1,").arg(QObject::tr("recording"));
}
if (user->bPrioritySpeaker) {
description += QString("%1,").arg(QObject::tr("priority speaker"));
}
if (!user->qsComment.isEmpty()) {
if (user->qsComment.length() <= 20) {
description += QString("%1,").arg(user->qsComment);
} else {
description += QString("%1,").arg(QObject::tr("has a long comment"));
}
}
if (user->bLocalIgnore) {
description += QString("%1,").arg(QObject::tr("text messages ignored"));
}
if (user->iId >= 0) {
description += QString("%1,").arg(QObject::tr("registered"));
}
return description;
}
QString channelToText(const Channel *channel) {
return QString("%1 %2").arg(QObject::tr("channel")).arg(channel->qsName);
}
QString channelToDescription(const Channel *channel) {
QString description;
bool selfChannel = false;
if (Global::get().uiSession != 0) {
const ClientUser *self = ClientUser::get(Global::get().uiSession);
if (self->cChannel == channel) {
selfChannel = true;
}
}
if (selfChannel) {
description = QString("%1 %2,").arg(QObject::tr("status")).arg(QObject::tr("your channel"));
} else if (channel->hasEnterRestrictions.load()) {
if (channel->localUserCanEnter.load()) {
description = QString("%1 %2,").arg(QObject::tr("status")).arg(QObject::tr("accessible"));
} else {
description = QString("%1 %2,").arg(QObject::tr("status")).arg(QObject::tr("inaccessible"));
}
} else {
description = QString("%1 %2,").arg(QObject::tr("status")).arg(QObject::tr("public"));
}
switch (channel->m_filterMode) {
case ChannelFilterMode::HIDE:
description += QString("%1,").arg(QObject::tr("filtered"));
break;
case ChannelFilterMode::PIN:
description += QString("%1,").arg(QObject::tr("pinned"));
break;
case ChannelFilterMode::NORMAL:
// NOOP
break;
}
if (!channel->qsDesc.isEmpty()) {
description += QString(": %1").arg(channel->qsDesc);
}
return description;
}
void setSliderSemanticValue(SemanticSlider *slider, QString value) {
slider->m_semanticValue = value;
QAccessibleEvent nameEvent(slider, QAccessible::NameChanged);
QAccessible::updateAccessibility(&nameEvent);
}
void setSliderSemanticValue(SemanticSlider *slider, SliderMode mode, QString suffix) {
QString description = QString("%1 %2");
switch (mode) {
case SliderMode::NONE:
description = description.arg("");
break;
case SliderMode::READ_RELATIVE:
description = description.arg(
QString::number(slider->value() / static_cast< double >(slider->maximum()), 'f', 2));
break;
case SliderMode::READ_PERCENT:
description = description.arg(
static_cast< int32_t >((slider->value() / static_cast< double >(slider->maximum())) * 100));
break;
case SliderMode::READ_ABSOLUTE:
description = description.arg(slider->value());
break;
}
description = description.arg(suffix);
setSliderSemanticValue(slider, description);
}
QWidget *getFirstFocusableChild(QObject *object) {
std::queue< QObject * > search;
search.push(object);
QWidget *selectedWidget = nullptr;
while (!search.empty()) {
QObject *o = search.front();
search.pop();
for (QObject *child : o->children()) {
search.push(child);
}
selectedWidget = qobject_cast< QWidget * >(o);
if (!selectedWidget) {
continue;
}
if (!selectedWidget->isEnabled()) {
selectedWidget = nullptr;
continue;
}
if (selectedWidget->focusPolicy() == Qt::NoFocus) {
selectedWidget = nullptr;
continue;
}
if (qobject_cast< QLabel * >(selectedWidget)) {
selectedWidget = nullptr;
continue;
}
break;
}
return selectedWidget;
}
} // namespace Accessibility
} // namespace Mumble