1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <QtAccessibleWidget.hxx>
22 #include <QtGui/QAccessibleInterface>
24 #include <QtAccessibleEventListener.hxx>
25 #include <QtAccessibleRegistry.hxx>
26 #include <QtFrame.hxx>
27 #include <QtTools.hxx>
28 #include <QtWidget.hxx>
29 #include <QtXAccessible.hxx>
31 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
32 #include <com/sun/star/accessibility/AccessibleRole.hpp>
33 #include <com/sun/star/accessibility/AccessibleScrollType.hpp>
34 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
35 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
36 #include <com/sun/star/accessibility/XAccessible.hpp>
37 #include <com/sun/star/accessibility/XAccessibleAction.hpp>
38 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
39 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
40 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
41 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
42 #include <com/sun/star/accessibility/XAccessibleKeyBinding.hpp>
43 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
44 #include <com/sun/star/accessibility/XAccessibleSelection.hpp>
45 #include <com/sun/star/accessibility/XAccessibleTable.hpp>
46 #include <com/sun/star/accessibility/XAccessibleTableSelection.hpp>
47 #include <com/sun/star/accessibility/XAccessibleText.hpp>
48 #include <com/sun/star/accessibility/XAccessibleValue.hpp>
49 #include <com/sun/star/awt/FontSlant.hpp>
50 #include <com/sun/star/awt/FontUnderline.hpp>
51 #include <com/sun/star/awt/FontWeight.hpp>
52 #include <com/sun/star/beans/PropertyValue.hpp>
53 #include <com/sun/star/lang/DisposedException.hpp>
54 #include <com/sun/star/uno/Sequence.hxx>
56 #include <comphelper/AccessibleImplementationHelper.hxx>
57 #include <o3tl/any.hxx>
58 #include <sal/log.hxx>
61 using namespace css::accessibility
;
62 using namespace css::beans
;
63 using namespace css::uno
;
65 QtAccessibleWidget::QtAccessibleWidget(const Reference
<XAccessible
> xAccessible
, QObject
* pObject
)
66 : m_xAccessible(xAccessible
)
69 Reference
<XAccessibleContext
> xContext
= xAccessible
->getAccessibleContext();
70 Reference
<XAccessibleEventBroadcaster
> xBroadcaster(xContext
, UNO_QUERY
);
71 if (xBroadcaster
.is())
73 Reference
<XAccessibleEventListener
> xListener(new QtAccessibleEventListener(this));
74 xBroadcaster
->addAccessibleEventListener(xListener
);
78 void QtAccessibleWidget::invalidate()
80 QtAccessibleRegistry::remove(m_xAccessible
);
81 m_xAccessible
.clear();
84 Reference
<XAccessibleContext
> QtAccessibleWidget::getAccessibleContextImpl() const
86 Reference
<XAccessibleContext
> xAc
;
88 if (m_xAccessible
.is())
92 xAc
= m_xAccessible
->getAccessibleContext();
94 catch (css::lang::DisposedException
/*ex*/)
96 SAL_WARN("vcl.qt", "Accessible context disposed already");
98 // sometimes getAccessibleContext throws also RuntimeException if context is no longer alive
99 catch (css::uno::RuntimeException
/*ex*/)
101 // so let's catch it here, cuz otherwise soffice falls flat on its face
102 // with FatalError and nothing else
103 SAL_WARN("vcl.qt", "Accessible context no longer alive");
110 css::uno::Reference
<css::accessibility::XAccessibleTable
>
111 QtAccessibleWidget::getAccessibleTableForParent() const
113 Reference
<XAccessibleContext
> xAcc
= getAccessibleContextImpl();
117 Reference
<XAccessible
> xParent
= xAcc
->getAccessibleParent();
121 Reference
<XAccessibleContext
> xParentContext
= xParent
->getAccessibleContext();
122 if (!xParentContext
.is())
125 return Reference
<XAccessibleTable
>(xParentContext
, UNO_QUERY
);
128 QWindow
* QtAccessibleWidget::window() const
131 if (m_pObject
->isWidgetType())
133 QWidget
* pWidget
= static_cast<QWidget
*>(m_pObject
);
134 QWidget
* pWindow
= pWidget
->window();
136 return pWindow
->windowHandle();
139 QAccessibleInterface
* pParent
= parent();
141 return pParent
->window();
146 int QtAccessibleWidget::childCount() const
148 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
152 sal_Int64 nChildCount
= xAc
->getAccessibleChildCount();
153 if (nChildCount
> std::numeric_limits
<int>::max())
155 SAL_WARN("vcl.qt", "QtAccessibleWidget::childCount: Child count exceeds maximum int value, "
156 "returning max int.");
157 nChildCount
= std::numeric_limits
<int>::max();
163 int QtAccessibleWidget::indexOfChild(const QAccessibleInterface
* pChild
) const
165 const QtAccessibleWidget
* pAccessibleWidget
= dynamic_cast<const QtAccessibleWidget
*>(pChild
);
166 if (!pAccessibleWidget
)
170 "QtAccessibleWidget::indexOfChild called with child that is no QtAccessibleWidget");
174 Reference
<XAccessibleContext
> xContext
= pAccessibleWidget
->getAccessibleContextImpl();
178 sal_Int64 nChildIndex
= xContext
->getAccessibleIndexInParent();
179 if (nChildIndex
> std::numeric_limits
<int>::max())
181 // use -2 when the child index is too large to fit into 32 bit to neither use the
182 // valid index of another child nor -1, which would e.g. make the Orca screen reader
183 // interpret the object as being a zombie
185 "QtAccessibleWidget::indexOfChild: Child index exceeds maximum int value, "
194 sal_Int16
lcl_matchQtTextBoundaryType(QAccessible::TextBoundaryType boundaryType
)
196 switch (boundaryType
)
198 case QAccessible::CharBoundary
:
199 return com::sun::star::accessibility::AccessibleTextType::CHARACTER
;
200 case QAccessible::WordBoundary
:
201 return com::sun::star::accessibility::AccessibleTextType::WORD
;
202 case QAccessible::SentenceBoundary
:
203 return com::sun::star::accessibility::AccessibleTextType::SENTENCE
;
204 case QAccessible::ParagraphBoundary
:
205 return com::sun::star::accessibility::AccessibleTextType::PARAGRAPH
;
206 case QAccessible::LineBoundary
:
207 return com::sun::star::accessibility::AccessibleTextType::LINE
;
208 case QAccessible::NoBoundary
:
209 // assert here, better handle it directly at call site
211 && "No match for QAccessible::NoBoundary, handle it separately at call site.");
217 SAL_WARN("vcl.qt", "Unmatched text boundary type: " << boundaryType
);
221 QAccessible::Relation
lcl_matchUnoRelation(short relationType
)
223 // Qt semantics is the other way around
224 switch (relationType
)
226 #if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
227 case AccessibleRelationType::CONTENT_FLOWS_FROM
:
228 return QAccessible::FlowsTo
;
229 case AccessibleRelationType::CONTENT_FLOWS_TO
:
230 return QAccessible::FlowsFrom
;
232 case AccessibleRelationType::CONTROLLED_BY
:
233 return QAccessible::Controller
;
234 case AccessibleRelationType::CONTROLLER_FOR
:
235 return QAccessible::Controlled
;
236 #if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
237 case AccessibleRelationType::DESCRIBED_BY
:
238 return QAccessible::DescriptionFor
;
240 case AccessibleRelationType::LABELED_BY
:
241 return QAccessible::Label
;
242 case AccessibleRelationType::LABEL_FOR
:
243 return QAccessible::Labelled
;
244 case AccessibleRelationType::INVALID
:
245 case AccessibleRelationType::MEMBER_OF
:
246 case AccessibleRelationType::SUB_WINDOW_OF
:
247 case AccessibleRelationType::NODE_CHILD_OF
:
249 SAL_WARN("vcl.qt", "Unmatched relation: " << relationType
);
254 void lcl_appendRelation(QVector
<QPair
<QAccessibleInterface
*, QAccessible::Relation
>>* relations
,
255 AccessibleRelation aRelation
, QAccessible::Relation match
)
257 QAccessible::Relation aQRelation
= lcl_matchUnoRelation(aRelation
.RelationType
);
258 // skip in case there's no Qt relation matching the filter
259 if (!(aQRelation
& match
))
262 sal_uInt32 nTargetCount
= aRelation
.TargetSet
.getLength();
264 for (sal_uInt32 i
= 0; i
< nTargetCount
; i
++)
266 Reference
<XAccessible
> xAccessible(aRelation
.TargetSet
[i
], uno::UNO_QUERY
);
268 { QAccessible::queryAccessibleInterface(QtAccessibleRegistry::getQObject(xAccessible
)),
274 QVector
<QPair
<QAccessibleInterface
*, QAccessible::Relation
>>
275 QtAccessibleWidget::relations(QAccessible::Relation match
) const
277 QVector
<QPair
<QAccessibleInterface
*, QAccessible::Relation
>> relations
;
279 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
283 Reference
<XAccessibleRelationSet
> xRelationSet
= xAc
->getAccessibleRelationSet();
284 if (xRelationSet
.is())
286 int count
= xRelationSet
->getRelationCount();
287 for (int i
= 0; i
< count
; i
++)
289 AccessibleRelation aRelation
= xRelationSet
->getRelation(i
);
290 lcl_appendRelation(&relations
, aRelation
, match
);
297 QAccessibleInterface
* QtAccessibleWidget::focusChild() const
299 /* if (m_pWindow->HasChildPathFocus())
300 return QAccessible::queryAccessibleInterface(
301 new QtXAccessible(m_xAccessible->getAccessibleContext()->getAccessibleChild(index))); */
302 return QAccessible::queryAccessibleInterface(object());
305 QRect
QtAccessibleWidget::rect() const
307 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
311 Reference
<XAccessibleComponent
> xAccessibleComponent(xAc
, UNO_QUERY
);
312 awt::Point aPoint
= xAccessibleComponent
->getLocationOnScreen();
313 awt::Size aSize
= xAccessibleComponent
->getSize();
315 return QRect(aPoint
.X
, aPoint
.Y
, aSize
.Width
, aSize
.Height
);
318 QAccessibleInterface
* QtAccessibleWidget::parent() const
320 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
324 if (xAc
->getAccessibleParent().is())
325 return QAccessible::queryAccessibleInterface(
326 QtAccessibleRegistry::getQObject(xAc
->getAccessibleParent()));
328 // go via the QObject hierarchy; some a11y objects like the application
329 // (at the root of the a11y hierarchy) are handled solely by Qt and have
330 // no LO-internal a11y objects associated with them
331 QObject
* pObj
= object();
332 if (pObj
&& pObj
->parent())
333 return QAccessible::queryAccessibleInterface(pObj
->parent());
338 QAccessibleInterface
* QtAccessibleWidget::child(int index
) const
340 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
343 return QAccessible::queryAccessibleInterface(
344 QtAccessibleRegistry::getQObject(xAc
->getAccessibleChild(index
)));
347 QString
QtAccessibleWidget::text(QAccessible::Text text
) const
349 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
355 case QAccessible::Name
:
356 return toQString(xAc
->getAccessibleName());
357 case QAccessible::Description
:
358 case QAccessible::DebugDescription
:
359 return toQString(xAc
->getAccessibleDescription());
360 case QAccessible::Value
:
361 case QAccessible::Help
:
362 case QAccessible::Accelerator
:
363 case QAccessible::UserText
:
365 return QString("Unknown");
368 QAccessible::Role
QtAccessibleWidget::role() const
370 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
372 return QAccessible::NoRole
;
374 switch (xAc
->getAccessibleRole())
376 case AccessibleRole::UNKNOWN
:
377 return QAccessible::NoRole
;
378 case AccessibleRole::ALERT
:
379 return QAccessible::AlertMessage
;
380 case AccessibleRole::COLUMN_HEADER
:
381 return QAccessible::ColumnHeader
;
382 case AccessibleRole::CANVAS
:
383 return QAccessible::Canvas
;
384 case AccessibleRole::CHECK_BOX
:
385 return QAccessible::CheckBox
;
386 case AccessibleRole::CHECK_MENU_ITEM
:
387 return QAccessible::MenuItem
;
388 case AccessibleRole::COLOR_CHOOSER
:
389 return QAccessible::ColorChooser
;
390 case AccessibleRole::COMBO_BOX
:
391 return QAccessible::ComboBox
;
392 case AccessibleRole::DATE_EDITOR
:
393 return QAccessible::EditableText
;
394 case AccessibleRole::DESKTOP_ICON
:
395 return QAccessible::Graphic
;
396 case AccessibleRole::DESKTOP_PANE
:
397 case AccessibleRole::DIRECTORY_PANE
:
398 return QAccessible::Pane
;
399 case AccessibleRole::DIALOG
:
400 return QAccessible::Dialog
;
401 case AccessibleRole::DOCUMENT
:
402 return QAccessible::Document
;
403 case AccessibleRole::EMBEDDED_OBJECT
:
404 return QAccessible::UserRole
;
405 case AccessibleRole::END_NOTE
:
406 return QAccessible::Note
;
407 case AccessibleRole::FILE_CHOOSER
:
408 return QAccessible::Dialog
;
409 case AccessibleRole::FILLER
:
410 return QAccessible::Whitespace
;
411 case AccessibleRole::FONT_CHOOSER
:
412 return QAccessible::UserRole
;
413 case AccessibleRole::FOOTER
:
414 return QAccessible::Footer
;
415 case AccessibleRole::FOOTNOTE
:
416 return QAccessible::Note
;
417 case AccessibleRole::FRAME
: // top-level window with title bar
418 return QAccessible::Window
;
419 case AccessibleRole::GLASS_PANE
:
420 return QAccessible::UserRole
;
421 case AccessibleRole::GRAPHIC
:
422 return QAccessible::Graphic
;
423 case AccessibleRole::GROUP_BOX
:
424 return QAccessible::Grouping
;
425 case AccessibleRole::HEADER
:
426 return QAccessible::UserRole
;
427 case AccessibleRole::HEADING
:
428 return QAccessible::Heading
;
429 case AccessibleRole::HYPER_LINK
:
430 return QAccessible::Link
;
431 case AccessibleRole::ICON
:
432 return QAccessible::Graphic
;
433 case AccessibleRole::INTERNAL_FRAME
:
434 return QAccessible::UserRole
;
435 case AccessibleRole::LABEL
:
436 return QAccessible::StaticText
;
437 case AccessibleRole::LAYERED_PANE
:
438 return QAccessible::Pane
;
439 case AccessibleRole::LIST
:
440 return QAccessible::List
;
441 case AccessibleRole::LIST_ITEM
:
442 return QAccessible::ListItem
;
443 case AccessibleRole::MENU
:
444 case AccessibleRole::MENU_BAR
:
445 return QAccessible::MenuBar
;
446 case AccessibleRole::MENU_ITEM
:
447 return QAccessible::MenuItem
;
448 case AccessibleRole::NOTIFICATION
:
449 #if QT_VERSION >= QT_VERSION_CHECK(5, 12, 5)
450 return QAccessible::Notification
;
452 return QAccessible::StaticText
;
454 case AccessibleRole::OPTION_PANE
:
455 return QAccessible::Pane
;
456 case AccessibleRole::PAGE_TAB
:
457 return QAccessible::PageTab
;
458 case AccessibleRole::PAGE_TAB_LIST
:
459 return QAccessible::PageTabList
;
460 case AccessibleRole::PANEL
:
461 return QAccessible::Pane
;
462 case AccessibleRole::PARAGRAPH
:
463 return QAccessible::Paragraph
;
464 case AccessibleRole::PASSWORD_TEXT
:
465 return QAccessible::EditableText
;
466 case AccessibleRole::POPUP_MENU
:
467 return QAccessible::PopupMenu
;
468 case AccessibleRole::PUSH_BUTTON
:
469 return QAccessible::Button
;
470 case AccessibleRole::PROGRESS_BAR
:
471 return QAccessible::ProgressBar
;
472 case AccessibleRole::RADIO_BUTTON
:
473 return QAccessible::RadioButton
;
474 case AccessibleRole::RADIO_MENU_ITEM
:
475 return QAccessible::MenuItem
;
476 case AccessibleRole::ROW_HEADER
:
477 return QAccessible::RowHeader
;
478 case AccessibleRole::ROOT_PANE
:
479 return QAccessible::Pane
;
480 case AccessibleRole::SCROLL_BAR
:
481 return QAccessible::ScrollBar
;
482 case AccessibleRole::SCROLL_PANE
:
483 return QAccessible::Pane
;
484 case AccessibleRole::SHAPE
:
485 return QAccessible::Graphic
;
486 case AccessibleRole::SEPARATOR
:
487 return QAccessible::Separator
;
488 case AccessibleRole::SLIDER
:
489 return QAccessible::Slider
;
490 case AccessibleRole::SPIN_BOX
:
491 return QAccessible::SpinBox
;
492 case AccessibleRole::SPLIT_PANE
:
493 return QAccessible::Pane
;
494 case AccessibleRole::STATUS_BAR
:
495 return QAccessible::StatusBar
;
496 case AccessibleRole::TABLE
:
497 return QAccessible::Table
;
498 case AccessibleRole::TABLE_CELL
:
499 return QAccessible::Cell
;
500 case AccessibleRole::TEXT
:
501 return QAccessible::EditableText
;
502 case AccessibleRole::TEXT_FRAME
:
503 return QAccessible::UserRole
;
504 case AccessibleRole::TOGGLE_BUTTON
:
505 return QAccessible::Button
;
506 case AccessibleRole::TOOL_BAR
:
507 return QAccessible::ToolBar
;
508 case AccessibleRole::TOOL_TIP
:
509 return QAccessible::ToolTip
;
510 case AccessibleRole::TREE
:
511 return QAccessible::Tree
;
512 case AccessibleRole::VIEW_PORT
:
513 return QAccessible::UserRole
;
514 case AccessibleRole::BUTTON_DROPDOWN
:
515 return QAccessible::ButtonDropDown
;
516 case AccessibleRole::BUTTON_MENU
:
517 return QAccessible::ButtonMenu
;
518 case AccessibleRole::CAPTION
:
519 return QAccessible::StaticText
;
520 case AccessibleRole::CHART
:
521 return QAccessible::Chart
;
522 case AccessibleRole::EDIT_BAR
:
523 return QAccessible::Equation
;
524 case AccessibleRole::FORM
:
525 return QAccessible::Form
;
526 case AccessibleRole::IMAGE_MAP
:
527 return QAccessible::Graphic
;
528 case AccessibleRole::NOTE
:
529 return QAccessible::Note
;
530 case AccessibleRole::RULER
:
531 return QAccessible::UserRole
;
532 case AccessibleRole::SECTION
:
533 return QAccessible::Section
;
534 case AccessibleRole::TREE_ITEM
:
535 return QAccessible::TreeItem
;
536 case AccessibleRole::TREE_TABLE
:
537 return QAccessible::Tree
;
538 case AccessibleRole::COMMENT
:
539 return QAccessible::Note
;
540 case AccessibleRole::COMMENT_END
:
541 return QAccessible::UserRole
;
542 case AccessibleRole::DOCUMENT_PRESENTATION
:
543 return QAccessible::Document
;
544 case AccessibleRole::DOCUMENT_SPREADSHEET
:
545 return QAccessible::Document
;
546 case AccessibleRole::DOCUMENT_TEXT
:
547 return QAccessible::Document
;
548 case AccessibleRole::STATIC
:
549 return QAccessible::StaticText
;
550 case AccessibleRole::WINDOW
: // top-level window without title bar
551 return QAccessible::Window
;
554 SAL_WARN("vcl.qt", "Unmapped role: " << getAccessibleContextImpl()->getAccessibleRole());
555 return QAccessible::NoRole
;
560 void lcl_addState(QAccessible::State
* state
, sal_Int64 nState
)
564 case AccessibleStateType::INVALID
:
565 state
->invalid
= true;
567 case AccessibleStateType::ACTIVE
:
568 state
->active
= true;
570 case AccessibleStateType::ARMED
:
573 case AccessibleStateType::BUSY
:
576 case AccessibleStateType::CHECKED
:
577 state
->checked
= true;
579 case AccessibleStateType::EDITABLE
:
580 state
->editable
= true;
582 case AccessibleStateType::ENABLED
:
583 state
->disabled
= false;
585 case AccessibleStateType::EXPANDABLE
:
586 state
->expandable
= true;
588 case AccessibleStateType::EXPANDED
:
589 state
->expanded
= true;
591 case AccessibleStateType::FOCUSABLE
:
592 state
->focusable
= true;
594 case AccessibleStateType::FOCUSED
:
595 state
->focused
= true;
597 case AccessibleStateType::HORIZONTAL
:
600 case AccessibleStateType::ICONIFIED
:
603 case AccessibleStateType::INDETERMINATE
:
606 case AccessibleStateType::MANAGES_DESCENDANTS
:
609 case AccessibleStateType::MODAL
:
612 case AccessibleStateType::MOVEABLE
:
613 state
->movable
= true;
615 case AccessibleStateType::MULTI_LINE
:
616 state
->multiLine
= true;
618 case AccessibleStateType::OPAQUE
:
621 case AccessibleStateType::PRESSED
:
622 state
->pressed
= true;
624 case AccessibleStateType::RESIZABLE
:
625 state
->sizeable
= true;
627 case AccessibleStateType::SELECTABLE
:
628 state
->selectable
= true;
630 case AccessibleStateType::SELECTED
:
631 state
->selected
= true;
633 case AccessibleStateType::SENSITIVE
:
636 case AccessibleStateType::SHOWING
:
639 case AccessibleStateType::SINGLE_LINE
:
642 case AccessibleStateType::STALE
:
645 case AccessibleStateType::TRANSIENT
:
648 case AccessibleStateType::VERTICAL
:
651 case AccessibleStateType::VISIBLE
:
652 state
->invisible
= false;
654 case AccessibleStateType::DEFAULT
:
657 case AccessibleStateType::DEFUNC
:
658 state
->invalid
= true;
660 case AccessibleStateType::MULTI_SELECTABLE
:
661 state
->multiSelectable
= true;
664 SAL_WARN("vcl.qt", "Unmapped state: " << nState
);
670 QAccessible::State
QtAccessibleWidget::state() const
672 QAccessible::State state
;
674 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
678 sal_Int64
nStateSet(xAc
->getAccessibleStateSet());
680 for (int i
= 0; i
< 63; ++i
)
682 sal_Int64 nState
= sal_Int64(1) << i
;
683 if (nStateSet
& nState
)
684 lcl_addState(&state
, nState
);
690 QColor
QtAccessibleWidget::foregroundColor() const
692 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
696 Reference
<XAccessibleComponent
> xAccessibleComponent(xAc
, UNO_QUERY
);
697 return toQColor(Color(ColorTransparency
, xAccessibleComponent
->getForeground()));
700 QColor
QtAccessibleWidget::backgroundColor() const
702 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
706 Reference
<XAccessibleComponent
> xAccessibleComponent(xAc
, UNO_QUERY
);
707 return toQColor(Color(ColorTransparency
, xAccessibleComponent
->getBackground()));
710 void* QtAccessibleWidget::interface_cast(QAccessible::InterfaceType t
)
712 if (t
== QAccessible::ActionInterface
&& accessibleProvidesInterface
<XAccessibleAction
>())
713 return static_cast<QAccessibleActionInterface
*>(this);
714 if (t
== QAccessible::TextInterface
&& accessibleProvidesInterface
<XAccessibleText
>())
715 return static_cast<QAccessibleTextInterface
*>(this);
716 if (t
== QAccessible::EditableTextInterface
717 && accessibleProvidesInterface
<XAccessibleEditableText
>())
718 return static_cast<QAccessibleEditableTextInterface
*>(this);
719 if (t
== QAccessible::ValueInterface
&& accessibleProvidesInterface
<XAccessibleValue
>())
720 return static_cast<QAccessibleValueInterface
*>(this);
721 if (t
== QAccessible::TableCellInterface
)
723 // parent must be a table
724 Reference
<XAccessibleTable
> xTable
= getAccessibleTableForParent();
726 return static_cast<QAccessibleTableCellInterface
*>(this);
728 if (t
== QAccessible::TableInterface
&& accessibleProvidesInterface
<XAccessibleTable
>())
729 return static_cast<QAccessibleTableInterface
*>(this);
730 #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
731 if (t
== QAccessible::SelectionInterface
&& accessibleProvidesInterface
<XAccessibleSelection
>())
732 return static_cast<QAccessibleSelectionInterface
*>(this);
737 bool QtAccessibleWidget::isValid() const
739 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
743 QObject
* QtAccessibleWidget::object() const { return m_pObject
; }
745 void QtAccessibleWidget::setText(QAccessible::Text
/* t */, const QString
& /* text */) {}
747 QAccessibleInterface
* QtAccessibleWidget::childAt(int x
, int y
) const
749 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
753 Reference
<XAccessibleComponent
> xAccessibleComponent(xAc
, UNO_QUERY
);
754 // convert from screen to local coordinates
755 QPoint aLocalCoords
= QPoint(x
, y
) - rect().topLeft();
756 return QAccessible::queryAccessibleInterface(
757 QtAccessibleRegistry::getQObject(xAccessibleComponent
->getAccessibleAtPoint(
758 awt::Point(aLocalCoords
.x(), aLocalCoords
.y()))));
761 QAccessibleInterface
* QtAccessibleWidget::customFactory(const QString
& classname
, QObject
* object
)
763 if (classname
== QLatin1String("QtWidget") && object
&& object
->isWidgetType())
765 QtWidget
* pWidget
= static_cast<QtWidget
*>(object
);
766 vcl::Window
* pWindow
= pWidget
->frame().GetWindow();
770 css::uno::Reference
<XAccessible
> xAcc
= pWindow
->GetAccessible();
771 // insert into registry so the association between the XAccessible and the QtWidget
772 // is remembered rather than creating a different QtXAccessible when a QObject is needed later
773 QtAccessibleRegistry::insert(xAcc
, object
);
774 return new QtAccessibleWidget(xAcc
, object
);
777 if (classname
== QLatin1String("QtXAccessible") && object
)
779 QtXAccessible
* pXAccessible
= static_cast<QtXAccessible
*>(object
);
780 if (pXAccessible
->m_xAccessible
.is())
782 QtAccessibleWidget
* pRet
= new QtAccessibleWidget(pXAccessible
->m_xAccessible
, object
);
783 // clear the reference in the QtXAccessible, no longer needed now that the QtAccessibleWidget holds one
784 pXAccessible
->m_xAccessible
.clear();
792 // QAccessibleActionInterface
793 QStringList
QtAccessibleWidget::actionNames() const
795 QStringList actionNames
;
796 Reference
<XAccessibleAction
> xAccessibleAction(getAccessibleContextImpl(), UNO_QUERY
);
797 if (!xAccessibleAction
.is())
800 int count
= xAccessibleAction
->getAccessibleActionCount();
801 for (int i
= 0; i
< count
; i
++)
803 OUString desc
= xAccessibleAction
->getAccessibleActionDescription(i
);
804 actionNames
.append(toQString(desc
));
809 void QtAccessibleWidget::doAction(const QString
& actionName
)
811 Reference
<XAccessibleAction
> xAccessibleAction(getAccessibleContextImpl(), UNO_QUERY
);
812 if (!xAccessibleAction
.is())
815 int index
= actionNames().indexOf(actionName
);
818 xAccessibleAction
->doAccessibleAction(index
);
821 QStringList
QtAccessibleWidget::keyBindingsForAction(const QString
& actionName
) const
823 QStringList keyBindings
;
824 Reference
<XAccessibleAction
> xAccessibleAction(getAccessibleContextImpl(), UNO_QUERY
);
825 if (!xAccessibleAction
.is())
828 int index
= actionNames().indexOf(actionName
);
832 Reference
<XAccessibleKeyBinding
> xKeyBinding
833 = xAccessibleAction
->getAccessibleActionKeyBinding(index
);
835 if (!xKeyBinding
.is())
838 int count
= xKeyBinding
->getAccessibleKeyBindingCount();
839 for (int i
= 0; i
< count
; i
++)
841 Sequence
<awt::KeyStroke
> keyStroke
= xKeyBinding
->getAccessibleKeyBinding(i
);
842 keyBindings
.append(toQString(comphelper::GetkeyBindingStrByXkeyBinding(keyStroke
)));
847 // QAccessibleTextInterface
848 void QtAccessibleWidget::addSelection(int /* startOffset */, int /* endOffset */)
850 SAL_INFO("vcl.qt", "Unsupported QAccessibleTextInterface::addSelection");
855 OUString
lcl_convertFontWeight(double fontWeight
)
857 if (fontWeight
== awt::FontWeight::THIN
|| fontWeight
== awt::FontWeight::ULTRALIGHT
)
859 if (fontWeight
== awt::FontWeight::LIGHT
)
861 if (fontWeight
== awt::FontWeight::SEMILIGHT
)
863 if (fontWeight
== awt::FontWeight::NORMAL
)
865 if (fontWeight
== awt::FontWeight::SEMIBOLD
)
867 if (fontWeight
== awt::FontWeight::BOLD
)
869 if (fontWeight
== awt::FontWeight::ULTRABOLD
)
871 if (fontWeight
== awt::FontWeight::BLACK
)
874 // awt::FontWeight::DONTKNOW || fontWeight == awt::FontWeight::NORMAL
878 OUString
lcl_ConvertFontSlant(awt::FontSlant eFontSlant
)
882 case awt::FontSlant::FontSlant_NONE
:
884 case awt::FontSlant::FontSlant_OBLIQUE
:
885 case awt::FontSlant::FontSlant_REVERSE_OBLIQUE
:
887 case awt::FontSlant::FontSlant_ITALIC
:
888 case awt::FontSlant::FontSlant_REVERSE_ITALIC
:
890 case awt::FontSlant::FontSlant_DONTKNOW
:
891 case awt::FontSlant::FontSlant_MAKE_FIXED_SIZE
:
897 // s. https://wiki.linuxfoundation.org/accessibility/iaccessible2/textattributes
899 void lcl_ConvertFontUnderline(sal_Int16 nFontUnderline
, OUString
& rUnderlineStyle
,
900 OUString
& rUnderlineType
, OUString
& rUnderlineWidth
)
902 rUnderlineStyle
= u
"";
903 rUnderlineType
= u
"single";
904 rUnderlineWidth
= u
"auto";
906 switch (nFontUnderline
)
908 case awt::FontUnderline::BOLD
:
909 rUnderlineWidth
= u
"bold";
911 case awt::FontUnderline::BOLDDASH
:
912 rUnderlineWidth
= u
"bold";
913 rUnderlineStyle
= u
"dash";
915 case awt::FontUnderline::BOLDDASHDOT
:
916 rUnderlineWidth
= u
"bold";
917 rUnderlineStyle
= u
"dot-dash";
919 case awt::FontUnderline::BOLDDASHDOTDOT
:
920 rUnderlineWidth
= u
"bold";
921 rUnderlineStyle
= u
"dot-dot-dash";
923 case awt::FontUnderline::BOLDDOTTED
:
924 rUnderlineWidth
= u
"bold";
925 rUnderlineStyle
= u
"dotted";
927 case awt::FontUnderline::BOLDLONGDASH
:
928 rUnderlineWidth
= u
"bold";
929 rUnderlineStyle
= u
"long-dash";
931 case awt::FontUnderline::BOLDWAVE
:
932 rUnderlineWidth
= u
"bold";
933 rUnderlineStyle
= u
"wave";
935 case awt::FontUnderline::DASH
:
936 rUnderlineStyle
= u
"dash";
938 case awt::FontUnderline::DASHDOT
:
939 rUnderlineStyle
= u
"dot-dash";
941 case awt::FontUnderline::DASHDOTDOT
:
942 rUnderlineStyle
= u
"dot-dot-dash";
944 case awt::FontUnderline::DONTKNOW
:
945 rUnderlineWidth
= u
"";
946 rUnderlineStyle
= u
"";
947 rUnderlineType
= u
"";
949 case awt::FontUnderline::DOTTED
:
950 rUnderlineStyle
= u
"dotted";
952 case awt::FontUnderline::DOUBLE
:
953 rUnderlineType
= u
"double";
955 case awt::FontUnderline::DOUBLEWAVE
:
956 rUnderlineStyle
= u
"wave";
957 rUnderlineType
= u
"double";
959 case awt::FontUnderline::LONGDASH
:
960 rUnderlineStyle
= u
"long-dash";
962 case awt::FontUnderline::NONE
:
963 rUnderlineWidth
= u
"none";
964 rUnderlineStyle
= u
"none";
965 rUnderlineType
= u
"none";
967 case awt::FontUnderline::SINGLE
:
968 rUnderlineType
= u
"single";
970 case awt::FontUnderline::SMALLWAVE
:
971 case awt::FontUnderline::WAVE
:
972 rUnderlineStyle
= u
"wave";
975 assert(false && "Unhandled font underline type");
979 /** Converts Color to "rgb(r,g,b)" as specified in https://wiki.linuxfoundation.org/accessibility/iaccessible2/textattributes. */
980 OUString
lcl_ConvertColor(Color aColor
)
982 return u
"rgb(" + OUString::number(aColor
.GetRed()) + u
"," + OUString::number(aColor
.GetGreen())
983 + u
"," + OUString::number(aColor
.GetBlue()) + u
")";
987 // Text attributes are returned in format specified in IAccessible2 spec, since that
988 // is what Qt handles:
989 // https://wiki.linuxfoundation.org/accessibility/iaccessible2/textattributes
990 QString
QtAccessibleWidget::attributes(int offset
, int* startOffset
, int* endOffset
) const
992 if (startOffset
== nullptr || endOffset
== nullptr)
998 Reference
<XAccessibleText
> xText(getAccessibleContextImpl(), UNO_QUERY
);
1002 // handle special values for offset the same way base class's QAccessibleTextWidget::attributes does
1003 // (as defined in IAccessible 2: -1 -> length, -2 -> cursor position)
1005 offset
= cursorPosition();
1007 const int nTextLength
= characterCount();
1008 if (offset
== -1 || offset
== nTextLength
)
1009 offset
= nTextLength
- 1;
1011 if (offset
< 0 || offset
> nTextLength
)
1013 SAL_WARN("vcl.qt", "QtAccessibleWidget::attributes called with invalid offset: " << offset
);
1017 const Sequence
<PropertyValue
> attribs
1018 = xText
->getCharacterAttributes(offset
, Sequence
<OUString
>());
1020 for (PropertyValue
const& prop
: attribs
)
1022 OUString sAttribute
;
1024 if (prop
.Name
== "CharBackColor")
1026 sAttribute
= "background-color";
1027 sValue
= lcl_ConvertColor(
1028 Color(ColorTransparency
, *o3tl::doAccess
<sal_Int32
>(prop
.Value
)));
1030 else if (prop
.Name
== "CharColor")
1032 sAttribute
= "color";
1033 sValue
= lcl_ConvertColor(
1034 Color(ColorTransparency
, *o3tl::doAccess
<sal_Int32
>(prop
.Value
)));
1036 else if (prop
.Name
== "CharFontName")
1038 sAttribute
= "font-family";
1039 sValue
= *o3tl::doAccess
<OUString
>(prop
.Value
);
1041 else if (prop
.Name
== "CharHeight")
1043 sAttribute
= "font-size";
1044 sValue
= OUString::number(*o3tl::doAccess
<double>(prop
.Value
)) + "pt";
1046 else if (prop
.Name
== "CharPosture")
1048 sAttribute
= "font-style";
1049 const awt::FontSlant eFontSlant
= *o3tl::doAccess
<awt::FontSlant
>(prop
.Value
);
1050 sValue
= lcl_ConvertFontSlant(eFontSlant
);
1052 else if (prop
.Name
== "CharUnderline")
1054 OUString sUnderlineStyle
;
1055 OUString sUnderlineType
;
1056 OUString sUnderlineWidth
;
1057 const sal_Int16 nUnderline
= *o3tl::doAccess
<sal_Int16
>(prop
.Value
);
1058 lcl_ConvertFontUnderline(nUnderline
, sUnderlineStyle
, sUnderlineType
, sUnderlineWidth
);
1060 // leave 'sAttribute' and 'sName' empty, set all attributes here
1061 if (!sUnderlineStyle
.isEmpty())
1062 aRet
+= u
"text-underline-style:" + sUnderlineStyle
+ ";";
1063 if (!sUnderlineType
.isEmpty())
1064 aRet
+= u
"text-underline-type:" + sUnderlineType
+ ";";
1065 if (!sUnderlineWidth
.isEmpty())
1066 aRet
+= u
"text-underline-width:" + sUnderlineWidth
+ ";";
1068 else if (prop
.Name
== "CharWeight")
1070 sAttribute
= "font-weight";
1071 sValue
= lcl_convertFontWeight(*o3tl::doAccess
<double>(prop
.Value
));
1074 if (!sAttribute
.isEmpty() && !sValue
.isEmpty())
1075 aRet
+= sAttribute
+ ":" + sValue
+ ";";
1078 accessibility::TextSegment aAttributeRun
1079 = xText
->getTextAtIndex(offset
, accessibility::AccessibleTextType::ATTRIBUTE_RUN
);
1080 *startOffset
= aAttributeRun
.SegmentStart
;
1081 *endOffset
= aAttributeRun
.SegmentEnd
;
1082 return toQString(aRet
);
1085 int QtAccessibleWidget::characterCount() const
1087 Reference
<XAccessibleText
> xText(getAccessibleContextImpl(), UNO_QUERY
);
1089 return xText
->getCharacterCount();
1093 QRect
QtAccessibleWidget::characterRect(int nOffset
) const
1095 Reference
<XAccessibleText
> xText(getAccessibleContextImpl(), UNO_QUERY
);
1099 if (nOffset
< 0 || nOffset
> xText
->getCharacterCount())
1102 "QtAccessibleWidget::characterRect called with invalid offset: " << nOffset
);
1106 const awt::Rectangle aBounds
= xText
->getCharacterBounds(nOffset
);
1107 const QRect
aRect(aBounds
.X
, aBounds
.Y
, aBounds
.Width
, aBounds
.Height
);
1108 // convert to screen coordinates
1109 const QRect aScreenPos
= rect();
1110 return aRect
.translated(aScreenPos
.x(), aScreenPos
.y());
1113 int QtAccessibleWidget::cursorPosition() const
1115 Reference
<XAccessibleText
> xText(getAccessibleContextImpl(), UNO_QUERY
);
1117 return xText
->getCaretPosition();
1121 int QtAccessibleWidget::offsetAtPoint(const QPoint
& rPoint
) const
1123 Reference
<XAccessibleText
> xText(getAccessibleContextImpl(), UNO_QUERY
);
1127 // convert from screen to local coordinates
1128 QPoint aLocalCoords
= rPoint
- rect().topLeft();
1129 awt::Point
aPoint(aLocalCoords
.x(), aLocalCoords
.y());
1130 return xText
->getIndexAtPoint(aPoint
);
1133 void QtAccessibleWidget::removeSelection(int /* selectionIndex */)
1135 SAL_INFO("vcl.qt", "Unsupported QAccessibleTextInterface::removeSelection");
1138 void QtAccessibleWidget::scrollToSubstring(int startIndex
, int endIndex
)
1140 Reference
<XAccessibleText
> xText(getAccessibleContextImpl(), UNO_QUERY
);
1144 sal_Int32 nTextLength
= xText
->getCharacterCount();
1145 if (startIndex
< 0 || startIndex
> nTextLength
|| endIndex
< 0 || endIndex
> nTextLength
)
1147 SAL_WARN("vcl.qt", "QtAccessibleWidget::scrollToSubstring called with invalid offset.");
1151 xText
->scrollSubstringTo(startIndex
, endIndex
, AccessibleScrollType_SCROLL_ANYWHERE
);
1154 void QtAccessibleWidget::selection(int selectionIndex
, int* startOffset
, int* endOffset
) const
1156 if (!startOffset
&& !endOffset
)
1159 Reference
<XAccessibleText
> xText
;
1160 if (selectionIndex
== 0)
1161 xText
= Reference
<XAccessibleText
>(getAccessibleContextImpl(), UNO_QUERY
);
1164 *startOffset
= xText
.is() ? xText
->getSelectionStart() : 0;
1166 *endOffset
= xText
.is() ? xText
->getSelectionEnd() : 0;
1169 int QtAccessibleWidget::selectionCount() const
1171 Reference
<XAccessibleText
> xText(getAccessibleContextImpl(), UNO_QUERY
);
1172 if (xText
.is() && !xText
->getSelectedText().isEmpty())
1173 return 1; // Only 1 selection supported atm
1177 void QtAccessibleWidget::setCursorPosition(int position
)
1179 Reference
<XAccessibleText
> xText(getAccessibleContextImpl(), UNO_QUERY
);
1183 if (position
< 0 || position
> xText
->getCharacterCount())
1186 "QtAccessibleWidget::setCursorPosition called with invalid offset: " << position
);
1190 xText
->setCaretPosition(position
);
1193 void QtAccessibleWidget::setSelection(int /* selectionIndex */, int startOffset
, int endOffset
)
1195 Reference
<XAccessibleText
> xText(getAccessibleContextImpl(), UNO_QUERY
);
1199 sal_Int32 nTextLength
= xText
->getCharacterCount();
1200 if (startOffset
< 0 || startOffset
> nTextLength
|| endOffset
< 0 || endOffset
> nTextLength
)
1202 SAL_WARN("vcl.qt", "QtAccessibleWidget::setSelection called with invalid offset.");
1206 xText
->setSelection(startOffset
, endOffset
);
1209 QString
QtAccessibleWidget::text(int startOffset
, int endOffset
) const
1211 Reference
<XAccessibleText
> xText(getAccessibleContextImpl(), UNO_QUERY
);
1215 sal_Int32 nTextLength
= xText
->getCharacterCount();
1216 if (startOffset
< 0 || startOffset
> nTextLength
|| endOffset
< 0 || endOffset
> nTextLength
)
1218 SAL_WARN("vcl.qt", "QtAccessibleWidget::text called with invalid offset.");
1222 return toQString(xText
->getTextRange(startOffset
, endOffset
));
1225 QString
QtAccessibleWidget::textAfterOffset(int nOffset
,
1226 QAccessible::TextBoundaryType eBoundaryType
,
1227 int* pStartOffset
, int* pEndOffset
) const
1229 if (pStartOffset
== nullptr || pEndOffset
== nullptr)
1235 Reference
<XAccessibleText
> xText(getAccessibleContextImpl(), UNO_QUERY
);
1239 const int nCharCount
= characterCount();
1240 // -1 is special value for text length
1242 nOffset
= nCharCount
;
1243 else if (nOffset
< -1 || nOffset
> nCharCount
)
1246 "QtAccessibleWidget::textAfterOffset called with invalid offset: " << nOffset
);
1250 if (eBoundaryType
== QAccessible::NoBoundary
)
1252 if (nOffset
== nCharCount
)
1254 *pStartOffset
= nOffset
+ 1;
1255 *pEndOffset
= nCharCount
;
1256 return text(nOffset
+ 1, nCharCount
);
1259 sal_Int16 nUnoBoundaryType
= lcl_matchQtTextBoundaryType(eBoundaryType
);
1260 assert(nUnoBoundaryType
> 0);
1261 const TextSegment aSegment
= xText
->getTextBehindIndex(nOffset
, nUnoBoundaryType
);
1262 *pStartOffset
= aSegment
.SegmentStart
;
1263 *pEndOffset
= aSegment
.SegmentEnd
;
1264 return toQString(aSegment
.SegmentText
);
1267 QString
QtAccessibleWidget::textAtOffset(int offset
, QAccessible::TextBoundaryType boundaryType
,
1268 int* startOffset
, int* endOffset
) const
1270 if (startOffset
== nullptr || endOffset
== nullptr)
1273 const int nCharCount
= characterCount();
1274 if (boundaryType
== QAccessible::NoBoundary
)
1277 *endOffset
= nCharCount
;
1278 return text(0, nCharCount
);
1281 Reference
<XAccessibleText
> xText(getAccessibleContextImpl(), UNO_QUERY
);
1285 sal_Int16 nUnoBoundaryType
= lcl_matchQtTextBoundaryType(boundaryType
);
1286 assert(nUnoBoundaryType
> 0);
1288 // special value of -1 for offset means text length
1290 offset
= nCharCount
;
1292 if (offset
< 0 || offset
> nCharCount
)
1295 "QtAccessibleWidget::textAtOffset called with invalid offset: " << offset
);
1299 const TextSegment segment
= xText
->getTextAtIndex(offset
, nUnoBoundaryType
);
1300 *startOffset
= segment
.SegmentStart
;
1301 *endOffset
= segment
.SegmentEnd
;
1302 return toQString(segment
.SegmentText
);
1305 QString
QtAccessibleWidget::textBeforeOffset(int nOffset
,
1306 QAccessible::TextBoundaryType eBoundaryType
,
1307 int* pStartOffset
, int* pEndOffset
) const
1309 if (pStartOffset
== nullptr || pEndOffset
== nullptr)
1315 Reference
<XAccessibleText
> xText(getAccessibleContextImpl(), UNO_QUERY
);
1319 const int nCharCount
= characterCount();
1320 // -1 is special value for text length
1322 nOffset
= nCharCount
;
1323 else if (nOffset
< -1 || nOffset
> nCharCount
)
1326 "QtAccessibleWidget::textBeforeOffset called with invalid offset: " << nOffset
);
1330 if (eBoundaryType
== QAccessible::NoBoundary
)
1333 *pEndOffset
= nOffset
;
1334 return text(0, nOffset
);
1337 sal_Int16 nUnoBoundaryType
= lcl_matchQtTextBoundaryType(eBoundaryType
);
1338 assert(nUnoBoundaryType
> 0);
1339 const TextSegment aSegment
= xText
->getTextBeforeIndex(nOffset
, nUnoBoundaryType
);
1340 *pStartOffset
= aSegment
.SegmentStart
;
1341 *pEndOffset
= aSegment
.SegmentEnd
;
1342 return toQString(aSegment
.SegmentText
);
1345 // QAccessibleEditableTextInterface
1347 void QtAccessibleWidget::deleteText(int startOffset
, int endOffset
)
1349 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1353 Reference
<XAccessibleEditableText
> xEditableText(xAc
, UNO_QUERY
);
1354 if (!xEditableText
.is())
1357 sal_Int32 nTextLength
= xEditableText
->getCharacterCount();
1358 if (startOffset
< 0 || startOffset
> nTextLength
|| endOffset
< 0 || endOffset
> nTextLength
)
1360 SAL_WARN("vcl.qt", "QtAccessibleWidget::deleteText called with invalid offset.");
1364 xEditableText
->deleteText(startOffset
, endOffset
);
1367 void QtAccessibleWidget::insertText(int offset
, const QString
& text
)
1369 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1373 Reference
<XAccessibleEditableText
> xEditableText(xAc
, UNO_QUERY
);
1374 if (!xEditableText
.is())
1377 if (offset
< 0 || offset
> xEditableText
->getCharacterCount())
1379 SAL_WARN("vcl.qt", "QtAccessibleWidget::insertText called with invalid offset: " << offset
);
1383 xEditableText
->insertText(toOUString(text
), offset
);
1386 void QtAccessibleWidget::replaceText(int startOffset
, int endOffset
, const QString
& text
)
1388 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1392 Reference
<XAccessibleEditableText
> xEditableText(xAc
, UNO_QUERY
);
1393 if (!xEditableText
.is())
1396 sal_Int32 nTextLength
= xEditableText
->getCharacterCount();
1397 if (startOffset
< 0 || startOffset
> nTextLength
|| endOffset
< 0 || endOffset
> nTextLength
)
1399 SAL_WARN("vcl.qt", "QtAccessibleWidget::replaceText called with invalid offset.");
1403 xEditableText
->replaceText(startOffset
, endOffset
, toOUString(text
));
1406 // QAccessibleValueInterface
1407 QVariant
QtAccessibleWidget::currentValue() const
1409 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1413 Reference
<XAccessibleValue
> xValue(xAc
, UNO_QUERY
);
1417 xValue
->getCurrentValue() >>= aDouble
;
1418 return QVariant(aDouble
);
1421 QVariant
QtAccessibleWidget::maximumValue() const
1423 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1427 Reference
<XAccessibleValue
> xValue(xAc
, UNO_QUERY
);
1431 xValue
->getMaximumValue() >>= aDouble
;
1432 return QVariant(aDouble
);
1435 QVariant
QtAccessibleWidget::minimumStepSize() const
1437 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1441 Reference
<XAccessibleValue
> xValue(xAc
, UNO_QUERY
);
1444 double dMinStep
= 0;
1445 xValue
->getMinimumIncrement() >>= dMinStep
;
1446 return QVariant(dMinStep
);
1449 QVariant
QtAccessibleWidget::minimumValue() const
1451 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1455 Reference
<XAccessibleValue
> xValue(xAc
, UNO_QUERY
);
1459 xValue
->getMinimumValue() >>= aDouble
;
1460 return QVariant(aDouble
);
1463 void QtAccessibleWidget::setCurrentValue(const QVariant
& value
)
1465 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1469 Reference
<XAccessibleValue
> xValue(xAc
, UNO_QUERY
);
1472 xValue
->setCurrentValue(Any(value
.toDouble()));
1475 // QAccessibleTableInterface
1476 QAccessibleInterface
* QtAccessibleWidget::caption() const
1478 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1482 Reference
<XAccessibleTable
> xTable(xAc
, UNO_QUERY
);
1485 return QAccessible::queryAccessibleInterface(
1486 QtAccessibleRegistry::getQObject(xTable
->getAccessibleCaption()));
1489 QAccessibleInterface
* QtAccessibleWidget::cellAt(int row
, int column
) const
1491 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1495 Reference
<XAccessibleTable
> xTable(xAc
, UNO_QUERY
);
1499 if (row
< 0 || row
>= xTable
->getAccessibleRowCount() || column
< 0
1500 || column
>= xTable
->getAccessibleColumnCount())
1502 SAL_WARN("vcl.qt", "QtAccessibleWidget::cellAt called with invalid row/column index ("
1503 << row
<< ", " << column
<< ")");
1507 return QAccessible::queryAccessibleInterface(
1508 QtAccessibleRegistry::getQObject(xTable
->getAccessibleCellAt(row
, column
)));
1511 int QtAccessibleWidget::columnCount() const
1513 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1517 Reference
<XAccessibleTable
> xTable(xAc
, UNO_QUERY
);
1520 return xTable
->getAccessibleColumnCount();
1523 QString
QtAccessibleWidget::columnDescription(int column
) const
1525 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1529 Reference
<XAccessibleTable
> xTable(xAc
, UNO_QUERY
);
1532 return toQString(xTable
->getAccessibleColumnDescription(column
));
1535 bool QtAccessibleWidget::isColumnSelected(int nColumn
) const
1537 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1541 Reference
<XAccessibleTable
> xTable(xAc
, UNO_QUERY
);
1545 if (nColumn
< 0 || nColumn
>= xTable
->getAccessibleColumnCount())
1547 SAL_WARN("vcl.qt", "QtAccessibleWidget::isColumnSelected called with invalid column index "
1552 return xTable
->isAccessibleColumnSelected(nColumn
);
1555 bool QtAccessibleWidget::isRowSelected(int nRow
) const
1557 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1561 Reference
<XAccessibleTable
> xTable(xAc
, UNO_QUERY
);
1565 if (nRow
< 0 || nRow
>= xTable
->getAccessibleRowCount())
1568 "QtAccessibleWidget::isRowSelected called with invalid row index " << nRow
);
1572 return xTable
->isAccessibleRowSelected(nRow
);
1575 void QtAccessibleWidget::modelChange(QAccessibleTableModelChangeEvent
*) {}
1577 int QtAccessibleWidget::rowCount() const
1579 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1583 Reference
<XAccessibleTable
> xTable(xAc
, UNO_QUERY
);
1586 return xTable
->getAccessibleRowCount();
1589 QString
QtAccessibleWidget::rowDescription(int row
) const
1591 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1595 Reference
<XAccessibleTable
> xTable(xAc
, UNO_QUERY
);
1598 return toQString(xTable
->getAccessibleRowDescription(row
));
1601 bool QtAccessibleWidget::selectColumn(int column
)
1603 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1607 if (column
< 0 || column
>= columnCount())
1610 "QtAccessibleWidget::selectColumn called with invalid column index " << column
);
1614 Reference
<XAccessibleTableSelection
> xTableSelection(xAc
, UNO_QUERY
);
1615 if (!xTableSelection
.is())
1617 return xTableSelection
->selectColumn(column
);
1620 bool QtAccessibleWidget::selectRow(int row
)
1622 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1626 if (row
< 0 || row
>= rowCount())
1628 SAL_WARN("vcl.qt", "QtAccessibleWidget::selectRow called with invalid row index " << row
);
1632 Reference
<XAccessibleTableSelection
> xTableSelection(xAc
, UNO_QUERY
);
1633 if (!xTableSelection
.is())
1635 return xTableSelection
->selectRow(row
);
1638 int QtAccessibleWidget::selectedCellCount() const { return selectedItemCount(); }
1640 QList
<QAccessibleInterface
*> QtAccessibleWidget::selectedCells() const { return selectedItems(); }
1642 int QtAccessibleWidget::selectedColumnCount() const
1644 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1648 Reference
<XAccessibleTable
> xTable(xAc
, UNO_QUERY
);
1651 return xTable
->getSelectedAccessibleColumns().getLength();
1654 QList
<int> QtAccessibleWidget::selectedColumns() const
1656 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1658 return QList
<int>();
1660 Reference
<XAccessibleTable
> xTable(xAc
, UNO_QUERY
);
1662 return QList
<int>();
1663 return toQList(xTable
->getSelectedAccessibleColumns());
1666 int QtAccessibleWidget::selectedRowCount() const
1668 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1672 Reference
<XAccessibleTable
> xTable(xAc
, UNO_QUERY
);
1675 return xTable
->getSelectedAccessibleRows().getLength();
1678 QList
<int> QtAccessibleWidget::selectedRows() const
1680 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1682 return QList
<int>();
1684 Reference
<XAccessibleTable
> xTable(xAc
, UNO_QUERY
);
1686 return QList
<int>();
1687 return toQList(xTable
->getSelectedAccessibleRows());
1690 QAccessibleInterface
* QtAccessibleWidget::summary() const
1692 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1696 Reference
<XAccessibleTable
> xTable(xAc
, UNO_QUERY
);
1699 return QAccessible::queryAccessibleInterface(
1700 QtAccessibleRegistry::getQObject(xTable
->getAccessibleSummary()));
1703 bool QtAccessibleWidget::unselectColumn(int column
)
1705 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1709 Reference
<XAccessibleTableSelection
> xTableSelection(xAc
, UNO_QUERY
);
1710 if (!xTableSelection
.is())
1712 return xTableSelection
->unselectColumn(column
);
1715 bool QtAccessibleWidget::unselectRow(int row
)
1717 Reference
<XAccessibleContext
> xAc
= getAccessibleContextImpl();
1721 Reference
<XAccessibleTableSelection
> xTableSelection(xAc
, UNO_QUERY
);
1722 if (!xTableSelection
.is())
1724 return xTableSelection
->unselectRow(row
);
1727 // QAccessibleTableCellInterface
1728 QList
<QAccessibleInterface
*> QtAccessibleWidget::columnHeaderCells() const
1730 Reference
<XAccessibleTable
> xTable
= getAccessibleTableForParent();
1732 return QList
<QAccessibleInterface
*>();
1734 Reference
<XAccessibleTable
> xHeaders
= xTable
->getAccessibleColumnHeaders();
1736 return QList
<QAccessibleInterface
*>();
1738 const sal_Int32 nCol
= columnIndex();
1739 QList
<QAccessibleInterface
*> aHeaderCells
;
1740 for (sal_Int32 nRow
= 0; nRow
< xHeaders
->getAccessibleRowCount(); nRow
++)
1742 Reference
<XAccessible
> xCell
= xHeaders
->getAccessibleCellAt(nRow
, nCol
);
1743 QAccessibleInterface
* pInterface
1744 = QAccessible::queryAccessibleInterface(QtAccessibleRegistry::getQObject(xCell
));
1745 aHeaderCells
.push_back(pInterface
);
1747 return aHeaderCells
;
1750 int QtAccessibleWidget::columnIndex() const
1752 Reference
<XAccessibleContext
> xAcc
= getAccessibleContextImpl();
1756 Reference
<XAccessibleTable
> xTable
= getAccessibleTableForParent();
1760 const sal_Int64 nIndexInParent
= xAcc
->getAccessibleIndexInParent();
1761 return xTable
->getAccessibleColumn(nIndexInParent
);
1764 bool QtAccessibleWidget::isSelected() const
1766 Reference
<XAccessibleContext
> xAcc
= getAccessibleContextImpl();
1770 Reference
<XAccessibleTable
> xTable
= getAccessibleTableForParent();
1774 const sal_Int32 nColumn
= columnIndex();
1775 const sal_Int32 nRow
= rowIndex();
1776 return xTable
->isAccessibleSelected(nRow
, nColumn
);
1779 int QtAccessibleWidget::columnExtent() const
1781 Reference
<XAccessibleContext
> xAcc
= getAccessibleContextImpl();
1785 Reference
<XAccessibleTable
> xTable
= getAccessibleTableForParent();
1789 const sal_Int32 nColumn
= columnIndex();
1790 const sal_Int32 nRow
= rowIndex();
1791 return xTable
->getAccessibleColumnExtentAt(nRow
, nColumn
);
1794 QList
<QAccessibleInterface
*> QtAccessibleWidget::rowHeaderCells() const
1796 Reference
<XAccessibleTable
> xTable
= getAccessibleTableForParent();
1798 return QList
<QAccessibleInterface
*>();
1800 Reference
<XAccessibleTable
> xHeaders
= xTable
->getAccessibleRowHeaders();
1802 return QList
<QAccessibleInterface
*>();
1804 const sal_Int32 nRow
= rowIndex();
1805 QList
<QAccessibleInterface
*> aHeaderCells
;
1806 for (sal_Int32 nCol
= 0; nCol
< xHeaders
->getAccessibleColumnCount(); nCol
++)
1808 Reference
<XAccessible
> xCell
= xHeaders
->getAccessibleCellAt(nRow
, nCol
);
1809 QAccessibleInterface
* pInterface
1810 = QAccessible::queryAccessibleInterface(QtAccessibleRegistry::getQObject(xCell
));
1811 aHeaderCells
.push_back(pInterface
);
1813 return aHeaderCells
;
1816 int QtAccessibleWidget::rowExtent() const
1818 Reference
<XAccessibleContext
> xAcc
= getAccessibleContextImpl();
1822 Reference
<XAccessibleTable
> xTable
= getAccessibleTableForParent();
1826 const sal_Int32 nColumn
= columnIndex();
1827 const sal_Int32 nRow
= rowIndex();
1828 return xTable
->getAccessibleRowExtentAt(nRow
, nColumn
);
1831 int QtAccessibleWidget::rowIndex() const
1833 Reference
<XAccessibleContext
> xAcc
= getAccessibleContextImpl();
1837 Reference
<XAccessibleTable
> xTable
= getAccessibleTableForParent();
1841 const sal_Int64 nIndexInParent
= xAcc
->getAccessibleIndexInParent();
1842 return xTable
->getAccessibleRow(nIndexInParent
);
1845 QAccessibleInterface
* QtAccessibleWidget::table() const
1847 Reference
<XAccessibleTable
> xTable
= getAccessibleTableForParent();
1851 Reference
<XAccessible
> xTableAcc(xTable
, UNO_QUERY
);
1852 if (!xTableAcc
.is())
1855 return QAccessible::queryAccessibleInterface(QtAccessibleRegistry::getQObject(xTableAcc
));
1858 // QAccessibleSelectionInterface
1859 int QtAccessibleWidget::selectedItemCount() const
1861 Reference
<XAccessibleContext
> xAcc
= getAccessibleContextImpl();
1865 Reference
<XAccessibleSelection
> xSelection(xAcc
, UNO_QUERY
);
1866 if (!xSelection
.is())
1869 sal_Int64 nSelected
= xSelection
->getSelectedAccessibleChildCount();
1870 if (nSelected
> std::numeric_limits
<int>::max())
1873 "QtAccessibleWidget::selectedItemCount: Cell count exceeds maximum int value, "
1875 nSelected
= std::numeric_limits
<int>::max();
1880 QList
<QAccessibleInterface
*> QtAccessibleWidget::selectedItems() const
1882 Reference
<XAccessibleContext
> xAcc
= getAccessibleContextImpl();
1884 return QList
<QAccessibleInterface
*>();
1886 Reference
<XAccessibleSelection
> xSelection(xAcc
, UNO_QUERY
);
1887 if (!xSelection
.is())
1888 return QList
<QAccessibleInterface
*>();
1890 QList
<QAccessibleInterface
*> aSelectedItems
;
1891 sal_Int64 nSelected
= xSelection
->getSelectedAccessibleChildCount();
1892 if (nSelected
> std::numeric_limits
<int>::max())
1895 "QtAccessibleWidget::selectedItems: Cell count exceeds maximum int value, "
1897 nSelected
= std::numeric_limits
<int>::max();
1899 for (sal_Int64 i
= 0; i
< nSelected
; i
++)
1901 Reference
<XAccessible
> xChild
= xSelection
->getSelectedAccessibleChild(i
);
1902 QAccessibleInterface
* pInterface
1903 = QAccessible::queryAccessibleInterface(QtAccessibleRegistry::getQObject(xChild
));
1904 aSelectedItems
.push_back(pInterface
);
1906 return aSelectedItems
;
1909 #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
1910 QAccessibleInterface
* QtAccessibleWidget::selectedItem(int nSelectionIndex
) const
1912 Reference
<XAccessibleContext
> xAcc
= getAccessibleContextImpl();
1916 Reference
<XAccessibleSelection
> xSelection(xAcc
, UNO_QUERY
);
1917 if (!xSelection
.is())
1920 if (nSelectionIndex
< 0 || nSelectionIndex
>= xSelection
->getSelectedAccessibleChildCount())
1923 "QtAccessibleWidget::selectedItem called with invalid index: " << nSelectionIndex
);
1927 Reference
<XAccessible
> xChild
= xSelection
->getSelectedAccessibleChild(nSelectionIndex
);
1931 return QAccessible::queryAccessibleInterface(QtAccessibleRegistry::getQObject(xChild
));
1934 bool QtAccessibleWidget::isSelected(QAccessibleInterface
* pItem
) const
1936 Reference
<XAccessibleContext
> xAcc
= getAccessibleContextImpl();
1940 Reference
<XAccessibleSelection
> xSelection(xAcc
, UNO_QUERY
);
1941 if (!xSelection
.is())
1944 int nChildIndex
= indexOfChild(pItem
);
1945 if (nChildIndex
< 0)
1948 return xSelection
->isAccessibleChildSelected(nChildIndex
);
1951 bool QtAccessibleWidget::select(QAccessibleInterface
* pItem
)
1953 Reference
<XAccessibleContext
> xAcc
= getAccessibleContextImpl();
1957 Reference
<XAccessibleSelection
> xSelection(xAcc
, UNO_QUERY
);
1958 if (!xSelection
.is())
1961 int nChildIndex
= indexOfChild(pItem
);
1962 if (nChildIndex
< 0)
1965 xSelection
->selectAccessibleChild(nChildIndex
);
1969 bool QtAccessibleWidget::unselect(QAccessibleInterface
* pItem
)
1971 Reference
<XAccessibleContext
> xAcc
= getAccessibleContextImpl();
1975 Reference
<XAccessibleSelection
> xSelection(xAcc
, UNO_QUERY
);
1976 if (!xSelection
.is())
1979 int nChildIndex
= indexOfChild(pItem
);
1980 if (nChildIndex
< 0)
1983 xSelection
->deselectAccessibleChild(nChildIndex
);
1987 bool QtAccessibleWidget::selectAll()
1989 Reference
<XAccessibleContext
> xAcc
= getAccessibleContextImpl();
1993 Reference
<XAccessibleSelection
> xSelection(xAcc
, UNO_QUERY
);
1994 if (!xSelection
.is())
1997 xSelection
->selectAllAccessibleChildren();
2001 bool QtAccessibleWidget::clear()
2003 Reference
<XAccessibleContext
> xAcc
= getAccessibleContextImpl();
2007 Reference
<XAccessibleSelection
> xSelection(xAcc
, UNO_QUERY
);
2008 if (!xSelection
.is())
2011 xSelection
->clearAccessibleSelection();
2016 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */