weld ScRetypePassDlg

Change-Id: I50c9ce27e7a5e469423d2d23e45038b73983fec5
Reviewed-on: https://gerrit.libreoffice.org/69045
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/sc/UIConfig_scalc.mk b/sc/UIConfig_scalc.mk
index 8b36d06..9523c42 100644
--- a/sc/UIConfig_scalc.mk
+++ b/sc/UIConfig_scalc.mk
@@ -180,6 +180,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/scalc,\
	sc/uiconfig/scalc/ui/pastespecial \
	sc/uiconfig/scalc/ui/paradialog \
	sc/uiconfig/scalc/ui/paratemplatedialog \
	sc/uiconfig/scalc/ui/passfragment \
	sc/uiconfig/scalc/ui/pivotfielddialog \
	sc/uiconfig/scalc/ui/pivotfilterdialog \
	sc/uiconfig/scalc/ui/pivottablelayoutdialog \
diff --git a/sc/source/ui/inc/retypepassdlg.hxx b/sc/source/ui/inc/retypepassdlg.hxx
index 89543e3..967d5bb 100644
--- a/sc/source/ui/inc/retypepassdlg.hxx
+++ b/sc/source/ui/inc/retypepassdlg.hxx
@@ -20,31 +20,33 @@
#ifndef INCLUDED_SC_SOURCE_UI_INC_RETYPEPASSDLG_HXX
#define INCLUDED_SC_SOURCE_UI_INC_RETYPEPASSDLG_HXX

#include <vcl/button.hxx>
#include <vcl/dialog.hxx>
#include <vcl/fixed.hxx>
#include <vcl/layout.hxx>
#include <vcl/weld.hxx>

#include <tabprotection.hxx>

#include <memory>

namespace vcl { class Window; }
class ScDocument;

class ScRetypePassDlg : public ModalDialog
struct PassFragment
{
    std::unique_ptr<weld::Builder> m_xBuilder;
    std::unique_ptr<weld::Container> m_xSheetsBox;
    std::unique_ptr<weld::Label> m_xName;
    std::unique_ptr<weld::Label> m_xStatus;
    std::unique_ptr<weld::Button> m_xButton;

    PassFragment(weld::Widget* pParent);
};

class ScRetypePassDlg : public weld::GenericDialogController
{
public:
    typedef std::shared_ptr<ScDocProtection>    DocProtectionPtr;
    typedef std::shared_ptr<ScTableProtection>  TabProtectionPtr;

    ScRetypePassDlg() = delete;
    explicit ScRetypePassDlg(vcl::Window* pParent);
    explicit ScRetypePassDlg(weld::Window* pParent);
    virtual ~ScRetypePassDlg() override;
    virtual void dispose() override;

    virtual short Execute() override;
    virtual short run() override;

    void SetDataFromDocument(const ScDocument& rDoc);
    void SetDesiredHash(ScPasswordHash eHash);
@@ -66,20 +68,13 @@ private:
    void DeleteSheets();

private:
    VclPtr<OKButton>       mpBtnOk;
    VclPtr<FixedText>      mpTextDocStatus;
    VclPtr<PushButton>     mpBtnRetypeDoc;
    VclPtr<VclVBox>        mpSheetsBox;

    std::vector<VclPtr<VclHBox>> maSheets;

    OUString const        maTextNotProtected;
    OUString const        maTextNotPassProtected;
    OUString const        maTextHashBad;
    OUString const        maTextHashGood;

    DECL_LINK( OKHdl, Button*, void );
    DECL_LINK( RetypeBtnHdl, Button*, void );
    DECL_LINK(OKHdl, weld::Button&, void);
    DECL_LINK(RetypeBtnHdl, weld::Button&, void);

    struct TableItem
    {
@@ -90,6 +85,13 @@ private:

    DocProtectionPtr    mpDocItem;
    ScPasswordHash      meDesiredHash;

    std::unique_ptr<weld::Button> mxBtnOk;
    std::unique_ptr<weld::Label> mxTextDocStatus;
    std::unique_ptr<weld::Button> mxBtnRetypeDoc;
    std::unique_ptr<weld::ScrolledWindow> mxScrolledWindow;
    std::unique_ptr<weld::Container> mxSheetsBox;
    std::vector<std::unique_ptr<PassFragment>> maSheets;
};

class ScRetypePassInputDlg : public weld::GenericDialogController
diff --git a/sc/source/ui/miscdlgs/retypepassdlg.cxx b/sc/source/ui/miscdlgs/retypepassdlg.cxx
index 2af3344..84f8ef1 100644
--- a/sc/source/ui/miscdlgs/retypepassdlg.cxx
+++ b/sc/source/ui/miscdlgs/retypepassdlg.cxx
@@ -17,72 +17,56 @@
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <vcl/svapp.hxx>
#include <strings.hrc>
#include <retypepassdlg.hxx>
#include <scresid.hxx>
#include <document.hxx>
#include <tabprotection.hxx>

ScRetypePassDlg::ScRetypePassDlg(vcl::Window* pParent) :
    ModalDialog(pParent, "RetypePass", "modules/scalc/ui/retypepassdialog.ui"),

    maTextNotProtected(ScResId(STR_NOT_PROTECTED)),
    maTextNotPassProtected(ScResId(STR_NOT_PASS_PROTECTED)),
    maTextHashBad(ScResId(STR_HASH_BAD)),
    maTextHashGood(ScResId(STR_HASH_GOOD)),

    mpDocItem(static_cast<ScDocProtection*>(nullptr)),
    meDesiredHash(PASSHASH_SHA1)
ScRetypePassDlg::ScRetypePassDlg(weld::Window* pParent)
    : GenericDialogController(pParent, "modules/scalc/ui/retypepassdialog.ui", "RetypePass")
    , maTextNotProtected(ScResId(STR_NOT_PROTECTED))
    , maTextNotPassProtected(ScResId(STR_NOT_PASS_PROTECTED))
    , maTextHashBad(ScResId(STR_HASH_BAD))
    , maTextHashGood(ScResId(STR_HASH_GOOD))
    , mpDocItem(static_cast<ScDocProtection*>(nullptr))
    , meDesiredHash(PASSHASH_SHA1)
    , mxBtnOk(m_xBuilder->weld_button("ok"))
    , mxTextDocStatus(m_xBuilder->weld_label("docStatusLabel"))
    , mxBtnRetypeDoc(m_xBuilder->weld_button("retypeDocButton"))
    , mxScrolledWindow(m_xBuilder->weld_scrolled_window("scrolledwindow"))
    , mxSheetsBox(m_xBuilder->weld_container("sheetsBox"))
{
    get(mpBtnOk ,"ok");
    get(mpTextDocStatus, "docStatusLabel");
    get(mpBtnRetypeDoc, "retypeDocButton");
    vcl::Window *pScrolledWindow = get<vcl::Window>("scrolledwindow");
    Size aSize(LogicToPixel(Size(190, 90), MapMode(MapUnit::MapAppFont)));
    pScrolledWindow->set_width_request(aSize.Width());
    pScrolledWindow->set_height_request(aSize.Height());
    get(mpSheetsBox, "sheetsBox");

    mxScrolledWindow->set_size_request(mxScrolledWindow->get_approximate_digit_width() * 46,
                                       mxScrolledWindow->get_text_height() * 10);
    Init();
}

ScRetypePassDlg::~ScRetypePassDlg()
{
    disposeOnce();
}

void ScRetypePassDlg::dispose()
{
    DeleteSheets();
    mpBtnOk.clear();
    mpTextDocStatus.clear();
    mpBtnRetypeDoc.clear();
    mpSheetsBox.clear();
    maSheets.clear();
    ModalDialog::dispose();
}

void ScRetypePassDlg::DeleteSheets()
{
    for(auto& rxSheet : maSheets)
    {
        VclPtr<vcl::Window> pWindow = rxSheet;
        vcl::Window *pChild = pWindow->GetWindow(GetWindowType::FirstChild);
        while (pChild)
        {
            VclPtr<vcl::Window> pOldChild = pChild;
            pChild = pChild->GetWindow(GetWindowType::Next);
            pOldChild.disposeAndClear();
        }
        pWindow.disposeAndClear();
    }
    maSheets.clear();
}

short ScRetypePassDlg::Execute()
short ScRetypePassDlg::run()
{
    PopulateDialog();
    CheckHashStatus();
    return ModalDialog::Execute();
    return GenericDialogController::run();
}

PassFragment::PassFragment(weld::Widget* pParent)
    : m_xBuilder(Application::CreateBuilder(pParent, "modules/scalc/ui/passfragment.ui"))
    , m_xSheetsBox(m_xBuilder->weld_container("PassEntry"))
    , m_xName(m_xBuilder->weld_label("name"))
    , m_xStatus(m_xBuilder->weld_label("status"))
    , m_xButton(m_xBuilder->weld_button("button"))
{
    m_xButton->set_label(ScResId(STR_RETYPE));
}

void ScRetypePassDlg::SetDataFromDocument(const ScDocument& rDoc)
@@ -105,23 +89,8 @@ void ScRetypePassDlg::SetDataFromDocument(const ScDocument& rDoc)
            aTabItem.mpProtect.reset(new ScTableProtection(*pTabProtect));

        maTableItems.push_back(aTabItem);
        VclPtr<VclHBox> pSheet = VclPtr<VclHBox>::Create(mpSheetsBox, false, 12);
        pSheet->Show();

        VclPtr<FixedText> pFtSheetName = VclPtr<FixedText>::Create(pSheet);
        pFtSheetName->Show();
        pFtSheetName->SetStyle(WB_VCENTER);
        VclPtr<FixedText> pFtSheetStatus = VclPtr<FixedText>::Create(pSheet);
        pFtSheetStatus->Show();
        pFtSheetStatus->SetStyle(WB_VCENTER);

        VclPtr<PushButton> pBtnSheet = VclPtr<PushButton>::Create(static_cast<vcl::Window*>(pSheet));
        pBtnSheet->SetText(ScResId(STR_RETYPE));
        pBtnSheet->SetClickHdl(LINK(this, ScRetypePassDlg, RetypeBtnHdl));
        pBtnSheet->Disable();
        pBtnSheet->Show();

        maSheets.push_back(pSheet);
        maSheets.emplace_back(new PassFragment(mxSheetsBox.get()));
        maSheets.back()->m_xButton->connect_clicked(LINK(this, ScRetypePassDlg, RetypeBtnHdl));
    }
}

@@ -150,14 +119,14 @@ void ScRetypePassDlg::WriteNewDataToDocument(ScDocument& rDoc) const

void ScRetypePassDlg::Init()
{
    Link<Button*,void> aLink = LINK( this, ScRetypePassDlg, OKHdl );
    mpBtnOk->SetClickHdl(aLink);
    Link<weld::Button&,void> aLink = LINK( this, ScRetypePassDlg, OKHdl );
    mxBtnOk->connect_clicked(aLink);

    aLink = LINK( this, ScRetypePassDlg, RetypeBtnHdl );
    mpBtnRetypeDoc->SetClickHdl(aLink);
    mxBtnRetypeDoc->connect_clicked(aLink);

    mpTextDocStatus->SetText(maTextNotProtected);
    mpBtnRetypeDoc->Disable();
    mxTextDocStatus->set_label(maTextNotProtected);
    mxBtnRetypeDoc->set_sensitive(false);
}

void ScRetypePassDlg::PopulateDialog()
@@ -176,47 +145,47 @@ void ScRetypePassDlg::SetDocData()
    if (mpDocItem.get() && mpDocItem->isProtected())
    {
        if (mpDocItem->isPasswordEmpty())
            mpTextDocStatus->SetText(maTextNotPassProtected);
            mxTextDocStatus->set_label(maTextNotPassProtected);
        else if (mpDocItem->hasPasswordHash(meDesiredHash))
            mpTextDocStatus->SetText(maTextHashGood);
            mxTextDocStatus->set_label(maTextHashGood);
        else
        {
            // incompatible hash
            mpTextDocStatus->SetText(maTextHashBad);
            mxTextDocStatus->set_label(maTextHashBad);
            bBtnEnabled = true;
        }
    }
    mpBtnRetypeDoc->Enable(bBtnEnabled);
    mxBtnRetypeDoc->set_sensitive(bBtnEnabled);
}

void ScRetypePassDlg::SetTableData(size_t nRowPos, SCTAB nTab)
{
    if(nRowPos < maSheets.size())
    if (nRowPos < maSheets.size())
    {
        FixedText* pName = static_cast<FixedText*>(maSheets[nRowPos]->GetChild(0));
        FixedText* pStatus = static_cast<FixedText*>(maSheets[nRowPos]->GetChild(1));
        PushButton* pBtn = static_cast<PushButton*>(maSheets[nRowPos]->GetChild(2));
        weld::Label& rName = *maSheets[nRowPos]->m_xName;
        weld::Label& rStatus = *maSheets[nRowPos]->m_xStatus;
        weld::Button& rBtn = *maSheets[nRowPos]->m_xButton;

        bool bBtnEnabled = false;
        pName->SetText(maTableItems[nTab].maName);
        rName.set_label(maTableItems[nTab].maName);
        const ScTableProtection* pTabProtect = maTableItems[nTab].mpProtect.get();
        if (pTabProtect && pTabProtect->isProtected())
        {
            if (pTabProtect->isPasswordEmpty())
                pStatus->SetText(maTextNotPassProtected);
                rStatus.set_label(maTextNotPassProtected);
            else if (pTabProtect->hasPasswordHash(meDesiredHash))
                pStatus->SetText(maTextHashGood);
                rStatus.set_label(maTextHashGood);
            else
            {
                // incompatible hash
                pStatus->SetText(maTextHashBad);
                rStatus.set_label(maTextHashBad);
                bBtnEnabled = true;
            }
        }
        else
            pStatus->SetText(maTextNotProtected);
            rStatus.set_label(maTextNotProtected);

        pBtn->Enable(bBtnEnabled);
        rBtn.set_sensitive(bBtnEnabled);
    }
}

@@ -252,23 +221,23 @@ void ScRetypePassDlg::CheckHashStatus()
        if (!bStatusGood)
            break;

        mpBtnOk->Enable();
        mxBtnOk->set_sensitive(true);
        return;
    }
    while (false);

    mpBtnOk->Disable();
    mxBtnOk->set_sensitive(false);
}

IMPL_LINK_NOARG(ScRetypePassDlg, OKHdl, Button*, void)
IMPL_LINK_NOARG(ScRetypePassDlg, OKHdl, weld::Button&, void)
{
    EndDialog(RET_OK);
    m_xDialog->response(RET_OK);
}

IMPL_LINK( ScRetypePassDlg, RetypeBtnHdl, Button*, pBtn, void )
IMPL_LINK(ScRetypePassDlg, RetypeBtnHdl, weld::Button&, rBtn, void)
{
    ScPassHashProtectable* pProtected = nullptr;
    if (pBtn == mpBtnRetypeDoc)
    if (&rBtn == mxBtnRetypeDoc.get())
    {
        // document protection.
        pProtected = mpDocItem.get();
@@ -277,7 +246,7 @@ IMPL_LINK( ScRetypePassDlg, RetypeBtnHdl, Button*, pBtn, void )
    {
        // sheet protection.
        size_t aPos = 0;
        while(aPos < maSheets.size() && pBtn != maSheets[aPos]->GetChild(2))
        while (aPos < maSheets.size() && &rBtn != maSheets[aPos]->m_xButton.get())
            ++aPos;

        pProtected = aPos < maSheets.size() ? maTableItems[aPos].mpProtect.get() : nullptr;
@@ -287,7 +256,7 @@ IMPL_LINK( ScRetypePassDlg, RetypeBtnHdl, Button*, pBtn, void )
        // What the ... !?
        return;

    ScRetypePassInputDlg aDlg(GetFrameWeld(), pProtected);
    ScRetypePassInputDlg aDlg(m_xDialog.get(), pProtected);
    if (aDlg.run() == RET_OK)
    {
        // OK is pressed.  Update the protected item.
diff --git a/sc/source/ui/view/tabvwshh.cxx b/sc/source/ui/view/tabvwshh.cxx
index aebcfee4..a91585c 100644
--- a/sc/source/ui/view/tabvwshh.cxx
+++ b/sc/source/ui/view/tabvwshh.cxx
@@ -248,13 +248,13 @@ bool ScTabViewShell::ExecuteRetypePassDlg(ScPasswordHash eDesiredHash)
{
    ScDocument* pDoc = GetViewData().GetDocument();

    VclPtrInstance< ScRetypePassDlg > pDlg(GetDialogParent());
    pDlg->SetDataFromDocument(*pDoc);
    pDlg->SetDesiredHash(eDesiredHash);
    if (pDlg->Execute() != RET_OK)
    ScRetypePassDlg aDlg(GetFrameWeld());
    aDlg.SetDataFromDocument(*pDoc);
    aDlg.SetDesiredHash(eDesiredHash);
    if (aDlg.run() != RET_OK)
        return false;

    pDlg->WriteNewDataToDocument(*pDoc);
    aDlg.WriteNewDataToDocument(*pDoc);
    return true;
}

diff --git a/sc/uiconfig/scalc/ui/passfragment.ui b/sc/uiconfig/scalc/ui/passfragment.ui
new file mode 100644
index 0000000..ad89c00
--- /dev/null
+++ b/sc/uiconfig/scalc/ui/passfragment.ui
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface domain="sw">
  <requires lib="gtk+" version="3.18"/>
  <object class="GtkGrid" id="PassEntry">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="no_show_all">True</property>
    <property name="valign">start</property>
    <property name="hexpand">True</property>
    <property name="column_spacing">12</property>
    <child>
      <object class="GtkLabel" id="name">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="xalign">0</property>
      </object>
      <packing>
        <property name="left_attach">0</property>
        <property name="top_attach">0</property>
      </packing>
    </child>
    <child>
      <object class="GtkLabel" id="status">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="xalign">0</property>
      </object>
      <packing>
        <property name="left_attach">1</property>
        <property name="top_attach">0</property>
      </packing>
    </child>
    <child>
      <object class="GtkButton" id="button">
        <property name="visible">True</property>
        <property name="sensitive">False</property>
        <property name="can_focus">True</property>
        <property name="receives_default">True</property>
        <property name="use_underline">True</property>
      </object>
      <packing>
        <property name="left_attach">2</property>
        <property name="top_attach">0</property>
      </packing>
    </child>
  </object>
</interface>
diff --git a/sc/uiconfig/scalc/ui/retypepassdialog.ui b/sc/uiconfig/scalc/ui/retypepassdialog.ui
index f550063..31b2b13 100644
--- a/sc/uiconfig/scalc/ui/retypepassdialog.ui
+++ b/sc/uiconfig/scalc/ui/retypepassdialog.ui
@@ -190,6 +190,7 @@
                        <property name="can_focus">False</property>
                        <property name="hexpand">True</property>
                        <property name="vexpand">True</property>
                        <property name="shadow_type">in</property>
                        <child>
                          <object class="GtkViewport" id="viewport1">
                            <property name="visible">True</property>
diff --git a/solenv/sanitizers/ui/modules/scalc.suppr b/solenv/sanitizers/ui/modules/scalc.suppr
index 91878c0..1ba1313 100644
--- a/solenv/sanitizers/ui/modules/scalc.suppr
+++ b/solenv/sanitizers/ui/modules/scalc.suppr
@@ -126,6 +126,7 @@ sc/uiconfig/scalc/ui/movingaveragedialog.ui://GtkLabel[@id='interval-label'] orp
sc/uiconfig/scalc/ui/movingaveragedialog.ui://GtkSpinButton[@id='interval-spin'] no-labelled-by
sc/uiconfig/scalc/ui/nosolutiondialog.ui://GtkLabel[@id='label1'] orphan-label
sc/uiconfig/scalc/ui/nosolutiondialog.ui://GtkLabel[@id='error'] orphan-label
sc/uiconfig/scalc/ui/passfragment.ui://GtkButton[@id='button'] button-no-label
sc/uiconfig/scalc/ui/pivotfielddialog.ui://GtkLabel[@id='label2'] orphan-label
sc/uiconfig/scalc/ui/pivotfielddialog.ui://GtkLabel[@id='name'] orphan-label
sc/uiconfig/scalc/ui/pivotfilterdialog.ui://GtkComboBoxText[@id='connect1'] missing-label-for