bump product version to 6.4.0.3
[LibreOffice.git] / vcl / qt5 / Qt5AccessibleWidget.cxx
blob6a828865036ed18264bd6e7f0dee316225b09bab
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/AccessibleStateType.hpp>
34 #include <com/sun/star/accessibility/XAccessible.hpp>
35 #include <com/sun/star/accessibility/XAccessibleAction.hpp>
36 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
37 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
38 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
39 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
40 #include <com/sun/star/accessibility/XAccessibleKeyBinding.hpp>
41 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
42 #include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
43 #include <com/sun/star/accessibility/XAccessibleTable.hpp>
44 #include <com/sun/star/accessibility/XAccessibleTableSelection.hpp>
45 #include <com/sun/star/accessibility/XAccessibleText.hpp>
46 #include <com/sun/star/accessibility/XAccessibleValue.hpp>
47 #include <com/sun/star/awt/FontWeight.hpp>
48 #include <com/sun/star/beans/PropertyValue.hpp>
49 #include <com/sun/star/lang/DisposedException.hpp>
50 #include <com/sun/star/uno/Sequence.hxx>
52 #include <comphelper/AccessibleImplementationHelper.hxx>
53 #include <sal/log.hxx>
54 #include <vcl/popupmenuwindow.hxx>
56 using namespace css;
57 using namespace css::accessibility;
58 using namespace css::beans;
59 using namespace css::uno;
61 Qt5AccessibleWidget::Qt5AccessibleWidget(const Reference<XAccessible> xAccessible)
62 : m_xAccessible(xAccessible)
64 Reference<XAccessibleContext> xContext = xAccessible->getAccessibleContext();
65 Reference<XAccessibleEventBroadcaster> xBroadcaster(xContext, UNO_QUERY);
66 if (xBroadcaster.is())
68 Reference<XAccessibleEventListener> xListener(
69 new Qt5AccessibleEventListener(xAccessible, this));
70 xBroadcaster->addAccessibleEventListener(xListener);
74 Reference<XAccessibleContext> Qt5AccessibleWidget::getAccessibleContextImpl() const
76 Reference<XAccessibleContext> xAc;
78 if (m_xAccessible.is())
80 try
82 xAc = m_xAccessible->getAccessibleContext();
84 catch (css::lang::DisposedException /*ex*/)
86 SAL_WARN("vcl.qt5", "Accessible context disposed already");
88 // sometimes getAccessibleContext throws also RuntimeException if context is no longer alive
89 catch (css::uno::RuntimeException /*ex*/)
91 // so let's catch it here, cuz otherwise soffice falls flat on its face
92 // with FatalError and nothing else
93 SAL_WARN("vcl.qt5", "Accessible context no longer alive");
97 return xAc;
100 QWindow* Qt5AccessibleWidget::window() const { return nullptr; }
102 int Qt5AccessibleWidget::childCount() const
104 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
105 if (!xAc.is())
106 return 0;
108 return xAc->getAccessibleChildCount();
111 int Qt5AccessibleWidget::indexOfChild(const QAccessibleInterface* /* child */) const { return 0; }
113 namespace
115 QAccessible::Relation lcl_matchUnoRelation(short relationType)
117 switch (relationType)
119 case AccessibleRelationType::CONTROLLER_FOR:
120 return QAccessible::Controller;
121 case AccessibleRelationType::CONTROLLED_BY:
122 return QAccessible::Controlled;
123 case AccessibleRelationType::LABEL_FOR:
124 return QAccessible::Label;
125 case AccessibleRelationType::LABELED_BY:
126 return QAccessible::Labelled;
127 case AccessibleRelationType::INVALID:
128 case AccessibleRelationType::CONTENT_FLOWS_FROM:
129 case AccessibleRelationType::CONTENT_FLOWS_TO:
130 case AccessibleRelationType::MEMBER_OF:
131 case AccessibleRelationType::SUB_WINDOW_OF:
132 case AccessibleRelationType::NODE_CHILD_OF:
133 case AccessibleRelationType::DESCRIBED_BY:
134 default:
135 SAL_WARN("vcl.qt5", "Unmatched relation: " << relationType);
136 return nullptr;
140 short lcl_matchQtRelation(QAccessible::Relation relationType)
142 switch (relationType)
144 case QAccessible::Controller:
145 return AccessibleRelationType::CONTROLLER_FOR;
146 case QAccessible::Controlled:
147 return AccessibleRelationType::CONTROLLED_BY;
148 case QAccessible::Label:
149 return AccessibleRelationType::LABEL_FOR;
150 case QAccessible::Labelled:
151 return AccessibleRelationType::LABELED_BY;
152 default:
153 SAL_WARN("vcl.qt5", "Unmatched relation: " << relationType);
155 return 0;
158 void lcl_appendRelation(QVector<QPair<QAccessibleInterface*, QAccessible::Relation>>* relations,
159 AccessibleRelation aRelation)
161 QAccessible::Relation aQRelation = lcl_matchUnoRelation(aRelation.RelationType);
162 sal_uInt32 nTargetCount = aRelation.TargetSet.getLength();
164 for (sal_uInt32 i = 0; i < nTargetCount; i++)
166 Reference<XAccessible> xAccessible(aRelation.TargetSet[i], uno::UNO_QUERY);
167 relations->append(
168 { QAccessible::queryAccessibleInterface(new Qt5XAccessible(xAccessible)), aQRelation });
173 QVector<QPair<QAccessibleInterface*, QAccessible::Relation>>
174 Qt5AccessibleWidget::relations(QAccessible::Relation match) const
176 QVector<QPair<QAccessibleInterface*, QAccessible::Relation>> relations;
178 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
179 if (!xAc.is())
180 return relations;
182 Reference<XAccessibleRelationSet> xRelationSet = xAc->getAccessibleRelationSet();
183 if (xRelationSet.is())
185 if (match == QAccessible::AllRelations)
187 int count = xRelationSet->getRelationCount();
188 for (int i = 0; i < count; i++)
190 AccessibleRelation aRelation = xRelationSet->getRelation(i);
191 lcl_appendRelation(&relations, aRelation);
194 else
196 AccessibleRelation aRelation = xRelationSet->getRelation(lcl_matchQtRelation(match));
197 lcl_appendRelation(&relations, aRelation);
201 return relations;
204 QAccessibleInterface* Qt5AccessibleWidget::focusChild() const
206 /* if (m_pWindow->HasChildPathFocus())
207 return QAccessible::queryAccessibleInterface(
208 new Qt5XAccessible(m_xAccessible->getAccessibleContext()->getAccessibleChild(index))); */
209 return QAccessible::queryAccessibleInterface(object());
212 QRect Qt5AccessibleWidget::rect() const
214 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
215 if (!xAc.is())
216 return QRect();
218 Reference<XAccessibleComponent> xAccessibleComponent(xAc, UNO_QUERY);
219 awt::Point aPoint = xAccessibleComponent->getLocation();
220 awt::Size aSize = xAccessibleComponent->getSize();
222 return QRect(aPoint.X, aPoint.Y, aSize.Width, aSize.Height);
225 QAccessibleInterface* Qt5AccessibleWidget::parent() const
227 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
228 if (!xAc.is())
229 return nullptr;
231 return QAccessible::queryAccessibleInterface(new Qt5XAccessible(xAc->getAccessibleParent()));
233 QAccessibleInterface* Qt5AccessibleWidget::child(int index) const
235 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
236 if (!xAc.is())
237 return nullptr;
239 return QAccessible::queryAccessibleInterface(
240 new Qt5XAccessible(xAc->getAccessibleChild(index)));
243 QString Qt5AccessibleWidget::text(QAccessible::Text text) const
245 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
246 if (!xAc.is())
247 return QString();
249 switch (text)
251 case QAccessible::Name:
252 return toQString(xAc->getAccessibleName());
253 case QAccessible::Description:
254 case QAccessible::DebugDescription:
255 return toQString(xAc->getAccessibleDescription());
256 case QAccessible::Value:
257 case QAccessible::Help:
258 case QAccessible::Accelerator:
259 case QAccessible::UserText:
260 default:
261 return QString("Unknown");
264 QAccessible::Role Qt5AccessibleWidget::role() const
266 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
267 if (!xAc.is())
268 return QAccessible::NoRole;
270 switch (xAc->getAccessibleRole())
272 case AccessibleRole::UNKNOWN:
273 return QAccessible::NoRole;
275 case AccessibleRole::ALERT:
276 return QAccessible::AlertMessage;
278 case AccessibleRole::COLUMN_HEADER:
279 return QAccessible::ColumnHeader;
281 case AccessibleRole::CANVAS:
282 return QAccessible::Canvas;
284 case AccessibleRole::CHECK_BOX:
285 return QAccessible::CheckBox;
287 case AccessibleRole::CHECK_MENU_ITEM:
288 return QAccessible::MenuItem;
290 case AccessibleRole::COLOR_CHOOSER:
291 return QAccessible::ColorChooser;
293 case AccessibleRole::COMBO_BOX:
294 return QAccessible::ComboBox;
296 case AccessibleRole::DATE_EDITOR:
297 return QAccessible::EditableText;
299 case AccessibleRole::DESKTOP_ICON:
300 return QAccessible::Graphic;
302 case AccessibleRole::DESKTOP_PANE:
303 case AccessibleRole::DIRECTORY_PANE:
304 return QAccessible::Pane;
306 case AccessibleRole::DIALOG:
307 return QAccessible::Dialog;
309 case AccessibleRole::DOCUMENT:
310 return QAccessible::Document;
312 case AccessibleRole::EMBEDDED_OBJECT:
313 return QAccessible::UserRole;
315 case AccessibleRole::END_NOTE:
316 return QAccessible::Note;
318 case AccessibleRole::FILLER:
319 return QAccessible::Whitespace;
321 case AccessibleRole::FONT_CHOOSER:
322 return QAccessible::UserRole;
324 case AccessibleRole::FOOTER:
325 return QAccessible::Footer;
327 case AccessibleRole::FOOTNOTE:
328 return QAccessible::Note;
330 case AccessibleRole::FRAME: // top-level window with title bar
331 return QAccessible::Window;
333 case AccessibleRole::GLASS_PANE:
334 return QAccessible::UserRole;
336 case AccessibleRole::GRAPHIC:
337 return QAccessible::Graphic;
339 case AccessibleRole::GROUP_BOX:
340 return QAccessible::Grouping;
342 case AccessibleRole::HEADER:
343 return QAccessible::UserRole;
345 case AccessibleRole::HEADING:
346 return QAccessible::Heading;
348 case AccessibleRole::HYPER_LINK:
349 return QAccessible::Link;
351 case AccessibleRole::ICON:
352 return QAccessible::Graphic;
354 case AccessibleRole::INTERNAL_FRAME:
355 return QAccessible::UserRole;
357 case AccessibleRole::LABEL:
358 return QAccessible::StaticText;
360 case AccessibleRole::LAYERED_PANE:
361 return QAccessible::Pane;
363 case AccessibleRole::LIST:
364 return QAccessible::List;
366 case AccessibleRole::LIST_ITEM:
367 return QAccessible::ListItem;
369 case AccessibleRole::MENU:
370 case AccessibleRole::MENU_BAR:
371 return QAccessible::MenuBar;
373 case AccessibleRole::MENU_ITEM:
374 return QAccessible::MenuItem;
376 case AccessibleRole::OPTION_PANE:
377 return QAccessible::Pane;
379 case AccessibleRole::PAGE_TAB:
380 return QAccessible::PageTab;
382 case AccessibleRole::PAGE_TAB_LIST:
383 return QAccessible::PageTabList;
385 case AccessibleRole::PANEL:
386 return QAccessible::Pane;
388 case AccessibleRole::PARAGRAPH:
389 return QAccessible::Paragraph;
391 case AccessibleRole::PASSWORD_TEXT:
392 return QAccessible::EditableText;
394 case AccessibleRole::POPUP_MENU:
395 return QAccessible::PopupMenu;
397 case AccessibleRole::PUSH_BUTTON:
398 return QAccessible::Button;
400 case AccessibleRole::PROGRESS_BAR:
401 return QAccessible::ProgressBar;
403 case AccessibleRole::RADIO_BUTTON:
404 return QAccessible::RadioButton;
406 case AccessibleRole::RADIO_MENU_ITEM:
407 return QAccessible::MenuItem;
409 case AccessibleRole::ROW_HEADER:
410 return QAccessible::RowHeader;
412 case AccessibleRole::ROOT_PANE:
413 return QAccessible::Pane;
415 case AccessibleRole::SCROLL_BAR:
416 return QAccessible::ScrollBar;
418 case AccessibleRole::SCROLL_PANE:
419 return QAccessible::Pane;
421 case AccessibleRole::SHAPE:
422 return QAccessible::Graphic;
424 case AccessibleRole::SEPARATOR:
425 return QAccessible::Separator;
427 case AccessibleRole::SLIDER:
428 return QAccessible::Slider;
430 case AccessibleRole::SPIN_BOX:
431 return QAccessible::SpinBox;
433 case AccessibleRole::SPLIT_PANE:
434 return QAccessible::Pane;
436 case AccessibleRole::STATUS_BAR:
437 return QAccessible::StatusBar;
439 case AccessibleRole::TABLE:
440 return QAccessible::Table;
442 case AccessibleRole::TABLE_CELL:
443 return QAccessible::Cell;
445 case AccessibleRole::TEXT:
446 return QAccessible::EditableText;
448 case AccessibleRole::TEXT_FRAME:
449 return QAccessible::UserRole;
451 case AccessibleRole::TOGGLE_BUTTON:
452 return QAccessible::Button;
454 case AccessibleRole::TOOL_BAR:
455 return QAccessible::ToolBar;
457 case AccessibleRole::TOOL_TIP:
458 return QAccessible::ToolTip;
460 case AccessibleRole::TREE:
461 return QAccessible::Tree;
463 case AccessibleRole::VIEW_PORT:
464 return QAccessible::UserRole;
466 case AccessibleRole::BUTTON_DROPDOWN:
467 return QAccessible::Button;
469 case AccessibleRole::BUTTON_MENU:
470 return QAccessible::Button;
472 case AccessibleRole::CAPTION:
473 return QAccessible::StaticText;
475 case AccessibleRole::CHART:
476 return QAccessible::Chart;
478 case AccessibleRole::EDIT_BAR:
479 return QAccessible::Equation;
481 case AccessibleRole::FORM:
482 return QAccessible::Form;
484 case AccessibleRole::IMAGE_MAP:
485 return QAccessible::Graphic;
487 case AccessibleRole::NOTE:
488 return QAccessible::Note;
490 case AccessibleRole::RULER:
491 return QAccessible::UserRole;
493 case AccessibleRole::SECTION:
494 return QAccessible::Section;
496 case AccessibleRole::TREE_ITEM:
497 return QAccessible::TreeItem;
499 case AccessibleRole::TREE_TABLE:
500 return QAccessible::Tree;
502 case AccessibleRole::COMMENT:
503 return QAccessible::Note;
505 case AccessibleRole::COMMENT_END:
506 return QAccessible::UserRole;
508 case AccessibleRole::DOCUMENT_PRESENTATION:
509 return QAccessible::Document;
511 case AccessibleRole::DOCUMENT_SPREADSHEET:
512 return QAccessible::Document;
514 case AccessibleRole::DOCUMENT_TEXT:
515 return QAccessible::Document;
517 case AccessibleRole::STATIC:
518 return QAccessible::StaticText;
520 /* Ignore window objects for sub-menus, combo- and list boxes,
521 * which are exposed as children of their parents.
523 case AccessibleRole::WINDOW: // top-level window without title bar
525 return QAccessible::Window;
529 SAL_WARN("vcl.qt5",
530 "Unmapped role: " << m_xAccessible->getAccessibleContext()->getAccessibleRole());
531 return QAccessible::NoRole;
534 namespace
536 void lcl_addState(QAccessible::State* state, sal_Int16 nState)
538 switch (nState)
540 case AccessibleStateType::INVALID:
541 state->invalid = true;
542 break;
543 case AccessibleStateType::ACTIVE:
544 state->active = true;
545 break;
546 case AccessibleStateType::ARMED:
547 // No match
548 break;
549 case AccessibleStateType::BUSY:
550 state->busy = true;
551 break;
552 case AccessibleStateType::CHECKED:
553 state->checked = true;
554 break;
555 case AccessibleStateType::EDITABLE:
556 state->editable = true;
557 break;
558 case AccessibleStateType::ENABLED:
559 state->disabled = false;
560 break;
561 case AccessibleStateType::EXPANDABLE:
562 state->expandable = true;
563 break;
564 case AccessibleStateType::FOCUSABLE:
565 state->focusable = true;
566 break;
567 case AccessibleStateType::FOCUSED:
568 state->focused = true;
569 break;
570 case AccessibleStateType::HORIZONTAL:
571 // No match
572 break;
573 case AccessibleStateType::ICONIFIED:
574 // No match
575 break;
576 case AccessibleStateType::INDETERMINATE:
577 // No match
578 break;
579 case AccessibleStateType::MANAGES_DESCENDANTS:
580 // No match
581 break;
582 case AccessibleStateType::MODAL:
583 state->modal = true;
584 break;
585 case AccessibleStateType::OPAQUE:
586 // No match
587 break;
588 case AccessibleStateType::PRESSED:
589 state->pressed = true;
590 break;
591 case AccessibleStateType::RESIZABLE:
592 state->sizeable = true;
593 break;
594 case AccessibleStateType::SELECTABLE:
595 state->selectable = true;
596 break;
597 case AccessibleStateType::SELECTED:
598 state->selected = true;
599 break;
600 case AccessibleStateType::SENSITIVE:
601 // No match
602 break;
603 case AccessibleStateType::SHOWING:
604 // No match
605 break;
606 case AccessibleStateType::SINGLE_LINE:
607 // No match
608 break;
609 case AccessibleStateType::STALE:
610 // No match
611 break;
612 case AccessibleStateType::TRANSIENT:
613 // No match
614 break;
615 case AccessibleStateType::VERTICAL:
616 // No match
617 break;
618 case AccessibleStateType::VISIBLE:
619 state->invisible = false;
620 break;
621 case AccessibleStateType::DEFAULT:
622 // No match
623 break;
624 case AccessibleStateType::DEFUNC:
625 state->invalid = true;
626 break;
627 case AccessibleStateType::MULTI_SELECTABLE:
628 state->multiSelectable = true;
629 break;
630 default:
631 SAL_WARN("vcl.qt5", "Unmapped state: " << nState);
632 break;
637 QAccessible::State Qt5AccessibleWidget::state() const
639 QAccessible::State state;
641 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
642 if (!xAc.is())
643 return state;
645 Reference<XAccessibleStateSet> xStateSet(xAc->getAccessibleStateSet());
647 if (!xStateSet.is())
648 return state;
650 Sequence<sal_Int16> aStates = xStateSet->getStates();
652 for (sal_Int32 n = 0; n < aStates.getLength(); n++)
654 lcl_addState(&state, n);
657 return state;
660 QColor Qt5AccessibleWidget::foregroundColor() const
662 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
663 if (!xAc.is())
664 return QColor();
666 Reference<XAccessibleComponent> xAccessibleComponent(xAc, UNO_QUERY);
667 return toQColor(xAccessibleComponent->getForeground());
670 QColor Qt5AccessibleWidget::backgroundColor() const
672 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
673 if (!xAc.is())
674 return QColor();
676 Reference<XAccessibleComponent> xAccessibleComponent(xAc, UNO_QUERY);
677 return toQColor(xAccessibleComponent->getBackground());
680 void* Qt5AccessibleWidget::interface_cast(QAccessible::InterfaceType t)
682 if (t == QAccessible::ActionInterface)
683 return static_cast<QAccessibleActionInterface*>(this);
684 if (t == QAccessible::TextInterface)
685 return static_cast<QAccessibleTextInterface*>(this);
686 if (t == QAccessible::EditableTextInterface)
687 return static_cast<QAccessibleEditableTextInterface*>(this);
688 if (t == QAccessible::ValueInterface)
689 return static_cast<QAccessibleValueInterface*>(this);
690 if (t == QAccessible::TableInterface)
691 return static_cast<QAccessibleTableInterface*>(this);
692 return nullptr;
695 bool Qt5AccessibleWidget::isValid() const
697 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
698 return xAc.is();
701 QObject* Qt5AccessibleWidget::object() const { return nullptr; }
703 void Qt5AccessibleWidget::setText(QAccessible::Text /* t */, const QString& /* text */) {}
705 QAccessibleInterface* Qt5AccessibleWidget::childAt(int x, int y) const
707 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
708 if (!xAc.is())
709 return nullptr;
711 Reference<XAccessibleComponent> xAccessibleComponent(xAc, UNO_QUERY);
712 return QAccessible::queryAccessibleInterface(
713 new Qt5XAccessible(xAccessibleComponent->getAccessibleAtPoint(awt::Point(x, y))));
716 QAccessibleInterface* Qt5AccessibleWidget::customFactory(const QString& classname, QObject* object)
718 if (classname == QLatin1String("Qt5Widget") && object && object->isWidgetType())
720 Qt5Widget* pWidget = static_cast<Qt5Widget*>(object);
721 vcl::Window* pWindow = pWidget->frame().GetWindow();
723 if (pWindow)
724 return new Qt5AccessibleWidget(pWindow->GetAccessible());
726 if (classname == QLatin1String("Qt5XAccessible") && object)
728 Qt5XAccessible* pXAccessible = dynamic_cast<Qt5XAccessible*>(object);
729 if (pXAccessible && pXAccessible->m_xAccessible.is())
730 return new Qt5AccessibleWidget(pXAccessible->m_xAccessible);
733 return nullptr;
736 // QAccessibleActionInterface
737 QStringList Qt5AccessibleWidget::actionNames() const
739 QStringList actionNames;
740 Reference<XAccessibleAction> xAccessibleAction(m_xAccessible, UNO_QUERY);
741 if (!xAccessibleAction.is())
742 return actionNames;
744 int count = xAccessibleAction->getAccessibleActionCount();
745 for (int i = 0; i < count; i++)
747 OUString desc = xAccessibleAction->getAccessibleActionDescription(i);
748 actionNames.append(toQString(desc));
750 return actionNames;
753 void Qt5AccessibleWidget::doAction(const QString& actionName)
755 Reference<XAccessibleAction> xAccessibleAction(m_xAccessible, UNO_QUERY);
756 if (!xAccessibleAction.is())
757 return;
759 int index = actionNames().indexOf(actionName);
760 if (index == -1)
761 return;
762 xAccessibleAction->doAccessibleAction(index);
765 QStringList Qt5AccessibleWidget::keyBindingsForAction(const QString& actionName) const
767 QStringList keyBindings;
768 Reference<XAccessibleAction> xAccessibleAction(m_xAccessible, UNO_QUERY);
769 if (!xAccessibleAction.is())
770 return keyBindings;
772 int index = actionNames().indexOf(actionName);
773 if (index == -1)
774 return keyBindings;
776 Reference<XAccessibleKeyBinding> xKeyBinding
777 = xAccessibleAction->getAccessibleActionKeyBinding(index);
779 if (!xKeyBinding.is())
780 return keyBindings;
782 int count = xKeyBinding->getAccessibleKeyBindingCount();
783 for (int i = 0; i < count; i++)
785 Sequence<awt::KeyStroke> keyStroke = xKeyBinding->getAccessibleKeyBinding(i);
786 keyBindings.append(toQString(comphelper::GetkeyBindingStrByXkeyBinding(keyStroke)));
788 return keyBindings;
791 QAccessibleValueInterface* Qt5AccessibleWidget::valueInterface() { return nullptr; }
793 QAccessibleTextInterface* Qt5AccessibleWidget::textInterface() { return nullptr; }
795 // QAccessibleTextInterface
796 void Qt5AccessibleWidget::addSelection(int /* startOffset */, int /* endOffset */)
798 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::addSelection");
801 namespace
803 OUString lcl_convertFontWeight(double fontWeight)
805 if (fontWeight == awt::FontWeight::THIN || fontWeight == awt::FontWeight::ULTRALIGHT)
806 return "100";
807 if (fontWeight == awt::FontWeight::LIGHT)
808 return "200";
809 if (fontWeight == awt::FontWeight::SEMILIGHT)
810 return "300";
811 if (fontWeight == awt::FontWeight::NORMAL)
812 return "normal";
813 if (fontWeight == awt::FontWeight::SEMIBOLD)
814 return "500";
815 if (fontWeight == awt::FontWeight::BOLD)
816 return "bold";
817 if (fontWeight == awt::FontWeight::ULTRABOLD)
818 return "800";
819 if (fontWeight == awt::FontWeight::BLACK)
820 return "900";
822 // awt::FontWeight::DONTKNOW || fontWeight == awt::FontWeight::NORMAL
823 return "normal";
827 QString Qt5AccessibleWidget::attributes(int offset, int* startOffset, int* endOffset) const
829 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
830 if (!xText.is())
831 return QString();
833 // handle special values for offset the same way base class's QAccessibleTextWidget::attributes does
834 // (as defined in IAccessible 2: -1 -> length, -2 -> cursor position)
835 if (offset == -2)
836 offset = cursorPosition(); // currently always returns 0
838 const int nTextLength = characterCount();
839 if (offset == -1 || offset == nTextLength)
840 offset = nTextLength - 1;
842 if (offset < 0 || offset > nTextLength)
844 *startOffset = -1;
845 *endOffset = -1;
846 return QString();
849 Sequence<PropertyValue> attribs = xText->getCharacterAttributes(offset, Sequence<OUString>());
850 const PropertyValue* pValues = attribs.getConstArray();
851 OUString aRet;
852 for (sal_Int32 i = 0; i < attribs.getLength(); i++)
854 if (pValues[i].Name == "CharFontName")
856 OUString aStr;
857 pValues[i].Value >>= aStr;
858 aRet += "font-family:" + aStr + ";";
859 continue;
861 if (pValues[i].Name == "CharHeight")
863 double fHeight;
864 pValues[i].Value >>= fHeight;
865 aRet += "font-size:" + OUString::number(fHeight) + "pt;";
866 continue;
868 if (pValues[i].Name == "CharWeight")
870 double fWeight;
871 pValues[i].Value >>= fWeight;
872 aRet += "font-weight:" + lcl_convertFontWeight(fWeight) + ";";
873 continue;
876 *startOffset = offset;
877 *endOffset = offset + 1;
878 return toQString(aRet);
880 int Qt5AccessibleWidget::characterCount() const
882 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
883 if (xText.is())
884 return xText->getCharacterCount();
885 return 0;
887 QRect Qt5AccessibleWidget::characterRect(int /* offset */) const
889 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::characterRect");
890 return QRect();
892 int Qt5AccessibleWidget::cursorPosition() const
894 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::cursorPosition");
895 return 0;
897 int Qt5AccessibleWidget::offsetAtPoint(const QPoint& /* point */) const
899 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::offsetAtPoint");
900 return 0;
902 void Qt5AccessibleWidget::removeSelection(int /* selectionIndex */)
904 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::removeSelection");
906 void Qt5AccessibleWidget::scrollToSubstring(int /* startIndex */, int /* endIndex */)
908 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::scrollToSubstring");
911 void Qt5AccessibleWidget::selection(int selectionIndex, int* startOffset, int* endOffset) const
913 if (!startOffset && !endOffset)
914 return;
916 Reference<XAccessibleText> xText;
917 if (selectionIndex == 0)
918 xText = Reference<XAccessibleText>(m_xAccessible, UNO_QUERY);
920 if (startOffset)
921 *startOffset = xText.is() ? xText->getSelectionStart() : 0;
922 if (endOffset)
923 *endOffset = xText.is() ? xText->getSelectionEnd() : 0;
926 int Qt5AccessibleWidget::selectionCount() const
928 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
929 if (xText.is() && !xText->getSelectedText().isEmpty())
930 return 1; // Only 1 selection supported atm
931 return 0;
933 void Qt5AccessibleWidget::setCursorPosition(int position)
935 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
936 if (xText.is())
937 xText->setCaretPosition(position);
939 void Qt5AccessibleWidget::setSelection(int /* selectionIndex */, int startOffset, int endOffset)
941 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
942 if (xText.is())
943 xText->setSelection(startOffset, endOffset);
945 QString Qt5AccessibleWidget::text(int startOffset, int endOffset) const
947 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
948 if (xText.is())
949 return toQString(xText->getTextRange(startOffset, endOffset));
950 return QString();
952 QString Qt5AccessibleWidget::textAfterOffset(int /* offset */,
953 QAccessible::TextBoundaryType /* boundaryType */,
954 int* /* startOffset */, int* /* endOffset */) const
956 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::textAfterOffset");
957 return QString();
959 QString Qt5AccessibleWidget::textAtOffset(int /* offset */,
960 QAccessible::TextBoundaryType /* boundaryType */,
961 int* /* startOffset */, int* /* endOffset */) const
963 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::textAtOffset");
964 return QString();
966 QString Qt5AccessibleWidget::textBeforeOffset(int /* offset */,
967 QAccessible::TextBoundaryType /* boundaryType */,
968 int* /* startOffset */, int* /* endOffset */) const
970 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::textBeforeOffset");
971 return QString();
974 // QAccessibleEditableTextInterface
976 void Qt5AccessibleWidget::deleteText(int startOffset, int endOffset)
978 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
979 if (!xAc.is())
980 return;
982 Reference<XAccessibleEditableText> xEditableText(xAc, UNO_QUERY);
983 if (!xEditableText.is())
984 return;
985 xEditableText->deleteText(startOffset, endOffset);
988 void Qt5AccessibleWidget::insertText(int offset, const QString& text)
990 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
991 if (!xAc.is())
992 return;
994 Reference<XAccessibleEditableText> xEditableText(xAc, UNO_QUERY);
995 if (!xEditableText.is())
996 return;
997 xEditableText->insertText(toOUString(text), offset);
1000 void Qt5AccessibleWidget::replaceText(int startOffset, int endOffset, const QString& text)
1002 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1003 if (!xAc.is())
1004 return;
1006 Reference<XAccessibleEditableText> xEditableText(xAc, UNO_QUERY);
1007 if (!xEditableText.is())
1008 return;
1009 xEditableText->replaceText(startOffset, endOffset, toOUString(text));
1012 // QAccessibleValueInterface
1013 QVariant Qt5AccessibleWidget::currentValue() const
1015 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1016 if (!xAc.is())
1017 return QVariant();
1019 Reference<XAccessibleValue> xValue(xAc, UNO_QUERY);
1020 if (!xValue.is())
1021 return QVariant();
1022 double aDouble = 0;
1023 xValue->getCurrentValue() >>= aDouble;
1024 return QVariant(aDouble);
1026 QVariant Qt5AccessibleWidget::maximumValue() const
1028 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1029 if (!xAc.is())
1030 return QVariant();
1032 Reference<XAccessibleValue> xValue(xAc, UNO_QUERY);
1033 if (!xValue.is())
1034 return QVariant();
1035 double aDouble = 0;
1036 xValue->getMaximumValue() >>= aDouble;
1037 return QVariant(aDouble);
1039 QVariant Qt5AccessibleWidget::minimumStepSize() const { return QVariant(); }
1040 QVariant Qt5AccessibleWidget::minimumValue() const
1042 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1043 if (!xAc.is())
1044 return QVariant();
1046 Reference<XAccessibleValue> xValue(xAc, UNO_QUERY);
1047 if (!xValue.is())
1048 return QVariant();
1049 double aDouble = 0;
1050 xValue->getMinimumValue() >>= aDouble;
1051 return QVariant(aDouble);
1053 void Qt5AccessibleWidget::setCurrentValue(const QVariant& value)
1055 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1056 if (!xAc.is())
1057 return;
1059 Reference<XAccessibleValue> xValue(xAc, UNO_QUERY);
1060 if (!xValue.is())
1061 return;
1062 xValue->setCurrentValue(Any(value.toDouble()));
1065 // QAccessibleTable
1066 QAccessibleInterface* Qt5AccessibleWidget::caption() const
1068 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1069 if (!xAc.is())
1070 return nullptr;
1072 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1073 if (!xTable.is())
1074 return nullptr;
1075 return QAccessible::queryAccessibleInterface(
1076 new Qt5XAccessible(xTable->getAccessibleCaption()));
1079 QAccessibleInterface* Qt5AccessibleWidget::cellAt(int row, int column) const
1081 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1082 if (!xAc.is())
1083 return nullptr;
1085 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1086 if (!xTable.is())
1087 return nullptr;
1088 return QAccessible::queryAccessibleInterface(
1089 new Qt5XAccessible(xTable->getAccessibleCellAt(row, column)));
1092 int Qt5AccessibleWidget::columnCount() const
1094 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1095 if (!xAc.is())
1096 return 0;
1098 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1099 if (!xTable.is())
1100 return 0;
1101 return xTable->getAccessibleColumnCount();
1104 QString Qt5AccessibleWidget::columnDescription(int column) const
1106 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1107 if (!xAc.is())
1108 return QString();
1110 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1111 if (!xTable.is())
1112 return QString();
1113 return toQString(xTable->getAccessibleColumnDescription(column));
1116 bool Qt5AccessibleWidget::isColumnSelected(int /* column */) const { return true; }
1118 bool Qt5AccessibleWidget::isRowSelected(int /* row */) const { return true; }
1120 void Qt5AccessibleWidget::modelChange(QAccessibleTableModelChangeEvent*) {}
1122 int Qt5AccessibleWidget::rowCount() const
1124 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1125 if (!xAc.is())
1126 return 0;
1128 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1129 if (!xTable.is())
1130 return 0;
1131 return xTable->getAccessibleRowCount();
1134 QString Qt5AccessibleWidget::rowDescription(int row) const
1136 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1137 if (!xAc.is())
1138 return QString();
1140 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1141 if (!xTable.is())
1142 return QString();
1143 return toQString(xTable->getAccessibleRowDescription(row));
1146 bool Qt5AccessibleWidget::selectColumn(int column)
1148 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1149 if (!xAc.is())
1150 return false;
1152 Reference<XAccessibleTableSelection> xTableSelection(xAc, UNO_QUERY);
1153 if (!xTableSelection.is())
1154 return false;
1155 return xTableSelection->selectColumn(column);
1158 bool Qt5AccessibleWidget::selectRow(int row)
1160 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1161 if (!xAc.is())
1162 return false;
1164 Reference<XAccessibleTableSelection> xTableSelection(xAc, UNO_QUERY);
1165 if (!xTableSelection.is())
1166 return false;
1167 return xTableSelection->selectRow(row);
1170 int Qt5AccessibleWidget::selectedCellCount() const
1172 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTableInterface::selectedCellCount");
1173 return 0;
1176 QList<QAccessibleInterface*> Qt5AccessibleWidget::selectedCells() const
1178 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTableInterface::selectedCells");
1179 return QList<QAccessibleInterface*>();
1182 int Qt5AccessibleWidget::selectedColumnCount() const
1184 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1185 if (!xAc.is())
1186 return 0;
1188 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1189 if (!xTable.is())
1190 return 0;
1191 return xTable->getSelectedAccessibleColumns().getLength();
1194 QList<int> Qt5AccessibleWidget::selectedColumns() const
1196 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1197 if (!xAc.is())
1198 return QList<int>();
1200 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1201 if (!xTable.is())
1202 return QList<int>();
1203 return toQList(xTable->getSelectedAccessibleColumns());
1206 int Qt5AccessibleWidget::selectedRowCount() const
1208 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1209 if (!xAc.is())
1210 return 0;
1212 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1213 if (!xTable.is())
1214 return 0;
1215 return xTable->getSelectedAccessibleRows().getLength();
1218 QList<int> Qt5AccessibleWidget::selectedRows() const
1220 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1221 if (!xAc.is())
1222 return QList<int>();
1224 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1225 if (!xTable.is())
1226 return QList<int>();
1227 return toQList(xTable->getSelectedAccessibleRows());
1230 QAccessibleInterface* Qt5AccessibleWidget::summary() const
1232 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1233 if (!xAc.is())
1234 return nullptr;
1236 Reference<XAccessibleTable> xTable(xAc, UNO_QUERY);
1237 if (!xTable.is())
1238 return nullptr;
1239 return QAccessible::queryAccessibleInterface(
1240 new Qt5XAccessible(xTable->getAccessibleSummary()));
1243 bool Qt5AccessibleWidget::unselectColumn(int column)
1245 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1246 if (!xAc.is())
1247 return false;
1249 Reference<XAccessibleTableSelection> xTableSelection(xAc, UNO_QUERY);
1250 if (!xTableSelection.is())
1251 return false;
1252 return xTableSelection->unselectColumn(column);
1255 bool Qt5AccessibleWidget::unselectRow(int row)
1257 Reference<XAccessibleContext> xAc = getAccessibleContextImpl();
1258 if (!xAc.is())
1259 return false;
1261 Reference<XAccessibleTableSelection> xTableSelection(xAc, UNO_QUERY);
1262 if (!xTableSelection.is())
1263 return false;
1264 return xTableSelection->unselectRow(row);
1267 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */