tdf#106731 Warn user that a module/dialog is read-only in Basic IDE

As discussed in the ticket the Basic IDE does not make it clear that the currently opened module is read-only, which can cause confusion to the user, since they may be pressing keys and seeing no result.

With this patch the IDE clarifies that the module/dialog is read-only in two ways:
1) In the status bar the string "(Read-only)" is added after the module/dialog name
2) When a module/dialog is opened an infobar is shown warning that it is read-only.
3) In a module, if the user closed the infobar and tries to edit the code, the infobar is shown again.

Change-Id: I15197c4316bb2ed19e54be0c33f4fb61b5bbd862
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145307
Tested-by: Jenkins
Reviewed-by: Heiko Tietze <heiko.tietze@documentfoundation.org>
diff --git a/basctl/inc/strings.hrc b/basctl/inc/strings.hrc
index 09190a0..1384e95 100644
--- a/basctl/inc/strings.hrc
+++ b/basctl/inc/strings.hrc
@@ -110,6 +110,9 @@
#define RID_STR_EXPORTPACKAGE               NC_("RID_STR_EXPORTPACKAGE", "Export library as extension")
#define RID_STR_EXPORTBASIC                 NC_("RID_STR_EXPORTBASIC", "Export as BASIC library")
#define RID_STR_PACKAGE_BUNDLE              NC_("RID_STR_PACKAGE_BUNDLE", "Extension")
#define RID_STR_READONLY                    NC_("RID_STR_READONLY", "Read-only")
#define RID_STR_MODULE_READONLY             NC_("RID_STR_READONLY_WARNING", "This module is read-only and cannot be edited.")
#define RID_STR_DIALOG_READONLY             NC_("RID_STR_READONLY_WARNING", "This dialog is read-only and cannot be edited.")

#endif

diff --git a/basctl/source/basicide/baside2.cxx b/basctl/source/basicide/baside2.cxx
index 9452ef2..3c18485 100644
--- a/basctl/source/basicide/baside2.cxx
+++ b/basctl/source/basicide/baside2.cxx
@@ -1130,6 +1130,9 @@ void ModulWindow::GetState( SfxItemSet &rSet )
                    if (!sProcName.isEmpty())
                        aTitle += "." + sProcName;

                    if (IsReadOnly())
                        aTitle += " (" + IDEResId(RID_STR_READONLY) + ")";

                    SfxStringItem aTitleItem( SID_BASICIDE_STAT_TITLE, aTitle );
                    rSet.Put( aTitleItem );
                }
diff --git a/basctl/source/basicide/baside2b.cxx b/basctl/source/basicide/baside2b.cxx
index b5deee9..e5de6ab 100644
--- a/basctl/source/basicide/baside2b.cxx
+++ b/basctl/source/basicide/baside2b.cxx
@@ -627,6 +627,13 @@ void EditorWindow::KeyInput( const KeyEvent& rKEvt )
                pBindings->Update( SID_BASICIDE_STAT_POS );
                pBindings->Update( SID_BASICIDE_STAT_TITLE );
            }
            if ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_ALPHA ||
                 rKEvt.GetKeyCode().GetGroup() == KEYGROUP_NUM )
            {
                // If the module is read-only, warn that it cannont be edited
                if ( rModulWindow.IsReadOnly() )
                    rModulWindow.ShowReadOnlyInfoBar();
            }
            if ( !bWasModified && pEditEngine->IsModified() )
            {
                pBindings->Invalidate( SID_SAVEDOC );
diff --git a/basctl/source/basicide/basides1.cxx b/basctl/source/basicide/basides1.cxx
index 430b795..b870a14 100644
--- a/basctl/source/basicide/basides1.cxx
+++ b/basctl/source/basicide/basides1.cxx
@@ -1019,6 +1019,8 @@ void Shell::GetState(SfxItemSet &rSet)
                if ( pCurWin )
                {
                    OUString aTitle = pCurWin->CreateQualifiedName();
                    if (pCurWin->IsReadOnly())
                        aTitle += " (" + IDEResId(RID_STR_READONLY) + ")";
                    SfxStringItem aItem( SID_BASICIDE_STAT_TITLE, aTitle );
                    rSet.Put( aItem );
                }
diff --git a/basctl/source/basicide/bastypes.cxx b/basctl/source/basicide/bastypes.cxx
index c682094..0bf829b 100644
--- a/basctl/source/basicide/bastypes.cxx
+++ b/basctl/source/basicide/bastypes.cxx
@@ -35,8 +35,10 @@
#include <com/sun/star/script/XLibraryContainerPassword.hpp>
#include <sal/log.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/infobar.hxx>
#include <sfx2/passwd.hxx>
#include <sfx2/sfxsids.hrc>
#include <sfx2/viewfrm.hxx>
#include <svl/intitem.hxx>
#include <svl/stritem.hxx>
#include <svl/srchdefs.hxx>
@@ -51,6 +53,9 @@
namespace basctl
{

// ID used for the read-only infobar
constexpr OUStringLiteral BASIC_IDE_READONLY_INFOBAR = u"readonly";

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star;

@@ -87,6 +92,12 @@ void BaseWindow::Init()
        pShellVScrollBar->SetScrollHdl( LINK( this, BaseWindow, VertScrollHdl ) );
    if ( pShellHScrollBar )
        pShellHScrollBar->SetScrollHdl( LINK( this, BaseWindow, HorzScrollHdl ) );

    // Show the read-only infobar if the module/dialog is read-only
    GetShell()->GetViewFrame()->RemoveInfoBar(BASIC_IDE_READONLY_INFOBAR);
    if (IsReadOnly())
        ShowReadOnlyInfoBar();

    DoInit();   // virtual...
}

@@ -220,6 +231,19 @@ bool BaseWindow::IsReadOnly ()
    return false;
}

// Show the read-only warning messages for module and dialog windows
void BaseWindow::ShowReadOnlyInfoBar()
{
    OUString aMsg;
    if (dynamic_cast<ModulWindow*>(this))
        aMsg = IDEResId(RID_STR_MODULE_READONLY);
    else
        aMsg = IDEResId(RID_STR_DIALOG_READONLY);

    GetShell()->GetViewFrame()->AppendInfoBar(BASIC_IDE_READONLY_INFOBAR, OUString(),
                                              aMsg, InfobarType::INFO, true);
}

void BaseWindow::BasicStarted()
{
}
diff --git a/basctl/source/inc/bastypes.hxx b/basctl/source/inc/bastypes.hxx
index 79229f9..4bc9248 100644
--- a/basctl/source/inc/bastypes.hxx
+++ b/basctl/source/inc/bastypes.hxx
@@ -211,6 +211,7 @@ public:

    virtual void    SetReadOnly (bool bReadOnly);
    virtual bool    IsReadOnly();
    void            ShowReadOnlyInfoBar();

    int GetStatus() const { return nStatus; }
    void SetStatus(int n) { nStatus = n; }