tdf#122056: catch DisposedException to avoid crash w/ screen reader
[LibreOffice.git] / vcl / qt5 / Qt5AccessibleWidget.cxx
blobefafab17f3cf2814d6fcfb1a5ec4cd1c65ab38f2
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 QWindow* Qt5AccessibleWidget::window() const { return nullptr; }
76 int Qt5AccessibleWidget::childCount() const
78 return m_xAccessible->getAccessibleContext()->getAccessibleChildCount();
81 int Qt5AccessibleWidget::indexOfChild(const QAccessibleInterface* /* child */) const { return 0; }
83 namespace
85 QAccessible::Relation lcl_matchUnoRelation(short relationType)
87 switch (relationType)
89 case AccessibleRelationType::CONTROLLER_FOR:
90 return QAccessible::Controller;
91 case AccessibleRelationType::CONTROLLED_BY:
92 return QAccessible::Controlled;
93 case AccessibleRelationType::LABEL_FOR:
94 return QAccessible::Label;
95 case AccessibleRelationType::LABELED_BY:
96 return QAccessible::Labelled;
97 case AccessibleRelationType::INVALID:
98 case AccessibleRelationType::CONTENT_FLOWS_FROM:
99 case AccessibleRelationType::CONTENT_FLOWS_TO:
100 case AccessibleRelationType::MEMBER_OF:
101 case AccessibleRelationType::SUB_WINDOW_OF:
102 case AccessibleRelationType::NODE_CHILD_OF:
103 case AccessibleRelationType::DESCRIBED_BY:
104 default:
105 SAL_WARN("vcl.qt5", "Unmatched relation: " << relationType);
106 return nullptr;
110 short lcl_matchQtRelation(QAccessible::Relation relationType)
112 switch (relationType)
114 case QAccessible::Controller:
115 return AccessibleRelationType::CONTROLLER_FOR;
116 case QAccessible::Controlled:
117 return AccessibleRelationType::CONTROLLED_BY;
118 case QAccessible::Label:
119 return AccessibleRelationType::LABEL_FOR;
120 case QAccessible::Labelled:
121 return AccessibleRelationType::LABELED_BY;
122 default:
123 SAL_WARN("vcl.qt5", "Unmatched relation: " << relationType);
125 return 0;
128 void lcl_appendRelation(QVector<QPair<QAccessibleInterface*, QAccessible::Relation>>* relations,
129 AccessibleRelation aRelation)
131 QAccessible::Relation aQRelation = lcl_matchUnoRelation(aRelation.RelationType);
132 sal_uInt32 nTargetCount = aRelation.TargetSet.getLength();
134 for (sal_uInt32 i = 0; i < nTargetCount; i++)
136 Reference<XAccessible> xAccessible(aRelation.TargetSet[i], uno::UNO_QUERY);
137 relations->append(
138 { QAccessible::queryAccessibleInterface(new Qt5XAccessible(xAccessible)), aQRelation });
143 QVector<QPair<QAccessibleInterface*, QAccessible::Relation>>
144 Qt5AccessibleWidget::relations(QAccessible::Relation match) const
146 QVector<QPair<QAccessibleInterface*, QAccessible::Relation>> relations;
147 Reference<XAccessibleRelationSet> xRelationSet
148 = m_xAccessible->getAccessibleContext()->getAccessibleRelationSet();
149 if (!xRelationSet.is())
150 return relations;
152 if (match == QAccessible::AllRelations)
154 int count = xRelationSet->getRelationCount();
155 for (int i = 0; i < count; i++)
157 AccessibleRelation aRelation = xRelationSet->getRelation(i);
158 lcl_appendRelation(&relations, aRelation);
161 else
163 AccessibleRelation aRelation = xRelationSet->getRelation(lcl_matchQtRelation(match));
164 lcl_appendRelation(&relations, aRelation);
167 return relations;
170 QAccessibleInterface* Qt5AccessibleWidget::focusChild() const
172 /* if (m_pWindow->HasChildPathFocus())
173 return QAccessible::queryAccessibleInterface(
174 new Qt5XAccessible(m_xAccessible->getAccessibleContext()->getAccessibleChild(index))); */
175 return QAccessible::queryAccessibleInterface(object());
178 QRect Qt5AccessibleWidget::rect() const
180 Reference<XAccessibleComponent> xAccessibleComponent(m_xAccessible->getAccessibleContext(),
181 UNO_QUERY);
182 awt::Point aPoint = xAccessibleComponent->getLocation();
183 awt::Size aSize = xAccessibleComponent->getSize();
185 return QRect(aPoint.X, aPoint.Y, aSize.Width, aSize.Height);
188 QAccessibleInterface* Qt5AccessibleWidget::parent() const
190 return QAccessible::queryAccessibleInterface(
191 new Qt5XAccessible(m_xAccessible->getAccessibleContext()->getAccessibleParent()));
193 QAccessibleInterface* Qt5AccessibleWidget::child(int index) const
195 return QAccessible::queryAccessibleInterface(
196 new Qt5XAccessible(m_xAccessible->getAccessibleContext()->getAccessibleChild(index)));
199 QString Qt5AccessibleWidget::text(QAccessible::Text text) const
201 switch (text)
203 case QAccessible::Name:
204 return toQString(m_xAccessible->getAccessibleContext()->getAccessibleName());
205 case QAccessible::Description:
206 case QAccessible::DebugDescription:
207 return toQString(m_xAccessible->getAccessibleContext()->getAccessibleDescription());
208 case QAccessible::Value:
209 case QAccessible::Help:
210 case QAccessible::Accelerator:
211 case QAccessible::UserText:
212 default:
213 return QString("Unknown");
216 QAccessible::Role Qt5AccessibleWidget::role() const
218 if (!m_xAccessible.is())
219 return QAccessible::NoRole;
221 switch (m_xAccessible->getAccessibleContext()->getAccessibleRole())
223 case AccessibleRole::UNKNOWN:
224 return QAccessible::NoRole;
226 case AccessibleRole::ALERT:
227 return QAccessible::AlertMessage;
229 case AccessibleRole::COLUMN_HEADER:
230 return QAccessible::ColumnHeader;
232 case AccessibleRole::CANVAS:
233 return QAccessible::Canvas;
235 case AccessibleRole::CHECK_BOX:
236 return QAccessible::CheckBox;
238 case AccessibleRole::CHECK_MENU_ITEM:
239 return QAccessible::MenuItem;
241 case AccessibleRole::COLOR_CHOOSER:
242 return QAccessible::ColorChooser;
244 case AccessibleRole::COMBO_BOX:
245 return QAccessible::ComboBox;
247 case AccessibleRole::DATE_EDITOR:
248 return QAccessible::EditableText;
250 case AccessibleRole::DESKTOP_ICON:
251 return QAccessible::Graphic;
253 case AccessibleRole::DESKTOP_PANE:
254 case AccessibleRole::DIRECTORY_PANE:
255 return QAccessible::Pane;
257 case AccessibleRole::DIALOG:
258 return QAccessible::Dialog;
260 case AccessibleRole::DOCUMENT:
261 return QAccessible::Document;
263 case AccessibleRole::EMBEDDED_OBJECT:
264 return QAccessible::UserRole;
266 case AccessibleRole::END_NOTE:
267 return QAccessible::Note;
269 case AccessibleRole::FILLER:
270 return QAccessible::Whitespace;
272 case AccessibleRole::FONT_CHOOSER:
273 return QAccessible::UserRole;
275 case AccessibleRole::FOOTER:
276 return QAccessible::Footer;
278 case AccessibleRole::FOOTNOTE:
279 return QAccessible::Note;
281 case AccessibleRole::FRAME: // top-level window with title bar
282 return QAccessible::Window;
284 case AccessibleRole::GLASS_PANE:
285 return QAccessible::UserRole;
287 case AccessibleRole::GRAPHIC:
288 return QAccessible::Graphic;
290 case AccessibleRole::GROUP_BOX:
291 return QAccessible::Grouping;
293 case AccessibleRole::HEADER:
294 return QAccessible::UserRole;
296 case AccessibleRole::HEADING:
297 return QAccessible::Heading;
299 case AccessibleRole::HYPER_LINK:
300 return QAccessible::Link;
302 case AccessibleRole::ICON:
303 return QAccessible::Graphic;
305 case AccessibleRole::INTERNAL_FRAME:
306 return QAccessible::UserRole;
308 case AccessibleRole::LABEL:
309 return QAccessible::StaticText;
311 case AccessibleRole::LAYERED_PANE:
312 return QAccessible::Pane;
314 case AccessibleRole::LIST:
315 return QAccessible::List;
317 case AccessibleRole::LIST_ITEM:
318 return QAccessible::ListItem;
320 case AccessibleRole::MENU:
321 case AccessibleRole::MENU_BAR:
322 return QAccessible::MenuBar;
324 case AccessibleRole::MENU_ITEM:
325 return QAccessible::MenuItem;
327 case AccessibleRole::OPTION_PANE:
328 return QAccessible::Pane;
330 case AccessibleRole::PAGE_TAB:
331 return QAccessible::PageTab;
333 case AccessibleRole::PAGE_TAB_LIST:
334 return QAccessible::PageTabList;
336 case AccessibleRole::PANEL:
337 return QAccessible::Pane;
339 case AccessibleRole::PARAGRAPH:
340 return QAccessible::Paragraph;
342 case AccessibleRole::PASSWORD_TEXT:
343 return QAccessible::EditableText;
345 case AccessibleRole::POPUP_MENU:
346 return QAccessible::PopupMenu;
348 case AccessibleRole::PUSH_BUTTON:
349 return QAccessible::Button;
351 case AccessibleRole::PROGRESS_BAR:
352 return QAccessible::ProgressBar;
354 case AccessibleRole::RADIO_BUTTON:
355 return QAccessible::RadioButton;
357 case AccessibleRole::RADIO_MENU_ITEM:
358 return QAccessible::MenuItem;
360 case AccessibleRole::ROW_HEADER:
361 return QAccessible::RowHeader;
363 case AccessibleRole::ROOT_PANE:
364 return QAccessible::Pane;
366 case AccessibleRole::SCROLL_BAR:
367 return QAccessible::ScrollBar;
369 case AccessibleRole::SCROLL_PANE:
370 return QAccessible::Pane;
372 case AccessibleRole::SHAPE:
373 return QAccessible::Graphic;
375 case AccessibleRole::SEPARATOR:
376 return QAccessible::Separator;
378 case AccessibleRole::SLIDER:
379 return QAccessible::Slider;
381 case AccessibleRole::SPIN_BOX:
382 return QAccessible::SpinBox;
384 case AccessibleRole::SPLIT_PANE:
385 return QAccessible::Pane;
387 case AccessibleRole::STATUS_BAR:
388 return QAccessible::StatusBar;
390 case AccessibleRole::TABLE:
391 return QAccessible::Table;
393 case AccessibleRole::TABLE_CELL:
394 return QAccessible::Cell;
396 case AccessibleRole::TEXT:
397 return QAccessible::EditableText;
399 case AccessibleRole::TEXT_FRAME:
400 return QAccessible::UserRole;
402 case AccessibleRole::TOGGLE_BUTTON:
403 return QAccessible::Button;
405 case AccessibleRole::TOOL_BAR:
406 return QAccessible::ToolBar;
408 case AccessibleRole::TOOL_TIP:
409 return QAccessible::ToolTip;
411 case AccessibleRole::TREE:
412 return QAccessible::Tree;
414 case AccessibleRole::VIEW_PORT:
415 return QAccessible::UserRole;
417 case AccessibleRole::BUTTON_DROPDOWN:
418 return QAccessible::Button;
420 case AccessibleRole::BUTTON_MENU:
421 return QAccessible::Button;
423 case AccessibleRole::CAPTION:
424 return QAccessible::StaticText;
426 case AccessibleRole::CHART:
427 return QAccessible::Chart;
429 case AccessibleRole::EDIT_BAR:
430 return QAccessible::Equation;
432 case AccessibleRole::FORM:
433 return QAccessible::Form;
435 case AccessibleRole::IMAGE_MAP:
436 return QAccessible::Graphic;
438 case AccessibleRole::NOTE:
439 return QAccessible::Note;
441 case AccessibleRole::RULER:
442 return QAccessible::UserRole;
444 case AccessibleRole::SECTION:
445 return QAccessible::Section;
447 case AccessibleRole::TREE_ITEM:
448 return QAccessible::TreeItem;
450 case AccessibleRole::TREE_TABLE:
451 return QAccessible::Tree;
453 case AccessibleRole::COMMENT:
454 return QAccessible::Note;
456 case AccessibleRole::COMMENT_END:
457 return QAccessible::UserRole;
459 case AccessibleRole::DOCUMENT_PRESENTATION:
460 return QAccessible::Document;
462 case AccessibleRole::DOCUMENT_SPREADSHEET:
463 return QAccessible::Document;
465 case AccessibleRole::DOCUMENT_TEXT:
466 return QAccessible::Document;
468 case AccessibleRole::STATIC:
469 return QAccessible::StaticText;
471 /* Ignore window objects for sub-menus, combo- and list boxes,
472 * which are exposed as children of their parents.
474 case AccessibleRole::WINDOW: // top-level window without title bar
476 return QAccessible::Window;
480 SAL_WARN("vcl.qt5",
481 "Unmapped role: " << m_xAccessible->getAccessibleContext()->getAccessibleRole());
482 return QAccessible::NoRole;
485 namespace
487 void lcl_addState(QAccessible::State* state, sal_Int16 nState)
489 switch (nState)
491 case AccessibleStateType::INVALID:
492 state->invalid = true;
493 break;
494 case AccessibleStateType::ACTIVE:
495 state->active = true;
496 break;
497 case AccessibleStateType::ARMED:
498 // No match
499 break;
500 case AccessibleStateType::BUSY:
501 state->busy = true;
502 break;
503 case AccessibleStateType::CHECKED:
504 state->checked = true;
505 break;
506 case AccessibleStateType::EDITABLE:
507 state->editable = true;
508 break;
509 case AccessibleStateType::ENABLED:
510 state->disabled = false;
511 break;
512 case AccessibleStateType::EXPANDABLE:
513 state->expandable = true;
514 break;
515 case AccessibleStateType::FOCUSABLE:
516 state->focusable = true;
517 break;
518 case AccessibleStateType::FOCUSED:
519 state->focused = true;
520 break;
521 case AccessibleStateType::HORIZONTAL:
522 // No match
523 break;
524 case AccessibleStateType::ICONIFIED:
525 // No match
526 break;
527 case AccessibleStateType::INDETERMINATE:
528 // No match
529 break;
530 case AccessibleStateType::MANAGES_DESCENDANTS:
531 // No match
532 break;
533 case AccessibleStateType::MODAL:
534 state->modal = true;
535 break;
536 case AccessibleStateType::OPAQUE:
537 // No match
538 break;
539 case AccessibleStateType::PRESSED:
540 state->pressed = true;
541 break;
542 case AccessibleStateType::RESIZABLE:
543 state->sizeable = true;
544 break;
545 case AccessibleStateType::SELECTABLE:
546 state->selectable = true;
547 break;
548 case AccessibleStateType::SELECTED:
549 state->selected = true;
550 break;
551 case AccessibleStateType::SENSITIVE:
552 // No match
553 break;
554 case AccessibleStateType::SHOWING:
555 // No match
556 break;
557 case AccessibleStateType::SINGLE_LINE:
558 // No match
559 break;
560 case AccessibleStateType::STALE:
561 // No match
562 break;
563 case AccessibleStateType::TRANSIENT:
564 // No match
565 break;
566 case AccessibleStateType::VERTICAL:
567 // No match
568 break;
569 case AccessibleStateType::VISIBLE:
570 state->invisible = false;
571 break;
572 case AccessibleStateType::DEFAULT:
573 // No match
574 break;
575 case AccessibleStateType::DEFUNC:
576 state->invalid = true;
577 break;
578 case AccessibleStateType::MULTI_SELECTABLE:
579 state->multiSelectable = true;
580 break;
581 default:
582 SAL_WARN("vcl.qt5", "Unmapped state: " << nState);
583 break;
588 QAccessible::State Qt5AccessibleWidget::state() const
590 QAccessible::State state;
592 if (!m_xAccessible.is())
593 return state;
594 Reference<XAccessibleStateSet> xStateSet(
595 m_xAccessible->getAccessibleContext()->getAccessibleStateSet());
597 if (!xStateSet.is())
598 return state;
600 Sequence<sal_Int16> aStates = xStateSet->getStates();
602 for (sal_Int32 n = 0; n < aStates.getLength(); n++)
604 lcl_addState(&state, n);
607 return state;
610 QColor Qt5AccessibleWidget::foregroundColor() const
612 Reference<XAccessibleComponent> xAccessibleComponent(m_xAccessible->getAccessibleContext(),
613 UNO_QUERY);
614 return toQColor(xAccessibleComponent->getForeground());
616 QColor Qt5AccessibleWidget::backgroundColor() const
618 Reference<XAccessibleComponent> xAccessibleComponent(m_xAccessible->getAccessibleContext(),
619 UNO_QUERY);
620 return toQColor(xAccessibleComponent->getBackground());
623 void* Qt5AccessibleWidget::interface_cast(QAccessible::InterfaceType t)
625 if (t == QAccessible::ActionInterface)
626 return static_cast<QAccessibleActionInterface*>(this);
627 if (t == QAccessible::TextInterface)
628 return static_cast<QAccessibleTextInterface*>(this);
629 if (t == QAccessible::EditableTextInterface)
630 return static_cast<QAccessibleEditableTextInterface*>(this);
631 if (t == QAccessible::ValueInterface)
632 return static_cast<QAccessibleValueInterface*>(this);
633 if (t == QAccessible::TableInterface)
634 return static_cast<QAccessibleTableInterface*>(this);
635 return nullptr;
638 bool Qt5AccessibleWidget::isValid() const
640 if (m_xAccessible.is())
644 // getAccessibleContext throws RuntimeException if context is no longer alive
645 Reference<XAccessibleContext> xAc = m_xAccessible->getAccessibleContext();
646 return xAc.is();
648 // so let's catch it here, cuz otherwise soffice falls flat on its face
649 // with FatalError and nothing else
650 catch (css::uno::RuntimeException /*ex*/)
652 return false;
655 return false;
658 QObject* Qt5AccessibleWidget::object() const { return nullptr; }
660 void Qt5AccessibleWidget::setText(QAccessible::Text /* t */, const QString& /* text */) {}
662 QAccessibleInterface* Qt5AccessibleWidget::childAt(int x, int y) const
664 if (!m_xAccessible.is())
665 return nullptr;
667 Reference<XAccessibleContext> xAc;
670 xAc = m_xAccessible->getAccessibleContext();
672 catch (css::lang::DisposedException /*ex*/)
674 return nullptr;
677 Reference<XAccessibleComponent> xAccessibleComponent(xAc, UNO_QUERY);
678 return QAccessible::queryAccessibleInterface(
679 new Qt5XAccessible(xAccessibleComponent->getAccessibleAtPoint(awt::Point(x, y))));
682 QAccessibleInterface* Qt5AccessibleWidget::customFactory(const QString& classname, QObject* object)
684 if (classname == QLatin1String("Qt5Widget") && object && object->isWidgetType())
686 Qt5Widget* pWidget = static_cast<Qt5Widget*>(object);
687 vcl::Window* pWindow = pWidget->m_pFrame->GetWindow();
689 if (pWindow)
690 return new Qt5AccessibleWidget(pWindow->GetAccessible());
692 if (classname == QLatin1String("Qt5XAccessible") && object)
694 Qt5XAccessible* pXAccessible = dynamic_cast<Qt5XAccessible*>(object);
695 if (pXAccessible && pXAccessible->m_xAccessible.is())
696 return new Qt5AccessibleWidget(pXAccessible->m_xAccessible);
699 return nullptr;
702 // QAccessibleActionInterface
703 QStringList Qt5AccessibleWidget::actionNames() const
705 QStringList actionNames;
706 Reference<XAccessibleAction> xAccessibleAction(m_xAccessible, UNO_QUERY);
707 if (!xAccessibleAction.is())
708 return actionNames;
710 int count = xAccessibleAction->getAccessibleActionCount();
711 for (int i = 0; i < count; i++)
713 OUString desc = xAccessibleAction->getAccessibleActionDescription(i);
714 actionNames.append(toQString(desc));
716 return actionNames;
719 void Qt5AccessibleWidget::doAction(const QString& actionName)
721 Reference<XAccessibleAction> xAccessibleAction(m_xAccessible, UNO_QUERY);
722 if (!xAccessibleAction.is())
723 return;
725 int index = actionNames().indexOf(actionName);
726 if (index == -1)
727 return;
728 xAccessibleAction->doAccessibleAction(index);
731 QStringList Qt5AccessibleWidget::keyBindingsForAction(const QString& actionName) const
733 QStringList keyBindings;
734 Reference<XAccessibleAction> xAccessibleAction(m_xAccessible, UNO_QUERY);
735 if (!xAccessibleAction.is())
736 return keyBindings;
738 int index = actionNames().indexOf(actionName);
739 if (index == -1)
740 return keyBindings;
742 Reference<XAccessibleKeyBinding> xKeyBinding
743 = xAccessibleAction->getAccessibleActionKeyBinding(index);
745 if (!xKeyBinding.is())
746 return keyBindings;
748 int count = xKeyBinding->getAccessibleKeyBindingCount();
749 for (int i = 0; i < count; i++)
751 Sequence<awt::KeyStroke> keyStroke = xKeyBinding->getAccessibleKeyBinding(i);
752 keyBindings.append(toQString(comphelper::GetkeyBindingStrByXkeyBinding(keyStroke)));
754 return keyBindings;
757 QAccessibleValueInterface* Qt5AccessibleWidget::valueInterface() { return nullptr; }
759 QAccessibleTextInterface* Qt5AccessibleWidget::textInterface() { return nullptr; }
761 // QAccessibleTextInterface
762 void Qt5AccessibleWidget::addSelection(int /* startOffset */, int /* endOffset */)
764 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::addSelection");
767 namespace
769 OUString lcl_convertFontWeight(double fontWeight)
771 if (fontWeight == awt::FontWeight::THIN || fontWeight == awt::FontWeight::ULTRALIGHT)
772 return OUString("100");
773 if (fontWeight == awt::FontWeight::LIGHT)
774 return OUString("200");
775 if (fontWeight == awt::FontWeight::SEMILIGHT)
776 return OUString("300");
777 if (fontWeight == awt::FontWeight::NORMAL)
778 return OUString("normal");
779 if (fontWeight == awt::FontWeight::SEMIBOLD)
780 return OUString("500");
781 if (fontWeight == awt::FontWeight::BOLD)
782 return OUString("bold");
783 if (fontWeight == awt::FontWeight::ULTRABOLD)
784 return OUString("800");
785 if (fontWeight == awt::FontWeight::BLACK)
786 return OUString("900");
788 // awt::FontWeight::DONTKNOW || fontWeight == awt::FontWeight::NORMAL
789 return OUString("normal");
793 QString Qt5AccessibleWidget::attributes(int offset, int* startOffset, int* endOffset) const
795 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
796 if (!xText.is())
797 return QString();
799 Sequence<PropertyValue> attribs = xText->getCharacterAttributes(offset, Sequence<OUString>());
800 const PropertyValue* pValues = attribs.getConstArray();
801 OUString aRet;
802 for (sal_Int32 i = 0; i < attribs.getLength(); i++)
804 if (pValues[i].Name == "CharFontName")
806 OUString aStr;
807 pValues[i].Value >>= aStr;
808 aRet += "font-family:" + aStr + ";";
809 continue;
811 if (pValues[i].Name == "CharHeight")
813 double fHeight;
814 pValues[i].Value >>= fHeight;
815 aRet += "font-size:" + OUString::number(fHeight) + "pt;";
816 continue;
818 if (pValues[i].Name == "CharWeight")
820 double fWeight;
821 pValues[i].Value >>= fWeight;
822 aRet += "font-weight:" + lcl_convertFontWeight(fWeight) + ";";
823 continue;
826 *startOffset = offset;
827 *endOffset = offset + 1;
828 return toQString(aRet);
830 int Qt5AccessibleWidget::characterCount() const
832 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
833 if (xText.is())
834 return xText->getCharacterCount();
835 return 0;
837 QRect Qt5AccessibleWidget::characterRect(int /* offset */) const
839 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::characterRect");
840 return QRect();
842 int Qt5AccessibleWidget::cursorPosition() const
844 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::cursorPosition");
845 return 0;
847 int Qt5AccessibleWidget::offsetAtPoint(const QPoint& /* point */) const
849 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::offsetAtPoint");
850 return 0;
852 void Qt5AccessibleWidget::removeSelection(int /* selectionIndex */)
854 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::removeSelection");
856 void Qt5AccessibleWidget::scrollToSubstring(int /* startIndex */, int /* endIndex */)
858 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::scrollToSubstring");
861 void Qt5AccessibleWidget::selection(int selectionIndex, int* startOffset, int* endOffset) const
863 if (!startOffset && !endOffset)
864 return;
866 Reference<XAccessibleText> xText;
867 if (selectionIndex == 0)
868 xText = Reference<XAccessibleText>(m_xAccessible, UNO_QUERY);
870 if (startOffset)
871 *startOffset = xText.is() ? xText->getSelectionStart() : 0;
872 if (endOffset)
873 *endOffset = xText.is() ? xText->getSelectionEnd() : 0;
876 int Qt5AccessibleWidget::selectionCount() const
878 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
879 if (xText.is() && !xText->getSelectedText().isEmpty())
880 return 1; // Only 1 selection supported atm
881 return 0;
883 void Qt5AccessibleWidget::setCursorPosition(int position)
885 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
886 if (xText.is())
887 xText->setCaretPosition(position);
889 void Qt5AccessibleWidget::setSelection(int /* selectionIndex */, int startOffset, int endOffset)
891 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
892 if (xText.is())
893 xText->setSelection(startOffset, endOffset);
895 QString Qt5AccessibleWidget::text(int startOffset, int endOffset) const
897 Reference<XAccessibleText> xText(m_xAccessible, UNO_QUERY);
898 if (xText.is())
899 return toQString(xText->getTextRange(startOffset, endOffset));
900 return QString();
902 QString Qt5AccessibleWidget::textAfterOffset(int /* offset */,
903 QAccessible::TextBoundaryType /* boundaryType */,
904 int* /* startOffset */, int* /* endOffset */) const
906 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::textAfterOffset");
907 return QString();
909 QString Qt5AccessibleWidget::textAtOffset(int /* offset */,
910 QAccessible::TextBoundaryType /* boundaryType */,
911 int* /* startOffset */, int* /* endOffset */) const
913 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::textAtOffset");
914 return QString();
916 QString Qt5AccessibleWidget::textBeforeOffset(int /* offset */,
917 QAccessible::TextBoundaryType /* boundaryType */,
918 int* /* startOffset */, int* /* endOffset */) const
920 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTextInterface::textBeforeOffset");
921 return QString();
924 // QAccessibleEditableTextInterface
926 void Qt5AccessibleWidget::deleteText(int startOffset, int endOffset)
928 Reference<XAccessibleEditableText> xEditableText(m_xAccessible->getAccessibleContext(),
929 UNO_QUERY);
930 if (!xEditableText.is())
931 return;
932 xEditableText->deleteText(startOffset, endOffset);
935 void Qt5AccessibleWidget::insertText(int offset, const QString& text)
937 Reference<XAccessibleEditableText> xEditableText(m_xAccessible->getAccessibleContext(),
938 UNO_QUERY);
939 if (!xEditableText.is())
940 return;
941 xEditableText->insertText(toOUString(text), offset);
944 void Qt5AccessibleWidget::replaceText(int startOffset, int endOffset, const QString& text)
946 Reference<XAccessibleEditableText> xEditableText(m_xAccessible->getAccessibleContext(),
947 UNO_QUERY);
948 if (!xEditableText.is())
949 return;
950 xEditableText->replaceText(startOffset, endOffset, toOUString(text));
953 // QAccessibleValueInterface
954 QVariant Qt5AccessibleWidget::currentValue() const
956 Reference<XAccessibleValue> xValue(m_xAccessible->getAccessibleContext(), UNO_QUERY);
957 if (!xValue.is())
958 return QVariant();
959 double aDouble = 0;
960 xValue->getCurrentValue() >>= aDouble;
961 return QVariant(aDouble);
963 QVariant Qt5AccessibleWidget::maximumValue() const
965 Reference<XAccessibleValue> xValue(m_xAccessible->getAccessibleContext(), UNO_QUERY);
966 if (!xValue.is())
967 return QVariant();
968 double aDouble = 0;
969 xValue->getMaximumValue() >>= aDouble;
970 return QVariant(aDouble);
972 QVariant Qt5AccessibleWidget::minimumStepSize() const { return QVariant(); }
973 QVariant Qt5AccessibleWidget::minimumValue() const
975 Reference<XAccessibleValue> xValue(m_xAccessible->getAccessibleContext(), UNO_QUERY);
976 if (!xValue.is())
977 return QVariant();
978 double aDouble = 0;
979 xValue->getMinimumValue() >>= aDouble;
980 return QVariant(aDouble);
982 void Qt5AccessibleWidget::setCurrentValue(const QVariant& value)
984 Reference<XAccessibleValue> xValue(m_xAccessible->getAccessibleContext(), UNO_QUERY);
985 if (!xValue.is())
986 return;
987 xValue->setCurrentValue(Any(value.toDouble()));
990 // QAccessibleTable
991 QAccessibleInterface* Qt5AccessibleWidget::caption() const
993 Reference<XAccessibleTable> xTable(m_xAccessible->getAccessibleContext(), UNO_QUERY);
994 if (!xTable.is())
995 return nullptr;
996 return QAccessible::queryAccessibleInterface(
997 new Qt5XAccessible(xTable->getAccessibleCaption()));
1000 QAccessibleInterface* Qt5AccessibleWidget::cellAt(int row, int column) const
1002 Reference<XAccessibleTable> xTable(m_xAccessible->getAccessibleContext(), UNO_QUERY);
1003 if (!xTable.is())
1004 return nullptr;
1005 return QAccessible::queryAccessibleInterface(
1006 new Qt5XAccessible(xTable->getAccessibleCellAt(row, column)));
1009 int Qt5AccessibleWidget::columnCount() const
1011 Reference<XAccessibleTable> xTable(m_xAccessible->getAccessibleContext(), UNO_QUERY);
1012 if (!xTable.is())
1013 return 0;
1014 return xTable->getAccessibleColumnCount();
1017 QString Qt5AccessibleWidget::columnDescription(int column) const
1019 Reference<XAccessibleTable> xTable(m_xAccessible->getAccessibleContext(), UNO_QUERY);
1020 if (!xTable.is())
1021 return QString();
1022 return toQString(xTable->getAccessibleColumnDescription(column));
1025 bool Qt5AccessibleWidget::isColumnSelected(int /* column */) const { return true; }
1027 bool Qt5AccessibleWidget::isRowSelected(int /* row */) const { return true; }
1029 void Qt5AccessibleWidget::modelChange(QAccessibleTableModelChangeEvent*) {}
1031 int Qt5AccessibleWidget::rowCount() const
1033 Reference<XAccessibleTable> xTable(m_xAccessible->getAccessibleContext(), UNO_QUERY);
1034 if (!xTable.is())
1035 return 0;
1036 return xTable->getAccessibleRowCount();
1039 QString Qt5AccessibleWidget::rowDescription(int row) const
1041 Reference<XAccessibleTable> xTable(m_xAccessible->getAccessibleContext(), UNO_QUERY);
1042 if (!xTable.is())
1043 return QString();
1044 return toQString(xTable->getAccessibleRowDescription(row));
1047 bool Qt5AccessibleWidget::selectColumn(int column)
1049 Reference<XAccessibleTableSelection> xTableSelection(m_xAccessible->getAccessibleContext(),
1050 UNO_QUERY);
1051 if (!xTableSelection.is())
1052 return false;
1053 return xTableSelection->selectColumn(column);
1056 bool Qt5AccessibleWidget::selectRow(int row)
1058 Reference<XAccessibleTableSelection> xTableSelection(m_xAccessible->getAccessibleContext(),
1059 UNO_QUERY);
1060 if (!xTableSelection.is())
1061 return false;
1062 return xTableSelection->selectRow(row);
1065 int Qt5AccessibleWidget::selectedCellCount() const
1067 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTableInterface::selectedCellCount");
1068 return 0;
1071 QList<QAccessibleInterface*> Qt5AccessibleWidget::selectedCells() const
1073 SAL_INFO("vcl.qt5", "Unsupported QAccessibleTableInterface::selectedCells");
1074 return QList<QAccessibleInterface*>();
1077 int Qt5AccessibleWidget::selectedColumnCount() const
1079 Reference<XAccessibleTable> xTable(m_xAccessible->getAccessibleContext(), UNO_QUERY);
1080 if (!xTable.is())
1081 return 0;
1082 return xTable->getSelectedAccessibleColumns().getLength();
1085 QList<int> Qt5AccessibleWidget::selectedColumns() const
1087 Reference<XAccessibleTable> xTable(m_xAccessible->getAccessibleContext(), UNO_QUERY);
1088 if (!xTable.is())
1089 return QList<int>();
1090 return toQList(xTable->getSelectedAccessibleColumns());
1093 int Qt5AccessibleWidget::selectedRowCount() const
1095 Reference<XAccessibleTable> xTable(m_xAccessible->getAccessibleContext(), UNO_QUERY);
1096 if (!xTable.is())
1097 return 0;
1098 return xTable->getSelectedAccessibleRows().getLength();
1101 QList<int> Qt5AccessibleWidget::selectedRows() const
1103 Reference<XAccessibleTable> xTable(m_xAccessible->getAccessibleContext(), UNO_QUERY);
1104 if (!xTable.is())
1105 return QList<int>();
1106 return toQList(xTable->getSelectedAccessibleRows());
1109 QAccessibleInterface* Qt5AccessibleWidget::summary() const
1111 Reference<XAccessibleTable> xTable(m_xAccessible->getAccessibleContext(), UNO_QUERY);
1112 if (!xTable.is())
1113 return nullptr;
1114 return QAccessible::queryAccessibleInterface(
1115 new Qt5XAccessible(xTable->getAccessibleSummary()));
1118 bool Qt5AccessibleWidget::unselectColumn(int column)
1120 Reference<XAccessibleTableSelection> xTableSelection(m_xAccessible->getAccessibleContext(),
1121 UNO_QUERY);
1122 if (!xTableSelection.is())
1123 return false;
1124 return xTableSelection->unselectColumn(column);
1127 bool Qt5AccessibleWidget::unselectRow(int row)
1129 Reference<XAccessibleTableSelection> xTableSelection(m_xAccessible->getAccessibleContext(),
1130 UNO_QUERY);
1131 if (!xTableSelection.is())
1132 return false;
1133 return xTableSelection->unselectRow(row);
1136 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */