weld SvxEditModulesDlg

Change-Id: I802d4c92924b379f11c73ddfe758f4c6a63feb37
Reviewed-on: https://gerrit.libreoffice.org/73354
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/cui/source/inc/optlingu.hxx b/cui/source/inc/optlingu.hxx
index 77e016d..8478f9b 100644
--- a/cui/source/inc/optlingu.hxx
+++ b/cui/source/inc/optlingu.hxx
@@ -50,18 +50,8 @@ class SvxLinguData_Impl;

// forward ---------------------------------------------------------------

class SvxEditModulesDlg : public ModalDialog
class SvxEditModulesDlg : public weld::GenericDialogController
{
    VclPtr<SvxLanguageBox>     m_pLanguageLB;

    VclPtr<SvxCheckListBox>    m_pModulesCLB;
    VclPtr<PushButton>         m_pPrioUpPB;
    VclPtr<PushButton>         m_pPrioDownPB;
    VclPtr<PushButton>         m_pBackPB;
    VclPtr<FixedHyperlink>     m_pMoreDictsLink;

    VclPtr<CloseButton>        m_pClosePB;

    OUString            sSpell;
    OUString            sHyph;
    OUString            sThes;
@@ -70,23 +60,26 @@ class SvxEditModulesDlg : public ModalDialog
    std::unique_ptr<SvxLinguData_Impl>  pDefaultLinguData;
    SvxLinguData_Impl&  rLinguData;

    std::unique_ptr<SvLBoxButtonData>   m_xCheckButtonData;
    std::unique_ptr<weld::TreeView> m_xModulesCLB;
    std::unique_ptr<weld::Button> m_xPrioUpPB;
    std::unique_ptr<weld::Button> m_xPrioDownPB;
    std::unique_ptr<weld::Button> m_xBackPB;
    std::unique_ptr<weld::LinkButton> m_xMoreDictsLink;
    std::unique_ptr<weld::Button> m_xClosePB;
    std::unique_ptr<LanguageBox> m_xLanguageLB;

    SvTreeListEntry*    CreateEntry(OUString& rTxt, sal_uInt16 nCol);

    DECL_LINK( SelectHdl_Impl, SvTreeListBox*, void );
    DECL_LINK( UpDownHdl_Impl, Button*, void );
    DECL_LINK( ClickHdl_Impl, Button*, void );
    DECL_LINK( BackHdl_Impl, Button*, void );
    DECL_LINK( LangSelectListBoxHdl_Impl, ListBox&, void );
    DECL_LINK( BoxCheckButtonHdl_Impl2, SvLBoxButtonData*, void );
    DECL_LINK( BoxCheckButtonHdl_Impl, SvTreeListBox*, void );
    void LangSelectHdl_Impl(ListBox const *);
    DECL_LINK( SelectHdl_Impl, weld::TreeView&, void );
    DECL_LINK( UpDownHdl_Impl, weld::Button&, void );
    DECL_LINK( ClickHdl_Impl, weld::Button&, void );
    DECL_LINK( BackHdl_Impl, weld::Button&, void );
    DECL_LINK( LangSelectListBoxHdl_Impl, weld::ComboBox&, void );
    typedef std::pair<int, int> row_col;
    DECL_LINK( BoxCheckButtonHdl_Impl, const row_col&, void );
    void LangSelectHdl_Impl(const LanguageBox* pBox);

public:
    SvxEditModulesDlg(vcl::Window* pParent, SvxLinguData_Impl& rData);
    SvxEditModulesDlg(weld::Window* pParent, SvxLinguData_Impl& rData);
    virtual ~SvxEditModulesDlg() override;
    virtual void dispose() override;
};

// class SvxLinguTabPage -------------------------------------------------
diff --git a/cui/source/options/optlingu.cxx b/cui/source/options/optlingu.cxx
index 5be9468..ed8b59e 100644
--- a/cui/source/options/optlingu.cxx
+++ b/cui/source/options/optlingu.cxx
@@ -78,9 +78,6 @@ using namespace css::uno;
using namespace css::linguistic2;
using namespace css::beans;

#define CBCOL_FIRST     0
#define CBCOL_SECOND    1

static const sal_Char cSpell[]   = SN_SPELLCHECKER;
static const sal_Char cGrammar[] = SN_GRAMMARCHECKER;
static const sal_Char cHyph[]    = SN_HYPHENATOR;
@@ -88,29 +85,6 @@ static const sal_Char cThes[]    = SN_THESAURUS;

// static ----------------------------------------------------------------

static std::vector< LanguageType > lcl_LocaleSeqToLangSeq( const Sequence< Locale > &rSeq )
{
    sal_Int32 nLen = rSeq.getLength();
    std::vector<LanguageType> aRes;
    aRes.reserve(nLen);
    const Locale *pSeq = rSeq.getConstArray();
    for (sal_Int32 i = 0;  i < nLen;  ++i)
    {
        aRes.push_back( LanguageTag::convertToLanguageType( pSeq[i] ) );
    }
    return aRes;
}


static bool lcl_SeqHasLang( const std::vector< LanguageType > &rSeq, LanguageType nLang )
{
    for (auto const & i : rSeq)
        if (i == nLang)
            return true;
    return false;
}


static sal_Int32 lcl_SeqGetEntryPos(
    const Sequence< OUString > &rSeq, const OUString &rEntry )
{
@@ -214,49 +188,6 @@ DicUserData::DicUserData(
            (static_cast<sal_uInt32>(bDeletable ? 1 : 0)    << 10);
}

static void lcl_SetCheckButton( SvTreeListEntry* pEntry, bool bCheck )
{
    SvLBoxButton* pItem = static_cast<SvLBoxButton*>(pEntry->GetFirstItem(SvLBoxItemType::Button));

    DBG_ASSERT(pItem,"SetCheckButton:Item not found");
    if (pItem && pItem->GetType() == SvLBoxItemType::Button)
    {
        if (bCheck)
            pItem->SetStateChecked();
        else
            pItem->SetStateUnchecked();
    }
}

class BrwStringDic_Impl : public SvLBoxString
{
public:

    explicit BrwStringDic_Impl( const OUString& rStr ) : SvLBoxString( rStr ) {}

    virtual void Paint(const Point& rPos, SvTreeListBox& rOutDev, vcl::RenderContext& rRenderContext,
                       const SvViewDataEntry* pView, const SvTreeListEntry& rEntry) override;
};

void BrwStringDic_Impl::Paint(const Point& rPos, SvTreeListBox& /*rDev*/, vcl::RenderContext& rRenderContext,
                              const SvViewDataEntry* /*pView*/, const SvTreeListEntry& rEntry)
{
    ModuleUserData_Impl* pData = static_cast<ModuleUserData_Impl*>(rEntry.GetUserData());
    Point aPos(rPos);
    rRenderContext.Push(PushFlags::FONT);
    if (pData->IsParent())
    {
        vcl::Font aFont(rRenderContext.GetFont());
        aFont.SetWeight(WEIGHT_BOLD);
        rRenderContext.SetFont(aFont);
        aPos.setX( 0 );
    }
    else
        aPos.AdjustX(5 );
    rRenderContext.DrawText(aPos, GetText());
    rRenderContext.Pop();
}

/*--------------------------------------------------
    Entry IDs for options listbox of dialog
--------------------------------------------------*/
@@ -1411,8 +1342,8 @@ IMPL_LINK(SvxLinguTabPage, ClickHdl_Impl, weld::Button&, rBtn, void)
            pLinguData.reset( new SvxLinguData_Impl );

        SvxLinguData_Impl   aOldLinguData( *pLinguData );
        ScopedVclPtrInstance< SvxEditModulesDlg > aDlg( this, *pLinguData );
        if (aDlg->Execute() != RET_OK)
        SvxEditModulesDlg aDlg(GetDialogFrameWeld(), *pLinguData);
        if (aDlg.run() != RET_OK)
            *pLinguData = aOldLinguData;

        // evaluate new status of 'bConfigured' flag
@@ -1618,189 +1549,123 @@ void SvxLinguTabPage::HideGroups( sal_uInt16 nGrp )
    }
}

SvxEditModulesDlg::SvxEditModulesDlg(vcl::Window* pParent, SvxLinguData_Impl& rData)
    : ModalDialog( pParent, "EditModulesDialog",
        "cui/ui/editmodulesdialog.ui")
SvxEditModulesDlg::SvxEditModulesDlg(weld::Window* pParent, SvxLinguData_Impl& rData)
    : GenericDialogController(pParent, "cui/ui/editmodulesdialog.ui", "EditModulesDialog")
    , sSpell(CuiResId(RID_SVXSTR_SPELL))
    , sHyph(CuiResId(RID_SVXSTR_HYPH))
    , sThes(CuiResId(RID_SVXSTR_THES))
    , sGrammar(CuiResId(RID_SVXSTR_GRAMMAR))
    , rLinguData(rData)
    , m_xModulesCLB(m_xBuilder->weld_tree_view("lingudicts"))
    , m_xPrioUpPB(m_xBuilder->weld_button("up"))
    , m_xPrioDownPB(m_xBuilder->weld_button("down"))
    , m_xBackPB(m_xBuilder->weld_button("back"))
    , m_xMoreDictsLink(m_xBuilder->weld_link_button("moredictslink"))
    , m_xClosePB(m_xBuilder->weld_button("close"))
    , m_xLanguageLB(new LanguageBox(m_xBuilder->weld_combo_box("language")))
{
    get(m_pClosePB, "close");
    get(m_pMoreDictsLink, "moredictslink");
    get(m_pBackPB, "back");
    get(m_pPrioDownPB, "down");
    get(m_pPrioUpPB, "up");
    get(m_pModulesCLB, "lingudicts");
    Size aListSize(m_pModulesCLB->LogicToPixel(Size(166, 120), MapMode(MapUnit::MapAppFont)));
    m_pModulesCLB->set_height_request(aListSize.Height());
    m_pModulesCLB->set_width_request(aListSize.Width());
    get(m_pLanguageLB, "language");
    m_pLanguageLB->SetStyle(m_pLanguageLB->GetStyle() | WB_SORT);
    m_xModulesCLB->set_size_request(m_xModulesCLB->get_approximate_digit_width() * 40,
                                    m_xModulesCLB->get_height_rows(12));

    std::vector<int> aWidths;
    aWidths.push_back(m_xModulesCLB->get_checkbox_column_width());
    m_xModulesCLB->set_column_fixed_widths(aWidths);

    pDefaultLinguData.reset( new SvxLinguData_Impl( rLinguData ) );

    m_pModulesCLB->SetStyle( m_pModulesCLB->GetStyle()|WB_CLIPCHILDREN|WB_HSCROLL );
    m_pModulesCLB->SetForceMakeVisible(true);
    m_pModulesCLB->SetHighlightRange();
    m_pModulesCLB->SetSelectHdl( LINK( this, SvxEditModulesDlg, SelectHdl_Impl ));
    m_pModulesCLB->SetCheckButtonHdl( LINK( this, SvxEditModulesDlg, BoxCheckButtonHdl_Impl) );
    m_xModulesCLB->connect_changed( LINK( this, SvxEditModulesDlg, SelectHdl_Impl ));
    m_xModulesCLB->connect_toggled(LINK(this, SvxEditModulesDlg, BoxCheckButtonHdl_Impl));

    m_pClosePB->SetClickHdl( LINK( this, SvxEditModulesDlg, ClickHdl_Impl ));
    m_pPrioUpPB->SetClickHdl( LINK( this, SvxEditModulesDlg, UpDownHdl_Impl ));
    m_pPrioDownPB->SetClickHdl( LINK( this, SvxEditModulesDlg, UpDownHdl_Impl ));
    m_pBackPB->SetClickHdl( LINK( this, SvxEditModulesDlg, BackHdl_Impl ));
    m_xClosePB->connect_clicked( LINK( this, SvxEditModulesDlg, ClickHdl_Impl ));
    m_xPrioUpPB->connect_clicked( LINK( this, SvxEditModulesDlg, UpDownHdl_Impl ));
    m_xPrioDownPB->connect_clicked( LINK( this, SvxEditModulesDlg, UpDownHdl_Impl ));
    m_xBackPB->connect_clicked( LINK( this, SvxEditModulesDlg, BackHdl_Impl ));
    // in case of not installed language modules
    m_pPrioUpPB->Enable( false );
    m_pPrioDownPB->Enable( false );
    m_xPrioUpPB->set_sensitive( false );
    m_xPrioDownPB->set_sensitive( false );

    if ( SvtExtendedSecurityOptions().GetOpenHyperlinkMode() == SvtExtendedSecurityOptions::OPEN_NEVER )
        m_pMoreDictsLink->Hide();
        m_xMoreDictsLink->hide();

    // set that we want the checkbox shown if spellchecking is available
    m_xLanguageLB->SetLanguageList(SvxLanguageListFlags::EMPTY, false, false, true);

    //fill language box
    std::vector< LanguageType > aAvailLang;
    uno::Reference< XAvailableLocales > xAvail( rLinguData.GetManager(), UNO_QUERY );
    if (xAvail.is())
    {
        aAvailLang = lcl_LocaleSeqToLangSeq(
                        xAvail->getAvailableLocales( cSpell ) );
    }
    const Sequence< Locale >& rLoc = rLinguData.GetAllSupportedLocales();
    const Locale* pLocales = rLoc.getConstArray();
    m_pLanguageLB->Clear();
    for(long i = 0; i < rLoc.getLength(); i++)
    for (int i = 0; i < rLoc.getLength(); ++i)
    {
        LanguageType nLang = LanguageTag::convertToLanguageType( pLocales[i] );
        m_pLanguageLB->InsertLanguage( nLang, lcl_SeqHasLang( aAvailLang, nLang ) );
        m_xLanguageLB->InsertLanguage(nLang);
    }
    LanguageType eSysLang = MsLangId::getSystemLanguage();
    m_pLanguageLB->SelectLanguage( eSysLang );
    if(!m_pLanguageLB->IsLanguageSelected( eSysLang ) )
        m_pLanguageLB->SelectEntryPos(0);
    m_xLanguageLB->set_active_id( eSysLang );
    if (m_xLanguageLB->get_active_id() != eSysLang)
        m_xLanguageLB->set_active(0);

    m_pLanguageLB->SetSelectHdl( LINK( this, SvxEditModulesDlg, LangSelectListBoxHdl_Impl ));
    LangSelectHdl_Impl(m_pLanguageLB);
    m_xLanguageLB->connect_changed( LINK( this, SvxEditModulesDlg, LangSelectListBoxHdl_Impl ));
    LangSelectHdl_Impl(m_xLanguageLB.get());
}


SvxEditModulesDlg::~SvxEditModulesDlg()
{
    disposeOnce();
    for (int i = 0, nEntryCount = m_xModulesCLB->n_children(); i < nEntryCount; ++i)
        delete reinterpret_cast<ModuleUserData_Impl*>(m_xModulesCLB->get_id(i).toInt64());
}

void SvxEditModulesDlg::dispose()
IMPL_LINK( SvxEditModulesDlg, SelectHdl_Impl, weld::TreeView&, rBox, void )
{
    pDefaultLinguData.reset();
    m_pLanguageLB.clear();
    for(sal_uLong i = 0; i < m_pModulesCLB->GetEntryCount(); i++)
        delete static_cast<ModuleUserData_Impl*>(m_pModulesCLB->GetEntry(i)->GetUserData());
    m_pModulesCLB.clear();
    m_pPrioUpPB.clear();
    m_pPrioDownPB.clear();
    m_pBackPB.clear();
    m_pMoreDictsLink.clear();
    m_pClosePB.clear();
    ModalDialog::dispose();
}

SvTreeListEntry* SvxEditModulesDlg::CreateEntry( OUString& rTxt, sal_uInt16 nCol )
{
    SvTreeListEntry* pEntry = new SvTreeListEntry;
    if (!m_xCheckButtonData )
    int nCurPos = rBox.get_selected_index();
    if (nCurPos != -1)
    {
        m_xCheckButtonData.reset(new SvLBoxButtonData(m_pModulesCLB));
        m_xCheckButtonData->SetLink( LINK( this, SvxEditModulesDlg, BoxCheckButtonHdl_Impl2 ) );
    }

    if (CBCOL_FIRST == nCol)
        pEntry->AddItem(std::make_unique<SvLBoxButton>(SvLBoxButtonKind::EnabledCheckbox, m_xCheckButtonData.get()));
    if (CBCOL_SECOND == nCol)
        pEntry->AddItem(std::make_unique<SvLBoxString>(""));    // empty column
    pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(Image(), Image(), false));
    pEntry->AddItem(std::make_unique<BrwStringDic_Impl>(rTxt));

    return pEntry;
}

IMPL_LINK( SvxEditModulesDlg, SelectHdl_Impl, SvTreeListBox*, pBox, void )
{
    if (m_pModulesCLB == pBox)
    {
        SvTreeListEntry *pEntry = pBox->GetCurEntry();
        if (pEntry)
        bool bDisableUp = true;
        bool bDisableDown = true;
        ModuleUserData_Impl* pData = reinterpret_cast<ModuleUserData_Impl*>(rBox.get_id(nCurPos).toInt64());
        if (!pData->IsParent() && pData->GetType() != TYPE_HYPH)
        {
            bool bDisableUp = true;
            bool bDisableDown = true;
            ModuleUserData_Impl* pData = static_cast<ModuleUserData_Impl*>(pEntry->GetUserData());
            if(!pData->IsParent() && pData->GetType() != TYPE_HYPH)
            if (nCurPos < rBox.n_children() - 1)
            {
                sal_uLong  nCurPos = static_cast<SvxCheckListBox*>(pBox)->GetSelectedEntryPos();
                if(nCurPos < pBox->GetEntryCount() - 1)
                {
                    bDisableDown = static_cast<ModuleUserData_Impl*>(pBox->
                            GetEntry(nCurPos + 1)->GetUserData())->IsParent();
                }
                if(nCurPos > 1)
                {
                    bDisableUp = static_cast<ModuleUserData_Impl*>(pBox->
                            GetEntry(nCurPos - 1)->GetUserData())->IsParent();
                }
                bDisableDown = reinterpret_cast<ModuleUserData_Impl*>(rBox.get_id(nCurPos + 1).toInt64())->IsParent();
            }
            m_pPrioUpPB->Enable(!bDisableUp);
            m_pPrioDownPB->Enable(!bDisableDown);
        }
    }
    else
    {
        OSL_FAIL( "pBox unexpected value" );
    }
}

IMPL_LINK_NOARG( SvxEditModulesDlg, BoxCheckButtonHdl_Impl2, SvLBoxButtonData*, void )
{
    BoxCheckButtonHdl_Impl(nullptr);
}

IMPL_LINK_NOARG( SvxEditModulesDlg, BoxCheckButtonHdl_Impl, SvTreeListBox *, void )
{
    SvTreeListEntry *pCurEntry = m_pModulesCLB->GetCurEntry();
    if (pCurEntry)
    {
        ModuleUserData_Impl* pData = static_cast<ModuleUserData_Impl *>(
                                            pCurEntry->GetUserData());
        if (!pData->IsParent()  &&  pData->GetType() == TYPE_HYPH)
        {
            // make hyphenator checkboxes function as radio-buttons
            // (at most one box may be checked)
            SvTreeListEntry *pEntry = m_pModulesCLB->First();
            while (pEntry)
            if (nCurPos > 1)
            {
                pData = static_cast<ModuleUserData_Impl*>(pEntry->GetUserData());
                if (!pData->IsParent()  &&
                     pData->GetType() == TYPE_HYPH  &&
                     pEntry != pCurEntry)
                {
                    lcl_SetCheckButton( pEntry, false );
                    m_pModulesCLB->InvalidateEntry( pEntry );
                }
                pEntry = m_pModulesCLB->Next( pEntry );
                bDisableUp = reinterpret_cast<ModuleUserData_Impl*>(rBox.get_id(nCurPos - 1).toInt64())->IsParent();
            }
        }
        m_xPrioUpPB->set_sensitive(!bDisableUp);
        m_xPrioDownPB->set_sensitive(!bDisableDown);
    }
}

IMPL_LINK( SvxEditModulesDlg, BoxCheckButtonHdl_Impl, const row_col&, rRowCol, void )
{
    auto nPos = rRowCol.first;
    ModuleUserData_Impl* pData = reinterpret_cast<ModuleUserData_Impl*>(m_xModulesCLB->get_id(nPos).toInt64());
    if (!pData->IsParent() && pData->GetType() == TYPE_HYPH)
    {
        // make hyphenator checkboxes function as radio-buttons
        // (at most one box may be checked)
        for (int i = 0, nEntryCount = m_xModulesCLB->n_children(); i < nEntryCount; ++i)
        {
            pData = reinterpret_cast<ModuleUserData_Impl*>(m_xModulesCLB->get_id(i).toInt64());
            if (!pData->IsParent() && pData->GetType() == TYPE_HYPH && i != nPos)
            {
                m_xModulesCLB->set_toggle(i, TRISTATE_FALSE, 0);
            }
        }
    }
}

IMPL_LINK( SvxEditModulesDlg, LangSelectListBoxHdl_Impl, ListBox&, rBox, void )
IMPL_LINK_NOARG(SvxEditModulesDlg, LangSelectListBoxHdl_Impl, weld::ComboBox&, void)
{
    LangSelectHdl_Impl(&rBox);
    LangSelectHdl_Impl(m_xLanguageLB.get());
}

void SvxEditModulesDlg::LangSelectHdl_Impl(ListBox const * pBox)
void SvxEditModulesDlg::LangSelectHdl_Impl(const LanguageBox* pBox)
{
    LanguageType  eCurLanguage = m_pLanguageLB->GetSelectedLanguage();
    LanguageType  eCurLanguage = m_xLanguageLB->get_active_id();
    static Locale aLastLocale;
    Locale aCurLocale( LanguageTag::convertToLocale( eCurLanguage));
    SvTreeList *pModel = m_pModulesCLB->GetModel();

    if (pBox)
    {
@@ -1812,13 +1677,12 @@ void SvxEditModulesDlg::LangSelectHdl_Impl(ListBox const * pBox)
        sal_Int32 nStart = 0, nLocalIndex = 0;
        Sequence< OUString > aChange;
        bool bChanged = false;
        for(sal_uLong i = 0; i < m_pModulesCLB->GetEntryCount(); i++)
        for (int i = 0, nEntryCount = m_xModulesCLB->n_children(); i < nEntryCount; ++i)
        {
            SvTreeListEntry *pEntry = m_pModulesCLB->GetEntry(i);
            ModuleUserData_Impl* pData = static_cast<ModuleUserData_Impl*>(pEntry->GetUserData());
            if(pData->IsParent())
            ModuleUserData_Impl* pData = reinterpret_cast<ModuleUserData_Impl*>(m_xModulesCLB->get_id(i).toInt64());
            if (pData->IsParent())
            {
                if(bChanged)
                if (bChanged)
                {
                    LangImplNameTable *pTable = nullptr;
                    sal_uInt8 nType = pData->GetType();
@@ -1836,7 +1700,7 @@ void SvxEditModulesDlg::LangSelectHdl_Impl(ListBox const * pBox)
                    }
                }
                nLocalIndex = nStart = 0;
                aChange.realloc(m_pModulesCLB->GetEntryCount());
                aChange.realloc(nEntryCount);
                bChanged = false;
            }
            else
@@ -1844,8 +1708,8 @@ void SvxEditModulesDlg::LangSelectHdl_Impl(ListBox const * pBox)
                OUString* pChange = aChange.getArray();
                pChange[nStart] = pData->GetImplName();
                bChanged |= pData->GetIndex() != nLocalIndex ||
                    pData->IsChecked() != m_pModulesCLB->IsChecked(i);
                if(m_pModulesCLB->IsChecked(i))
                    static_cast<TriState>(pData->IsChecked()) != m_xModulesCLB->get_toggle(i, 0);
                if (m_xModulesCLB->get_toggle(i, 0))
                    nStart++;
                ++nLocalIndex;
            }
@@ -1857,26 +1721,28 @@ void SvxEditModulesDlg::LangSelectHdl_Impl(ListBox const * pBox)
        }
    }

    for(sal_uLong i = 0; i < m_pModulesCLB->GetEntryCount(); i++)
        delete static_cast<ModuleUserData_Impl*>(m_pModulesCLB->GetEntry(i)->GetUserData());

    for (int i = 0, nEntryCount = m_xModulesCLB->n_children(); i < nEntryCount; ++i)
        delete reinterpret_cast<ModuleUserData_Impl*>(m_xModulesCLB->get_id(i).toInt64());
    m_xModulesCLB->clear();

    // display entries for new selected language

    m_pModulesCLB->Clear();
    if(LANGUAGE_DONTKNOW != eCurLanguage)
    if (LANGUAGE_DONTKNOW != eCurLanguage)
    {
        sal_uLong n;
        ServiceInfo_Impl* pInfo;


        int nRow = 0;
        // spellchecker entries

        SvTreeListEntry* pEntry = CreateEntry( sSpell,  CBCOL_SECOND );
        ModuleUserData_Impl* pUserData = new ModuleUserData_Impl(
                                         OUString(), true, false, TYPE_SPELL, 0 );
        pEntry->SetUserData( static_cast<void *>(pUserData) );
        pModel->Insert( pEntry );
        OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pUserData)));
        m_xModulesCLB->append(nullptr);
        m_xModulesCLB->set_id(nRow, sId);
        m_xModulesCLB->set_text(nRow, sSpell, 1);
        m_xModulesCLB->set_text_emphasis(nRow, true, 1);
        ++nRow;

        Sequence< OUString > aNames( rLinguData.GetSortedImplNames( eCurLanguage, TYPE_SPELL ) );
        const OUString *pName = aNames.getConstArray();
@@ -1897,7 +1763,6 @@ void SvxEditModulesDlg::LangSelectHdl_Impl(ListBox const * pBox)
            if (!aImplName.isEmpty() && bIsSuppLang)
            {
                OUString aTxt( pInfo->sDisplayName );
                SvTreeListEntry* pNewEntry = CreateEntry( aTxt, CBCOL_FIRST );

                LangImplNameTable &rTable = rLinguData.GetSpellTable();
                const bool bHasLang = rTable.count( eCurLanguage );
@@ -1906,21 +1771,27 @@ void SvxEditModulesDlg::LangSelectHdl_Impl(ListBox const * pBox)
                    SAL_INFO( "cui.options", "language entry missing" );    // only relevant if all languages found should be supported
                }
                const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
                lcl_SetCheckButton( pNewEntry, bCheck );
                pUserData = new ModuleUserData_Impl( aImplName, false,
                                        bCheck, TYPE_SPELL, static_cast<sal_uInt8>(nLocalIndex++) );
                pNewEntry->SetUserData( static_cast<void *>(pUserData) );
                pModel->Insert( pNewEntry );
                sId = OUString::number(reinterpret_cast<sal_Int64>(pUserData));

                m_xModulesCLB->append(nullptr);
                m_xModulesCLB->set_id(nRow, sId);
                m_xModulesCLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE, 0);
                m_xModulesCLB->set_text(nRow, aTxt, 1);
                ++nRow;
            }
        }


        // grammar checker entries

        pEntry = CreateEntry( sGrammar,    CBCOL_SECOND );
        pUserData = new ModuleUserData_Impl( OUString(), true, false, TYPE_GRAMMAR, 0 );
        pEntry->SetUserData( static_cast<void *>(pUserData) );
        pModel->Insert( pEntry );
        sId = OUString::number(reinterpret_cast<sal_Int64>(pUserData));
        m_xModulesCLB->append(nullptr);
        m_xModulesCLB->set_id(nRow, sId);
        m_xModulesCLB->set_text(nRow, sGrammar, 1);
        m_xModulesCLB->set_text_emphasis(nRow, true, 1);
        ++nRow;

        aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_GRAMMAR );
        pName = aNames.getConstArray();
@@ -1941,7 +1812,6 @@ void SvxEditModulesDlg::LangSelectHdl_Impl(ListBox const * pBox)
            if (!aImplName.isEmpty() && bIsSuppLang)
            {
                OUString aTxt( pInfo->sDisplayName );
                SvTreeListEntry* pNewEntry = CreateEntry( aTxt, CBCOL_FIRST );

                LangImplNameTable &rTable = rLinguData.GetGrammarTable();
                const bool bHasLang = rTable.count( eCurLanguage );
@@ -1950,21 +1820,28 @@ void SvxEditModulesDlg::LangSelectHdl_Impl(ListBox const * pBox)
                    SAL_INFO( "cui.options", "language entry missing" );    // only relevant if all languages found should be supported
                }
                const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
                lcl_SetCheckButton( pNewEntry, bCheck );
                pUserData = new ModuleUserData_Impl( aImplName, false,
                                        bCheck, TYPE_GRAMMAR, static_cast<sal_uInt8>(nLocalIndex++) );
                pNewEntry->SetUserData( static_cast<void *>(pUserData) );
                pModel->Insert( pNewEntry );

                sId = OUString::number(reinterpret_cast<sal_Int64>(pUserData));

                m_xModulesCLB->append(nullptr);
                m_xModulesCLB->set_id(nRow, sId);
                m_xModulesCLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE, 0);
                m_xModulesCLB->set_text(nRow, aTxt, 1);
                ++nRow;
            }
        }


        // hyphenator entries

        pEntry = CreateEntry( sHyph,    CBCOL_SECOND );
        pUserData = new ModuleUserData_Impl( OUString(), true, false, TYPE_HYPH, 0 );
        pEntry->SetUserData( static_cast<void *>(pUserData) );
        pModel->Insert( pEntry );
        sId = OUString::number(reinterpret_cast<sal_Int64>(pUserData));
        m_xModulesCLB->append(nullptr);
        m_xModulesCLB->set_id(nRow, sId);
        m_xModulesCLB->set_text(nRow, sHyph, 1);
        m_xModulesCLB->set_text_emphasis(nRow, true, 1);
        ++nRow;

        aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_HYPH );
        pName = aNames.getConstArray();
@@ -1985,7 +1862,6 @@ void SvxEditModulesDlg::LangSelectHdl_Impl(ListBox const * pBox)
            if (!aImplName.isEmpty() && bIsSuppLang)
            {
                OUString aTxt( pInfo->sDisplayName );
                SvTreeListEntry* pNewEntry = CreateEntry( aTxt, CBCOL_FIRST );

                LangImplNameTable &rTable = rLinguData.GetHyphTable();
                const bool bHasLang = rTable.count( eCurLanguage );
@@ -1994,21 +1870,27 @@ void SvxEditModulesDlg::LangSelectHdl_Impl(ListBox const * pBox)
                    SAL_INFO( "cui.options", "language entry missing" );    // only relevant if all languages found should be supported
                }
                const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
                lcl_SetCheckButton( pNewEntry, bCheck );
                pUserData = new ModuleUserData_Impl( aImplName, false,
                                        bCheck, TYPE_HYPH, static_cast<sal_uInt8>(nLocalIndex++) );
                pNewEntry->SetUserData( static_cast<void *>(pUserData) );
                pModel->Insert( pNewEntry );
                sId = OUString::number(reinterpret_cast<sal_Int64>(pUserData));

                m_xModulesCLB->append(nullptr);
                m_xModulesCLB->set_id(nRow, sId);
                m_xModulesCLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE, 0);
                m_xModulesCLB->set_text(nRow, aTxt, 1);
                ++nRow;
            }
        }


        // thesaurus entries

        pEntry = CreateEntry( sThes,    CBCOL_SECOND );
        pUserData = new ModuleUserData_Impl( OUString(), true, false, TYPE_THES, 0 );
        pEntry->SetUserData( static_cast<void *>(pUserData) );
        pModel->Insert( pEntry );
        sId = OUString::number(reinterpret_cast<sal_Int64>(pUserData));
        m_xModulesCLB->append(nullptr);
        m_xModulesCLB->set_id(nRow, sId);
        m_xModulesCLB->set_text(nRow, sThes, 1);
        m_xModulesCLB->set_text_emphasis(nRow, true, 1);
        ++nRow;

        aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_THES );
        pName = aNames.getConstArray();
@@ -2029,7 +1911,6 @@ void SvxEditModulesDlg::LangSelectHdl_Impl(ListBox const * pBox)
            if (!aImplName.isEmpty() && bIsSuppLang)
            {
                OUString aTxt( pInfo->sDisplayName );
                SvTreeListEntry* pNewEntry = CreateEntry( aTxt, CBCOL_FIRST );

                LangImplNameTable &rTable = rLinguData.GetThesTable();
                const bool bHasLang = rTable.count( eCurLanguage );
@@ -2038,53 +1919,56 @@ void SvxEditModulesDlg::LangSelectHdl_Impl(ListBox const * pBox)
                    SAL_INFO( "cui.options", "language entry missing" );    // only relevant if all languages found should be supported
                }
                const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
                lcl_SetCheckButton( pNewEntry, bCheck );
                pUserData = new ModuleUserData_Impl( aImplName, false,
                                        bCheck, TYPE_THES, static_cast<sal_uInt8>(nLocalIndex++) );
                pNewEntry->SetUserData( static_cast<void *>(pUserData) );
                pModel->Insert( pNewEntry );
                sId = OUString::number(reinterpret_cast<sal_Int64>(pUserData));

                m_xModulesCLB->append(nullptr);
                m_xModulesCLB->set_id(nRow, sId);
                m_xModulesCLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE, 0);
                m_xModulesCLB->set_text(nRow, aTxt, 1);
                ++nRow;
            }
        }
    }
    aLastLocale = aCurLocale;
}

IMPL_LINK( SvxEditModulesDlg, UpDownHdl_Impl, Button *, pBtn, void )
IMPL_LINK( SvxEditModulesDlg, UpDownHdl_Impl, weld::Button&, rBtn, void )
{
    bool bUp = m_pPrioUpPB == pBtn;
    sal_uLong  nCurPos = m_pModulesCLB->GetSelectedEntryPos();
    SvTreeListEntry* pEntry;
    if (nCurPos != TREELIST_ENTRY_NOTFOUND  &&
        nullptr != (pEntry = m_pModulesCLB->GetEntry(nCurPos)))
    bool bUp = m_xPrioUpPB.get() == &rBtn;
    int nCurPos = m_xModulesCLB->get_selected_index();
    if (nCurPos != -1)
    {
        m_pModulesCLB->SetUpdateMode(false);
        SvTreeList *pModel = m_pModulesCLB->GetModel();
        m_xModulesCLB->freeze();

        ModuleUserData_Impl* pData = static_cast<ModuleUserData_Impl*>(pEntry->GetUserData());
        OUString aStr(m_pModulesCLB->GetEntryText(pEntry));
        SvTreeListEntry* pToInsert = CreateEntry( aStr, CBCOL_FIRST );
        pToInsert->SetUserData( static_cast<void *>(pData));
        bool bIsChecked = m_pModulesCLB->IsChecked(nCurPos);
        OUString sId(m_xModulesCLB->get_id(nCurPos));
        OUString sStr(m_xModulesCLB->get_text(nCurPos));
        bool bIsChecked = m_xModulesCLB->get_toggle(nCurPos, nCurPos);

        pModel->Remove(pEntry);
        m_xModulesCLB->remove(nCurPos);

        sal_uLong nDestPos = bUp ? nCurPos - 1 : nCurPos + 1;
        pModel->Insert(pToInsert, nDestPos);
        m_pModulesCLB->CheckEntryPos(nDestPos, bIsChecked );
        m_pModulesCLB->SelectEntryPos(nDestPos );
        SelectHdl_Impl(m_pModulesCLB);
        m_pModulesCLB->SetUpdateMode(true);
        int nDestPos = bUp ? nCurPos - 1 : nCurPos + 1;

        m_xModulesCLB->insert_text(nDestPos, sStr);
        m_xModulesCLB->set_id(nDestPos, sId);
        m_xModulesCLB->set_toggle(nDestPos, bIsChecked ? TRISTATE_TRUE : TRISTATE_FALSE, 0);

        m_xModulesCLB->thaw();

        m_xModulesCLB->select(nDestPos);
        SelectHdl_Impl(*m_xModulesCLB);
    }
}

IMPL_LINK_NOARG(SvxEditModulesDlg, ClickHdl_Impl, Button*, void)
IMPL_LINK_NOARG(SvxEditModulesDlg, ClickHdl_Impl, weld::Button&, void)
{
    // store language config
    LangSelectHdl_Impl(m_pLanguageLB);
    EndDialog( RET_OK );
    LangSelectHdl_Impl(m_xLanguageLB.get());
    m_xDialog->response(RET_OK);
}

IMPL_LINK_NOARG(SvxEditModulesDlg, BackHdl_Impl, Button*, void)
IMPL_LINK_NOARG(SvxEditModulesDlg, BackHdl_Impl, weld::Button&, void)
{
    rLinguData = *pDefaultLinguData;
    LangSelectHdl_Impl(nullptr);
diff --git a/cui/uiconfig/ui/editmodulesdialog.ui b/cui/uiconfig/ui/editmodulesdialog.ui
index a7e6f15..77b8af66 100644
--- a/cui/uiconfig/ui/editmodulesdialog.ui
+++ b/cui/uiconfig/ui/editmodulesdialog.ui
@@ -1,13 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<!-- Generated with glade 3.22.1 -->
<interface domain="cui">
  <requires lib="gtk+" version="3.18"/>
  <requires lib="LibreOffice" version="1.0"/>
  <object class="GtkTreeStore" id="liststore1">
    <columns>
      <!-- column-name check1 -->
      <column type="gboolean"/>
      <!-- column-name text -->
      <column type="gchararray"/>
      <!-- column-name id -->
      <column type="gchararray"/>
      <!-- column-name checkvis1 -->
      <column type="gboolean"/>
      <!-- column-name checktri1 -->
      <column type="gboolean"/>
      <!-- column-name weight1 -->
      <column type="gint"/>
    </columns>
  </object>
  <object class="GtkListStore" id="liststore6">
    <columns>
      <!-- column-name text -->
      <column type="gchararray"/>
      <!-- column-name id -->
      <column type="gchararray"/>
      <!-- column-name image -->
      <column type="GdkPixbuf"/>
    </columns>
  </object>
  <object class="GtkDialog" id="EditModulesDialog">
    <property name="can_focus">False</property>
    <property name="border_width">6</property>
    <property name="title" translatable="yes" context="editmodulesdialog|EditModulesDialog">Edit Modules</property>
    <property name="modal">True</property>
    <property name="default_width">0</property>
    <property name="default_height">0</property>
    <property name="type_hint">dialog</property>
    <child>
      <placeholder/>
    </child>
    <child internal-child="vbox">
      <object class="GtkBox" id="dialog-vbox1">
        <property name="can_focus">False</property>
@@ -104,10 +135,10 @@
                          <object class="GtkLabel" id="label2">
                            <property name="visible">True</property>
                            <property name="can_focus">False</property>
                            <property name="xalign">0</property>
                            <property name="label" translatable="yes" context="editmodulesdialog|label2">Language:</property>
                            <property name="use_underline">True</property>
                            <property name="mnemonic_widget">language</property>
                            <property name="xalign">0</property>
                          </object>
                          <packing>
                            <property name="expand">False</property>
@@ -116,11 +147,24 @@
                          </packing>
                        </child>
                        <child>
                          <object class="svxcorelo-SvxLanguageBox" id="language">
                          <object class="GtkComboBox" id="language">
                            <property name="visible">True</property>
                            <property name="can_focus">False</property>
                            <property name="halign">start</property>
                            <property name="hexpand">False</property>
                            <property name="model">liststore6</property>
                            <property name="entry_text_column">0</property>
                            <property name="id_column">1</property>
                            <child>
                              <object class="GtkCellRendererText" id="cellrenderertext9"/>
                              <attributes>
                                <attribute name="text">0</attribute>
                              </attributes>
                            </child>
                            <child>
                              <object class="GtkCellRendererPixbuf" id="cellrenderertext6"/>
                              <attributes>
                                <attribute name="pixbuf">2</attribute>
                              </attributes>
                            </child>
                          </object>
                          <packing>
                            <property name="expand">False</property>
@@ -197,13 +241,54 @@
                          </packing>
                        </child>
                        <child>
                          <object class="svxcorelo-SvxCheckListBox" id="lingudicts:border">
                          <object class="GtkScrolledWindow">
                            <property name="visible">True</property>
                            <property name="can_focus">True</property>
                            <property name="hexpand">True</property>
                            <property name="vexpand">True</property>
                            <child internal-child="selection">
                              <object class="GtkTreeSelection" id="Check List Box-selection5"/>
                            <property name="shadow_type">in</property>
                            <child>
                              <object class="GtkTreeView" id="lingudicts">
                                <property name="visible">True</property>
                                <property name="can_focus">True</property>
                                <property name="receives_default">True</property>
                                <property name="vexpand">True</property>
                                <property name="model">liststore1</property>
                                <property name="headers_visible">False</property>
                                <property name="search_column">0</property>
                                <property name="show_expanders">False</property>
                                <child internal-child="selection">
                                  <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
                                </child>
                                <child>
                                  <object class="GtkTreeViewColumn" id="treeviewcolumn1">
                                    <property name="resizable">True</property>
                                    <property name="spacing">6</property>
                                    <property name="alignment">0.5</property>
                                    <child>
                                      <object class="GtkCellRendererToggle" id="cellrenderer5"/>
                                      <attributes>
                                        <attribute name="visible">3</attribute>
                                        <attribute name="active">0</attribute>
                                      </attributes>
                                    </child>
                                  </object>
                                </child>
                                <child>
                                  <object class="GtkTreeViewColumn" id="treeviewcolumn2">
                                    <property name="resizable">True</property>
                                    <property name="spacing">6</property>
                                    <property name="alignment">0.5</property>
                                    <child>
                                      <object class="GtkCellRendererText" id="cellrenderer4"/>
                                      <attributes>
                                        <attribute name="text">1</attribute>
                                        <attribute name="weight">5</attribute>
                                      </attributes>
                                    </child>
                                  </object>
                                </child>
                              </object>
                            </child>
                          </object>
                          <packing>