Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Audit Qt Widget applications for accessibility compliance using QAccessible interface and platform accessibility APIs
.claude/skills/a5c-ai-qt-widget-accessibility-audit/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | -18% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 45% | 0% |
| case-18 | ✗→✓ | ▲ Improved | 69% | 0% |
| case-19 | ✗→✓ | ▲ Improved | 20% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 64% | 0% |
Audit Qt Widget and Qt Quick applications for accessibility compliance. This skill checks QAccessible interface implementations, keyboard navigation, screen reader compatibility, and WCAG guidelines adherence.
json{ "type": "object", "properties": { "projectPath": { "type": "string", "description": "Path to the Qt project" }, "auditLevel": { "enum": ["basic", "wcag-a", "wcag-aa", "wcag-aaa"], "default": "wcag-aa" }, "targetPlatform": { "enum": ["windows", "macos", "linux"], "description": "Platform to focus accessibility checks" }, "checkCategories": { "type": "array", "items": { "enum": ["keyboard", "screen-reader", "visual", "focus", "labels", "navigation"] }, "default": ["keyboard", "screen-reader", "visual", "focus", "labels"] }, "includeQml": { "type": "boolean", "default": true } }, "required": ["projectPath"] }
json{ "type": "object", "properties": { "success": { "type": "boolean" }, "complianceLevel": { "enum": ["none", "wcag-a", "wcag-aa", "wcag-aaa"] }, "score": { "type": "number", "description": "Accessibility score 0-100" }, "issues": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "severity": { "enum": ["critical", "major", "minor"] }, "category": { "type": "string" }, "wcagCriteria": { "type": "string" }, "description": { "type": "string" }, "file": { "type": "string" }, "widget": { "type": "string" }, "recommendation": { "type": "string" } } } }, "recommendations": { "type": "array", "items": { "type": "string" } } }, "required": ["success", "issues"] }
cpp// Check: Widget has accessible name bool hasAccessibleName(QWidget* widget) { return !widget->accessibleName().isEmpty() || !widget->accessibleDescription().isEmpty(); } // Check: Custom widget implements QAccessibleInterface class CustomWidget : public QWidget { // Must implement for screen readers QAccessibleInterface* accessibleInterface() { return QAccessible::queryAccessibleInterface(this); } };
cpp// Check: All interactive widgets are focusable void auditFocusPolicy(QWidget* widget) { if (isInteractive(widget)) { if (widget->focusPolicy() == Qt::NoFocus) { reportIssue("Interactive widget not focusable", widget); } } } // Check: Tab order is logical void auditTabOrder(QWidget* container) { QList<QWidget*> tabOrder = getTabOrder(container); // Verify left-to-right, top-to-bottom order }
cpp// Check: Sufficient color contrast bool hasAdequateContrast(QColor foreground, QColor background) { double ratio = calculateContrastRatio(foreground, background); return ratio >= 4.5; // WCAG AA for normal text } // Check: Text is scalable void auditFontScaling(QWidget* widget) { QFont font = widget->font(); if (font.pixelSize() > 0) { reportIssue("Use point size instead of pixel size", widget); } }
cpp// BAD: No accessible name QPushButton* btn = new QPushButton(QIcon(":/save.png"), ""); // GOOD: Has accessible name QPushButton* btn = new QPushButton(QIcon(":/save.png"), ""); btn->setAccessibleName(tr("Save")); btn->setAccessibleDescription(tr("Save the current document"));
cpp// BAD: Custom control not focusable CustomControl* ctrl = new CustomControl(); ctrl->setFocusPolicy(Qt::NoFocus); // GOOD: Focusable with keyboard support CustomControl* ctrl = new CustomControl(); ctrl->setFocusPolicy(Qt::StrongFocus);
cpp// BAD: Low contrast text label->setStyleSheet("color: #888888; background: white;"); // GOOD: WCAG AA compliant contrast label->setStyleSheet("color: #595959; background: white;");
qml// Accessible QML component Button { text: qsTr("Submit") Accessible.name: qsTr("Submit form") Accessible.description: qsTr("Submit the registration form") Accessible.role: Accessible.Button // Keyboard handling Keys.onReturnPressed: clicked() Keys.onEnterPressed: clicked() } // Accessible image Image { source: "chart.png" Accessible.name: qsTr("Sales chart for Q4 2024") Accessible.role: Accessible.Graphic } // Focus indicator Rectangle { border.color: parent.activeFocus ? "blue" : "transparent" border.width: 2 }
cpp// Verify with Windows Narrator // Use Accessibility Insights tool void testWithUIAutomation() { // Check UI Automation tree // Verify all controls have automation IDs }
cpp// Verify with VoiceOver // Check NSAccessibility compliance void testWithVoiceOver() { // Check accessibility hierarchy // Verify labels are announced correctly }
cpp// Verify with Orca screen reader // Use Accerciser for AT-SPI inspection void testWithATSPI() { // Check AT-SPI tree // Verify accessible events }
| WCAG Criterion | Qt Implementation | |----------------|-------------------| | 1.1.1 Non-text Content | setAccessibleName() for images/icons | | 1.4.3 Contrast | QPalette with sufficient contrast | | 2.1.1 Keyboard | setFocusPolicy(), key handlers | | 2.4.3 Focus Order | setTabOrder() | | 2.4.7 Focus Visible | Focus indicators in stylesheet | | 4.1.2 Name, Role, Value | QAccessible interface |
accessibility-test-runner - Automated testingqt-qml-component-generator - Accessible componentsdesktop-accessibility process - Full workflowaccessibility-compliance-auditor - Compliance expertiseqt-cpp-specialist - Qt implementation guidance| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 25,298 | 9,297 | -63% | 1 | 1 | 0% | 4,488 | 3,670 | -18% | 0 | 0 | — |
case-02 | fail→fail | 22,371 | 18,597 | -17% | 1 | 1 | 0% | 4,964 | 5,947 | +20% | 0 | 0 | — |
case-03 | fail→pass | 20,450 | 24,379 | +19% | 1 | 1 | 0% | 4,072 | 5,913 | +45% | 0 | 0 | — |
case-04 | pass→pass | 9,550 | 5,964 | -38% | 1 | 1 | 0% | 1,875 | 3,070 | +64% | 0 | 0 | — |
case-05 | pass→pass | 12,363 | 11,317 | -8% | 1 | 1 | 0% | 2,474 | 3,636 | +47% | 0 | 0 | — |
case-06 | pass→pass | 9,330 | 6,163 | -34% | 1 | 1 | 0% | 1,756 | 2,874 | +64% | 0 | 0 | — |
case-07 | pass→pass | 4,407 | 6,442 | +46% | 1 | 1 | 0% | 832 | 2,906 | +249% | 0 | 0 | — |
case-08 | pass→pass | 2,827 | 4,595 | +63% | 1 | 1 | 0% | 500 | 2,648 | +430% | 0 | 0 | — |
case-09 | pass→pass | 9,483 | 7,170 | -24% | 1 | 1 | 0% | 1,901 | 2,943 | +55% | 0 | 0 | — |
case-10 | pass→pass | 7,043 | 6,614 | -6% | 1 | 1 | 0% | 1,377 | 3,010 | +119% | 0 | 0 | — |
case-11 | pass→pass | 7,635 | 5,773 | -24% | 1 | 1 | 0% | 1,378 | 2,938 | +113% | 0 | 0 | — |
case-12 | pass→pass | 5,414 | 4,225 | -22% | 1 | 1 | 0% | 971 | 2,627 | +171% | 0 | 0 | — |
case-13 | pass→pass | 9,437 | 6,410 | -32% | 1 | 1 | 0% | 1,645 | 2,957 | +80% | 0 | 0 | — |
case-14 | pass→pass | 6,628 | 3,427 | -48% | 1 | 1 | 0% | 1,095 | 2,432 | +122% | 0 | 0 | — |
case-15 | pass→pass | 12,592 | 6,999 | -44% | 1 | 1 | 0% | 2,433 | 3,134 | +29% | 0 | 0 | — |
case-16 | pass→pass | 6,676 | 3,175 | -52% | 1 | 1 | 0% | 1,159 | 2,400 | +107% | 0 | 0 | — |
case-17 | pass→pass | 3,600 | 4,092 | +14% | 1 | 1 | 0% | 549 | 2,492 | +354% | 0 | 0 | — |
case-18 | fail→pass | 8,021 | 1,365 | -83% | 1 | 1 | 0% | 1,206 | 2,033 | +69% | 0 | 0 | — |
case-19 | fail→pass | 10,224 | 2,523 | -75% | 1 | 1 | 0% | 1,876 | 2,242 | +20% | 0 | 0 | — |
case-20 | pass→pass | 17,259 | 12,307 | -29% | 1 | 1 | 0% | 2,993 | 3,918 | +31% | 0 | 0 | — |
case-21 | pass→pass | 16,732 | 12,583 | -25% | 1 | 1 | 0% | 2,861 | 4,128 | +44% | 0 | 0 | — |
case-22 | pass→pass | 13,341 | 9,369 | -30% | 1 | 1 | 0% | 2,368 | 3,862 | +63% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +18 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.