include/sfx2/AccessibilityIssue.hxx | 1 sw/inc/AccessibilityCheckStrings.hrc | 1 sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx | 11 ++ sw/qa/core/accessibilitycheck/data/TableFormattingTest.odt |binary sw/source/core/access/AccessibilityCheck.cxx | 49 +++++++++++++ 5 files changed, 62 insertions(+)
New commits: commit 5c8934809ac60488d6160e27ff5962350c612a09 Author: Paris Oplopoios <paris.oplopo...@collabora.com> AuthorDate: Thu Nov 3 01:02:40 2022 +0200 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Thu Nov 3 07:53:53 2022 +0100 a11y: Add check for table used for text formatting Add accessibility check and relevant test for a document that uses a table for text formatting Change-Id: I20290a3ec89cd5333f3c66867b50aa7b80ed494f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142188 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/include/sfx2/AccessibilityIssue.hxx b/include/sfx2/AccessibilityIssue.hxx index b9e3266c73a2..0c22d9e19238 100644 --- a/include/sfx2/AccessibilityIssue.hxx +++ b/include/sfx2/AccessibilityIssue.hxx @@ -29,6 +29,7 @@ enum class AccessibilityIssueID NO_ALT_SHAPE, TABLE_MERGE_SPLIT, TEXT_FORMATTING, + TABLE_FORMATTING, HYPERLINK_IS_TEXT, HYPERLINK_SHORT, FAKE_FOOTNOTE, diff --git a/sw/inc/AccessibilityCheckStrings.hrc b/sw/inc/AccessibilityCheckStrings.hrc index e63d304d1063..7245a2b8d3e0 100644 --- a/sw/inc/AccessibilityCheckStrings.hrc +++ b/sw/inc/AccessibilityCheckStrings.hrc @@ -34,6 +34,7 @@ #define STR_HEADING_IN_TABLE NC_("STR_HEADING_IN_TABLE", "Tables must not contain headings.") #define STR_HEADING_ORDER NC_("STR_HEADING_ORDER", "Keep headings' levels ordered. Heading level %LEVEL_CURRENT% must not go after %LEVEL_PREV%.") #define STR_FONTWORKS NC_("STR_FONTWORKS", "Avoid Fontwork objects in your documents. Make sure you use it for samples or other meaningless text.") +#define STR_TABLE_FORMATTING NC_("STR_TABLE_FORMATTING", "Avoid using empty table cells for formatting.") #define STR_DOCUMENT_DEFAULT_LANGUAGE NC_("STR_DOCUMENT_DEFAULT_LANGUAGE", "Document default language is not set") #define STR_STYLE_NO_LANGUAGE NC_("STR_STYLE_NO_LANGUAGE", "Style '%STYLE_NAME%' has no language set") diff --git a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx index 02912e4c9d35..b7561ad01764 100644 --- a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx +++ b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx @@ -154,6 +154,17 @@ CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckFakeCaption) CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::FAKE_CAPTION, aIssues[0]->m_eIssueID); } +CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckTableFormatting) +{ + SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "TableFormattingTest.odt"); + CPPUNIT_ASSERT(pDoc); + sw::AccessibilityCheck aCheck(pDoc); + aCheck.check(); + auto& aIssues = aCheck.getIssueCollection().getIssues(); + CPPUNIT_ASSERT_EQUAL(size_t(1), aIssues.size()); + CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TABLE_FORMATTING, aIssues[0]->m_eIssueID); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/core/accessibilitycheck/data/TableFormattingTest.odt b/sw/qa/core/accessibilitycheck/data/TableFormattingTest.odt new file mode 100644 index 000000000000..adc63daaf7cb Binary files /dev/null and b/sw/qa/core/accessibilitycheck/data/TableFormattingTest.odt differ diff --git a/sw/source/core/access/AccessibilityCheck.cxx b/sw/source/core/access/AccessibilityCheck.cxx index 0170003c4a48..ce0409d6ba5b 100644 --- a/sw/source/core/access/AccessibilityCheck.cxx +++ b/sw/source/core/access/AccessibilityCheck.cxx @@ -236,6 +236,50 @@ public: } }; +class TableFormattingCheck : public NodeCheck +{ +private: + void checkTableNode(SwTableNode* pTableNode) + { + if (!pTableNode) + return; + + const SwTable& rTable = pTableNode->GetTable(); + if (!rTable.IsTableComplex()) + { + size_t nEmptyBoxes = 0; + size_t nBoxCount = 0; + for (const SwTableLine* pTableLine : rTable.GetTabLines()) + { + nBoxCount += pTableLine->GetTabBoxes().size(); + for (const SwTableBox* pBox : pTableLine->GetTabBoxes()) + if (pBox->IsEmpty()) + ++nEmptyBoxes; + } + // If more than half of the boxes are empty we can assume that it is used for formatting + if (nEmptyBoxes > nBoxCount / 2) + lclAddIssue(m_rIssueCollection, SwResId(STR_TABLE_FORMATTING), + sfx::AccessibilityIssueID::TABLE_FORMATTING); + } + } + +public: + TableFormattingCheck(sfx::AccessibilityIssueCollection& rIssueCollection) + : NodeCheck(rIssueCollection) + { + } + + void check(SwNode* pCurrent) override + { + if (pCurrent->GetNodeType() & SwNodeType::Table) + { + SwTableNode* pTableNode = pCurrent->GetTableNode(); + if (pTableNode) + checkTableNode(pTableNode); + } + } +}; + class NumberingCheck : public NodeCheck { private: @@ -674,6 +718,10 @@ public: if (!pCurrent->IsTextNode()) return; + // Don't count empty table box text nodes + if (pCurrent->GetTableBox()) + return; + SwTextNode* pTextNode = pCurrent->GetTextNode(); auto nParagraphLength = pTextNode->GetText().getLength(); if (nParagraphLength == 0) @@ -1318,6 +1366,7 @@ void AccessibilityCheck::check() std::vector<std::unique_ptr<NodeCheck>> aNodeChecks; aNodeChecks.push_back(std::make_unique<NoTextNodeAltTextCheck>(m_aIssueCollection)); aNodeChecks.push_back(std::make_unique<TableNodeMergeSplitCheck>(m_aIssueCollection)); + aNodeChecks.push_back(std::make_unique<TableFormattingCheck>(m_aIssueCollection)); aNodeChecks.push_back(std::make_unique<NumberingCheck>(m_aIssueCollection)); aNodeChecks.push_back(std::make_unique<HyperlinkCheck>(m_aIssueCollection)); aNodeChecks.push_back(std::make_unique<TextContrastCheck>(m_aIssueCollection));