tdf#67770: Read/writer LastActiveDeck bits

Change-Id: Id5e3c3cb4144b9fc56ab5e4a4e49f1fc69e70023
Reviewed-on: https://gerrit.libreoffice.org/43493
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Katarina Behrens <Katarina.Behrens@cib.de>
diff --git a/include/sfx2/sidebar/ResourceManager.hxx b/include/sfx2/sidebar/ResourceManager.hxx
index 8c50ecf..2d68d352 100644
--- a/include/sfx2/sidebar/ResourceManager.hxx
+++ b/include/sfx2/sidebar/ResourceManager.hxx
@@ -51,6 +51,7 @@ public:
    void InitDeckContext(const Context& rContex);
    void SaveDecksSettings(const Context& rContext);
    void SaveDeckSettings(const DeckDescriptor* pDeckDesc);
    void SaveLastActiveDeck(const Context& rContext, const OUString& rActiveDeck);

    void disposeDecks();

@@ -84,6 +85,8 @@ public:
                                            const OUString& rsDeckId,
                                            const css::uno::Reference<css::frame::XController>& rxController);

    const OUString& GetLastActiveDeck( const Context& rContext );

    /** Remember the expansions state per panel and context.
    */
    void StorePanelExpansionState(const OUString& rsPanelId,
@@ -99,11 +102,13 @@ private:
    typedef std::vector<std::shared_ptr<PanelDescriptor>> PanelContainer;
    PanelContainer maPanels;
    mutable std::set<rtl::OUString> maProcessedApplications;
    std::map<OUString, OUString> maLastActiveDecks;

    SvtMiscOptions maMiscOptions;

    void ReadDeckList();
    void ReadPanelList();
    void ReadLastActive();
    static void ReadContextList(const utl::OConfigurationNode& rNode,
                         ContextList& rContextList,
                         const OUString& rsDefaultMenuCommand);
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu b/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu
index 6a7f5ad..f65558a 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu
@@ -1549,10 +1549,5 @@
        </prop>
      </node>
    </node>
    <prop oor:name="LastActiveDeck">
      <value oor:separator=";">
         any, PropertyDeck;
      </value>
    </prop>
  </node>
</oor:component-data>
diff --git a/officecfg/registry/schema/org/openoffice/Office/UI/Sidebar.xcs b/officecfg/registry/schema/org/openoffice/Office/UI/Sidebar.xcs
index 6c5fc3a..3258798 100644
--- a/officecfg/registry/schema/org/openoffice/Office/UI/Sidebar.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/UI/Sidebar.xcs
@@ -245,7 +245,7 @@
          <desc>Contains all registered sidebar content panels.</desc>
        </info>
      </set>
      <prop oor:name="LastActiveDeck" oor:type="oor:string-list">
      <prop oor:name="LastActiveDeck" oor:type="oor:string-list" oor:nillable="false">
        <info>
	  <desc>Contains IDs of the decks that were active last time the application was closed.
	    Each entry is a string of 2 comma-separated values, application name and DeckID. Valid
@@ -255,6 +255,9 @@
	    Impress, PropertyDeck;
	  </desc>
	</info>
	<value>
	  <it>any,PropertyDeck</it>
	</value>
      </prop>
    </group>
  </component>
diff --git a/sfx2/source/sidebar/ResourceManager.cxx b/sfx2/source/sidebar/ResourceManager.cxx
index 1f8fb28..ead0ce7 100644
--- a/sfx2/source/sidebar/ResourceManager.cxx
+++ b/sfx2/source/sidebar/ResourceManager.cxx
@@ -20,9 +20,11 @@
#include <sfx2/sidebar/ResourceManager.hxx>
#include <sfx2/sidebar/Tools.hxx>

#include <officecfg/Office/UI/Sidebar.hxx>
#include <unotools/confignode.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/namedvaluecollection.hxx>
#include <comphelper/sequence.hxx>
#include <comphelper/types.hxx>

#include <rtl/ustrbuf.hxx>
@@ -98,6 +100,7 @@ ResourceManager::ResourceManager()
{
    ReadDeckList();
    ReadPanelList();
    ReadLastActive();
}

ResourceManager::~ResourceManager()
@@ -243,6 +246,14 @@ const ResourceManager::PanelContextDescriptorContainer& ResourceManager::GetMatc
    return rPanelIds;
}

const OUString& ResourceManager::GetLastActiveDeck( const Context& rContext )
{
    if( maLastActiveDecks.find( rContext.msApplication ) == maLastActiveDecks.end())
        return maLastActiveDecks["any"];
    else
        return maLastActiveDecks[rContext.msApplication];
}

void ResourceManager::ReadDeckList()
{
    const utl::OConfigurationTreeRoot aDeckRootNode(
@@ -394,6 +405,21 @@ void ResourceManager::SaveDeckSettings(const DeckDescriptor* pDeckDesc)
        aPanelRootNode.commit();
}

void ResourceManager::SaveLastActiveDeck(const Context& rContext, const OUString& rActiveDeck)
{
    maLastActiveDecks[rContext.msApplication] = rActiveDeck;

    std::set<OUString> aLastActiveDecks;
    for ( auto const & rEntry : maLastActiveDecks )
        aLastActiveDecks.insert( rEntry.first + "," +  rEntry.second);

    std::shared_ptr<comphelper::ConfigurationChanges> cfgWriter( comphelper::ConfigurationChanges::create() );

    officecfg::Office::UI::Sidebar::Content::LastActiveDeck::set(comphelper::containerToSequence(aLastActiveDecks), cfgWriter);
    cfgWriter->commit();

}

void ResourceManager::ReadPanelList()
{
    const utl::OConfigurationTreeRoot aPanelRootNode(
@@ -435,6 +461,29 @@ void ResourceManager::ReadPanelList()
    }
}

void ResourceManager::ReadLastActive()
{
    Sequence <OUString> aLastActive (officecfg::Office::UI::Sidebar::Content::LastActiveDeck::get());

    for (auto& rDeckInfo : aLastActive)
    {
        sal_Int32 nCharIdx = rDeckInfo.lastIndexOf(',');
        if ( nCharIdx <= 0 || (nCharIdx == rDeckInfo.getLength() - 1) )
        {
            SAL_WARN("sfx.sidebar", "Expecting 2 values separated by comma");
            continue;
        }

        const OUString sApplicationName = rDeckInfo.copy( 0, nCharIdx );
        vcl::EnumContext::Application eApplication (vcl::EnumContext::GetApplicationEnum(sApplicationName));
        const OUString sLastUsed = rDeckInfo.copy( nCharIdx + 1 );

        // guard against garbage in place of application
        if (eApplication != vcl::EnumContext::Application::NONE)
            maLastActiveDecks.insert( std::make_pair(sApplicationName, sLastUsed ) );
    }
}

void ResourceManager::ReadContextList (
                        const utl::OConfigurationNode& rParentNode,
                        ContextList& rContextList,
diff --git a/sfx2/source/sidebar/SidebarController.cxx b/sfx2/source/sidebar/SidebarController.cxx
index e5cc429..fb50b26 100644
--- a/sfx2/source/sidebar/SidebarController.cxx
+++ b/sfx2/source/sidebar/SidebarController.cxx
@@ -140,7 +140,7 @@ rtl::Reference<SidebarController> SidebarController::create(
    if (instance->mxReadOnlyModeDispatch.is())
        instance->mxReadOnlyModeDispatch->addStatusListener(instance.get(), aURL);

    instance->SwitchToDeck(gsDefaultDeckId);
    //first UpdateConfigurations call will SwitchToDeck

    return instance;
}
@@ -210,7 +210,10 @@ void SAL_CALL SidebarController::disposing()
    // so need to test if GetCurrentContext is still valid regarding msApplication

    if (GetCurrentContext().msApplication != "none")
    {
        mpResourceManager->SaveDecksSettings(GetCurrentContext());
        mpResourceManager->SaveLastActiveDeck(GetCurrentContext(), msCurrentDeckId);
    }

    // clear decks
    ResourceManager::DeckContextDescriptorContainer aDecks;
@@ -437,6 +440,15 @@ void SidebarController::UpdateConfigurations()
        if (maCurrentContext.msApplication != "none")
            mpResourceManager->SaveDecksSettings(maCurrentContext);

        // get last active deck for this application on first update
        if (!maRequestedContext.msApplication.isEmpty() &&
             (maCurrentContext.msApplication != maRequestedContext.msApplication))
        {
           OUString sLastActiveDeck = mpResourceManager->GetLastActiveDeck( maRequestedContext );
           if (!sLastActiveDeck.isEmpty())
               msCurrentDeckId = sLastActiveDeck;
        }

        maCurrentContext = maRequestedContext;

        mpResourceManager->InitDeckContext(GetCurrentContext());