Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QStringListModel, AccessibleTextRole and NVDA (Braille Displays and Speech)



  • I have an application with a ListView, which uses a QStringListModel to store / manage the data, and am using the application on a Windows PC, using NVDA screen reader with a braille display.

    The entries in the ListView contain dates and times, e.g. "Sun 14 Aug 12:30", and I'd like to see the same text as on the screen displayed on the braille display, and a more understandable version spoken, e.g. "Sunday the 14th August, twelve thirty pm".

    I realised that if the QStringListModel is overridden, I can add responses for additional roles, and have managed to add a response for the Qt::AccessibleTextRole, which means that the ListView shows one thing on the screen, and speaks another thing - however, the braille display now shows the spoken 'view', rather than the screen view.

    **Q: What can I do to have the same output on the screen and Braille display, but override the spoken output?

    Q: Is it something I can do with roles in the overridden QStringListModel?**

    I've attached my "working" AccessibleStringListModel class - this class shows one thing on the screen (Qt::DisplayRole), but both speaks and displays on the braille display the other (Qt::AccessibleTextRole).

    Thanks, Steve

    #include "accessiblestringlistmodel.h"
    
    AccessibleStringListModel::AccessibleStringListModel()
    {
    
    }
    
    
    bool AccessibleStringListModel::insertRow(int row, const QModelIndex &parent)
    {
        QList<QVariant> newentry ;
        newentry.append(QVariant(""));
        newentry.append(QVariant(""));
        newentry.append(QVariant(""));
        modeldata.insert(row, newentry) ;
        return true ;
    }
    
    bool AccessibleStringListModel::setData(const QModelIndex &index, QVariant data, int role)
    {
        int row = index.row() ;
        if (row<0 || row>=modeldata.size()) return false ;
    
        const QList<QVariant>& selected = modeldata.at(row) ;
        switch (role) {
    
        case Qt::DisplayRole: {
                QVariant& item = (QVariant&)selected.at(0) ;
                item.setValue(data) ;
                emit dataChanged(index, index) ;
                return true ;
            }
            break ;
    
        case Qt::AccessibleTextRole: {
                QVariant& item = (QVariant&)selected.at(1) ;
                item.setValue(data) ;
                emit dataChanged(index, index) ;
                return true ;
            }
            break ;
    
        case Qt::UserRole: {
                QVariant& item = (QVariant&)selected.at(2) ;
                item.setValue(data) ;
                emit dataChanged(index, index) ;
                return true ;
            }
            break ;
    
        default:
            return false ;
            break ;
    
        }
    }
    
    QVariant AccessibleStringListModel::data(const QModelIndex &index, int role) const
    {
        int row = index.row() ;
        if (row<0 || row>=modeldata.size()) return QVariant() ;
        const QList<QVariant>& selected = modeldata.at(row) ;
        switch (role){
            case Qt::DisplayRole:
                return selected.at(0) ;
                break ;
            case Qt::AccessibleTextRole:
                return selected.at(1) ;
                break ;
            case Qt::UserRole:
                return selected.at(2) ;
                break ;
            default: return QVariant() ;
        }
    }
    
    
    QModelIndex AccessibleStringListModel::index(int row, int column, const QModelIndex &parent) const
    {
        Q_UNUSED(parent) ;
        Q_UNUSED(column) ;
        return createIndex(row, column) ;
    }
    
    int AccessibleStringListModel::rowCount(const QModelIndex &parent) const
    {
        Q_UNUSED(parent) ;
        return modeldata.size() ;
    }
    
    Qt::ItemFlags AccessibleStringListModel::flags(const QModelIndex &index) const
    {
        if (!index.isValid()) return 0;
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    }
    
    


  • I have no way of testing but try setting the string you want spoken out to Qt::AccessibleDescriptionRole and Qt::AccessibleTextRole to the same as Qt::DisplayRole for the braille.

    P.S.
    AccessibleStringListModel::insertRow is wrong:

    • You forgot to call beginInsertRows/endInsertRow
    • insertRow is not virtual, insertRows is. You should override that method instead


  • Thanks for the reply, and for the ps hints!

    I did try both the AccessibleTextRole and the AccessibleDescriptionRole, but in each case, the spoken output matches the displayed output.

    DisplayRole & AccessibleTextRole:

    QListWidget: DisplayRole Text
    Braille Display: AccessibleTextRole Text
    Spoken: AccessibleTextRole Text

    DisplayRole & AccessibleDescriptionRole

    QListWidget: DisplayRole Text
    Braille Display: DisplayRole Text then AccessibleTextRoleText
    Spoken: DisplayRole Text then AccessibleTextRoleText

    I am beginning to think that it is not possible to differentiate these accessible string outputs within Qt - is that right?

    Steve


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    To have a definite answer, you should bring your question to the interest mailing list. The developers behind the accessibility features are there. This is more a user forum.


Log in to reply