tdf#159925 - A11Y sidebar: Check for missing hyperlink name

Check if the hyperlink have missing name and add a fix button
to fix the warning.

Change-Id: I3a69490aa81cf0ed9d0edb04eaa3401e4b47eb7f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169508
Tested-by: Jenkins
Tested-by: Gabor Kelemen <gabor.kelemen.extern@allotropia.de>
Reviewed-by: Balazs Varga <balazs.varga.extern@allotropia.de>
diff --git a/include/sfx2/AccessibilityIssue.hxx b/include/sfx2/AccessibilityIssue.hxx
index d6dd7eb..1533159 100644
--- a/include/sfx2/AccessibilityIssue.hxx
+++ b/include/sfx2/AccessibilityIssue.hxx
@@ -37,6 +37,7 @@ enum class AccessibilityIssueID
    TABLE_FORMATTING,
    HYPERLINK_IS_TEXT,
    HYPERLINK_SHORT,
    HYPERLINK_NO_NAME,
    FAKE_FOOTNOTE,
    FAKE_CAPTION,
    MANUAL_NUMBERING
diff --git a/sw/inc/AccessibilityCheckStrings.hrc b/sw/inc/AccessibilityCheckStrings.hrc
index 8073f9c..11a5b52 100644
--- a/sw/inc/AccessibilityCheckStrings.hrc
+++ b/sw/inc/AccessibilityCheckStrings.hrc
@@ -19,6 +19,7 @@
#define STR_FAKE_NUMBERING              NC_("STR_FAKE_NUMBERING", "Simulated numbering “%NUMBERING%”.")
#define STR_HYPERLINK_TEXT_IS_LINK      NC_("STR_HYPERLINK_TEXT_IS_LINK", "Hyperlink text is the same as the link address “%LINK%”.")
#define STR_HYPERLINK_TEXT_IS_SHORT     NC_("STR_HYPERLINK_TEXT_IS_SHORT", "Hyperlink text is too short.")
#define STR_HYPERLINK_NO_NAME           NC_("STR_HYPERLINK_NO_NAME", "Missing 'Name' property of hyperlink.")
#define STR_TEXT_CONTRAST               NC_("STR_TEXT_CONTRAST", "Text contrast is too low.")
#define STR_TEXT_BLINKING               NC_("STR_TEXT_BLINKING", "Blinking text.")
#define STR_AVOID_FOOTNOTES             NC_("STR_AVOID_FOOTNOTES", "Avoid footnotes.")
@@ -45,6 +46,7 @@
#define STR_DOCUMENT_TITLE              NC_("STR_DOCUMENT_TITLE", "Document title is not set.")
#define STR_DOCUMENT_TITLE_DLG_TITLE    NC_("STR_DOCUMENT_TITLE_DLG_TITLE", "Document title")
#define STR_DOCUMENT_TITLE_DLG_DESC     NC_("STR_DOCUMENT_TITLE_DLG_DESC", "Enter document title:")
#define STR_HYPERLINK_NO_NAME_DLG       NC_("STR_HYPERLINK_NO_NAME_DLG", "Enter a name of the hyperlink:")

#define STR_ENTER_ALT                   NC_("STR_ENTER_ALT", "Enter alternative text:")

diff --git a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
index d3355bc..302efe2 100644
--- a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
+++ b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
@@ -129,9 +129,11 @@ CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testHyperlinks)
    sw::AccessibilityCheck aCheck(pDoc);
    aCheck.check();
    auto& aIssues = aCheck.getIssueCollection().getIssues();
    CPPUNIT_ASSERT_EQUAL(size_t(2), aIssues.size());
    CPPUNIT_ASSERT_EQUAL(size_t(4), aIssues.size());
    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::HYPERLINK_SHORT, aIssues[0]->m_eIssueID);
    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::HYPERLINK_IS_TEXT, aIssues[1]->m_eIssueID);
    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::HYPERLINK_NO_NAME, aIssues[1]->m_eIssueID);
    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::HYPERLINK_IS_TEXT, aIssues[2]->m_eIssueID);
    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::HYPERLINK_NO_NAME, aIssues[3]->m_eIssueID);
}

CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckHighlightedText)
diff --git a/sw/source/core/access/AccessibilityCheck.cxx b/sw/source/core/access/AccessibilityCheck.cxx
index cd75eda..70e71f4 100644
--- a/sw/source/core/access/AccessibilityCheck.cxx
+++ b/sw/source/core/access/AccessibilityCheck.cxx
@@ -406,6 +406,32 @@ private:
                pIssue->setStart(nStart);
                pIssue->setEnd(nStart + sText.getLength());
            }

            if (aHyperlink.GetProtocol() != INetProtocol::NotValid)
            {
                // Check if the Hyperlink have Name settled.
                if (!xProperties->getPropertySetInfo()->hasPropertyByName(u"HyperLinkName"_ustr))
                    return;

                OUString sHyperlinkName;
                xProperties->getPropertyValue(u"HyperLinkName"_ustr) >>= sHyperlinkName;
                if (sHyperlinkName.isEmpty())
                {
                    std::shared_ptr<sw::AccessibilityIssue> pNameIssue
                        = lclAddIssue(m_rIssueCollection, SwResId(STR_HYPERLINK_NO_NAME),
                                      sfx::AccessibilityIssueID::HYPERLINK_NO_NAME);

                    if (pNameIssue)
                    {
                        pNameIssue->setIssueObject(IssueObject::HYPERLINKTEXT);
                        pNameIssue->setNode(pTextNode);
                        SwDoc& rDocument = pTextNode->GetDoc();
                        pNameIssue->setDoc(rDocument);
                        pNameIssue->setStart(nStart);
                        pNameIssue->setEnd(nStart + sText.getLength());
                    }
                }
            }
        }
    }

diff --git a/sw/source/core/access/AccessibilityIssue.cxx b/sw/source/core/access/AccessibilityIssue.cxx
index 7347559..5c34449 100644
--- a/sw/source/core/access/AccessibilityIssue.cxx
+++ b/sw/source/core/access/AccessibilityIssue.cxx
@@ -29,6 +29,7 @@

#include <svx/svdview.hxx>
#include <flyfrm.hxx>
#include <unotextrange.hxx>
#include <txatbase.hxx>
#include <txtfrm.hxx>

@@ -185,6 +186,7 @@ void AccessibilityIssue::gotoIssue() const
        }
        break;
        case IssueObject::TEXT:
        case IssueObject::HYPERLINKTEXT:
        {
            SwContentNode* pContentNode = TempIssueObject.m_pNode->GetContentNode();
            SwPosition aStart(*pContentNode, TempIssueObject.m_nStart);
@@ -241,7 +243,8 @@ bool AccessibilityIssue::canQuickFixIssue() const
           || m_eIssueObject == IssueObject::SHAPE || m_eIssueObject == IssueObject::FORM
           || m_eIssueObject == IssueObject::DOCUMENT_TITLE
           || m_eIssueObject == IssueObject::DOCUMENT_BACKGROUND
           || m_eIssueObject == IssueObject::LANGUAGE_NOT_SET;
           || m_eIssueObject == IssueObject::LANGUAGE_NOT_SET
           || m_eIssueObject == IssueObject::HYPERLINKTEXT;
}

void AccessibilityIssue::quickFixIssue() const
@@ -323,6 +326,33 @@ void AccessibilityIssue::quickFixIssue() const
            }
        }
        break;
        case IssueObject::HYPERLINKTEXT:
        {
            SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
            SwWrtShell* pWrtShell = m_pDoc->GetDocShell()->GetWrtShell();
            ScopedVclPtr<AbstractSvxNameDialog> aNameDialog(pFact->CreateSvxNameDialog(
                pWrtShell->GetView().GetFrameWeld(), OUString(), SwResId(STR_HYPERLINK_NO_NAME_DLG),
                SwResId(STR_HYPERLINK_NO_NAME_DLG)));
            if (aNameDialog->Execute() == RET_OK)
            {
                SwContentNode* pContentNode = m_pNode->GetContentNode();
                SwPosition aStart(*pContentNode, m_nStart);
                SwPosition aEnd(*pContentNode, m_nEnd);
                uno::Reference<text::XTextRange> xRun
                    = SwXTextRange::CreateXTextRange(*m_pDoc, aStart, &aEnd);
                if (xRun.is())
                {
                    uno::Reference<beans::XPropertySet> xProperties(xRun, uno::UNO_QUERY);
                    if (xProperties->getPropertySetInfo()->hasPropertyByName(u"HyperLinkName"_ustr))
                    {
                        xProperties->setPropertyValue(u"HyperLinkName"_ustr,
                                                      uno::Any(aNameDialog->GetName()));
                    }
                }
                pWrtShell->SetModified();
            }
        }
        break;
        case IssueObject::DOCUMENT_TITLE:
        {
            SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
diff --git a/sw/source/core/inc/AccessibilityIssue.hxx b/sw/source/core/inc/AccessibilityIssue.hxx
index 5fe9857..e4c1b32 100644
--- a/sw/source/core/inc/AccessibilityIssue.hxx
+++ b/sw/source/core/inc/AccessibilityIssue.hxx
@@ -26,6 +26,7 @@ enum class IssueObject
    FORM,
    TABLE,
    TEXT,
    HYPERLINKTEXT,
    DOCUMENT_TITLE,
    DOCUMENT_BACKGROUND,
    LANGUAGE_NOT_SET,
diff --git a/sw/source/uibase/sidebar/A11yCheckIssuesPanel.cxx b/sw/source/uibase/sidebar/A11yCheckIssuesPanel.cxx
index a8de694..0dded3d 100644
--- a/sw/source/uibase/sidebar/A11yCheckIssuesPanel.cxx
+++ b/sw/source/uibase/sidebar/A11yCheckIssuesPanel.cxx
@@ -295,6 +295,7 @@ void A11yCheckIssuesPanel::populateIssues()
            break;
            case sfx::AccessibilityIssueID::HYPERLINK_IS_TEXT:
            case sfx::AccessibilityIssueID::HYPERLINK_SHORT:
            case sfx::AccessibilityIssueID::HYPERLINK_NO_NAME:
            {
                addEntryForGroup(AccessibilityCheckGroups::Hyperlink, nIndices, pIssue);
            }