1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "RecentlyUsedMasterPages.hxx"
21 #include "MasterPageObserver.hxx"
22 #include "MasterPagesSelector.hxx"
23 #include "MasterPageDescriptor.hxx"
24 #include "tools/ConfigurationAccess.hxx"
25 #include "drawdoc.hxx"
31 #include <comphelper/processfactory.hxx>
32 #include "unomodel.hxx"
33 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
34 #include <com/sun/star/drawing/XDrawPages.hpp>
35 #include <com/sun/star/frame/XComponentLoader.hpp>
36 #include <com/sun/star/container/XNameAccess.hpp>
37 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/beans/PropertyValue.hpp>
40 #include <com/sun/star/beans/PropertyState.hpp>
41 #include <unotools/confignode.hxx>
42 #include <osl/doublecheckedlocking.h>
43 #include <osl/getglobalmutex.hxx>
45 using namespace ::std
;
46 using namespace ::com::sun::star
;
47 using namespace ::com::sun::star::uno
;
51 static OUString
GetPathToImpressConfigurationRoot()
53 return OUString("/org.openoffice.Office.Impress/");
55 static OUString
GetPathToSetNode()
57 return OUString("MultiPaneGUI/ToolPanel/RecentlyUsedMasterPages");
60 } // end of anonymous namespace
62 namespace sd
{ namespace sidebar
{
64 RecentlyUsedMasterPages
* RecentlyUsedMasterPages::mpInstance
= NULL
;
66 RecentlyUsedMasterPages
& RecentlyUsedMasterPages::Instance()
68 if (mpInstance
== NULL
)
70 ::osl::GetGlobalMutex aMutexFunctor
;
71 ::osl::MutexGuard
aGuard (aMutexFunctor());
72 if (mpInstance
== NULL
)
74 RecentlyUsedMasterPages
* pInstance
= new RecentlyUsedMasterPages();
75 pInstance
->LateInit();
76 SdGlobalResourceContainer::Instance().AddResource (
77 ::std::unique_ptr
<SdGlobalResource
>(pInstance
));
78 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
79 mpInstance
= pInstance
;
83 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
89 RecentlyUsedMasterPages::RecentlyUsedMasterPages()
93 mpContainer(new MasterPageContainer())
97 RecentlyUsedMasterPages::~RecentlyUsedMasterPages()
99 Link
<> aLink (LINK(this,RecentlyUsedMasterPages
,MasterPageContainerChangeListener
));
100 mpContainer
->RemoveChangeListener(aLink
);
102 MasterPageObserver::Instance().RemoveEventListener(
103 LINK(this,RecentlyUsedMasterPages
,MasterPageChangeListener
));
106 void RecentlyUsedMasterPages::LateInit()
108 Link
<> aLink (LINK(this,RecentlyUsedMasterPages
,MasterPageContainerChangeListener
));
109 mpContainer
->AddChangeListener(aLink
);
111 LoadPersistentValues ();
112 MasterPageObserver::Instance().AddEventListener(
113 LINK(this,RecentlyUsedMasterPages
,MasterPageChangeListener
));
116 void RecentlyUsedMasterPages::LoadPersistentValues()
120 tools::ConfigurationAccess
aConfiguration (
121 GetPathToImpressConfigurationRoot(),
122 tools::ConfigurationAccess::READ_ONLY
);
123 Reference
<container::XNameAccess
> xSet (
124 aConfiguration
.GetConfigurationNode(GetPathToSetNode()),
129 const OUString
sURLMemberName("URL");
130 const OUString
sNameMemberName("Name");
134 // Read the names and URLs of the master pages.
135 Sequence
<OUString
> aKeys (xSet
->getElementNames());
136 mvMasterPages
.clear();
137 mvMasterPages
.reserve(aKeys
.getLength());
138 for (int i
=0; i
<aKeys
.getLength(); i
++)
140 Reference
<container::XNameAccess
> xSetItem (
141 xSet
->getByName(aKeys
[i
]), UNO_QUERY
);
144 Any
aURL (xSetItem
->getByName(sURLMemberName
));
145 Any
aName (xSetItem
->getByName(sNameMemberName
));
148 SharedMasterPageDescriptor
pDescriptor (new MasterPageDescriptor(
149 MasterPageContainer::TEMPLATE
,
155 ::boost::shared_ptr
<PageObjectProvider
>(
156 new TemplatePageObjectProvider(sURL
)),
157 ::boost::shared_ptr
<PreviewProvider
>(
158 new TemplatePreviewProvider(sURL
))));
159 // For user supplied templates we use a different
160 // preview provider: The preview in the document shows
161 // not only shapes on the master page but also shapes on
162 // the foreground. This is misleading and therefore
163 // these previews are discarded and created directly
164 // from the page objects.
165 if (pDescriptor
->GetURLClassification() == MasterPageDescriptor::URLCLASS_USER
)
166 pDescriptor
->mpPreviewProvider
= ::boost::shared_ptr
<PreviewProvider
>(
167 new PagePreviewProvider());
168 MasterPageContainer::Token
aToken (mpContainer
->PutMasterPage(pDescriptor
));
169 mvMasterPages
.push_back(Descriptor(aToken
,sURL
,sName
));
181 void RecentlyUsedMasterPages::SavePersistentValues()
185 tools::ConfigurationAccess
aConfiguration (
186 GetPathToImpressConfigurationRoot(),
187 tools::ConfigurationAccess::READ_WRITE
);
188 Reference
<container::XNameContainer
> xSet (
189 aConfiguration
.GetConfigurationNode(GetPathToSetNode()),
195 Sequence
<OUString
> aKeys (xSet
->getElementNames());
197 for (i
=0; i
<aKeys
.getLength(); i
++)
198 xSet
->removeByName (aKeys
[i
]);
200 // Fill it with the URLs of this object.
201 const OUString
sURLMemberName("URL");
202 const OUString
sNameMemberName("Name");
204 Reference
<lang::XSingleServiceFactory
> xChildFactory (
206 if ( ! xChildFactory
.is())
208 MasterPageList::const_iterator iDescriptor
;
210 for (iDescriptor
=mvMasterPages
.begin();
211 iDescriptor
!=mvMasterPages
.end();
212 ++iDescriptor
,++nIndex
)
215 OUString
sKey ("index_");
216 sKey
+= OUString::number(nIndex
);
217 Reference
<container::XNameReplace
> xChild(
218 xChildFactory
->createInstance(), UNO_QUERY
);
221 xSet
->insertByName (sKey
, makeAny(xChild
));
223 aValue
<<= OUString(iDescriptor
->msURL
);
224 xChild
->replaceByName (sURLMemberName
, aValue
);
226 aValue
<<= OUString(iDescriptor
->msName
);
227 xChild
->replaceByName (sNameMemberName
, aValue
);
231 // Write the data back to disk.
232 aConfiguration
.CommitChanges();
240 void RecentlyUsedMasterPages::AddEventListener (const Link
<>& rEventListener
)
245 rEventListener
) == maListeners
.end())
247 maListeners
.push_back (rEventListener
);
251 void RecentlyUsedMasterPages::RemoveEventListener (const Link
<>& rEventListener
)
260 int RecentlyUsedMasterPages::GetMasterPageCount() const
262 return mvMasterPages
.size();
265 MasterPageContainer::Token
RecentlyUsedMasterPages::GetTokenForIndex (sal_uInt32 nIndex
) const
267 if(nIndex
<mvMasterPages
.size())
268 return mvMasterPages
[nIndex
].maToken
;
270 return MasterPageContainer::NIL_TOKEN
;
273 void RecentlyUsedMasterPages::SendEvent()
275 ::std::vector
<Link
<>>::iterator
aLink (maListeners
.begin());
276 ::std::vector
<Link
<>>::iterator
aEnd (maListeners
.end());
284 IMPL_LINK(RecentlyUsedMasterPages
, MasterPageChangeListener
,
285 MasterPageObserverEvent
*, pEvent
)
287 switch (pEvent
->meType
)
289 case MasterPageObserverEvent::ET_MASTER_PAGE_ADDED
:
290 case MasterPageObserverEvent::ET_MASTER_PAGE_EXISTS
:
292 mpContainer
->GetTokenForStyleName(pEvent
->mrMasterPageName
));
295 case MasterPageObserverEvent::ET_MASTER_PAGE_REMOVED
:
296 // Do not change the list of recently master pages (the deleted
297 // page was recently used) but tell the listeners. They may want
298 // to update their lists.
305 IMPL_LINK(RecentlyUsedMasterPages
, MasterPageContainerChangeListener
,
306 MasterPageContainerChangeEvent
*, pEvent
)
309 switch (pEvent
->meEventType
)
311 case MasterPageContainerChangeEvent::CHILD_ADDED
:
312 case MasterPageContainerChangeEvent::CHILD_REMOVED
:
313 case MasterPageContainerChangeEvent::INDEX_CHANGED
:
314 case MasterPageContainerChangeEvent::INDEXES_CHANGED
:
325 void RecentlyUsedMasterPages::AddMasterPage (
326 MasterPageContainer::Token aToken
,
327 bool bMakePersistent
)
329 // For the page to be inserted the token has to be valid and the page
330 // has to have a valid URL. This excludes master pages that do not come
331 // from template files.
332 if (aToken
!= MasterPageContainer::NIL_TOKEN
333 && !mpContainer
->GetURLForToken(aToken
).isEmpty())
336 MasterPageList::iterator
aIterator (
337 ::std::find_if(mvMasterPages
.begin(),mvMasterPages
.end(),
338 Descriptor::TokenComparator(aToken
)));
339 if (aIterator
!= mvMasterPages
.end())
341 // When an entry for the given token already exists then remove
342 // it now and insert it later at the head of the list.
343 mvMasterPages
.erase (aIterator
);
346 mvMasterPages
.insert(mvMasterPages
.begin(),
349 mpContainer
->GetURLForToken(aToken
),
350 mpContainer
->GetStyleNameForToken(aToken
)));
352 // Shorten list to maximal size.
353 while (mvMasterPages
.size() > mnMaxListSize
)
355 mvMasterPages
.pop_back ();
359 SavePersistentValues ();
364 void RecentlyUsedMasterPages::ResolveList()
366 bool bNotify (false);
368 MasterPageList::iterator iDescriptor
;
369 for (iDescriptor
=mvMasterPages
.begin(); iDescriptor
!=mvMasterPages
.end(); ++iDescriptor
)
371 if (iDescriptor
->maToken
== MasterPageContainer::NIL_TOKEN
)
373 MasterPageContainer::Token
aToken (mpContainer
->GetTokenForURL(iDescriptor
->msURL
));
374 iDescriptor
->maToken
= aToken
;
375 if (aToken
!= MasterPageContainer::NIL_TOKEN
)
380 if ( ! mpContainer
->HasToken(iDescriptor
->maToken
))
382 iDescriptor
->maToken
= MasterPageContainer::NIL_TOKEN
;
392 } } // end of namespace sd::sidebar
394 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */