Warning, file /libraries/libqaccessibilityclient/examples/accessibleapps/uiview.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2012 Sebastian Sauer <sebastian.sauer@kdab.com> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "uiview.h" 0008 0009 #include <QPainter> 0010 #include <QApplication> 0011 #include <QScreen> 0012 #include <QVBoxLayout> 0013 #include <QHBoxLayout> 0014 #include <QDebug> 0015 0016 using namespace QAccessibleClient; 0017 0018 struct RoleColor 0019 { 0020 AccessibleObject::Role m_role; 0021 const char *m_color; 0022 RoleColor(AccessibleObject::Role role, const char *color) : m_role(role), m_color(color) {} 0023 }; 0024 0025 static RoleColor roleColors[] = { 0026 { AccessibleObject::NoRole, "#ff0000" }, 0027 // { ATSPI_ROLE_ACCELERATOR_LABEL, "" }, 0028 // { ATSPI_ROLE_ALERT, "#ffacac" }, 0029 //// { ATSPI_ROLE_ANIMATION, "" }, 0030 //// { ATSPI_ROLE_ARROW, "" }, 0031 //// { ATSPI_ROLE_CALENDAR, "" }, 0032 //// { ATSPI_ROLE_CANVAS, "" }, 0033 { AccessibleObject::CheckBox, "#6666ff" }, 0034 { AccessibleObject::MenuItem, "#ff6666" }, 0035 // { ATSPI_ROLE_COLOR_CHOOSER, "#6666ff" }, 0036 //// { ATSPI_ROLE_COLUMN_HEADER, "" }, 0037 { AccessibleObject::ComboBox, "#6666ff" }, 0038 // { ATSPI_ROLE_DATE_EDITOR, "#6666ff" }, 0039 //// { ATSPI_ROLE_DESKTOP_ICON, "" }, 0040 { AccessibleObject::DesktopFrame, "#c0c0c0" }, 0041 { AccessibleObject::Dial, "#6666ff" }, 0042 { AccessibleObject::Dialog, "#c0c0c0" }, 0043 //// { ATSPI_ROLE_DIRECTORY_PANE, "" }, 0044 //// { ATSPI_ROLE_DRAWING_AREA, "" }, 0045 // { ATSPI_ROLE_FILE_CHOOSER, "#6666ff" }, 0046 //// { ATSPI_ROLE_FILLER, "" }, 0047 //// { ATSPI_ROLE_FOCUS_TRAVERSABLE, "" }, 0048 // { ATSPI_ROLE_FONT_CHOOSER, "#6666ff" }, 0049 { AccessibleObject::Frame, "#c0c0c0" }, 0050 //// { ATSPI_ROLE_GLASS_PANE, "" }, 0051 //// { ATSPI_ROLE_HTML_CONTAINER, "" }, 0052 //// { ATSPI_ROLE_ICON, "" }, 0053 //// { ATSPI_ROLE_IMAGE, "" }, 0054 // { ATSPI_ROLE_INTERNAL_FRAME, "#c0c0c0" }, 0055 // { ATSPI_ROLE_LABEL, "#ffffaa" }, 0056 //// { ATSPI_ROLE_LAYERED_PANE, "" }, 0057 { AccessibleObject::ListView, "#acacff" }, 0058 { AccessibleObject::ListItem, "#6666ff" }, 0059 { AccessibleObject::Menu, "#acacff" }, 0060 { AccessibleObject::MenuBar, "#acacff" }, 0061 { AccessibleObject::MenuItem, "#6666ff" }, 0062 //// { ATSPI_ROLE_OPTION_PANE, "" }, 0063 { AccessibleObject::Tab, "#acacff" }, 0064 { AccessibleObject::TabContainer, "#6666ff" }, 0065 // { AccessibleObject::Panel, "#c0c0c0" }, 0066 { AccessibleObject::PasswordText, "#ffffaa" }, 0067 { AccessibleObject::PopupMenu, "#acacff" }, 0068 //// { ATSPI_ROLE_PROGRESS_BAR, "" }, 0069 { AccessibleObject::Button, "#6666ff" }, 0070 { AccessibleObject::RadioButton, "#6666ff" }, 0071 { AccessibleObject::RadioMenuItem, "#6666ff" }, 0072 // { ATSPI_ROLE_ROOT_PANE, "#c0c0c0" }, 0073 //// { ATSPI_ROLE_ROW_HEADER, "" }, 0074 //// { ATSPI_ROLE_SCROLL_BAR, "" }, 0075 //// { ATSPI_ROLE_SCROLL_PANE, "" }, 0076 { AccessibleObject::Separator, "#acacff" }, 0077 { AccessibleObject::Slider, "#6666ff" }, 0078 { AccessibleObject::SpinButton, "#6666ff" }, 0079 //// { ATSPI_ROLE_SPLIT_PANE, "" }, 0080 { AccessibleObject::StatusBar, "#c0c0c0" }, 0081 { AccessibleObject::TableView, "#acacff" }, 0082 { AccessibleObject::TableCell, "#6666ff" }, 0083 { AccessibleObject::TableColumnHeader, "#3333ff" }, 0084 { AccessibleObject::TableRowHeader, "#3333ff" }, 0085 // { ATSPI_ROLE_TEAROFF_MENU_ITEM, "#6666ff" }, 0086 { AccessibleObject::Terminal, "#6666ff" }, 0087 { AccessibleObject::Text, "#ffffaa" }, 0088 { AccessibleObject::ToggleButton, "#6666ff" }, 0089 // { ATSPI_ROLE_TOOL_BAR, "" }, 0090 { AccessibleObject::ToolTip, "#ffffaa" }, 0091 { AccessibleObject::TreeView, "#acacff" }, 0092 // { ATSPI_ROLE_TREE_TABLE, "#acacff" }, 0093 // { ATSPI_ROLE_UNKNOWN, "" }, 0094 // { ATSPI_ROLE_VIEWPORT, "#c0c0c0" }, 0095 { AccessibleObject::Window, "#c0c0c0" }, 0096 // { ATSPI_ROLE_EXTENDED, "" }, 0097 // { ATSPI_ROLE_HEADER, "" }, 0098 // { ATSPI_ROLE_FOOTER, "" }, 0099 // { ATSPI_ROLE_PARAGRAPH, "#ffffaa" }, 0100 // { ATSPI_ROLE_RULER, "" }, 0101 // { ATSPI_ROLE_APPLICATION, "" }, 0102 // { ATSPI_ROLE_AUTOCOMPLETE, "" }, 0103 // { ATSPI_ROLE_EDITBAR, "#6666ff" }, 0104 // { ATSPI_ROLE_EMBEDDED, "" }, 0105 // { ATSPI_ROLE_ENTRY, "" }, 0106 // { ATSPI_ROLE_CHART, "" }, 0107 // { ATSPI_ROLE_CAPTION, "#ffffaa" }, 0108 // { ATSPI_ROLE_DOCUMENT_FRAME, "" }, 0109 // { ATSPI_ROLE_HEADING, "" }, 0110 // { ATSPI_ROLE_PAGE, "" }, 0111 // { ATSPI_ROLE_SECTION, "#ffffaa" }, 0112 // { ATSPI_ROLE_REDUNDANT_OBJECT, "" }, 0113 // { ATSPI_ROLE_FORM, "" }, 0114 // { ATSPI_ROLE_LINK, "#6666ff" }, 0115 // { ATSPI_ROLE_INPUT_METHOD_WINDOW, "" }, 0116 { AccessibleObject::TableRow, "#6666ff" }, 0117 { AccessibleObject::TableCell, "#6666ff" }, 0118 // { ATSPI_ROLE_DOCUMENT_SPREADSHEET, "" }, 0119 // { ATSPI_ROLE_DOCUMENT_PRESENTATION, "" }, 0120 // { ATSPI_ROLE_DOCUMENT_TEXT, "#ffffaa" }, 0121 // { ATSPI_ROLE_DOCUMENT_WEB, "#ffffaa" }, 0122 // { ATSPI_ROLE_DOCUMENT_EMAIL, "#ffffaa" }, 0123 // { ATSPI_ROLE_COMMENT, "#ffffaa" }, 0124 // { ATSPI_ROLE_LIST_BOX, "#6666ff" }, 0125 //// { ATSPI_ROLE_GROUPING, "" }, 0126 //// { ATSPI_ROLE_IMAGE_MAP, "" }, 0127 //// { ATSPI_ROLE_NOTIFICATION, "" }, 0128 // { ATSPI_ROLE_INFO_BAR, "#ffffaa" }, 0129 // { ATSPI_ROLE_LAST_DEFINED, "" } 0130 }; 0131 0132 #define ROLECOLORSCOUNT (sizeof(roleColors)/(sizeof(roleColors[0]))) 0133 #define ROLECOLOR "#aaffff" 0134 0135 UiWidget::UiWidget(UiView *view) 0136 : QWidget(view) 0137 , m_image(nullptr) 0138 { 0139 QPalette p = view->palette(); 0140 p.setColor(QPalette::Window, Qt::white); 0141 view->setPalette(p); 0142 view->setAutoFillBackground(true); 0143 0144 for(int i = 0; i < ROLECOLORSCOUNT; ++i) { 0145 RoleColor &rc = roleColors[i]; 0146 m_roleColors[rc.m_role] = rc.m_color; 0147 } 0148 } 0149 0150 void UiWidget::setAccessibleObject(const QAccessibleClient::AccessibleObject &acc) 0151 { 0152 delete m_image; m_image = nullptr; 0153 m_object = acc; 0154 m_screen = QPixmap(); 0155 m_bounds = bounds(acc); 0156 0157 adjustSize(); 0158 updateGeometry(); 0159 update(); 0160 } 0161 0162 QSize UiWidget::sizeHint() const 0163 { 0164 return m_bounds.size(); 0165 } 0166 0167 void UiWidget::paintEvent(QPaintEvent *event) 0168 { 0169 if (!m_image) { 0170 if (m_bounds.isNull()) 0171 return; 0172 m_image = new QImage(m_bounds.size(), QImage::Format_ARGB32_Premultiplied); 0173 QPainter painter(m_image); 0174 //painter.setClipRect(QRect(QPoint(0,0), QSize(m_bounds.size()))); 0175 0176 if (m_screen.isNull()) 0177 m_screen = grabScreen(); 0178 painter.setOpacity(0.6); 0179 painter.drawPixmap(0, 0, m_screen); 0180 painter.setOpacity(1.0); 0181 0182 drawObject(&painter, m_object); 0183 } 0184 QPainter painter(this); 0185 painter.drawImage(0, 0, *m_image); 0186 painter.end(); 0187 } 0188 0189 QPixmap UiWidget::grabScreen() 0190 { 0191 if (m_bounds.isNull()) 0192 return QPixmap(); 0193 Q_ASSERT(m_bounds.left() < m_bounds.right() && m_bounds.top() < m_bounds.bottom()); 0194 QPixmap pm = grab(QRect(m_bounds.x(), m_bounds.y(), m_bounds.width(), m_bounds.height())); 0195 return pm; 0196 } 0197 0198 QRect UiWidget::bounds(const QAccessibleClient::AccessibleObject &acc) const 0199 { 0200 if (!acc.isValid()) 0201 return QRect(); 0202 QRect rect; 0203 AccessibleObject::Interfaces ifaces = acc.supportedInterfaces(); 0204 if( !(ifaces & AccessibleObject::ApplicationInterface) ) { 0205 QAccessibleClient::AccessibleObject parent = acc.parent(); 0206 rect = bounds(parent); 0207 } 0208 if( ifaces & AccessibleObject::ComponentInterface ) { 0209 QRect r = acc.boundingRect(); 0210 if (!r.isNull()) 0211 rect = rect.isNull() ? r : rect.united(r); 0212 } 0213 return rect; 0214 } 0215 0216 void UiWidget::drawObject(QPainter *painter, const QAccessibleClient::AccessibleObject &acc, int depth) 0217 { 0218 if (!acc.isValid()) 0219 return; 0220 ++depth; 0221 AccessibleObject::Interfaces ifaces = acc.supportedInterfaces(); 0222 if( !(ifaces & AccessibleObject::ApplicationInterface) ) { 0223 QAccessibleClient::AccessibleObject parent = acc.parent(); 0224 drawObject(painter, parent, depth); 0225 } 0226 if( ifaces & AccessibleObject::ComponentInterface ) { 0227 QRect r = acc.boundingRect(); 0228 if (!r.isNull()) { 0229 r.moveTopLeft(r.topLeft() - m_bounds.topLeft()); 0230 0231 QColor color; 0232 QMap<AccessibleObject::Role, const char*>::ConstIterator colorIt = m_roleColors.constFind(acc.role()); 0233 if (colorIt != m_roleColors.constEnd()) { 0234 color = QColor(colorIt.value()); 0235 } else { 0236 color = QColor(ROLECOLOR); 0237 } 0238 color.setAlphaF(0.3); 0239 0240 painter->fillRect(r, color); 0241 if (depth == 1) { 0242 color = QColor(Qt::red); 0243 } else { 0244 color = color.darker(); 0245 } 0246 painter->setPen(color); 0247 painter->drawRect(r); 0248 } 0249 } 0250 } 0251 0252 UiView::UiView(QWidget *parent) 0253 : QScrollArea(parent) 0254 { 0255 QWidget *widget = new QWidget(this); 0256 QVBoxLayout *layout = new QVBoxLayout(widget); 0257 widget->setLayout(layout); 0258 0259 m_uiWidget = new UiWidget(this); 0260 layout->addWidget(m_uiWidget); 0261 0262 setWidget(widget); 0263 } 0264 0265 UiView::~UiView() 0266 { 0267 } 0268 0269 void UiView::setAccessibleObject(const QAccessibleClient::AccessibleObject &acc) 0270 { 0271 m_uiWidget->setAccessibleObject(acc); 0272 widget()->resize(m_uiWidget->size()); 0273 } 0274 0275 #include "moc_uiview.cpp"