2023-02-16 13:51:55 +08:00
// Copyright (C) 2018 ~ 2020 Deepin Technology Co., Ltd.
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
2020-04-28 12:12:14 +08:00
// 为了方便使用,把相关定义独立出来,如有需要,直接包含这个头文件,然后使用SET_*的宏去设置,USE_*宏开启即可
2020-05-08 11:26:09 +08:00
// 注意: 对项目中出现的所有的QWidget的派生类都要再启用一次accessiblity, 包括qt的原生控件[qt未限制其标记名称为空的情况]
2020-10-21 20:51:13 +08:00
// 注意: 使用USE_ACCESSIBLE_BY_OBJECTNAME开启accessiblity的时候, 一定要再对这个类用一下USE_ACCESSIBLE, 否则标记可能会遗漏
2020-05-08 11:26:09 +08:00
2020-05-27 14:24:18 +08:00
# ifndef ACCESSIBLEINTERFACE_H
# define ACCESSIBLEINTERFACE_H
2020-04-28 12:12:14 +08:00
# include <QAccessible>
# include <QAccessibleWidget>
# include <QEvent>
# include <QMap>
# include <QString>
# include <QWidget>
# include <QObject>
# include <QMetaEnum>
# include <QMouseEvent>
# include <QApplication>
# define SEPARATOR "_"
2020-05-06 17:28:16 +08:00
inline QString getAccessibleName ( QWidget * w , QAccessible : : Role r , const QString & fallback )
2020-04-28 12:12:14 +08:00
{
2020-05-06 17:28:16 +08:00
const QString lowerFallback = fallback . toLower ( ) ;
2020-04-28 12:12:14 +08:00
// 避免重复生成
static QMap < QObject * , QString > objnameMap ;
if ( ! objnameMap [ w ] . isEmpty ( ) )
return objnameMap [ w ] ;
static QMap < QAccessible : : Role , QList < QString > > accessibleMap ;
2020-05-06 17:28:16 +08:00
QString oldAccessName = w - > accessibleName ( ) . toLower ( ) ;
2020-04-28 12:12:14 +08:00
oldAccessName . replace ( SEPARATOR , " " ) ;
// 按照类型添加固定前缀
QMetaEnum metaEnum = QMetaEnum : : fromType < QAccessible : : Role > ( ) ;
QByteArray prefix = metaEnum . valueToKeys ( r ) ;
switch ( r ) {
case QAccessible : : Button : prefix = " Btn " ; break ;
case QAccessible : : StaticText : prefix = " Label " ; break ;
default : break ;
}
// 再加上标识
QString accessibleName = QString : : fromLatin1 ( prefix ) + SEPARATOR ;
2020-05-27 14:24:18 +08:00
QString objectName = w - > objectName ( ) . toLower ( ) ;
accessibleName + = oldAccessName . isEmpty ( ) ? ( objectName . isEmpty ( ) ? lowerFallback : objectName ) : oldAccessName ;
2020-04-28 12:12:14 +08:00
// 检查名称是否唯一
if ( accessibleMap [ r ] . contains ( accessibleName ) ) {
2020-04-29 15:23:46 +08:00
if ( ! objnameMap . key ( accessibleName ) ) {
2020-04-28 12:12:14 +08:00
objnameMap . remove ( objnameMap . key ( accessibleName ) ) ;
objnameMap . insert ( w , accessibleName ) ;
return accessibleName ;
}
// 获取编号,然后+1
int pos = accessibleName . indexOf ( SEPARATOR ) ;
int id = accessibleName . mid ( pos + 1 ) . toInt ( ) ;
QString newAccessibleName ;
do {
// 一直找到一个不重复的名字
newAccessibleName = accessibleName + SEPARATOR + QString : : number ( + + id ) ;
} while ( accessibleMap [ r ] . contains ( newAccessibleName ) ) ;
accessibleMap [ r ] . append ( newAccessibleName ) ;
objnameMap . insert ( w , newAccessibleName ) ;
2020-05-29 13:08:42 +08:00
// 对象销毁后移除占用名称
QObject : : connect ( w , & QWidget : : destroyed , [ = ] ( QObject * obj ) {
objnameMap . remove ( obj ) ;
accessibleMap [ r ] . removeOne ( newAccessibleName ) ;
} ) ;
2020-04-28 12:12:14 +08:00
return newAccessibleName ;
} else {
accessibleMap [ r ] . append ( accessibleName ) ;
objnameMap . insert ( w , accessibleName ) ;
2020-05-29 13:08:42 +08:00
// 对象销毁后移除占用名称
QObject : : connect ( w , & QWidget : : destroyed , [ = ] ( QObject * obj ) {
objnameMap . remove ( obj ) ;
accessibleMap [ r ] . removeOne ( accessibleName ) ;
} ) ;
2020-04-28 12:12:14 +08:00
return accessibleName ;
}
}
2020-05-27 14:24:18 +08:00
// 公共的功能
2020-06-13 19:19:30 +08:00
# define FUNC_CREATE(classname,accessibletype,accessdescription) explicit Accessible##classname(classname *w) \
2020-05-27 14:24:18 +08:00
: QAccessibleWidget ( w , accessibletype , # classname ) \
, m_w ( w ) \
, m_description ( accessdescription ) \
{ } \
# define FUNC_TEXT(classname,accessiblename) QString Accessible##classname::text(QAccessible::Text t) const{\
switch ( t ) { \
case QAccessible : : Name : \
return getAccessibleName ( m_w , this - > role ( ) , accessiblename ) ; \
case QAccessible : : Description : \
return m_description ; \
default : \
return QString ( ) ; \
} \
} \
// button控件特有功能
# define FUNC_ACTIONNAMES(classname) QStringList Accessible##classname::actionNames() const{\
if ( ! m_w - > isEnabled ( ) ) \
return QStringList ( ) ; \
return QStringList ( ) < < pressAction ( ) < < showMenuAction ( ) ; \
} \
# define FUNC_DOACTION(classname) void Accessible##classname::doAction(const QString &actionName){\
if ( actionName = = pressAction ( ) ) \
{ \
QPointF localPos = m_w - > geometry ( ) . center ( ) ; \
QMouseEvent event ( QEvent : : MouseButtonPress , localPos , Qt : : LeftButton , Qt : : LeftButton , Qt : : NoModifier ) ; \
qApp - > sendEvent ( m_w , & event ) ; \
} \
else if ( actionName = = showMenuAction ( ) ) \
{ \
QPointF localPos = m_w - > geometry ( ) . center ( ) ; \
QMouseEvent event ( QEvent : : MouseButtonPress , localPos , Qt : : RightButton , Qt : : RightButton , Qt : : NoModifier ) ; \
qApp - > sendEvent ( m_w , & event ) ; \
} \
} \
// Label控件特有功能
# define FUNC_TEXT_(classname) QString Accessible##classname::text(int startOffset, int endOffset) const{\
Q_UNUSED ( startOffset ) \
Q_UNUSED ( endOffset ) \
return m_w - > text ( ) ; \
} \
// Slider控件特有功能
# define FUNC_CURRENTVALUE(classname) QVariant Accessible##classname::currentValue() const{\
return m_w - > value ( ) ; \
} \
# define FUNC_SETCURRENTVALUE(classname) void Accessible##classname::setCurrentValue(const QVariant &value){\
return m_w - > setValue ( value . toInt ( ) ) ; \
} \
# define FUNC_MAXMUMVALUE(classname) QVariant Accessible##classname::maximumValue() const{\
return QVariant ( m_w - > maximum ( ) ) ; \
} \
# define FUNC_FUNC_MINIMUMVALUE(classname) QVariant Accessible##classname::minimumValue() const{\
return QVariant ( m_w - > minimum ( ) ) ; \
} \
2020-10-12 14:03:41 +08:00
// DSlider控件特有功能函数
2020-05-27 14:24:18 +08:00
# define FUNC_FUNC_MINIMUMSTEPSIZE(classname) QVariant Accessible##classname::minimumStepSize() const{\
2020-10-12 14:03:41 +08:00
return QVariant ( m_w - > pageStep ( ) ) ; \
2020-05-27 14:24:18 +08:00
} \
# define SET_FORM_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget\
{ \
public : \
FUNC_CREATE ( classname , QAccessible : : Form , accessdescription ) \
QString text ( QAccessible : : Text t ) const override ; \
void * interface_cast ( QAccessible : : InterfaceType t ) override { \
switch ( t ) { \
case QAccessible : : ActionInterface : \
return static_cast < QAccessibleActionInterface * > ( this ) ; \
default : \
return nullptr ; \
} \
} \
2020-04-28 12:12:14 +08:00
private : \
classname * m_w ; \
QString m_description ; \
2020-05-27 14:24:18 +08:00
} ; \
FUNC_TEXT ( classname , accessiblename ) \
2020-04-28 12:12:14 +08:00
2020-05-27 14:24:18 +08:00
# define SET_BUTTON_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget\
{ \
public : \
FUNC_CREATE ( classname , QAccessible : : Button , accessdescription ) \
QString text ( QAccessible : : Text t ) const override ; \
void * interface_cast ( QAccessible : : InterfaceType t ) override { \
switch ( t ) { \
case QAccessible : : ActionInterface : \
return static_cast < QAccessibleActionInterface * > ( this ) ; \
default : \
return nullptr ; \
2020-04-28 12:12:14 +08:00
} \
2020-05-08 11:26:09 +08:00
} \
2020-05-27 14:24:18 +08:00
QStringList actionNames ( ) const override ; \
void doAction ( const QString & actionName ) override ; \
private : \
classname * m_w ; \
QString m_description ; \
} ; \
FUNC_TEXT ( classname , accessiblename ) \
FUNC_ACTIONNAMES ( classname ) \
FUNC_DOACTION ( classname ) \
2020-05-08 11:26:09 +08:00
2020-05-27 14:24:18 +08:00
# define SET_LABEL_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget, public QAccessibleTextInterface\
{ \
public : \
FUNC_CREATE ( classname , QAccessible : : StaticText , accessdescription ) \
QString text ( QAccessible : : Text t ) const override ; \
void * interface_cast ( QAccessible : : InterfaceType t ) override { \
switch ( t ) { \
case QAccessible : : ActionInterface : \
return static_cast < QAccessibleActionInterface * > ( this ) ; \
case QAccessible : : TextInterface : \
return static_cast < QAccessibleTextInterface * > ( this ) ; \
default : \
return nullptr ; \
2020-04-28 12:12:14 +08:00
} \
} \
2020-05-27 14:24:18 +08:00
QString text ( int startOffset , int endOffset ) const override ; \
2020-05-29 13:08:42 +08:00
void selection ( int selectionIndex , int * startOffset , int * endOffset ) const override { \
Q_UNUSED ( selectionIndex ) \
Q_UNUSED ( startOffset ) \
Q_UNUSED ( endOffset ) \
} \
2020-05-27 14:24:18 +08:00
int selectionCount ( ) const override { return 0 ; } \
2020-05-29 13:08:42 +08:00
void addSelection ( int startOffset , int endOffset ) override { \
Q_UNUSED ( startOffset ) \
Q_UNUSED ( endOffset ) \
} \
void removeSelection ( int selectionIndex ) override { \
Q_UNUSED ( selectionIndex ) \
} \
void setSelection ( int selectionIndex , int startOffset , int endOffset ) override { \
Q_UNUSED ( selectionIndex ) \
Q_UNUSED ( startOffset ) \
Q_UNUSED ( endOffset ) \
} \
2020-05-27 14:24:18 +08:00
int cursorPosition ( ) const override { return 0 ; } \
2020-05-29 13:08:42 +08:00
void setCursorPosition ( int position ) override { \
Q_UNUSED ( position ) \
} \
2020-05-27 14:24:18 +08:00
int characterCount ( ) const override { return 0 ; } \
2020-05-29 13:08:42 +08:00
QRect characterRect ( int offset ) const override { \
Q_UNUSED ( offset ) \
return QRect ( ) ; \
} \
int offsetAtPoint ( const QPoint & point ) const override { \
Q_UNUSED ( point ) \
return 0 ; \
} \
void scrollToSubstring ( int startIndex , int endIndex ) override { \
Q_UNUSED ( startIndex ) \
Q_UNUSED ( endIndex ) \
} \
QString attributes ( int offset , int * startOffset , int * endOffset ) const override { \
Q_UNUSED ( offset ) \
Q_UNUSED ( startOffset ) \
Q_UNUSED ( endOffset ) \
return QString ( ) ; \
} \
2020-05-27 14:24:18 +08:00
private : \
classname * m_w ; \
QString m_description ; \
} ; \
FUNC_TEXT ( classname , accessiblename ) \
FUNC_TEXT_ ( classname ) \
2020-04-28 12:12:14 +08:00
2020-05-27 14:24:18 +08:00
# define SET_SLIDER_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget, public QAccessibleValueInterface\
{ \
2020-04-28 12:12:14 +08:00
public : \
2020-05-27 14:24:18 +08:00
FUNC_CREATE ( classname , QAccessible : : Slider , accessdescription ) \
QString text ( QAccessible : : Text t ) const override ; \
void * interface_cast ( QAccessible : : InterfaceType t ) override { \
switch ( t ) { \
case QAccessible : : ActionInterface : \
return static_cast < QAccessibleActionInterface * > ( this ) ; \
case QAccessible : : ValueInterface : \
return static_cast < QAccessibleValueInterface * > ( this ) ; \
default : \
return nullptr ; \
} \
} \
QVariant currentValue ( ) const override ; \
void setCurrentValue ( const QVariant & value ) override ; \
QVariant maximumValue ( ) const override ; \
QVariant minimumValue ( ) const override ; \
QVariant minimumStepSize ( ) const override ; \
private : \
classname * m_w ; \
QString m_description ; \
2020-04-28 12:12:14 +08:00
} ; \
2020-05-27 14:24:18 +08:00
FUNC_TEXT ( classname , accessiblename ) \
FUNC_CURRENTVALUE ( classname ) \
FUNC_SETCURRENTVALUE ( classname ) \
FUNC_MAXMUMVALUE ( classname ) \
FUNC_FUNC_MINIMUMVALUE ( classname ) \
FUNC_FUNC_MINIMUMSTEPSIZE ( classname ) \
2020-04-28 12:12:14 +08:00
2020-05-27 14:24:18 +08:00
# define SET_EDITABLE_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget, public QAccessibleEditableTextInterface, public QAccessibleTextInterface\
{ \
2020-04-28 12:12:14 +08:00
public : \
2020-05-27 14:24:18 +08:00
FUNC_CREATE ( classname , QAccessible : : EditableText , accessdescription ) \
QString text ( QAccessible : : Text t ) const override ; \
2020-10-21 20:51:13 +08:00
QAccessibleInterface * child ( int index ) const override { Q_UNUSED ( index ) ; return nullptr ; } \
2020-05-27 14:24:18 +08:00
void * interface_cast ( QAccessible : : InterfaceType t ) override { \
switch ( t ) { \
case QAccessible : : ActionInterface : \
return static_cast < QAccessibleActionInterface * > ( this ) ; \
case QAccessible : : TextInterface : \
return static_cast < QAccessibleTextInterface * > ( this ) ; \
case QAccessible : : EditableTextInterface : \
return static_cast < QAccessibleEditableTextInterface * > ( this ) ; \
default : \
return nullptr ; \
} \
} \
QString text ( int startOffset , int endOffset ) const override ; \
void selection ( int selectionIndex , int * startOffset , int * endOffset ) const override { \
Q_UNUSED ( selectionIndex ) \
Q_UNUSED ( startOffset ) \
Q_UNUSED ( endOffset ) \
} \
int selectionCount ( ) const override { return 0 ; } \
void addSelection ( int startOffset , int endOffset ) override { \
Q_UNUSED ( startOffset ) \
Q_UNUSED ( endOffset ) \
} \
2020-10-21 20:51:13 +08:00
void removeSelection ( int selectionIndex ) override { Q_UNUSED ( selectionIndex ) ; } \
2020-05-27 14:24:18 +08:00
void setSelection ( int selectionIndex , int startOffset , int endOffset ) override { \
Q_UNUSED ( selectionIndex ) \
Q_UNUSED ( startOffset ) \
Q_UNUSED ( endOffset ) \
} \
int cursorPosition ( ) const override { return 0 ; } \
void setCursorPosition ( int position ) override { \
Q_UNUSED ( position ) \
} \
int characterCount ( ) const override { return 0 ; } \
QRect characterRect ( int offset ) const override { \
Q_UNUSED ( offset ) \
return QRect ( ) ; } \
int offsetAtPoint ( const QPoint & point ) const override { \
Q_UNUSED ( point ) \
return 0 ; } \
void scrollToSubstring ( int startIndex , int endIndex ) override { \
Q_UNUSED ( startIndex ) \
Q_UNUSED ( endIndex ) \
} \
QString attributes ( int offset , int * startOffset , int * endOffset ) const override { \
Q_UNUSED ( offset ) \
Q_UNUSED ( startOffset ) \
Q_UNUSED ( endOffset ) \
return QString ( ) ; } \
void insertText ( int offset , const QString & text ) override { \
Q_UNUSED ( offset ) \
Q_UNUSED ( text ) \
} \
void deleteText ( int startOffset , int endOffset ) override { \
Q_UNUSED ( startOffset ) \
Q_UNUSED ( endOffset ) \
2020-10-21 20:51:13 +08:00
} \
2020-05-27 14:24:18 +08:00
void replaceText ( int startOffset , int endOffset , const QString & text ) override { \
Q_UNUSED ( startOffset ) \
Q_UNUSED ( endOffset ) \
Q_UNUSED ( text ) \
} \
private : \
classname * m_w ; \
QString m_description ; \
} ; \
FUNC_TEXT ( classname , accessiblename ) \
FUNC_TEXT_ ( classname ) \
# define USE_ACCESSIBLE(classnamestring,classname) if (classnamestring == QLatin1String(#classname) && object && object->isWidgetType())\
{ \
interface = new Accessible # # classname ( static_cast < classname * > ( object ) ) ; \
} \
2021-05-25 13:05:45 +08:00
# define ELSE_USE_ACCESSIBLE(classnamestring,classname) else if (classnamestring == QLatin1String(#classname) && object && object->isWidgetType())\
{ \
interface = new Accessible # # classname ( static_cast < classname * > ( object ) ) ; \
} \
2020-05-27 14:24:18 +08:00
// [指定objectname]---适用同一个类, 但objectname不同的情况
# define USE_ACCESSIBLE_BY_OBJECTNAME(classnamestring,classname,objectname) if (classnamestring == QLatin1String(#classname) && object && (object->objectName() == objectname) && object->isWidgetType())\
2021-05-25 13:05:45 +08:00
{ \
interface = new Accessible # # classname ( static_cast < classname * > ( object ) ) ; \
} \
# define ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(classnamestring,classname,objectname) else if (classnamestring == QLatin1String(#classname) && object && (object->objectName() == objectname) && object->isWidgetType())\
2020-05-27 14:24:18 +08:00
{ \
interface = new Accessible # # classname ( static_cast < classname * > ( object ) ) ; \
} \
2020-04-28 12:12:14 +08:00
2020-05-08 11:26:09 +08:00
/*******************************************简化使用*******************************************/
2020-05-27 14:24:18 +08:00
# define SET_FORM_ACCESSIBLE(classname,accessiblename) SET_FORM_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"")
# define SET_BUTTON_ACCESSIBLE(classname,accessiblename) SET_BUTTON_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"")
2020-04-28 12:12:14 +08:00
2020-05-27 14:24:18 +08:00
# define SET_LABEL_ACCESSIBLE(classname,accessiblename) SET_LABEL_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"")
2020-04-28 12:12:14 +08:00
2020-05-27 14:24:18 +08:00
# define SET_SLIDER_ACCESSIBLE(classname,accessiblename) SET_SLIDER_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"")
2020-04-28 12:12:14 +08:00
2020-05-27 14:24:18 +08:00
# define SET_EDITABLE_ACCESSIBLE(classname,accessiblename) SET_EDITABLE_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"")
2020-04-28 12:12:14 +08:00
/************************************************************************************************/
2020-05-27 14:24:18 +08:00
# endif // ACCESSIBLEINTERFACE_H