tdf#105566: Add/remove infobar when the signature status changes

this time without stack overflow. Updating existing infobar needs
some work still

This patch is partially based on work of samuel_m

Change-Id: I2c44c14e27cf85a1014b01e5588b7b53990033b9
Reviewed-on: https://gerrit.libreoffice.org/38148
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
diff --git a/include/sfx2/infobar.hxx b/include/sfx2/infobar.hxx
index 4ad6d8a..4e49213 100644
--- a/include/sfx2/infobar.hxx
+++ b/include/sfx2/infobar.hxx
@@ -95,6 +95,7 @@ class SfxInfoBarContainerWindow : public vcl::Window
                                        InfoBarType ibType,
                                        WinBits nMessageStyle = WB_LEFT|WB_VCENTER);
        VclPtr<SfxInfoBarWindow> getInfoBar(const OUString& sId);
        bool hasInfoBarWithID(const OUString& sId);
        void removeInfoBar(VclPtr<SfxInfoBarWindow> const & pInfoBar);

        virtual void Resize() override;
diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx
index f3c916c..7ebafed 100644
--- a/include/sfx2/objsh.hxx
+++ b/include/sfx2/objsh.hxx
@@ -37,6 +37,7 @@
#include <com/sun/star/document/CmisVersion.hpp>

#include <vcl/vclptr.hxx>
#include <vcl/button.hxx>
#include <svl/poolitem.hxx>
#include <vcl/bitmap.hxx>
#include <sot/formats.hxx>
@@ -365,6 +366,7 @@ public:
    void                        SignDocumentContent();
    SignatureState              GetScriptingSignatureState();
    void                        SignScriptingContent();
    DECL_LINK(SignDocumentHandler, Button*, void);

    virtual VclPtr<SfxDocumentInfoDialog> CreateDocumentInfoDialog( const SfxItemSet& );

diff --git a/include/sfx2/viewfrm.hxx b/include/sfx2/viewfrm.hxx
index 9d803bf..e4392d5 100644
--- a/include/sfx2/viewfrm.hxx
+++ b/include/sfx2/viewfrm.hxx
@@ -176,6 +176,7 @@ public:
                                    const OUString& sMessage,
                                    InfoBarType aInfoBarType);
    void              RemoveInfoBar(const OUString& sId);
    bool              HasInfoBarWithID(const OUString& sId);

    SAL_DLLPRIVATE void GetDocNumber_Impl();
    SAL_DLLPRIVATE void SetViewShell_Impl( SfxViewShell *pVSh );
diff --git a/sfx2/source/dialog/infobar.cxx b/sfx2/source/dialog/infobar.cxx
index 69b4df4..b093718 100644
--- a/sfx2/source/dialog/infobar.cxx
+++ b/sfx2/source/dialog/infobar.cxx
@@ -359,6 +359,11 @@ VclPtr<SfxInfoBarWindow> SfxInfoBarContainerWindow::getInfoBar(const OUString& s
    return nullptr;
}

bool SfxInfoBarContainerWindow::hasInfoBarWithID( const OUString &sId )
{
    return ( getInfoBar( sId ) != nullptr );
}

void SfxInfoBarContainerWindow::removeInfoBar(VclPtr<SfxInfoBarWindow> const & pInfoBar)
{
    // Remove
diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx
index 6e1f008..edebf6a 100644
--- a/sfx2/source/doc/objserv.cxx
+++ b/sfx2/source/doc/objserv.cxx
@@ -64,6 +64,7 @@
#include <unotools/saveopt.hxx>
#include <svtools/asynclink.hxx>
#include <comphelper/documentconstants.hxx>
#include <tools/link.hxx>

#include <sfx2/app.hxx>
#include <sfx2/signaturestate.hxx>
@@ -90,6 +91,7 @@
#include <sfx2/msgpool.hxx>
#include <sfx2/objface.hxx>
#include <sfx2/checkin.hxx>
#include <sfx2/infobar.hxx>

#include "app.hrc"
#include <com/sun/star/document/XDocumentSubStorageSupplier.hpp>
@@ -1033,6 +1035,60 @@ void SfxObjectShell::GetState_Impl(SfxItemSet &rSet)
            }
            case SID_SIGNATURE:
            {
                SfxViewFrame *pFrame = SfxViewFrame::Current();
                if ( pFrame )
                {
                    SignatureState eState = GetDocumentSignatureState();
                    InfoBarType aInfoBarType(InfoBarType::Info);
                    OUString sMessage("");

                    switch (eState)
                    {
                    case SignatureState::BROKEN:
                        sMessage = SfxResId(STR_SIGNATURE_BROKEN);
                        aInfoBarType = InfoBarType::Danger;
                        break;
                    case SignatureState::NOTVALIDATED:
                        sMessage = SfxResId(STR_SIGNATURE_NOTVALIDATED);
                        aInfoBarType = InfoBarType::Warning;
                        break;
                    case SignatureState::PARTIAL_OK:
                        sMessage = SfxResId(STR_SIGNATURE_PARTIAL_OK);
                        aInfoBarType = InfoBarType::Warning;
                        break;
                    case SignatureState::OK:
                        sMessage = SfxResId(STR_SIGNATURE_OK);
                        aInfoBarType = InfoBarType::Info;
                        break;
                    default:
                        break;
                    }

                    // new info bar
                    if ( !pFrame->HasInfoBarWithID("signature") )
                    {

                        if (!sMessage.isEmpty())
                        {
                            auto pInfoBar = pFrame->AppendInfoBar("signature", sMessage, aInfoBarType);
                            if (pInfoBar == nullptr)
                                return;
                            VclPtrInstance<PushButton> xBtn(&(pFrame->GetWindow()));
                            xBtn->SetText(SfxResId(STR_SIGNATURE_SHOW));
                            xBtn->SetSizePixel(xBtn->GetOptimalSize());
                            xBtn->SetClickHdl(LINK(this, SfxObjectShell, SignDocumentHandler));
                            pInfoBar->addButton(xBtn);
                        }
                    }
                    else // signature info bar exists already
                    {
                        if (eState == SignatureState::NOSIGNATURES )
                             pFrame->RemoveInfoBar("signature");
                        //FIXME: Update existing info bar
                    }

                }

                rSet.Put( SfxUInt16Item( SID_SIGNATURE, static_cast<sal_uInt16>(GetDocumentSignatureState()) ) );
                break;
            }
@@ -1049,6 +1105,10 @@ void SfxObjectShell::GetState_Impl(SfxItemSet &rSet)
    }
}

IMPL_LINK_NOARG(SfxObjectShell, SignDocumentHandler, Button*, void)
{
    GetDispatcher()->Execute(SID_SIGNATURE);
}

void SfxObjectShell::ExecProps_Impl(SfxRequest &rReq)
{
diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx
index 6b7f5ea..aafff1f 100644
--- a/sfx2/source/view/viewfrm.cxx
+++ b/sfx2/source/view/viewfrm.cxx
@@ -1138,42 +1138,6 @@ void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
                rBind.Invalidate( SID_RELOAD );
                rBind.Invalidate( SID_EDITDOC );

                SignatureState nSignatureState = GetObjectShell()->GetDocumentSignatureState();
                InfoBarType aInfoBarType(InfoBarType::Info);
                OUString sMessage;

                switch (nSignatureState)
                {
                case SignatureState::BROKEN:
                    sMessage = SfxResId(STR_SIGNATURE_BROKEN);
                    aInfoBarType = InfoBarType::Danger;
                    break;
                case SignatureState::NOTVALIDATED:
                    sMessage = SfxResId(STR_SIGNATURE_NOTVALIDATED);
                    aInfoBarType = InfoBarType::Warning;
                    break;
                case SignatureState::PARTIAL_OK:
                    sMessage = SfxResId(STR_SIGNATURE_PARTIAL_OK);
                    aInfoBarType = InfoBarType::Warning;
                    break;
                case SignatureState::OK:
                    sMessage = SfxResId(STR_SIGNATURE_OK);
                    aInfoBarType = InfoBarType::Info;
                    break;
                default:
                    break;
                }

                if (!sMessage.isEmpty())
                {
                    auto pInfoBar = AppendInfoBar("signature", sMessage, aInfoBarType);
                    VclPtrInstance<PushButton> xBtn(&GetWindow());
                    xBtn->SetText(SfxResId(STR_SIGNATURE_SHOW));
                    xBtn->SetSizePixel(xBtn->GetOptimalSize());
                    xBtn->SetClickHdl(LINK(this, SfxViewFrame, SignDocumentHandler));
                    pInfoBar->addButton(xBtn);
                }

                const SfxViewShell *pVSh;
                const SfxShell *pFSh;
                if ( m_xObjSh->IsOriginallyReadOnlyMedium() &&
@@ -3054,4 +3018,18 @@ void SfxViewFrame::RemoveInfoBar( const OUString& sId )
    }
}

bool SfxViewFrame::HasInfoBarWithID( const OUString& sId )
{
    const sal_uInt16 nId = SfxInfoBarContainerChild::GetChildWindowId();

    SfxChildWindow* pChild = GetChildWindow(nId);
    if (pChild)
    {
        SfxInfoBarContainerWindow* pInfoBarContainer = static_cast<SfxInfoBarContainerWindow*>(pChild->GetWindow());
        return pInfoBarContainer->hasInfoBarWithID(sId);
    }

    return false;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */