Skip to content

Commit

Permalink
feat: 添加accessible标签名称
Browse files Browse the repository at this point in the history
  添加accessible标签名称

Log: 添加accessible标签名称
  • Loading branch information
starhcq committed Aug 30, 2023
1 parent 3fd93de commit 49152d8
Show file tree
Hide file tree
Showing 8 changed files with 314 additions and 33 deletions.
1 change: 1 addition & 0 deletions application/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ set (APP_HEADERS_FILES
logallexportthread.h
eventlogutils.h
logbackend.h
accessible.h
)

# 5. 头文件
Expand Down
270 changes: 270 additions & 0 deletions application/accessible.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef ACCESSIBLE_H
#define ACCESSIBLE_H

// 为了方便使用,把相关定义独立出来,如有需要,直接包含这个头文件,然后使用SET_*的宏去设置,USE_*宏开启即可
/* 宏参数说明
* classname:类名,例如DLineEdit
* accessiblename:accessible唯一标识,需保证唯一性[getAccessibleName函数处理],优先使用QObject::setAccessibleName值
* accessibletype:即QAccessible::Role,表示标识控件的类型
* classobj:QObject指针
* accessdescription:accessible描述内容,考虑到暂时用不到,目前都默认为空,有需要可自行设计接口
*
* 部分创建宏说明
* FUNC_CREATE:创建构造函数
* FUNC_PRESS:创建Press接口
* FUNC_SHOWMENU:创建右键菜单接口
* FUNC_PRESS_SHOWMENU:上两者的综合
* FUNC_RECT:实现rect接口
* FUNC_TEXT:实现text接口
* USE_ACCESSIBLE:对传入的类型设置其accessible功能
* USE_ACCESSIBLE_BY_OBJECTNAME:同上,[指定objectname]---适用同一个类,但objectname不同的情况
*
* 设置为指定类型的Accessible控件宏
* SET_BUTTON_ACCESSIBLE_PRESS_SHOWMENU:button类型,添加press和showmenu功能
* SET_BUTTON_ACCESSIBLE_SHOWMENU:button类型,添加showmenu功能
* SET_BUTTON_ACCESSIBLE:button类型,添加press功能
* SET_LABEL_ACCESSIBLE:label类型,用于标签控件
* SET_FORM_ACCESSIBLE:form类型,用于widget控件
* SET_SLIDER_ACCESSIBLE:slider类型,用于滑块控件
* SET_SEPARATOR_ACCESSIBLE:separator类型,用于分隔符控件
*/

#include <QAccessible>
#include <QAccessibleWidget>
#include <QMap>
#include <QObject>
#include <QMetaEnum>
#include <QWidget>

inline constexpr char kSeparator[] { "_" };

inline QString getObjPrefix(QAccessible::Role r)
{
// 按照类型添加固定前缀
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;
}
return QString::fromLatin1(prefix);
}

inline QString getIntelAccessibleName(QWidget *w, QAccessible::Role r, QString fallback)
{
// 避免重复生成
static QMap< QObject *, QString > objnameMap;
if (!objnameMap[w].isEmpty())
return objnameMap[w];

static QMap< QAccessible::Role, QList< QString > > accessibleMap;
QString oldAccessName = w->accessibleName();
oldAccessName.replace(kSeparator, "");

// 再加上标识
QString accessibleName = "";//getObjPrefix(r) + kSeparator;
accessibleName += oldAccessName.isEmpty() ? fallback : oldAccessName;
// 检查名称是否唯一
if (accessibleMap[r].contains(accessibleName)) {
if (objnameMap.key(accessibleName)) {
objnameMap.remove(objnameMap.key(accessibleName));
objnameMap.insert(w, accessibleName);
return accessibleName;
}
// 获取编号,然后+1
int pos = accessibleName.indexOf(kSeparator);
int id = accessibleName.mid(pos + 1).toInt();

QString newAccessibleName;
do {
// 一直找到一个不重复的名字
newAccessibleName = accessibleName + kSeparator + QString::number(++id);
} while (accessibleMap[r].contains(newAccessibleName));

accessibleMap[r].append(newAccessibleName);
objnameMap.insert(w, newAccessibleName);

return newAccessibleName;
} else {
accessibleMap[r].append(accessibleName);
objnameMap.insert(w, accessibleName);

return accessibleName;
}
}

inline QString getAccessibleName(QWidget *w, QAccessible::Role r, QString fallback)
{
QString accessibleName = getIntelAccessibleName(w, r, fallback);
if(accessibleName.isEmpty())
{
return getObjPrefix(r) + kSeparator;
}

return accessibleName;
}

#define FUNC_CREATE(classname,accessibletype,accessdescription) Accessible##classname(classname *w) \
: QAccessibleWidget(w,accessibletype,#classname)\
, m_w(w)\
, m_description(accessdescription)\
{}\
private:\
classname *m_w;\
QString m_description;\

#define FUNC_PRESS(classobj) QStringList actionNames() const override{\
if(!classobj->isEnabled())\
return QStringList();\
return QStringList() << pressAction();}\
void doAction(const QString &actionName) override{\
if(actionName == pressAction())\
{\
QPointF localPos = classobj->geometry().center();\
QMouseEvent event(QEvent::MouseButtonPress,localPos,Qt::LeftButton,Qt::LeftButton,Qt::NoModifier);\
QMouseEvent event2(QEvent::MouseButtonRelease,localPos,Qt::LeftButton,Qt::LeftButton,Qt::NoModifier);\
qApp->sendEvent(classobj,&event);\
qApp->sendEvent(classobj,&event2);\
}\
}\

#define FUNC_SHOWMENU(classobj) QStringList actionNames() const override{\
if(!classobj->isEnabled())\
return QStringList();\
return QStringList() << showMenuAction();}\
void doAction(const QString &actionName) override{\
if(actionName == showMenuAction())\
{\
QPointF localPos = classobj->geometry().center();\
QMouseEvent event(QEvent::MouseButtonPress,localPos,Qt::RightButton,Qt::RightButton,Qt::NoModifier);\
QMouseEvent event2(QEvent::MouseButtonRelease,localPos,Qt::RightButton,Qt::RightButton,Qt::NoModifier);\
qApp->sendEvent(classobj,&event);\
qApp->sendEvent(classobj,&event2);\
}\
}\

#define FUNC_PRESS_SHOWMENU(classobj) QStringList actionNames() const override{\
if(!classobj->isEnabled())\
return QStringList();\
return QStringList() << pressAction() << showMenuAction();}\
void doAction(const QString &actionName) override{\
if(actionName == pressAction())\
{\
QPointF localPos = classobj->geometry().center();\
QMouseEvent event(QEvent::MouseButtonPress,localPos,Qt::LeftButton,Qt::LeftButton,Qt::NoModifier);\
QMouseEvent event2(QEvent::MouseButtonRelease,localPos,Qt::LeftButton,Qt::LeftButton,Qt::NoModifier);\
qApp->sendEvent(classobj,&event);\
qApp->sendEvent(classobj,&event2);\
}\
else if(actionName == showMenuAction())\
{\
QPointF localPos = classobj->geometry().center();\
QMouseEvent event(QEvent::MouseButtonPress,localPos,Qt::RightButton,Qt::RightButton,Qt::NoModifier);\
QMouseEvent event2(QEvent::MouseButtonRelease,localPos,Qt::RightButton,Qt::RightButton,Qt::NoModifier);\
qApp->sendEvent(classobj,&event);\
qApp->sendEvent(classobj,&event2);\
}\
}\

#define FUNC_RECT(classobj) QRect rect() const override{\
if (!classobj->isVisible())\
return QRect();\
return classobj->geometry();\
}\

#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();\
}\
}\

#define USE_ACCESSIBLE(classnamestring,classname) if (classnamestring == QLatin1String(#classname) && object && object->isWidgetType())\
{\
interface = new Accessible##classname(static_cast<classname *>(object));\
}\

// [指定objectname]---适用同一个类,但objectname不同的情况
#define USE_ACCESSIBLE_BY_OBJECTNAME(classnamestring,classname,objectname) if (classnamestring == QLatin1String(#classname) && object && (object->objectName() == objectname) && object->isWidgetType())\
{\
interface = new Accessible##classname(static_cast<classname *>(object));\
}\

#define SET_BUTTON_ACCESSIBLE_PRESS_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget\
{\
public:\
FUNC_CREATE(classname,QAccessible::Button,accessdescription)\
QString text(QAccessible::Text t) const override;\
FUNC_PRESS(m_w)\
};\

#define SET_BUTTON_ACCESSIBLE_SHOWMENU_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget\
{\
public:\
FUNC_CREATE(classname,QAccessible::Button,accessdescription)\
QString text(QAccessible::Text t) const override;\
FUNC_SHOWMENU(m_w)\
};\

#define SET_BUTTON_ACCESSIBLE_PRESS_SHOEMENU_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget\
{\
public:\
FUNC_CREATE(classname,QAccessible::Button,accessdescription)\
QString text(QAccessible::Text t) const override;\
FUNC_PRESS_SHOWMENU(m_w)\
};\

#define SET_LABEL_ACCESSIBLE_WITH_DESCRIPTION(classname,aaccessibletype,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget\
{\
public:\
FUNC_CREATE(classname,aaccessibletype,accessdescription)\
QString text(QAccessible::Text t) const override;\
FUNC_RECT(m_w)\
};\

// /*******************************************简化使用*******************************************/
#define SET_BUTTON_ACCESSIBLE_PRESS_SHOWMENU(classname,accessiblename) SET_BUTTON_ACCESSIBLE_PRESS_SHOEMENU_DESCRIPTION(classname,accessiblename,"")\
FUNC_TEXT(classname,accessiblename)

#define SET_BUTTON_ACCESSIBLE_SHOWMENU(classname,accessiblename) SET_BUTTON_ACCESSIBLE_SHOWMENU_DESCRIPTION(classname,accessiblename,"")\
FUNC_TEXT(classname,accessiblename)

#define SET_BUTTON_ACCESSIBLE(classname,accessiblename) SET_BUTTON_ACCESSIBLE_PRESS_DESCRIPTION(classname,accessiblename,"")\
FUNC_TEXT(classname,accessiblename)

#define SET_LABEL_ACCESSIBLE(classname,accessiblename) SET_LABEL_ACCESSIBLE_WITH_DESCRIPTION(classname,QAccessible::StaticText,accessiblename,"")\
FUNC_TEXT(classname,accessiblename)

#define SET_FORM_ACCESSIBLE(classname,accessiblename) SET_LABEL_ACCESSIBLE_WITH_DESCRIPTION(classname,QAccessible::Form,accessiblename,"");\
FUNC_TEXT(classname,accessiblename)

#define SET_SLIDER_ACCESSIBLE(classname,accessiblename) SET_LABEL_ACCESSIBLE_WITH_DESCRIPTION(classname,QAccessible::Slider,accessiblename,"")\
FUNC_TEXT(classname,accessiblename)

#define SET_SEPARATOR_ACCESSIBLE(classname,accessiblename) SET_LABEL_ACCESSIBLE_WITH_DESCRIPTION(classname,QAccessible::Separator,accessiblename,"")\
FUNC_TEXT(classname,accessiblename)
/************************************************************************************************/


/********************** 添加accessible ***********************/
SET_FORM_ACCESSIBLE(QWidget,m_w->objectName())

QAccessibleInterface *accessibleFactory(const QString &classname, QObject *object)
{
QAccessibleInterface *interface = nullptr;
USE_ACCESSIBLE(classname, QWidget);

return interface;
}
/*************************************************************/

#endif // ACCESSIBLE_H
32 changes: 20 additions & 12 deletions application/displaycontent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,21 @@ void DisplayContent::initUI()

//m_spinnerWgt,m_spinnerWgt_K
m_spinnerWgt = new LogSpinnerWidget(this);
m_spinnerWgt->setAccessibleName("spinnerWidget");
m_spinnerWgt->setMinimumHeight(300);
m_spinnerWgt_K = new LogSpinnerWidget(this);
m_spinnerWgt_K->setAccessibleName("spinnerWidget_K");
m_spinnerWgt_K->setMinimumHeight(300);

//m_detailWgt
m_detailWgt = new logDetailInfoWidget(this);
m_detailWgt->setAccessibleName("detailInfoWidget");
m_detailWgt->setMinimumHeight(70);
m_detailWgt->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

//m_splitter
m_splitter = new Dtk::Widget::DSplitter( this);
m_splitter->setAccessibleName("splitterFrame");
m_splitter->setOrientation(Qt::Vertical);
m_splitter->setChildrenCollapsible(false);
m_splitter->addWidget(m_treeView);
Expand All @@ -146,8 +150,15 @@ void DisplayContent::initUI()

//m_exportDlg
m_exportDlg = new ExportProgressDlg(this);
m_exportDlg->setAccessibleName("ExportProgressDlg");
m_exportDlg->hide();


m_menu = new QMenu(m_treeView);
m_menu->setAccessibleName("table_menu");
m_act_openForder = m_menu->addAction(/*tr("在文件管理器中显示")*/ DApplication::translate("Action", "Display in file manager"));
m_act_refresh = m_menu->addAction(/*tr("刷新")*/ DApplication::translate("Action", "Refresh"));

//setLoadState
setLoadState(DATA_COMPLETE);
}
Expand Down Expand Up @@ -193,6 +204,7 @@ void DisplayContent::initTableView()
{
m_treeView = new LogTreeView(this);
m_treeView->setObjectName("mainLogTable");
m_treeView->setAccessibleName("mainLogTable");
m_pModel = new QStandardItemModel(this);
m_treeView->setModel(m_pModel);
m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
Expand Down Expand Up @@ -3952,41 +3964,37 @@ void DisplayContent::slot_requestShowRightMenu(const QPoint &pos)
if (m_treeView->indexAt(pos).isValid()) {
QModelIndex index = m_treeView->currentIndex();
if (!m_treeView->selectionModel()->selectedIndexes().empty()) {
QMenu *menu = new QMenu(m_treeView);
QAction *act_openForder = new QAction(/*tr("在文件管理器中显示")*/ DApplication::translate("Action", "Display in file manager"), this);
QAction *act_refresh = new QAction(/*tr("刷新")*/ DApplication::translate("Action", "Refresh"), this);

menu->addAction(act_openForder);
menu->addAction(act_refresh);

QString path;
if (m_flag == COREDUMP) {
if (index.siblingAtColumn(2).data().toString() == "missing") {
// 文件状态为missing,不能在文管中打开
act_openForder->setEnabled(false);
m_act_openForder->setEnabled(false);
} else {
act_openForder->setEnabled(true);
m_act_openForder->setEnabled(true);
}
//coredump文件不需要刷新
act_refresh->setEnabled(false);
m_act_refresh->setEnabled(false);

path = m_pModel->item(index.row(), 4)->data(Qt::UserRole + 2).toString();
} else {
path = m_pModel->item(index.row(), 0)->data(Qt::UserRole + 2).toString();
}

//显示当前日志目录
connect(act_openForder, &QAction::triggered, this, [ = ] {
m_act_openForder->disconnect();
connect(m_act_openForder, &QAction::triggered, this, [ = ] {
DDesktopServices::showFileItem(path);
});

//刷新逻辑
connect(act_refresh, &QAction::triggered, this, [ = ]() {
m_act_refresh->disconnect();
connect(m_act_refresh, &QAction::triggered, this, [ = ]() {
generateOOCFile(path);
});

m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
menu->exec(QCursor::pos());
m_menu->exec(QCursor::pos());
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions application/displaycontent.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,12 @@ public slots:
* @brief m_spinnerWgt_K 加载内核日志数据时转轮控件
*/
LogSpinnerWidget *m_spinnerWgt_K; // add by Airy

// 列表右键菜单
QMenu *m_menu{ nullptr };
QAction *m_act_openForder{ nullptr };
QAction *m_act_refresh{ nullptr };

/**
* @brief m_curAppLog 当前选中的应用的日志文件路径
*/
Expand Down
Loading

0 comments on commit 49152d8

Please sign in to comment.