/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include "RecentlyUsedMasterPages.hxx" #include "MasterPageObserver.hxx" #include "MasterPagesSelector.hxx" #include "MasterPageDescriptor.hxx" #include "tools/ConfigurationAccess.hxx" #include "drawdoc.hxx" #include "sdpage.hxx" #include #include #include #include "unomodel.hxx" #include #include #include #include #include #include #include #include #include #include #include using namespace ::std; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; namespace { static OUString GetPathToImpressConfigurationRoot() { return OUString("/org.openoffice.Office.Impress/"); } static OUString GetPathToSetNode() { return OUString("MultiPaneGUI/ToolPanel/RecentlyUsedMasterPages"); } } // end of anonymous namespace namespace sd { namespace sidebar { RecentlyUsedMasterPages* RecentlyUsedMasterPages::mpInstance = NULL; RecentlyUsedMasterPages& RecentlyUsedMasterPages::Instance() { if (mpInstance == NULL) { ::osl::GetGlobalMutex aMutexFunctor; ::osl::MutexGuard aGuard (aMutexFunctor()); if (mpInstance == NULL) { RecentlyUsedMasterPages* pInstance = new RecentlyUsedMasterPages(); pInstance->LateInit(); SdGlobalResourceContainer::Instance().AddResource ( ::std::unique_ptr(pInstance)); OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); mpInstance = pInstance; } } else { OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); } return *mpInstance; } RecentlyUsedMasterPages::RecentlyUsedMasterPages() : maListeners(), mvMasterPages(), mnMaxListSize(8), mpContainer(new MasterPageContainer()) { } RecentlyUsedMasterPages::~RecentlyUsedMasterPages() { Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener)); mpContainer->RemoveChangeListener(aLink); MasterPageObserver::Instance().RemoveEventListener( LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener)); } void RecentlyUsedMasterPages::LateInit() { Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener)); mpContainer->AddChangeListener(aLink); LoadPersistentValues (); MasterPageObserver::Instance().AddEventListener( LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener)); } void RecentlyUsedMasterPages::LoadPersistentValues() { try { tools::ConfigurationAccess aConfiguration ( GetPathToImpressConfigurationRoot(), tools::ConfigurationAccess::READ_ONLY); Reference xSet ( aConfiguration.GetConfigurationNode(GetPathToSetNode()), UNO_QUERY); if ( ! xSet.is()) return; const OUString sURLMemberName("URL"); const OUString sNameMemberName("Name"); OUString sURL; OUString sName; // Read the names and URLs of the master pages. Sequence aKeys (xSet->getElementNames()); mvMasterPages.clear(); mvMasterPages.reserve(aKeys.getLength()); for (int i=0; i xSetItem ( xSet->getByName(aKeys[i]), UNO_QUERY); if (xSetItem.is()) { Any aURL (xSetItem->getByName(sURLMemberName)); Any aName (xSetItem->getByName(sNameMemberName)); aURL >>= sURL; aName >>= sName; SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor( MasterPageContainer::TEMPLATE, -1, sURL, OUString(), sName, false, ::boost::shared_ptr( new TemplatePageObjectProvider(sURL)), ::boost::shared_ptr( new TemplatePreviewProvider(sURL)))); // For user supplied templates we use a different // preview provider: The preview in the document shows // not only shapes on the master page but also shapes on // the foreground. This is misleading and therefore // these previews are discarded and created directly // from the page objects. if (pDescriptor->GetURLClassification() == MasterPageDescriptor::URLCLASS_USER) pDescriptor->mpPreviewProvider = ::boost::shared_ptr( new PagePreviewProvider()); MasterPageContainer::Token aToken (mpContainer->PutMasterPage(pDescriptor)); mvMasterPages.push_back(Descriptor(aToken,sURL,sName)); } } ResolveList(); } catch (Exception&) { // Ignore exception. } } void RecentlyUsedMasterPages::SavePersistentValues() { try { tools::ConfigurationAccess aConfiguration ( GetPathToImpressConfigurationRoot(), tools::ConfigurationAccess::READ_WRITE); Reference xSet ( aConfiguration.GetConfigurationNode(GetPathToSetNode()), UNO_QUERY); if ( ! xSet.is()) return; // Clear the set. Sequence aKeys (xSet->getElementNames()); sal_Int32 i; for (i=0; iremoveByName (aKeys[i]); // Fill it with the URLs of this object. const OUString sURLMemberName("URL"); const OUString sNameMemberName("Name"); Any aValue; Reference xChildFactory ( xSet, UNO_QUERY); if ( ! xChildFactory.is()) return; MasterPageList::const_iterator iDescriptor; sal_Int32 nIndex(0); for (iDescriptor=mvMasterPages.begin(); iDescriptor!=mvMasterPages.end(); ++iDescriptor,++nIndex) { // Create new child. OUString sKey ("index_"); sKey += OUString::number(nIndex); Reference xChild( xChildFactory->createInstance(), UNO_QUERY); if (xChild.is()) { xSet->insertByName (sKey, makeAny(xChild)); aValue <<= OUString(iDescriptor->msURL); xChild->replaceByName (sURLMemberName, aValue); aValue <<= OUString(iDescriptor->msName); xChild->replaceByName (sNameMemberName, aValue); } } // Write the data back to disk. aConfiguration.CommitChanges(); } catch (Exception&) { // Ignore exception. } } void RecentlyUsedMasterPages::AddEventListener (const Link& rEventListener) { if (::std::find ( maListeners.begin(), maListeners.end(), rEventListener) == maListeners.end()) { maListeners.push_back (rEventListener); } } void RecentlyUsedMasterPages::RemoveEventListener (const Link& rEventListener) { maListeners.erase ( ::std::find ( maListeners.begin(), maListeners.end(), rEventListener)); } int RecentlyUsedMasterPages::GetMasterPageCount() const { return mvMasterPages.size(); } MasterPageContainer::Token RecentlyUsedMasterPages::GetTokenForIndex (sal_uInt32 nIndex) const { if(nIndexGetTokenForStyleName(rEvent.mrMasterPageName)); break; case MasterPageObserverEvent::ET_MASTER_PAGE_REMOVED: // Do not change the list of recently master pages (the deleted // page was recently used) but tell the listeners. They may want // to update their lists. SendEvent(); break; } } IMPL_LINK_TYPED(RecentlyUsedMasterPages, MasterPageContainerChangeListener, MasterPageContainerChangeEvent&, rEvent, void) { switch (rEvent.meEventType) { case MasterPageContainerChangeEvent::CHILD_ADDED: case MasterPageContainerChangeEvent::CHILD_REMOVED: case MasterPageContainerChangeEvent::INDEX_CHANGED: case MasterPageContainerChangeEvent::INDEXES_CHANGED: ResolveList(); break; default: // Ignored. break; } } void RecentlyUsedMasterPages::AddMasterPage ( MasterPageContainer::Token aToken, bool bMakePersistent) { // For the page to be inserted the token has to be valid and the page // has to have a valid URL. This excludes master pages that do not come // from template files. if (aToken != MasterPageContainer::NIL_TOKEN && !mpContainer->GetURLForToken(aToken).isEmpty()) { MasterPageList::iterator aIterator ( ::std::find_if(mvMasterPages.begin(),mvMasterPages.end(), Descriptor::TokenComparator(aToken))); if (aIterator != mvMasterPages.end()) { // When an entry for the given token already exists then remove // it now and insert it later at the head of the list. mvMasterPages.erase (aIterator); } mvMasterPages.insert(mvMasterPages.begin(), Descriptor( aToken, mpContainer->GetURLForToken(aToken), mpContainer->GetStyleNameForToken(aToken))); // Shorten list to maximal size. while (mvMasterPages.size() > mnMaxListSize) { mvMasterPages.pop_back (); } if (bMakePersistent) SavePersistentValues (); SendEvent(); } } void RecentlyUsedMasterPages::ResolveList() { bool bNotify (false); MasterPageList::iterator iDescriptor; for (iDescriptor=mvMasterPages.begin(); iDescriptor!=mvMasterPages.end(); ++iDescriptor) { if (iDescriptor->maToken == MasterPageContainer::NIL_TOKEN) { MasterPageContainer::Token aToken (mpContainer->GetTokenForURL(iDescriptor->msURL)); iDescriptor->maToken = aToken; if (aToken != MasterPageContainer::NIL_TOKEN) bNotify = true; } else { if ( ! mpContainer->HasToken(iDescriptor->maToken)) { iDescriptor->maToken = MasterPageContainer::NIL_TOKEN; bNotify = true; } } } if (bNotify) SendEvent(); } } } // end of namespace sd::sidebar /* vim:set shiftwidth=4 softtabstop=4 expandtab: */