Update git submodules
[LibreOffice.git] / vcl / qt5 / Qt5AccessibleWidget.cxx
blob879c451ec277277e28c6728845dcd0ef5d6ceceb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <Qt5AccessibleWidget.hxx>
21 #include <Qt5AccessibleWidget.moc>
23 #include <QtGui/QAccessibleInterface>
25 #include <Qt5AccessibleEventListener.hxx>
26 #include <Qt5Frame.hxx>
27 #include <Qt5Tools.hxx>
28 #include <Qt5Widget.hxx>
29 #include <Qt5XAccessible.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/XAccessible.hpp>
36 #include <com/sun/star/accessibility/XAccessibleAction.hpp>
37 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
38 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
39 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
40 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
41 #include <com/sun/star/accessibility/XAccessibleKeyBinding.hpp>
42 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
43 #include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
44 #include <com/sun/star/accessibility/XAccessibleTable.hpp>
45 #include <com/sun/star/accessibility/XAccessibleTableSelection.hpp>
46 #include <com/sun/star/accessibility/XAccessibleText.hpp>
47 #include <com/sun/star/accessibility/XAccessibleValue.hpp>
48 #include <com/sun/star/awt/FontWeight.hpp>
49 #include <com/sun/star/beans/PropertyValue.hpp>
50 #include <com/sun/star/lang/DisposedException.hpp>
51 #include <com/sun/star/uno/Sequence.hxx>
53 #include <comphelper/AccessibleImplementationHelper.hxx>
54 #include <o3tl/any.hxx>
55 #include <sal/log.hxx>
57 using namespace css;
58 using namespace css::accessibility;
59 using namespace css::beans;
60 using namespace css::uno;
62 Qt5AccessibleWidget::Qt5AccessibleWidget(const Reference<XAccessible> xAccessible, QObject* pObject)
63 : m_xAccessible(xAccessible)
64 , m_pObject(pObject)
66 Reference<XAccessibleContext> xContext = xAccessible->getAccessibleContext();
67 Reference<XAccessibleEventBroadcaster> xBroadcaster(xContext, UNO_QUERY);
68 if (xBroadcaster.is())
70 Reference<XAccessibleEventListener> xListener(
71 new Qt5AccessibleEventListener(xAccessible, this));
72 xBroadcaster->addAccessibleEventListener(xListener);
76 Reference<XAccessibleContext> Qt5AccessibleWidget::getAccessibleContextImpl() const
78 Reference<XAccessibleContext> xAc;
80 if (m_xAccessible.is())
82 try
84 xAc = m_xAccessible->getAccessibleContext();
86 catch (css::lang::DisposedException /*ex*/)
88 SAL_WARN("vcl.qt5", "Accessible context disposed already");
90 // sometimes getAccessibleContext throws also RuntimeException if context is no longer alive
91 catch (css::uno::RuntimeException /*ex*/)
93 // so let's catch it here, cuz otherwise soffice falls flat on its face
94 // with FatalError and nothing else
95 SAL_WARN("vcl.qt5", "Accessible context no longer alive");
99 return xAc;
102 QWindow* Qt5AccessibleWidget::window() const { return nullptr; }
104 int Qt5AccessibleWidget::childCount() const
106 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
107 if (!xAc.is())
108 return 0;
110 return xAc->getAccessibleChildCount();
113 int Qt5AccessibleWidget::indexOfChild(const QAccessibleInterface* /* child */) const { return 0; }
115 namespace
117 QAccessible::Relation lcl_matchUnoRelation(short relationType)
119 switch (relationType)
121 case AccessibleRelationType::CONTROLLER_FOR:
122 return QAccessible::Controller;
123 case AccessibleRelationType::CONTROLLED_BY:
124 return QAccessible::Controlled;
125 case AccessibleRelationType::LABEL_FOR:
126 return QAccessible::Label;
127 case AccessibleRelationType::LABELED_BY:
128 return QAccessible::Labelled;
129 case AccessibleRelationType::INVALID:
130 case AccessibleRelationType::CONTENT_FLOWS_FROM:
131 case AccessibleRelationType::CONTENT_FLOWS_TO:
132 case AccessibleRelationType::MEMBER_OF:
133 case AccessibleRelationType::SUB_WINDOW_OF:
134 case AccessibleRelationType::NODE_CHILD_OF:
135 case AccessibleRelationType::DESCRIBED_BY:
136 default:
137 SAL_WARN("vcl.qt5", "Unmatched relation: " << relationType);
138 return {};
142 short lcl_matchQtRelation(QAccessible::Relation relationType)
144 switch (relationType)
146 case QAccessible::Controller:
147 return AccessibleRelationType::CONTROLLER_FOR;
148 case QAccessible::Controlled:
149 return AccessibleRelationType::CONTROLLED_BY;
150 case QAccessible::Label:
151 return AccessibleRelationType::LABEL_FOR;
152 case QAccessible::Labelled:
153 return AccessibleRelationType::LABELED_BY;
154 default:
155 SAL_WARN("vcl.qt5", "Unmatched relation: " << relationType);
157 return 0;
160 void lcl_appendRelation(QVector<QPair<QAccessibleInterface*, QAccessible::Relation>>* relations,
161 AccessibleRelation aRelation)
163 QAccessible::Relation aQRelation = lcl_matchUnoRelation(aRelation.RelationType);
164 sal_uInt32 nTargetCount = aRelation.TargetSet.getLength();
166 for (sal_uInt32 i = 0; i < nTargetCount; i++)
168 Reference<XAccessible> xAccessible(aRelation.TargetSet[i], uno::UNO_QUERY);
169 relations->append(
170 { QAccessible::queryAccessibleInterface(new Qt5XAccessible(xAccessible)), aQRelation });
175 QVector<QPair<QAccessibleInterface*, QAccessible::Relation>>
176 Qt5AccessibleWidget::relations(QAccessible::Relation match) const
178 QVector<QPair<QAccessibleInterface*, QAccessible::Relation>> relations;
180 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
181 if (!xAc.is())
182 return relations;
184 Reference<XAccessibleRelationSet> xRelationSet = xAc->getAccessibleRelationSet();
185 if (xRelationSet.is())
187 if (match == QAccessible::AllRelations)
189 int count = xRelationSet->getRelationCount();
190 for (int i = 0; i < count; i++)
192 AccessibleRelation aRelation = xRelationSet->getRelation(i);
193 lcl_appendRelation(&relations, aRelation);
196 else
198 AccessibleRelation aRelation = xRelationSet->getRelation(lcl_matchQtRelation(match));
199 lcl_appendRelation(&relations, aRelation);
203 return relations;
206 QAccessibleInterface* Qt5AccessibleWidget::focusChild() const
208 /* if (m_pWindow->HasChildPathFocus())
209 return QAccessible::queryAccessibleInterface(
210 new Qt5XAccessible(m_xAccessible->getAccessibleContext()->getAccessibleChild(index))); */
211 return QAccessible::queryAccessibleInterface(object());
214 QRect Qt5AccessibleWidget::rect() const
216 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
217 if (!xAc.is())
218 return QRect();
220 Reference<XAccessibleComponent> xAccessibleComponent(xAc, UNO_QUERY);
221 awt::Point aPoint = xAccessibleComponent->getLocation();
222 awt::Size aSize = xAccessibleComponent->getSize();
224 return QRect(aPoint.X, aPoint.Y, aSize.Width, aSize.Height);
227 QAccessibleInterface* Qt5AccessibleWidget::parent() const
229 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
230 if (!xAc.is())
231 return nullptr;
233 return QAccessible::queryAccessibleInterface(new Qt5XAccessible(xAc->getAccessibleParent()));
235 QAccessibleInterface* Qt5AccessibleWidget::child(int index) const
237 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
238 if (!xAc.is())
239 return nullptr;
241 return QAccessible::queryAccessibleInterface(
242 new Qt5XAccessible(xAc->getAccessibleChild(index)));
245 QString Qt5AccessibleWidget::text(QAccessible::Text text) const
247 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
248 if (!xAc.is())
249 return QString();
251 switch (text)
253 case QAccessible::Name:
254 return toQString(xAc->getAccessibleName());
255 case QAccessible::Description:
256 case QAccessible::DebugDescription:
257 return toQString(xAc->getAccessibleDescription());
258 case QAccessible::Value:
259 case QAccessible::Help:
260 case QAccessible::Accelerator:
261 case QAccessible::UserText:
262 default:
263 return QString("Unknown");
266 QAccessible::Role Qt5AccessibleWidget::role() const
268 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
269 if (!xAc.is())
270 return QAccessible::NoRole;
272 switch (xAc->getAccessibleRole())
274 case AccessibleRole::UNKNOWN:
275 return QAccessible::NoRole;
277 case AccessibleRole::ALERT:
278 return QAccessible::AlertMessage;
280 case AccessibleRole::COLUMN_HEADER:
281 return QAccessible::ColumnHeader;
283 case AccessibleRole::CANVAS:
284 return QAccessible::Canvas;
286 case AccessibleRole::CHECK_BOX:
287 return QAccessible::CheckBox;
289 case AccessibleRole::CHECK_MENU_ITEM:
290 return QAccessible::MenuItem;
292 case AccessibleRole::COLOR_CHOOSER:
293 return QAccessible::ColorChooser;
295 case AccessibleRole::COMBO_BOX:
296 return QAccessible::ComboBox;
298 case AccessibleRole::DATE_EDITOR:
299 return QAccessible::EditableText;
301 case AccessibleRole::DESKTOP_ICON:
302 return QAccessible::Graphic;
304 case AccessibleRole::DESKTOP_PANE:
305 case AccessibleRole::DIRECTORY_PANE:
306 return QAccessible::Pane;
308 case AccessibleRole::DIALOG:
309 return QAccessible::Dialog;
311 case AccessibleRole::DOCUMENT:
312 return QAccessible::Document;
314 case AccessibleRole::EMBEDDED_OBJECT:
315 return QAccessible::UserRole;
317 case AccessibleRole::END_NOTE:
318 return QAccessible::Note;
320 case AccessibleRole::FILLER:
321 return QAccessible::Whitespace;
323 case AccessibleRole::FONT_CHOOSER:
324 return QAccessible::UserRole;
326 case AccessibleRole::FOOTER:
327 return QAccessible::Footer;
329 case AccessibleRole::FOOTNOTE:
330 return QAccessible::Note;
332 case AccessibleRole::FRAME: // top-level window with title bar
333 return QAccessible::Window;
335 case AccessibleRole::GLASS_PANE:
336 return QAccessible::UserRole;
338 case AccessibleRole::GRAPHIC:
339 return QAccessible::Graphic;
341 case AccessibleRole::GROUP_BOX:
342 return QAccessible::Grouping;
344 case AccessibleRole::HEADER:
345 return QAccessible::UserRole;
347 case AccessibleRole::HEADING:
348 return QAccessible::Heading;
350 case AccessibleRole::HYPER_LINK:
351 return QAccessible::Link;
353 case AccessibleRole::ICON:
354 return QAccessible::Graphic;
356 case AccessibleRole::INTERNAL_FRAME:
357 return QAccessible::UserRole;
359 case AccessibleRole::LABEL:
360 return QAccessible::StaticText;
362 case AccessibleRole::LAYERED_PANE:
363 return QAccessible::Pane;
365 case AccessibleRole::LIST:
366 return QAccessible::List;
368 case AccessibleRole::LIST_ITEM:
369 return QAccessible::ListItem;
371 case AccessibleRole::MENU:
372 case AccessibleRole::MENU_BAR:
373 return QAccessible::MenuBar;
375 case AccessibleRole::MENU_ITEM:
376 return QAccessible::MenuItem;
378 case AccessibleRole::OPTION_PANE:
379 return QAccessible::Pane;
381 case AccessibleRole::PAGE_TAB:
382 return QAccessible::PageTab;
384 case AccessibleRole::PAGE_TAB_LIST:
385 return QAccessible::PageTabList;
387 case AccessibleRole::PANEL:
388 return QAccessible::Pane;
390 case AccessibleRole::PARAGRAPH:
391 return QAccessible::Paragraph;
393 case AccessibleRole::PASSWORD_TEXT:
394 return QAccessible::EditableText;
396 case AccessibleRole::POPUP_MENU:
397 return QAccessible::PopupMenu;
399 case AccessibleRole::PUSH_BUTTON:
400 return QAccessible::Button;
402 case AccessibleRole::PROGRESS_BAR:
403 return QAccessible::ProgressBar;
405 case AccessibleRole::RADIO_BUTTON:
406 return QAccessible::RadioButton;
408 case AccessibleRole::RADIO_MENU_ITEM:
409 return QAccessible::MenuItem;
411 case AccessibleRole::ROW_HEADER:
412 return QAccessible::RowHeader;
414 case AccessibleRole::ROOT_PANE:
415 return QAccessible::Pane;
417 case AccessibleRole::SCROLL_BAR:
418 return QAccessible::ScrollBar;
420 case AccessibleRole::SCROLL_PANE:
421 return QAccessible::Pane;
423 case AccessibleRole::SHAPE:
424 return QAccessible::Graphic;
426 case AccessibleRole::SEPARATOR:
427 return QAccessible::Separator;
429 case AccessibleRole::SLIDER:
430 return QAccessible::Slider;
432 case AccessibleRole::SPIN_BOX:
433 return QAccessible::SpinBox;
435 case AccessibleRole::SPLIT_PANE:
436 return QAccessible::Pane;
438 case AccessibleRole::STATUS_BAR:
439 return QAccessible::StatusBar;
441 case AccessibleRole::TABLE:
442 return QAccessible::Table;
444 case AccessibleRole::TABLE_CELL:
445 return QAccessible::Cell;
447 case AccessibleRole::TEXT:
448 return QAccessible::EditableText;
450 case AccessibleRole::TEXT_FRAME:
451 return QAccessible::UserRole;
453 case AccessibleRole::TOGGLE_BUTTON:
454 return QAccessible::Button;
456 case AccessibleRole::TOOL_BAR:
457 return QAccessible::ToolBar;
459 case AccessibleRole::TOOL_TIP:
460 return QAccessible::ToolTip;
462 case AccessibleRole::TREE:
463 return QAccessible::Tree;
465 case AccessibleRole::VIEW_PORT:
466 return QAccessible::UserRole;
468 case AccessibleRole::BUTTON_DROPDOWN:
469 return QAccessible::Button;
471 case AccessibleRole::BUTTON_MENU:
472 return QAccessible::Button;
474 case AccessibleRole::CAPTION:
475 return QAccessible::StaticText;
477 case AccessibleRole::CHART:
478 return QAccessible::Chart;
480 case AccessibleRole::EDIT_BAR:
481 return QAccessible::Equation;
483 case AccessibleRole::FORM:
484 return QAccessible::Form;
486 case AccessibleRole::IMAGE_MAP:
487 return QAccessible::Graphic;
489 case AccessibleRole::NOTE:
490 return QAccessible::Note;
492 case AccessibleRole::RULER:
493 return QAccessible::UserRole;
495 case AccessibleRole::SECTION:
496 return QAccessible::Section;
498 case AccessibleRole::TREE_ITEM:
499 return QAccessible::TreeItem;
501 case AccessibleRole::TREE_TABLE:
502 return QAccessible::Tree;
504 case AccessibleRole::COMMENT:
505 return QAccessible::Note;
507 case AccessibleRole::COMMENT_END:
508 return QAccessible::UserRole;
510 case AccessibleRole::DOCUMENT_PRESENTATION:
511 return QAccessible::Document;
513 case AccessibleRole::DOCUMENT_SPREADSHEET:
514 return QAccessible::Document;
516 case AccessibleRole::DOCUMENT_TEXT:
517 return QAccessible::Document;
519 case AccessibleRole::STATIC:
520 return QAccessible::StaticText;
522 /* Ignore window objects for sub-menus, combo- and list boxes,
523 * which are exposed as children of their parents.
525 case AccessibleRole::WINDOW: // top-level window without title bar
527 return QAccessible::Window;
531 SAL_WARN("vcl.qt5",
532 "Unmapped role: " << m_xAccessible->getAccessibleContext()->getAccessibleRole());
533 return QAccessible::NoRole;
536 namespace
538 void lcl_addState(QAccessible::State* state, sal_Int16 nState)
540 switch (nState)
542 case AccessibleStateType::INVALID:
543 state->invalid = true;
544 break;
545 case AccessibleStateType::ACTIVE:
546 state->active = true;
547 break;
548 case AccessibleStateType::ARMED:
549 // No match
550 break;
551 case AccessibleStateType::BUSY:
552 state->busy = true;
553 break;
554 case AccessibleStateType::CHECKED:
555 state->checked = true;
556 break;
557 case AccessibleStateType::EDITABLE:
558 state->editable = true;
559 break;
560 case AccessibleStateType::ENABLED:
561 state->disabled = false;
562 break;
563 case AccessibleStateType::EXPANDABLE:
564 state->expandable = true;
565 break;
566 case AccessibleStateType::FOCUSABLE:
567 state->focusable = true;
568 break;
569 case AccessibleStateType::FOCUSED:
570 state->focused = true;
571 break;
572 case AccessibleStateType::HORIZONTAL:
573 // No match
574 break;
575 case AccessibleStateType::ICONIFIED:
576 // No match
577 break;
578 case AccessibleStateType::INDETERMINATE:
579 // No match
580 break;
581 case AccessibleStateType::MANAGES_DESCENDANTS:
582 // No match
583 break;
584 case AccessibleStateType::MODAL:
585 state->modal = true;
586 break;
587 case AccessibleStateType::OPAQUE:
588 // No match
589 break;
590 case AccessibleStateType::PRESSED:
591 state->pressed = true;
592 break;
593 case AccessibleStateType::RESIZABLE:
594 state->sizeable = true;
595 break;
596 case AccessibleStateType::SELECTABLE:
597 state->selectable = true;
598 break;
599 case AccessibleStateType::SELECTED:
600 state->selected = true;
601 break;
602 case AccessibleStateType::SENSITIVE:
603 // No match
604 break;
605 case AccessibleStateType::SHOWING:
606 // No match
607 break;
608 case AccessibleStateType::SINGLE_LINE:
609 // No match
610 break;
611 case AccessibleStateType::STALE:
612 // No match
613 break;
614 case AccessibleStateType::TRANSIENT:
615 // No match
616 break;
617 case AccessibleStateType::VERTICAL:
618 // No match
619 break;
620 case AccessibleStateType::VISIBLE:
621 state->invisible = false;
622 break;
623 case AccessibleStateType::DEFAULT:
624 // No match
625 break;
626 case AccessibleStateType::DEFUNC:
627 state->invalid = true;
628 break;
629 case AccessibleStateType::MULTI_SELECTABLE:
630 state->multiSelectable = true;
631 break;
632 default:
633 SAL_WARN("vcl.qt5", "Unmapped state: " << nState);
634 break;
639 QAccessible::State Qt5AccessibleWidget::state() const
641 QAccessible::State state;
643 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
644 if (!xAc.is())
645 return state;
647 Reference<XAccessibleStateSet> xStateSet(xAc->getAccessibleStateSet());
649 if (!xStateSet.is())
650 return state;
652 Sequence<sal_Int16> aStates = xStateSet->getStates();
654 for (sal_Int32 n = 0; n < aStates.getLength(); n++)
656 lcl_addState(&state, n);
659 return state;
662 QColor Qt5AccessibleWidget::foregroundColor() const
664 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
665 if (!xAc.is())
666 return QColor();
668 Reference<XAccessibleComponent> xAccessibleComponent(xAc, UNO_QUERY);
669 return toQColor(Color(ColorTransparency, xAccessibleComponent->getForeground()));
672 QColor Qt5AccessibleWidget::backgroundColor() const
674 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
675 if (!xAc.is())
676 return QColor();
678 Reference<XAccessibleComponent> xAccessibleComponent(xAc, UNO_QUERY);
679 return toQColor(Color(ColorTransparency, xAccessibleComponent->getBackground()));
682 void* Qt5AccessibleWidget::interface_cast(QAccessible::InterfaceType t)
684 if (t == QAccessible::ActionInterface)
685 return static_cast<QAccessibleActionInterface*>(this);
686 if (t == QAccessible::TextInterface)
687 return static_cast<QAccessibleTextInterface*>(this);
688 if (t == QAccessible::EditableTextInterface)
689 return static_cast<QAccessibleEditableTextInterface*>(this);
690 if (t == QAccessible::ValueInterface)
691 return static_cast<QAccessibleValueInterface*>(this);
692 if (t == QAccessible::TableInterface)
693 return static_cast<QAccessibleTableInterface*>(this);
694 return nullptr;
697 bool Qt5AccessibleWidget::isValid() const
699 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
700 return xAc.is();
703 QObject* Qt5AccessibleWidget::object() const { return m_pObject; }
705 void Qt5AccessibleWidget::setText(QAccessible::Text /* t */, const QString& /* text */) {}
707 QAccessibleInterface* Qt5AccessibleWidget::childAt(int x, int y) const
709 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
710 if (!xAc.is())
711 return nullptr;
713 Reference<XAccessibleComponent> xAccessibleComponent(xAc, UNO_QUERY);
714 return QAccessible::queryAccessibleInterface(
715 new Qt5XAccessible(xAccessibleComponent->getAccessibleAtPoint(awt::Point(x, y))));
718 QAccessibleInterface* Qt5AccessibleWidget::customFactory(const QString& classname, QObject* object)
720 if (classname == QLatin1String("Qt5Widget") && object && object->isWidgetType())
722 Qt5Widget* pWidget = static_cast<Qt5Widget*>(object);
723 vcl::Window* pWindow = pWidget->frame().GetWindow();
725 if (pWindow)
726 return new Qt5AccessibleWidget(pWindow->GetAccessible(), object);
728 if (classname == QLatin1String("Qt5XAccessible") && object)
730 Qt5XAccessible* pXAccessible = dynamic_cast<Qt5XAccessible*>(object);
731 if (pXAccessible && pXAccessible->m_xAccessible.is())
732 return new Qt5AccessibleWidget(pXAccessible->m_xAccessible, object);
735 return nullptr;
738 // QAccessibleActionInterface
739 QStringList Qt5AccessibleWidget::actionNames() const
741 QStringList actionNames;
742 Reference<XAccessibleAction> xAccessibleAction(m_xAccessible, UNO_QUERY);
743 if (!xAccessibleAction.is())
744 return actionNames;
746 int count = xAccessibleAction->getAccessibleActionCount();
747 for (int i = 0; i < count; i++)
749 OUString desc = xAccessibleAction->getAccessibleActionDescription(i);
750 actionNames.append(toQString(desc));
752 return actionNames;
755 void Qt5AccessibleWidget::doAction(const QString& actionName)
757 Reference<XAccessibleAction> xAccessibleAction(m_xAccessible, UNO_QUERY);
758 if (!xAccessibleAction.is())
759 return;
761 int index = actionNames().indexOf(actionName);
762 if (index == -1)
763 return;
764 xAccessibleAction->doAccessibleAction(index);
767 QStringList Qt5AccessibleWidget::keyBindingsForAction(const QString& actionName) const
769 QStringList keyBindings;
770 Reference<XAccessibleAction> xAccessibleAction(m_xAccessible, UNO_QUERY);
771 if (!xAccessibleAction.is())
772 return keyBindings;
774 int index = actionNames().indexOf(actionName);
775 if (index == -1)
776 return keyBindings;
778 Reference<XAccessibleKeyBinding> xKeyBinding
779 = xAccessibleAction->getAccessibleActionKeyBinding(index);
781 if (!xKeyBinding.is())
782 return keyBindings;
784 int count = xKeyBinding->getAccessibleKeyBindingCount();
785 for (int i = 0; i < count; i++)
787 Sequence<awt::KeyStroke> keyStroke = xKeyBinding->getAccessibleKeyBinding(i);
788 keyBindings.append(toQString(comphelper::GetkeyBindingStrByXkeyBinding(keyStroke)));
790 return keyBindings;
793 QAccessibleValueInterface* Qt5AccessibleWidget::valueInterface() { return nullptr; }
795 QAccessibleTextInterface* Qt5AccessibleWidget::textInterface() { return nullptr; }
797 // QAccessibleTextInterface
798 void Qt5AccessibleWidget::addSelection(int /* startOffset */, int /* endOffset */)
800 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::addSelection");
803 namespace
805 OUString lcl_convertFontWeight(double fontWeight)
807 if (fontWeight == awt::FontWeight::THIN || fontWeight == awt::FontWeight::ULTRALIGHT)
808 return "100";
809 if (fontWeight == awt::FontWeight::LIGHT)
810 return "200";
811 if (fontWeight == awt::FontWeight::SEMILIGHT)
812 return "300";
813 if (fontWeight == awt::FontWeight::NORMAL)
814 return "normal";
815 if (fontWeight == awt::FontWeight::SEMIBOLD)
816 return "500";
817 if (fontWeight == awt::FontWeight::BOLD)
818 return "bold";
819 if (fontWeight == awt::FontWeight::ULTRABOLD)
820 return "800";
821 if (fontWeight == awt::FontWeight::BLACK)
822 return "900";
824 // awt::FontWeight::DONTKNOW || fontWeight == awt::FontWeight::NORMAL
825 return "normal";
829 QString Qt5AccessibleWidget::attributes(int offset, int* startOffset, int* endOffset) const
831 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
832 if (!xText.is())
833 return QString();
835 // handle special values for offset the same way base class's QAccessibleTextWidget::attributes does
836 // (as defined in IAccessible 2: -1 -> length, -2 -> cursor position)
837 if (offset == -2)
838 offset = cursorPosition(); // currently always returns 0
840 const int nTextLength = characterCount();
841 if (offset == -1 || offset == nTextLength)
842 offset = nTextLength - 1;
844 if (offset < 0 || offset > nTextLength)
846 *startOffset = -1;
847 *endOffset = -1;
848 return QString();
851 const Sequence<PropertyValue> attribs
852 = xText->getCharacterAttributes(offset, Sequence<OUString>());
853 OUString aRet;
854 for (PropertyValue const& prop : attribs)
856 if (prop.Name == "CharFontName")
858 aRet += "font-family:" + *o3tl::doAccess<OUString>(prop.Value) + ";";
859 continue;
861 if (prop.Name == "CharHeight")
863 aRet += "font-size:" + OUString::number(*o3tl::doAccess<double>(prop.Value)) + "pt;";
864 continue;
866 if (prop.Name == "CharWeight")
868 aRet += "font-weight:" + lcl_convertFontWeight(*o3tl::doAccess<double>(prop.Value))
869 + ";";
870 continue;
873 *startOffset = offset;
874 *endOffset = offset + 1;
875 return toQString(aRet);
877 int Qt5AccessibleWidget::characterCount() const
879 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
880 if (xText.is())
881 return xText->getCharacterCount();
882 return 0;
884 QRect Qt5AccessibleWidget::characterRect(int /* offset */) const
886 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::characterRect");
887 return QRect();
889 int Qt5AccessibleWidget::cursorPosition() const
891 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::cursorPosition");
892 return 0;
894 int Qt5AccessibleWidget::offsetAtPoint(const QPoint& /* point */) const
896 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::offsetAtPoint");
897 return 0;
899 void Qt5AccessibleWidget::removeSelection(int /* selectionIndex */)
901 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::removeSelection");
903 void Qt5AccessibleWidget::scrollToSubstring(int startIndex, int endIndex)
905 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
906 if (xText.is())
907 xText->scrollSubstringTo(startIndex, endIndex, AccessibleScrollType_SCROLL_ANYWHERE);
910 void Qt5AccessibleWidget::selection(int selectionIndex, int* startOffset, int* endOffset) const
912 if (!startOffset && !endOffset)
913 return;
915 Reference<XAccessibleText> xText;
916 if (selectionIndex == 0)
917 xText = Reference<XAccessibleText>(m_xAccessible, UNO_QUERY);
919 if (startOffset)
920 *startOffset = xText.is() ? xText->getSelectionStart() : 0;
921 if (endOffset)
922 *endOffset = xText.is() ? xText->getSelectionEnd() : 0;
925 int Qt5AccessibleWidget::selectionCount() const
927 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
928 if (xText.is() && !xText->getSelectedText().isEmpty())
929 return 1; // Only 1 selection supported atm
930 return 0;
932 void Qt5AccessibleWidget::setCursorPosition(int position)
934 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
935 if (xText.is())
936 xText->setCaretPosition(position);
938 void Qt5AccessibleWidget::setSelection(int /* selectionIndex */, int startOffset, int endOffset)
940 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
941 if (xText.is())
942 xText->setSelection(startOffset, endOffset);
944 QString Qt5AccessibleWidget::text(int startOffset, int endOffset) const
946 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
947 if (xText.is())
948 return toQString(xText->getTextRange(startOffset, endOffset));
949 return QString();
951 QString Qt5AccessibleWidget::textAfterOffset(int /* offset */,
952 QAccessible::TextBoundaryType /* boundaryType */,
953 int* /* startOffset */, int* /* endOffset */) const
955 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::textAfterOffset");
956 return QString();
958 QString Qt5AccessibleWidget::textAtOffset(int /* offset */,
959 QAccessible::TextBoundaryType /* boundaryType */,
960 int* /* startOffset */, int* /* endOffset */) const
962 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::textAtOffset");
963 return QString();
965 QString Qt5AccessibleWidget::textBeforeOffset(int /* offset */,
966 QAccessible::TextBoundaryType /* boundaryType */,
967 int* /* startOffset */, int* /* endOffset */) const
969 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::textBeforeOffset");
970 return QString();
973 // QAccessibleEditableTextInterface
975 void Qt5AccessibleWidget::deleteText(int startOffset, int endOffset)
977 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
978 if (!xAc.is())
979 return;
981 Reference<XAccessibleEditableText> xEditableText(xAc, UNO_QUERY);
982 if (!xEditableText.is())
983 return;
984 xEditableText->deleteText(startOffset, endOffset);
987 void Qt5AccessibleWidget::insertText(int offset, const QString& text)
989 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
990 if (!xAc.is())
991 return;
993 Reference<XAccessibleEditableText> xEditableText(xAc, UNO_QUERY);
994 if (!xEditableText.is())
995 return;
996 xEditableText->insertText(toOUString(text), offset);
999 void Qt5AccessibleWidget::replaceText(int startOffset, int endOffset, const QString& text)
1001 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1002 if (!xAc.is())
1003 return;
1005 Reference<XAccessibleEditableText> xEditableText(xAc, UNO_QUERY);
1006 if (!xEditableText.is())
1007 return;
1008 xEditableText->replaceText(startOffset, endOffset, toOUString(text));
1011 // QAccessibleValueInterface
1012 QVariant Qt5AccessibleWidget::currentValue() const
1014 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1015 if (!xAc.is())
1016 return QVariant();
1018 Reference<XAccessibleValue> xValue(xAc, UNO_QUERY);
1019 if (!xValue.is())
1020 return QVariant();
1021 double aDouble = 0;
1022 xValue->getCurrentValue() >>= aDouble;
1023 return QVariant(aDouble);
1025 QVariant Qt5AccessibleWidget::maximumValue() const
1027 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1028 if (!xAc.is())
1029 return QVariant();
1031 Reference<XAccessibleValue> xValue(xAc, UNO_QUERY);
1032 if (!xValue.is())
1033 return QVariant();
1034 double aDouble = 0;
1035 xValue->getMaximumValue() >>= aDouble;
1036 return QVariant(aDouble);
1038 QVariant Qt5AccessibleWidget::minimumStepSize() const { return QVariant(); }
1039 QVariant Qt5AccessibleWidget::minimumValue() const
1041 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1042 if (!xAc.is())
1043 return QVariant();
1045 Reference<XAccessibleValue> xValue(xAc, UNO_QUERY);
1046 if (!xValue.is())
1047 return QVariant();
1048 double aDouble = 0;
1049 xValue->getMinimumValue() >>= aDouble;
1050 return QVariant(aDouble);
1052 void Qt5AccessibleWidget::setCurrentValue(const QVariant& value)
1054 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1055 if (!xAc.is())
1056 return;
1058 Reference<XAccessibleValue> xValue(xAc, UNO_QUERY);
1059 if (!xValue.is())
1060 return;
1061 xValue->setCurrentValue(Any(value.toDouble()));
1064 // QAccessibleTable
1065 QAccessibleInterface* Qt5AccessibleWidget::caption() const
1067 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1068 if (!xAc.is())
1069 return nullptr;
1071 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1072 if (!xTable.is())
1073 return nullptr;
1074 return QAccessible::queryAccessibleInterface(
1075 new Qt5XAccessible(xTable->getAccessibleCaption()));
1078 QAccessibleInterface* Qt5AccessibleWidget::cellAt(int row, int column) const
1080 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1081 if (!xAc.is())
1082 return nullptr;
1084 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1085 if (!xTable.is())
1086 return nullptr;
1087 return QAccessible::queryAccessibleInterface(
1088 new Qt5XAccessible(xTable->getAccessibleCellAt(row, column)));
1091 int Qt5AccessibleWidget::columnCount() const
1093 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1094 if (!xAc.is())
1095 return 0;
1097 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1098 if (!xTable.is())
1099 return 0;
1100 return xTable->getAccessibleColumnCount();
1103 QString Qt5AccessibleWidget::columnDescription(int column) const
1105 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1106 if (!xAc.is())
1107 return QString();
1109 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1110 if (!xTable.is())
1111 return QString();
1112 return toQString(xTable->getAccessibleColumnDescription(column));
1115 bool Qt5AccessibleWidget::isColumnSelected(int /* column */) const { return true; }
1117 bool Qt5AccessibleWidget::isRowSelected(int /* row */) const { return true; }
1119 void Qt5AccessibleWidget::modelChange(QAccessibleTableModelChangeEvent*) {}
1121 int Qt5AccessibleWidget::rowCount() const
1123 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1124 if (!xAc.is())
1125 return 0;
1127 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1128 if (!xTable.is())
1129 return 0;
1130 return xTable->getAccessibleRowCount();
1133 QString Qt5AccessibleWidget::rowDescription(int row) const
1135 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1136 if (!xAc.is())
1137 return QString();
1139 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1140 if (!xTable.is())
1141 return QString();
1142 return toQString(xTable->getAccessibleRowDescription(row));
1145 bool Qt5AccessibleWidget::selectColumn(int column)
1147 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1148 if (!xAc.is())
1149 return false;
1151 Reference<XAccessibleTableSelection> xTableSelection(xAc, UNO_QUERY);
1152 if (!xTableSelection.is())
1153 return false;
1154 return xTableSelection->selectColumn(column);
1157 bool Qt5AccessibleWidget::selectRow(int row)
1159 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1160 if (!xAc.is())
1161 return false;
1163 Reference<XAccessibleTableSelection> xTableSelection(xAc, UNO_QUERY);
1164 if (!xTableSelection.is())
1165 return false;
1166 return xTableSelection->selectRow(row);
1169 int Qt5AccessibleWidget::selectedCellCount() const
1171 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTableInterface::selectedCellCount");
1172 return 0;
1175 QList<QAccessibleInterface*> Qt5AccessibleWidget::selectedCells() const
1177 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTableInterface::selectedCells");
1178 return QList<QAccessibleInterface*>();
1181 int Qt5AccessibleWidget::selectedColumnCount() const
1183 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1184 if (!xAc.is())
1185 return 0;
1187 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1188 if (!xTable.is())
1189 return 0;
1190 return xTable->getSelectedAccessibleColumns().getLength();
1193 QList<int> Qt5AccessibleWidget::selectedColumns() const
1195 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1196 if (!xAc.is())
1197 return QList<int>();
1199 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1200 if (!xTable.is())
1201 return QList<int>();
1202 return toQList(xTable->getSelectedAccessibleColumns());
1205 int Qt5AccessibleWidget::selectedRowCount() const
1207 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1208 if (!xAc.is())
1209 return 0;
1211 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1212 if (!xTable.is())
1213 return 0;
1214 return xTable->getSelectedAccessibleRows().getLength();
1217 QList<int> Qt5AccessibleWidget::selectedRows() const
1219 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1220 if (!xAc.is())
1221 return QList<int>();
1223 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1224 if (!xTable.is())
1225 return QList<int>();
1226 return toQList(xTable->getSelectedAccessibleRows());
1229 QAccessibleInterface* Qt5AccessibleWidget::summary() const
1231 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1232 if (!xAc.is())
1233 return nullptr;
1235 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1236 if (!xTable.is())
1237 return nullptr;
1238 return QAccessible::queryAccessibleInterface(
1239 new Qt5XAccessible(xTable->getAccessibleSummary()));
1242 bool Qt5AccessibleWidget::unselectColumn(int column)
1244 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1245 if (!xAc.is())
1246 return false;
1248 Reference<XAccessibleTableSelection> xTableSelection(xAc, UNO_QUERY);
1249 if (!xTableSelection.is())
1250 return false;
1251 return xTableSelection->unselectColumn(column);
1254 bool Qt5AccessibleWidget::unselectRow(int row)
1256 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1257 if (!xAc.is())
1258 return false;
1260 Reference<XAccessibleTableSelection> xTableSelection(xAc, UNO_QUERY);
1261 if (!xTableSelection.is())
1262 return false;
1263 return xTableSelection->unselectRow(row);
1266 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */