| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the plugins of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "simplewidgets_p.h" |
| |
| #if QT_CONFIG(abstractbutton) |
| #include <qabstractbutton.h> |
| #endif |
| #if QT_CONFIG(checkbox) |
| #include <qcheckbox.h> |
| #endif |
| #if QT_CONFIG(pushbutton) |
| #include <qpushbutton.h> |
| #endif |
| #if QT_CONFIG(progressbar) |
| #include <qprogressbar.h> |
| #endif |
| #if QT_CONFIG(statusbar) |
| #include <qstatusbar.h> |
| #endif |
| #if QT_CONFIG(radiobutton) |
| #include <qradiobutton.h> |
| #endif |
| #if QT_CONFIG(toolbutton) |
| #include <qtoolbutton.h> |
| #endif |
| #if QT_CONFIG(menu) |
| #include <qmenu.h> |
| #endif |
| #if QT_CONFIG(label) |
| #include <qlabel.h> |
| #endif |
| #if QT_CONFIG(groupbox) |
| #include <qgroupbox.h> |
| #endif |
| #if QT_CONFIG(lcdnumber) |
| #include <qlcdnumber.h> |
| #endif |
| #if QT_CONFIG(lineedit) |
| #include <qlineedit.h> |
| #include <private/qlineedit_p.h> |
| #endif |
| #include <qstyle.h> |
| #include <qstyleoption.h> |
| #include <qtextdocument.h> |
| #include <qwindow.h> |
| #include <private/qwindowcontainer_p.h> |
| #include <QtCore/qvarlengtharray.h> |
| #include <QtGui/qvalidator.h> |
| |
| #ifdef Q_OS_MAC |
| #include <qfocusframe.h> |
| #endif |
| |
| QT_BEGIN_NAMESPACE |
| |
| #ifndef QT_NO_ACCESSIBILITY |
| |
| extern QList<QWidget*> childWidgets(const QWidget *widget); |
| |
| QString qt_accStripAmp(const QString &text); |
| QString qt_accHotKey(const QString &text); |
| |
| #if QT_CONFIG(abstractbutton) |
| /*! |
| \class QAccessibleButton |
| \brief The QAccessibleButton class implements the QAccessibleInterface for button type widgets. |
| \internal |
| |
| \ingroup accessibility |
| */ |
| |
| /*! |
| Creates a QAccessibleButton object for \a w. |
| */ |
| QAccessibleButton::QAccessibleButton(QWidget *w) |
| : QAccessibleWidget(w) |
| { |
| Q_ASSERT(button()); |
| |
| // FIXME: The checkable state of the button is dynamic, |
| // while we only update the controlling signal once :( |
| if (button()->isCheckable()) |
| addControllingSignal(QLatin1String("toggled(bool)")); |
| else |
| addControllingSignal(QLatin1String("clicked()")); |
| } |
| |
| /*! Returns the button. */ |
| QAbstractButton *QAccessibleButton::button() const |
| { |
| return qobject_cast<QAbstractButton*>(object()); |
| } |
| |
| /*! \reimp */ |
| QString QAccessibleButton::text(QAccessible::Text t) const |
| { |
| QString str; |
| switch (t) { |
| case QAccessible::Accelerator: |
| { |
| #if QT_CONFIG(shortcut) && QT_CONFIG(pushbutton) |
| QPushButton *pb = qobject_cast<QPushButton*>(object()); |
| if (pb && pb->isDefault()) |
| str = QKeySequence(Qt::Key_Enter).toString(QKeySequence::NativeText); |
| #endif |
| if (str.isEmpty()) |
| str = qt_accHotKey(button()->text()); |
| } |
| break; |
| case QAccessible::Name: |
| str = widget()->accessibleName(); |
| if (str.isEmpty()) |
| str = qt_accStripAmp(button()->text()); |
| break; |
| default: |
| break; |
| } |
| if (str.isEmpty()) |
| str = QAccessibleWidget::text(t); |
| return str; |
| } |
| |
| QAccessible::State QAccessibleButton::state() const |
| { |
| QAccessible::State state = QAccessibleWidget::state(); |
| |
| QAbstractButton *b = button(); |
| #if QT_CONFIG(checkbox) |
| QCheckBox *cb = qobject_cast<QCheckBox *>(b); |
| #endif |
| if (b->isCheckable()) |
| state.checkable = true; |
| if (b->isChecked()) |
| state.checked = true; |
| #if QT_CONFIG(checkbox) |
| if (cb && cb->checkState() == Qt::PartiallyChecked) |
| state.checkStateMixed = true; |
| #endif |
| if (b->isDown()) |
| state.pressed = true; |
| #if QT_CONFIG(pushbutton) |
| QPushButton *pb = qobject_cast<QPushButton*>(b); |
| if (pb) { |
| if (pb->isDefault()) |
| state.defaultButton = true; |
| #if QT_CONFIG(menu) |
| if (pb->menu()) |
| state.hasPopup = true; |
| #endif |
| } |
| #endif |
| |
| return state; |
| } |
| |
| QRect QAccessibleButton::rect() const |
| { |
| QAbstractButton *ab = button(); |
| if (!ab->isVisible()) |
| return QRect(); |
| |
| #if QT_CONFIG(checkbox) |
| if (QCheckBox *cb = qobject_cast<QCheckBox *>(ab)) { |
| QPoint wpos = cb->mapToGlobal(QPoint(0, 0)); |
| QStyleOptionButton opt; |
| cb->initStyleOption(&opt); |
| return cb->style()->subElementRect(QStyle::SE_CheckBoxClickRect, &opt, cb).translated(wpos); |
| } |
| #endif |
| #if QT_CONFIG(radiobutton) |
| else if (QRadioButton *rb = qobject_cast<QRadioButton *>(ab)) { |
| QPoint wpos = rb->mapToGlobal(QPoint(0, 0)); |
| QStyleOptionButton opt; |
| rb->initStyleOption(&opt); |
| return rb->style()->subElementRect(QStyle::SE_RadioButtonClickRect, &opt, rb).translated(wpos); |
| } |
| #endif |
| return QAccessibleWidget::rect(); |
| } |
| |
| QAccessible::Role QAccessibleButton::role() const |
| { |
| QAbstractButton *ab = button(); |
| |
| #if QT_CONFIG(menu) |
| if (QPushButton *pb = qobject_cast<QPushButton*>(ab)) { |
| if (pb->menu()) |
| return QAccessible::ButtonMenu; |
| } |
| #endif |
| |
| if (ab->isCheckable()) |
| return ab->autoExclusive() ? QAccessible::RadioButton : QAccessible::CheckBox; |
| |
| return QAccessible::Button; |
| } |
| |
| QStringList QAccessibleButton::actionNames() const |
| { |
| QStringList names; |
| if (widget()->isEnabled()) { |
| switch (role()) { |
| case QAccessible::ButtonMenu: |
| names << showMenuAction(); |
| break; |
| case QAccessible::RadioButton: |
| names << toggleAction(); |
| break; |
| default: |
| if (button()->isCheckable()) { |
| names << toggleAction(); |
| } else { |
| names << pressAction(); |
| } |
| break; |
| } |
| } |
| names << QAccessibleWidget::actionNames(); |
| return names; |
| } |
| |
| void QAccessibleButton::doAction(const QString &actionName) |
| { |
| if (!widget()->isEnabled()) |
| return; |
| if (actionName == pressAction() || |
| actionName == showMenuAction()) { |
| #if QT_CONFIG(menu) |
| QPushButton *pb = qobject_cast<QPushButton*>(object()); |
| if (pb && pb->menu()) |
| pb->showMenu(); |
| else |
| #endif |
| button()->animateClick(); |
| } else if (actionName == toggleAction()) { |
| button()->toggle(); |
| } else { |
| QAccessibleWidget::doAction(actionName); |
| } |
| } |
| |
| QStringList QAccessibleButton::keyBindingsForAction(const QString &actionName) const |
| { |
| if (actionName == pressAction()) { |
| #ifndef QT_NO_SHORTCUT |
| return QStringList() << button()->shortcut().toString(); |
| #endif |
| } |
| return QStringList(); |
| } |
| #endif // QT_CONFIG(abstractbutton) |
| |
| #if QT_CONFIG(toolbutton) |
| /*! |
| \class QAccessibleToolButton |
| \brief The QAccessibleToolButton class implements the QAccessibleInterface for tool buttons. |
| \internal |
| |
| \ingroup accessibility |
| */ |
| |
| /*! |
| Creates a QAccessibleToolButton object for \a w. |
| */ |
| QAccessibleToolButton::QAccessibleToolButton(QWidget *w) |
| : QAccessibleButton(w) |
| { |
| Q_ASSERT(toolButton()); |
| } |
| |
| /*! Returns the button. */ |
| QToolButton *QAccessibleToolButton::toolButton() const |
| { |
| return qobject_cast<QToolButton*>(object()); |
| } |
| |
| /*! |
| Returns \c true if this tool button is a split button. |
| */ |
| bool QAccessibleToolButton::isSplitButton() const |
| { |
| #if QT_CONFIG(menu) |
| return toolButton()->menu() && toolButton()->popupMode() == QToolButton::MenuButtonPopup; |
| #else |
| return false; |
| #endif |
| } |
| |
| QAccessible::State QAccessibleToolButton::state() const |
| { |
| QAccessible::State st = QAccessibleButton::state(); |
| if (toolButton()->autoRaise()) |
| st.hotTracked = true; |
| #if QT_CONFIG(menu) |
| if (toolButton()->menu()) |
| st.hasPopup = true; |
| #endif |
| return st; |
| } |
| |
| int QAccessibleToolButton::childCount() const |
| { |
| return isSplitButton() ? 1 : 0; |
| } |
| |
| QAccessible::Role QAccessibleToolButton::role() const |
| { |
| #if QT_CONFIG(menu) |
| QAbstractButton *ab = button(); |
| QToolButton *tb = qobject_cast<QToolButton*>(ab); |
| if (!tb->menu()) |
| return tb->isCheckable() ? QAccessible::CheckBox : QAccessible::PushButton; |
| else if (tb->popupMode() == QToolButton::DelayedPopup) |
| return QAccessible::ButtonDropDown; |
| #endif |
| |
| return QAccessible::ButtonMenu; |
| } |
| |
| QAccessibleInterface *QAccessibleToolButton::child(int index) const |
| { |
| #if QT_CONFIG(menu) |
| if (index == 0 && toolButton()->menu()) |
| { |
| return QAccessible::queryAccessibleInterface(toolButton()->menu()); |
| } |
| #else |
| Q_UNUSED(index) |
| #endif |
| return 0; |
| } |
| |
| /* |
| The three different tool button types can have the following actions: |
| | DelayedPopup | ShowMenuAction + (PressedAction || CheckedAction) | |
| | MenuButtonPopup | ShowMenuAction + (PressedAction || CheckedAction) | |
| | InstantPopup | ShowMenuAction | |
| */ |
| QStringList QAccessibleToolButton::actionNames() const |
| { |
| QStringList names; |
| if (widget()->isEnabled()) { |
| #if QT_CONFIG(menu) |
| if (toolButton()->menu()) |
| names << showMenuAction(); |
| if (toolButton()->popupMode() != QToolButton::InstantPopup) |
| names << QAccessibleButton::actionNames(); |
| #endif |
| } |
| return names; |
| } |
| |
| void QAccessibleToolButton::doAction(const QString &actionName) |
| { |
| if (!widget()->isEnabled()) |
| return; |
| |
| if (actionName == pressAction()) { |
| button()->click(); |
| } else if (actionName == showMenuAction()) { |
| #if QT_CONFIG(menu) |
| if (toolButton()->popupMode() != QToolButton::InstantPopup) { |
| toolButton()->setDown(true); |
| toolButton()->showMenu(); |
| } |
| #endif |
| } else { |
| QAccessibleButton::doAction(actionName); |
| } |
| |
| } |
| |
| #endif // QT_CONFIG(toolbutton) |
| |
| /*! |
| \class QAccessibleDisplay |
| \brief The QAccessibleDisplay class implements the QAccessibleInterface for widgets that display information. |
| \internal |
| |
| \ingroup accessibility |
| */ |
| |
| /*! |
| Constructs a QAccessibleDisplay object for \a w. |
| \a role is propagated to the QAccessibleWidget constructor. |
| */ |
| QAccessibleDisplay::QAccessibleDisplay(QWidget *w, QAccessible::Role role) |
| : QAccessibleWidget(w, role) |
| { |
| } |
| |
| QAccessible::Role QAccessibleDisplay::role() const |
| { |
| #if QT_CONFIG(label) |
| QLabel *l = qobject_cast<QLabel*>(object()); |
| if (l) { |
| if (l->pixmap()) |
| return QAccessible::Graphic; |
| #ifndef QT_NO_PICTURE |
| if (l->picture()) |
| return QAccessible::Graphic; |
| #endif |
| #if QT_CONFIG(movie) |
| if (l->movie()) |
| return QAccessible::Animation; |
| #endif |
| #if QT_CONFIG(progressbar) |
| } else if (qobject_cast<QProgressBar*>(object())) { |
| return QAccessible::ProgressBar; |
| #endif |
| #if QT_CONFIG(statusbar) |
| } else if (qobject_cast<QStatusBar*>(object())) { |
| return QAccessible::StatusBar; |
| #endif |
| } |
| #endif |
| return QAccessibleWidget::role(); |
| } |
| |
| QAccessible::State QAccessibleDisplay::state() const |
| { |
| QAccessible::State s = QAccessibleWidget::state(); |
| s.readOnly = true; |
| return s; |
| } |
| |
| QString QAccessibleDisplay::text(QAccessible::Text t) const |
| { |
| QString str; |
| switch (t) { |
| case QAccessible::Name: |
| str = widget()->accessibleName(); |
| if (str.isEmpty()) { |
| if (false) { |
| #if QT_CONFIG(label) |
| } else if (qobject_cast<QLabel*>(object())) { |
| QLabel *label = qobject_cast<QLabel*>(object()); |
| str = label->text(); |
| #ifndef QT_NO_TEXTHTMLPARSER |
| if (label->textFormat() == Qt::RichText |
| || (label->textFormat() == Qt::AutoText && Qt::mightBeRichText(str))) { |
| QTextDocument doc; |
| doc.setHtml(str); |
| str = doc.toPlainText(); |
| } |
| #endif |
| #ifndef QT_NO_SHORTCUT |
| if (label->buddy()) |
| str = qt_accStripAmp(str); |
| #endif |
| #endif // QT_CONFIG(label) |
| #if QT_CONFIG(lcdnumber) |
| } else if (qobject_cast<QLCDNumber*>(object())) { |
| QLCDNumber *l = qobject_cast<QLCDNumber*>(object()); |
| if (l->digitCount()) |
| str = QString::number(l->value()); |
| else |
| str = QString::number(l->intValue()); |
| #endif |
| #if QT_CONFIG(statusbar) |
| } else if (qobject_cast<QStatusBar*>(object())) { |
| return qobject_cast<QStatusBar*>(object())->currentMessage(); |
| #endif |
| } |
| } |
| break; |
| case QAccessible::Value: |
| #if QT_CONFIG(progressbar) |
| if (qobject_cast<QProgressBar*>(object())) |
| str = QString::number(qobject_cast<QProgressBar*>(object())->value()); |
| #endif |
| break; |
| default: |
| break; |
| } |
| if (str.isEmpty()) |
| str = QAccessibleWidget::text(t); |
| return str; |
| } |
| |
| /*! \reimp */ |
| QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > |
| QAccessibleDisplay::relations(QAccessible::Relation match /* = QAccessible::AllRelations */) const |
| { |
| QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > rels = QAccessibleWidget::relations(match); |
| #if QT_CONFIG(shortcut) && QT_CONFIG(label) |
| if (match & QAccessible::Labelled) { |
| if (QLabel *label = qobject_cast<QLabel*>(object())) { |
| const QAccessible::Relation rel = QAccessible::Labelled; |
| if (QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(label->buddy())) |
| rels.append(qMakePair(iface, rel)); |
| } |
| } |
| #endif |
| return rels; |
| } |
| |
| void *QAccessibleDisplay::interface_cast(QAccessible::InterfaceType t) |
| { |
| if (t == QAccessible::ImageInterface) |
| return static_cast<QAccessibleImageInterface*>(this); |
| return QAccessibleWidget::interface_cast(t); |
| } |
| |
| /*! \internal */ |
| QString QAccessibleDisplay::imageDescription() const |
| { |
| #ifndef QT_NO_TOOLTIP |
| return widget()->toolTip(); |
| #else |
| return QString(); |
| #endif |
| } |
| |
| /*! \internal */ |
| QSize QAccessibleDisplay::imageSize() const |
| { |
| #if QT_CONFIG(label) |
| QLabel *label = qobject_cast<QLabel *>(widget()); |
| if (!label) |
| #endif |
| return QSize(); |
| #if QT_CONFIG(label) |
| const QPixmap *pixmap = label->pixmap(); |
| if (!pixmap) |
| return QSize(); |
| return pixmap->size(); |
| #endif |
| } |
| |
| /*! \internal */ |
| QPoint QAccessibleDisplay::imagePosition() const |
| { |
| #if QT_CONFIG(label) |
| QLabel *label = qobject_cast<QLabel *>(widget()); |
| if (!label) |
| #endif |
| return QPoint(); |
| #if QT_CONFIG(label) |
| const QPixmap *pixmap = label->pixmap(); |
| if (!pixmap) |
| return QPoint(); |
| |
| return QPoint(label->mapToGlobal(label->pos())); |
| #endif |
| } |
| |
| #if QT_CONFIG(groupbox) |
| QAccessibleGroupBox::QAccessibleGroupBox(QWidget *w) |
| : QAccessibleWidget(w) |
| { |
| } |
| |
| QGroupBox* QAccessibleGroupBox::groupBox() const |
| { |
| return static_cast<QGroupBox *>(widget()); |
| } |
| |
| QString QAccessibleGroupBox::text(QAccessible::Text t) const |
| { |
| QString txt = QAccessibleWidget::text(t); |
| |
| if (txt.isEmpty()) { |
| switch (t) { |
| case QAccessible::Name: |
| txt = qt_accStripAmp(groupBox()->title()); |
| break; |
| #if QT_CONFIG(tooltip) |
| case QAccessible::Description: |
| txt = groupBox()->toolTip(); |
| break; |
| #endif |
| case QAccessible::Accelerator: |
| txt = qt_accHotKey(groupBox()->title()); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| return txt; |
| } |
| |
| QAccessible::State QAccessibleGroupBox::state() const |
| { |
| QAccessible::State st = QAccessibleWidget::state(); |
| st.checkable = groupBox()->isCheckable(); |
| st.checked = groupBox()->isChecked(); |
| return st; |
| } |
| |
| QAccessible::Role QAccessibleGroupBox::role() const |
| { |
| return groupBox()->isCheckable() ? QAccessible::CheckBox : QAccessible::Grouping; |
| } |
| |
| QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > |
| QAccessibleGroupBox::relations(QAccessible::Relation match /* = QAccessible::AllRelations */) const |
| { |
| QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > rels = QAccessibleWidget::relations(match); |
| |
| if ((match & QAccessible::Labelled) && (!groupBox()->title().isEmpty())) { |
| const QList<QWidget*> kids = childWidgets(widget()); |
| for (QWidget *kid : kids) { |
| QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(kid); |
| if (iface) |
| rels.append(qMakePair(iface, QAccessible::Relation(QAccessible::Labelled))); |
| } |
| } |
| return rels; |
| } |
| |
| QStringList QAccessibleGroupBox::actionNames() const |
| { |
| QStringList actions = QAccessibleWidget::actionNames(); |
| |
| if (groupBox()->isCheckable()) { |
| actions.prepend(QAccessibleActionInterface::toggleAction()); |
| } |
| return actions; |
| } |
| |
| void QAccessibleGroupBox::doAction(const QString &actionName) |
| { |
| if (actionName == QAccessibleActionInterface::toggleAction()) |
| groupBox()->setChecked(!groupBox()->isChecked()); |
| } |
| |
| QStringList QAccessibleGroupBox::keyBindingsForAction(const QString &) const |
| { |
| return QStringList(); |
| } |
| |
| #endif |
| |
| #if QT_CONFIG(lineedit) |
| /*! |
| \class QAccessibleLineEdit |
| \brief The QAccessibleLineEdit class implements the QAccessibleInterface for widgets with editable text |
| \internal |
| |
| \ingroup accessibility |
| */ |
| |
| /*! |
| Constructs a QAccessibleLineEdit object for \a w. |
| \a name is propagated to the QAccessibleWidget constructor. |
| */ |
| QAccessibleLineEdit::QAccessibleLineEdit(QWidget *w, const QString &name) |
| : QAccessibleWidget(w, QAccessible::EditableText, name) |
| { |
| addControllingSignal(QLatin1String("textChanged(const QString&)")); |
| addControllingSignal(QLatin1String("returnPressed()")); |
| } |
| |
| /*! Returns the line edit. */ |
| QLineEdit *QAccessibleLineEdit::lineEdit() const |
| { |
| return qobject_cast<QLineEdit*>(object()); |
| } |
| |
| QString QAccessibleLineEdit::text(QAccessible::Text t) const |
| { |
| QString str; |
| switch (t) { |
| case QAccessible::Value: |
| if (lineEdit()->echoMode() == QLineEdit::Normal) |
| str = lineEdit()->text(); |
| else if (lineEdit()->echoMode() != QLineEdit::NoEcho) |
| str = QString(lineEdit()->text().length(), QChar::fromLatin1('*')); |
| break; |
| default: |
| break; |
| } |
| if (str.isEmpty()) |
| str = QAccessibleWidget::text(t); |
| if (str.isEmpty() && t == QAccessible::Description) |
| str = lineEdit()->placeholderText(); |
| return str; |
| } |
| |
| void QAccessibleLineEdit::setText(QAccessible::Text t, const QString &text) |
| { |
| if (t != QAccessible::Value) { |
| QAccessibleWidget::setText(t, text); |
| return; |
| } |
| |
| QString newText = text; |
| #if QT_CONFIG(validator) |
| if (lineEdit()->validator()) { |
| int pos = 0; |
| if (lineEdit()->validator()->validate(newText, pos) != QValidator::Acceptable) |
| return; |
| } |
| #endif |
| lineEdit()->setText(newText); |
| } |
| |
| QAccessible::State QAccessibleLineEdit::state() const |
| { |
| QAccessible::State state = QAccessibleWidget::state(); |
| |
| QLineEdit *l = lineEdit(); |
| state.editable = true; |
| if (l->isReadOnly()) |
| state.readOnly = true; |
| |
| if (l->echoMode() != QLineEdit::Normal) |
| state.passwordEdit = true; |
| |
| state.selectableText = true; |
| return state; |
| } |
| |
| void *QAccessibleLineEdit::interface_cast(QAccessible::InterfaceType t) |
| { |
| if (t == QAccessible::TextInterface) |
| return static_cast<QAccessibleTextInterface*>(this); |
| if (t == QAccessible::EditableTextInterface) |
| return static_cast<QAccessibleEditableTextInterface*>(this); |
| return QAccessibleWidget::interface_cast(t); |
| } |
| |
| void QAccessibleLineEdit::addSelection(int startOffset, int endOffset) |
| { |
| setSelection(0, startOffset, endOffset); |
| } |
| |
| QString QAccessibleLineEdit::attributes(int offset, int *startOffset, int *endOffset) const |
| { |
| // QLineEdit doesn't have text attributes |
| *startOffset = *endOffset = offset; |
| return QString(); |
| } |
| |
| int QAccessibleLineEdit::cursorPosition() const |
| { |
| return lineEdit()->cursorPosition(); |
| } |
| |
| QRect QAccessibleLineEdit::characterRect(int offset) const |
| { |
| int x = lineEdit()->d_func()->control->cursorToX(offset); |
| int y = lineEdit()->textMargins().top(); |
| QFontMetrics fm(lineEdit()->font()); |
| const QString ch = text(offset, offset + 1); |
| if (ch.isEmpty()) |
| return QRect(); |
| int w = fm.horizontalAdvance(ch); |
| int h = fm.height(); |
| QRect r(x, y, w, h); |
| r.moveTo(lineEdit()->mapToGlobal(r.topLeft())); |
| return r; |
| } |
| |
| int QAccessibleLineEdit::selectionCount() const |
| { |
| return lineEdit()->hasSelectedText() ? 1 : 0; |
| } |
| |
| int QAccessibleLineEdit::offsetAtPoint(const QPoint &point) const |
| { |
| QPoint p = lineEdit()->mapFromGlobal(point); |
| |
| return lineEdit()->cursorPositionAt(p); |
| } |
| |
| void QAccessibleLineEdit::selection(int selectionIndex, int *startOffset, int *endOffset) const |
| { |
| *startOffset = *endOffset = 0; |
| if (selectionIndex != 0) |
| return; |
| |
| *startOffset = lineEdit()->selectionStart(); |
| *endOffset = *startOffset + lineEdit()->selectedText().count(); |
| } |
| |
| QString QAccessibleLineEdit::text(int startOffset, int endOffset) const |
| { |
| if (startOffset > endOffset) |
| return QString(); |
| |
| if (lineEdit()->echoMode() != QLineEdit::Normal) |
| return QString(); |
| |
| return lineEdit()->text().mid(startOffset, endOffset - startOffset); |
| } |
| |
| QString QAccessibleLineEdit::textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType, |
| int *startOffset, int *endOffset) const |
| { |
| if (lineEdit()->echoMode() != QLineEdit::Normal) { |
| *startOffset = *endOffset = -1; |
| return QString(); |
| } |
| if (offset == -2) |
| offset = cursorPosition(); |
| return QAccessibleTextInterface::textBeforeOffset(offset, boundaryType, startOffset, endOffset); |
| } |
| |
| QString QAccessibleLineEdit::textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType, |
| int *startOffset, int *endOffset) const |
| { |
| if (lineEdit()->echoMode() != QLineEdit::Normal) { |
| *startOffset = *endOffset = -1; |
| return QString(); |
| } |
| if (offset == -2) |
| offset = cursorPosition(); |
| return QAccessibleTextInterface::textAfterOffset(offset, boundaryType, startOffset, endOffset); |
| } |
| |
| QString QAccessibleLineEdit::textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType, |
| int *startOffset, int *endOffset) const |
| { |
| if (lineEdit()->echoMode() != QLineEdit::Normal) { |
| *startOffset = *endOffset = -1; |
| return QString(); |
| } |
| if (offset == -2) |
| offset = cursorPosition(); |
| return QAccessibleTextInterface::textAtOffset(offset, boundaryType, startOffset, endOffset); |
| } |
| |
| void QAccessibleLineEdit::removeSelection(int selectionIndex) |
| { |
| if (selectionIndex != 0) |
| return; |
| |
| lineEdit()->deselect(); |
| } |
| |
| void QAccessibleLineEdit::setCursorPosition(int position) |
| { |
| lineEdit()->setCursorPosition(position); |
| } |
| |
| void QAccessibleLineEdit::setSelection(int selectionIndex, int startOffset, int endOffset) |
| { |
| if (selectionIndex != 0) |
| return; |
| |
| lineEdit()->setSelection(startOffset, endOffset - startOffset); |
| } |
| |
| int QAccessibleLineEdit::characterCount() const |
| { |
| return lineEdit()->text().count(); |
| } |
| |
| void QAccessibleLineEdit::scrollToSubstring(int startIndex, int endIndex) |
| { |
| lineEdit()->setCursorPosition(endIndex); |
| lineEdit()->setCursorPosition(startIndex); |
| } |
| |
| void QAccessibleLineEdit::deleteText(int startOffset, int endOffset) |
| { |
| lineEdit()->setText(lineEdit()->text().remove(startOffset, endOffset - startOffset)); |
| } |
| |
| void QAccessibleLineEdit::insertText(int offset, const QString &text) |
| { |
| lineEdit()->setText(lineEdit()->text().insert(offset, text)); |
| } |
| |
| void QAccessibleLineEdit::replaceText(int startOffset, int endOffset, const QString &text) |
| { |
| lineEdit()->setText(lineEdit()->text().replace(startOffset, endOffset - startOffset, text)); |
| } |
| |
| #endif // QT_CONFIG(lineedit) |
| |
| #if QT_CONFIG(progressbar) |
| QAccessibleProgressBar::QAccessibleProgressBar(QWidget *o) |
| : QAccessibleDisplay(o) |
| { |
| Q_ASSERT(progressBar()); |
| } |
| |
| void *QAccessibleProgressBar::interface_cast(QAccessible::InterfaceType t) |
| { |
| if (t == QAccessible::ValueInterface) |
| return static_cast<QAccessibleValueInterface*>(this); |
| return QAccessibleDisplay::interface_cast(t); |
| } |
| |
| QVariant QAccessibleProgressBar::currentValue() const |
| { |
| return progressBar()->value(); |
| } |
| |
| QVariant QAccessibleProgressBar::maximumValue() const |
| { |
| return progressBar()->maximum(); |
| } |
| |
| QVariant QAccessibleProgressBar::minimumValue() const |
| { |
| return progressBar()->minimum(); |
| } |
| |
| QVariant QAccessibleProgressBar::minimumStepSize() const |
| { |
| // This is arbitrary since any value between min and max is valid. |
| // Some screen readers (orca use it to calculate how many digits to display though, |
| // so it makes sense to return a "sensible" value. Providing 100 increments seems ok. |
| return (progressBar()->maximum() - progressBar()->minimum()) / 100.0; |
| } |
| |
| QProgressBar *QAccessibleProgressBar::progressBar() const |
| { |
| return qobject_cast<QProgressBar *>(object()); |
| } |
| #endif |
| |
| |
| QAccessibleWindowContainer::QAccessibleWindowContainer(QWidget *w) |
| : QAccessibleWidget(w) |
| { |
| } |
| |
| int QAccessibleWindowContainer::childCount() const |
| { |
| if (container()->containedWindow() && QAccessible::queryAccessibleInterface(container()->containedWindow())) |
| return 1; |
| return 0; |
| } |
| |
| int QAccessibleWindowContainer::indexOfChild(const QAccessibleInterface *child) const |
| { |
| if (child->object() == container()->containedWindow()) |
| return 0; |
| return -1; |
| } |
| |
| QAccessibleInterface *QAccessibleWindowContainer::child(int i) const |
| { |
| if (i == 0) |
| return QAccessible::queryAccessibleInterface(container()->containedWindow()); |
| return 0; |
| } |
| |
| QWindowContainer *QAccessibleWindowContainer::container() const |
| { |
| return static_cast<QWindowContainer *>(widget()); |
| } |
| |
| #endif // QT_NO_ACCESSIBILITY |
| |
| QT_END_NAMESPACE |