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"