Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "RecentlyUsedMasterPages.hxx"
31 : : #include "MasterPageObserver.hxx"
32 : : #include "MasterPagesSelector.hxx"
33 : : #include "MasterPageDescriptor.hxx"
34 : : #include "tools/ConfigurationAccess.hxx"
35 : : #include "drawdoc.hxx"
36 : : #include "sdpage.hxx"
37 : :
38 : : #include <algorithm>
39 : : #include <vector>
40 : :
41 : : #include <comphelper/processfactory.hxx>
42 : : #include "unomodel.hxx"
43 : : #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
44 : : #include <com/sun/star/drawing/XDrawPages.hpp>
45 : : #include <com/sun/star/frame/XComponentLoader.hpp>
46 : : #include <com/sun/star/container/XNameAccess.hpp>
47 : : #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
48 : : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
49 : : #include <com/sun/star/beans/PropertyValue.hpp>
50 : : #include <com/sun/star/beans/PropertyState.hpp>
51 : : #include <unotools/confignode.hxx>
52 : : #include <osl/doublecheckedlocking.h>
53 : : #include <osl/getglobalmutex.hxx>
54 : :
55 : : using namespace ::std;
56 : : using ::rtl::OUString;
57 : : using namespace ::com::sun::star;
58 : : using namespace ::com::sun::star::uno;
59 : :
60 : :
61 : : namespace {
62 : :
63 : 0 : static const OUString& GetPathToImpressConfigurationRoot (void)
64 : : {
65 [ # # ][ # # ]: 0 : static const OUString sPathToImpressConfigurationRoot ("/org.openoffice.Office.Impress/");
66 : 0 : return sPathToImpressConfigurationRoot;
67 : : }
68 : 0 : static const OUString& GetPathToSetNode (void)
69 : : {
70 [ # # ][ # # ]: 0 : static const OUString sPathToSetNode("MultiPaneGUI/ToolPanel/RecentlyUsedMasterPages");
71 : 0 : return sPathToSetNode;
72 : : }
73 : :
74 : :
75 : 0 : class Descriptor
76 : : {
77 : : public:
78 : : ::rtl::OUString msURL;
79 : : ::rtl::OUString msName;
80 : : ::sd::toolpanel::controls::MasterPageContainer::Token maToken;
81 : : Descriptor (const ::rtl::OUString& rsURL, const ::rtl::OUString& rsName)
82 : : : msURL(rsURL),
83 : : msName(rsName),
84 : : maToken(::sd::toolpanel::controls::MasterPageContainer::NIL_TOKEN)
85 : : {}
86 : 0 : Descriptor (::sd::toolpanel::controls::MasterPageContainer::Token aToken,
87 : : const ::rtl::OUString& rsURL, const ::rtl::OUString& rsName)
88 : : : msURL(rsURL),
89 : : msName(rsName),
90 : 0 : maToken(aToken)
91 : 0 : {}
92 : : class TokenComparator
93 : : {
94 : : public:
95 : 0 : TokenComparator(::sd::toolpanel::controls::MasterPageContainer::Token aToken)
96 : 0 : : maToken(aToken) {}
97 : 0 : bool operator () (const Descriptor& rDescriptor) const
98 : 0 : { return maToken==rDescriptor.maToken; }
99 : : private:
100 : : ::sd::toolpanel::controls::MasterPageContainer::Token maToken;
101 : : };
102 : : };
103 : :
104 : : } // end of anonymous namespace
105 : :
106 : :
107 : :
108 : :
109 : : namespace sd { namespace toolpanel { namespace controls {
110 : :
111 : 0 : class RecentlyUsedMasterPages::MasterPageList : public ::std::vector<Descriptor>
112 : : {
113 : : public:
114 : 0 : MasterPageList (void) {}
115 : : };
116 : :
117 : :
118 : : RecentlyUsedMasterPages* RecentlyUsedMasterPages::mpInstance = NULL;
119 : :
120 : :
121 : 0 : RecentlyUsedMasterPages& RecentlyUsedMasterPages::Instance (void)
122 : : {
123 [ # # ]: 0 : if (mpInstance == NULL)
124 : : {
125 : : ::osl::GetGlobalMutex aMutexFunctor;
126 [ # # ][ # # ]: 0 : ::osl::MutexGuard aGuard (aMutexFunctor());
127 [ # # ]: 0 : if (mpInstance == NULL)
128 : : {
129 [ # # ][ # # ]: 0 : RecentlyUsedMasterPages* pInstance = new RecentlyUsedMasterPages();
130 [ # # ]: 0 : pInstance->LateInit();
131 [ # # ]: 0 : SdGlobalResourceContainer::Instance().AddResource (
132 [ # # ][ # # ]: 0 : ::std::auto_ptr<SdGlobalResource>(pInstance));
[ # # ]
133 : : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
134 : 0 : mpInstance = pInstance;
135 [ # # ]: 0 : }
136 : : }
137 : : else {
138 : : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
139 : : }
140 : :
141 : 0 : return *mpInstance;
142 : : }
143 : :
144 : :
145 : :
146 : :
147 : 0 : RecentlyUsedMasterPages::RecentlyUsedMasterPages (void)
148 : : : maListeners(),
149 : 0 : mpMasterPages(new MasterPageList()),
150 : : mnMaxListSize(8),
151 [ # # ][ # # ]: 0 : mpContainer(new MasterPageContainer())
[ # # ][ # # ]
[ # # ][ # # ]
152 : : {
153 : 0 : }
154 : :
155 : :
156 : :
157 : :
158 [ # # ]: 0 : RecentlyUsedMasterPages::~RecentlyUsedMasterPages (void)
159 : : {
160 [ # # ]: 0 : Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener));
161 [ # # ]: 0 : mpContainer->RemoveChangeListener(aLink);
162 : :
163 [ # # ]: 0 : MasterPageObserver::Instance().RemoveEventListener(
164 [ # # ][ # # ]: 0 : LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener));
165 [ # # ]: 0 : }
166 : :
167 : :
168 : :
169 : :
170 : 0 : void RecentlyUsedMasterPages::LateInit (void)
171 : : {
172 [ # # ]: 0 : Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener));
173 [ # # ]: 0 : mpContainer->AddChangeListener(aLink);
174 : :
175 [ # # ]: 0 : LoadPersistentValues ();
176 [ # # ]: 0 : MasterPageObserver::Instance().AddEventListener(
177 [ # # ][ # # ]: 0 : LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener));
178 : 0 : }
179 : :
180 : :
181 : :
182 : :
183 : 0 : void RecentlyUsedMasterPages::LoadPersistentValues (void)
184 : : {
185 : : try
186 : : {
187 : : tools::ConfigurationAccess aConfiguration (
188 [ # # ]: 0 : GetPathToImpressConfigurationRoot(),
189 [ # # ]: 0 : tools::ConfigurationAccess::READ_ONLY);
190 : : Reference<container::XNameAccess> xSet (
191 [ # # ]: 0 : aConfiguration.GetConfigurationNode(GetPathToSetNode()),
192 [ # # ][ # # ]: 0 : UNO_QUERY);
193 [ # # ]: 0 : if ( ! xSet.is())
194 : 0 : return;
195 : :
196 : 0 : const OUString sURLMemberName("URL");
197 : 0 : const OUString sNameMemberName("Name");
198 : 0 : OUString sURL;
199 : 0 : OUString sName;
200 : :
201 : : // Read the names and URLs of the master pages.
202 [ # # ][ # # ]: 0 : Sequence<OUString> aKeys (xSet->getElementNames());
203 : 0 : mpMasterPages->clear();
204 [ # # ]: 0 : mpMasterPages->reserve(aKeys.getLength());
205 [ # # ]: 0 : for (int i=0; i<aKeys.getLength(); i++)
206 : : {
207 : : Reference<container::XNameAccess> xSetItem (
208 [ # # ][ # # ]: 0 : xSet->getByName(aKeys[i]), UNO_QUERY);
[ # # ][ # # ]
209 [ # # ]: 0 : if (xSetItem.is())
210 : : {
211 [ # # ][ # # ]: 0 : Any aURL (xSetItem->getByName(sURLMemberName));
212 [ # # ][ # # ]: 0 : Any aName (xSetItem->getByName(sNameMemberName));
213 : 0 : aURL >>= sURL;
214 : 0 : aName >>= sName;
215 : : SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor(
216 : : MasterPageContainer::TEMPLATE,
217 : : -1,
218 : : sURL,
219 : : String(),
220 : : sName,
221 : : false,
222 : : ::boost::shared_ptr<PageObjectProvider>(
223 [ # # ]: 0 : new TemplatePageObjectProvider(sURL)),
224 : : ::boost::shared_ptr<PreviewProvider>(
225 [ # # ][ # # ]: 0 : new TemplatePreviewProvider(sURL))));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
226 : : // For user supplied templates we use a different
227 : : // preview provider: The preview in the document shows
228 : : // not only shapes on the master page but also shapes on
229 : : // the foreground. This is misleading and therefore
230 : : // these previews are discarded and created directly
231 : : // from the page objects.
232 [ # # ][ # # ]: 0 : if (pDescriptor->GetURLClassification() == MasterPageDescriptor::URLCLASS_USER)
233 : 0 : pDescriptor->mpPreviewProvider = ::boost::shared_ptr<PreviewProvider>(
234 [ # # ][ # # ]: 0 : new PagePreviewProvider());
[ # # # # ]
[ # # ]
235 [ # # ]: 0 : MasterPageContainer::Token aToken (mpContainer->PutMasterPage(pDescriptor));
236 [ # # ][ # # ]: 0 : mpMasterPages->push_back(Descriptor(aToken,sURL,sName));
237 : : }
238 : 0 : }
239 : :
240 [ # # ][ # # ]: 0 : ResolveList();
[ # # ][ # # ]
[ # # ][ # # ]
241 : : }
242 : 0 : catch (Exception&)
243 : : {
244 : : // Ignore exception.
245 : : }
246 : : }
247 : :
248 : :
249 : :
250 : :
251 : 0 : void RecentlyUsedMasterPages::SavePersistentValues (void)
252 : : {
253 : : try
254 : : {
255 : : tools::ConfigurationAccess aConfiguration (
256 [ # # ]: 0 : GetPathToImpressConfigurationRoot(),
257 [ # # ]: 0 : tools::ConfigurationAccess::READ_WRITE);
258 : : Reference<container::XNameContainer> xSet (
259 [ # # ]: 0 : aConfiguration.GetConfigurationNode(GetPathToSetNode()),
260 [ # # ][ # # ]: 0 : UNO_QUERY);
261 [ # # ]: 0 : if ( ! xSet.is())
262 : : return;
263 : :
264 : : // Clear the set.
265 [ # # ][ # # ]: 0 : Sequence<OUString> aKeys (xSet->getElementNames());
266 : : sal_Int32 i;
267 [ # # ]: 0 : for (i=0; i<aKeys.getLength(); i++)
268 [ # # ][ # # ]: 0 : xSet->removeByName (aKeys[i]);
[ # # ]
269 : :
270 : : // Fill it with the URLs of this object.
271 : 0 : const OUString sURLMemberName("URL");
272 : 0 : const OUString sNameMemberName("Name");
273 : 0 : Any aValue;
274 : : Reference<lang::XSingleServiceFactory> xChildFactory (
275 [ # # ]: 0 : xSet, UNO_QUERY);
276 [ # # ]: 0 : if ( ! xChildFactory.is())
277 : : return;
278 : 0 : MasterPageList::const_iterator iDescriptor;
279 : 0 : sal_Int32 nIndex(0);
280 [ # # ][ # # ]: 0 : for (iDescriptor=mpMasterPages->begin();
[ # # ]
281 : 0 : iDescriptor!=mpMasterPages->end();
282 : : ++iDescriptor,++nIndex)
283 : : {
284 : : // Create new child.
285 : 0 : OUString sKey ("index_");
286 : 0 : sKey += OUString::valueOf(nIndex);
287 : : Reference<container::XNameReplace> xChild(
288 [ # # ][ # # ]: 0 : xChildFactory->createInstance(), UNO_QUERY);
[ # # ]
289 [ # # ]: 0 : if (xChild.is())
290 : : {
291 [ # # ][ # # ]: 0 : xSet->insertByName (sKey, makeAny(xChild));
[ # # ]
292 : :
293 [ # # ]: 0 : aValue <<= OUString(iDescriptor->msURL);
294 [ # # ][ # # ]: 0 : xChild->replaceByName (sURLMemberName, aValue);
295 : :
296 [ # # ]: 0 : aValue <<= OUString(iDescriptor->msName);
297 [ # # ][ # # ]: 0 : xChild->replaceByName (sNameMemberName, aValue);
298 : : }
299 : 0 : }
300 : :
301 : : // Write the data back to disk.
302 [ # # ][ # # ]: 0 : aConfiguration.CommitChanges();
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
303 : : }
304 : 0 : catch (Exception&)
305 : : {
306 : : // Ignore exception.
307 : : }
308 : : }
309 : :
310 : :
311 : :
312 : :
313 : 0 : void RecentlyUsedMasterPages::AddEventListener (const Link& rEventListener)
314 : : {
315 [ # # ][ # # ]: 0 : if (::std::find (
316 : : maListeners.begin(),
317 : : maListeners.end(),
318 [ # # ]: 0 : rEventListener) == maListeners.end())
319 : : {
320 : 0 : maListeners.push_back (rEventListener);
321 : : }
322 : 0 : }
323 : :
324 : :
325 : :
326 : :
327 : 0 : void RecentlyUsedMasterPages::RemoveEventListener (const Link& rEventListener)
328 : : {
329 : : maListeners.erase (
330 : : ::std::find (
331 : : maListeners.begin(),
332 : : maListeners.end(),
333 : 0 : rEventListener));
334 : 0 : }
335 : :
336 : :
337 : :
338 : :
339 : 0 : int RecentlyUsedMasterPages::GetMasterPageCount (void) const
340 : : {
341 : 0 : return mpMasterPages->size();
342 : : }
343 : :
344 : :
345 : :
346 : :
347 : 0 : MasterPageContainer::Token RecentlyUsedMasterPages::GetTokenForIndex (sal_uInt32 nIndex) const
348 : : {
349 [ # # ]: 0 : if(nIndex<mpMasterPages->size())
350 : 0 : return (*mpMasterPages)[nIndex].maToken;
351 : : else
352 : 0 : return MasterPageContainer::NIL_TOKEN;
353 : : }
354 : :
355 : :
356 : :
357 : :
358 : 0 : void RecentlyUsedMasterPages::SendEvent (void)
359 : : {
360 : 0 : ::std::vector<Link>::iterator aLink (maListeners.begin());
361 : 0 : ::std::vector<Link>::iterator aEnd (maListeners.end());
362 [ # # ][ # # ]: 0 : while (aLink!=aEnd)
363 : : {
364 [ # # ][ # # ]: 0 : aLink->Call (NULL);
365 [ # # ]: 0 : ++aLink;
366 : : }
367 : 0 : }
368 : :
369 : :
370 : :
371 : :
372 : 0 : IMPL_LINK(RecentlyUsedMasterPages, MasterPageChangeListener,
373 : : MasterPageObserverEvent*, pEvent)
374 : : {
375 [ # # # ]: 0 : switch (pEvent->meType)
376 : : {
377 : : case MasterPageObserverEvent::ET_MASTER_PAGE_ADDED:
378 : : case MasterPageObserverEvent::ET_MASTER_PAGE_EXISTS:
379 : : AddMasterPage(
380 : 0 : mpContainer->GetTokenForStyleName(pEvent->mrMasterPageName));
381 : 0 : break;
382 : :
383 : : case MasterPageObserverEvent::ET_MASTER_PAGE_REMOVED:
384 : : // Do not change the list of recently master pages (the deleted
385 : : // page was recently used) but tell the listeners. They may want
386 : : // to update their lists.
387 : 0 : SendEvent();
388 : 0 : break;
389 : : }
390 : 0 : return 0;
391 : : }
392 : :
393 : :
394 : :
395 : :
396 : 0 : IMPL_LINK(RecentlyUsedMasterPages, MasterPageContainerChangeListener,
397 : : MasterPageContainerChangeEvent*, pEvent)
398 : : {
399 [ # # ]: 0 : if (pEvent != NULL)
400 [ # # ]: 0 : switch (pEvent->meEventType)
401 : : {
402 : : case MasterPageContainerChangeEvent::CHILD_ADDED:
403 : : case MasterPageContainerChangeEvent::CHILD_REMOVED:
404 : : case MasterPageContainerChangeEvent::INDEX_CHANGED:
405 : : case MasterPageContainerChangeEvent::INDEXES_CHANGED:
406 : 0 : ResolveList();
407 : 0 : break;
408 : :
409 : : default:
410 : : // Ignored.
411 : 0 : break;
412 : : }
413 : 0 : return 0;
414 : : }
415 : :
416 : :
417 : :
418 : :
419 : 0 : void RecentlyUsedMasterPages::AddMasterPage (
420 : : MasterPageContainer::Token aToken,
421 : : bool bMakePersistent)
422 : : {
423 : : // For the page to be inserted the token has to be valid and the page
424 : : // has to have a valid URL. This excludes master pages that do not come
425 : : // from template files.
426 [ # # # # ]: 0 : if (aToken != MasterPageContainer::NIL_TOKEN
[ # # ]
427 [ # # ][ # # ]: 0 : && mpContainer->GetURLForToken(aToken).Len()>0)
[ # # ]
428 : : {
429 : :
430 : : MasterPageList::iterator aIterator (
431 : 0 : ::std::find_if(mpMasterPages->begin(),mpMasterPages->end(),
432 [ # # ]: 0 : Descriptor::TokenComparator(aToken)));
433 [ # # ][ # # ]: 0 : if (aIterator != mpMasterPages->end())
434 : : {
435 : : // When an entry for the given token already exists then remove
436 : : // it now and insert it later at the head of the list.
437 [ # # ]: 0 : mpMasterPages->erase (aIterator);
438 : : }
439 : :
440 : 0 : mpMasterPages->insert(mpMasterPages->begin(),
441 : : Descriptor(
442 : : aToken,
443 : : mpContainer->GetURLForToken(aToken),
444 [ # # ][ # # ]: 0 : mpContainer->GetStyleNameForToken(aToken)));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
445 : :
446 : : // Shorten list to maximal size.
447 [ # # ]: 0 : while (mpMasterPages->size() > mnMaxListSize)
448 : : {
449 [ # # ]: 0 : mpMasterPages->pop_back ();
450 : : }
451 : :
452 [ # # ]: 0 : if (bMakePersistent)
453 [ # # ]: 0 : SavePersistentValues ();
454 [ # # ]: 0 : SendEvent();
455 : : }
456 : 0 : }
457 : :
458 : :
459 : :
460 : :
461 : 0 : void RecentlyUsedMasterPages::ResolveList (void)
462 : : {
463 : 0 : bool bNotify (false);
464 : :
465 : 0 : MasterPageList::iterator iDescriptor;
466 [ # # ][ # # ]: 0 : for (iDescriptor=mpMasterPages->begin(); iDescriptor!=mpMasterPages->end(); ++iDescriptor)
467 : : {
468 [ # # ]: 0 : if (iDescriptor->maToken == MasterPageContainer::NIL_TOKEN)
469 : : {
470 [ # # ][ # # ]: 0 : MasterPageContainer::Token aToken (mpContainer->GetTokenForURL(iDescriptor->msURL));
[ # # ]
471 : 0 : iDescriptor->maToken = aToken;
472 [ # # ]: 0 : if (aToken != MasterPageContainer::NIL_TOKEN)
473 : 0 : bNotify = true;
474 : : }
475 : : else
476 : : {
477 [ # # ][ # # ]: 0 : if ( ! mpContainer->HasToken(iDescriptor->maToken))
478 : : {
479 : 0 : iDescriptor->maToken = MasterPageContainer::NIL_TOKEN;
480 : 0 : bNotify = true;
481 : : }
482 : : }
483 : : }
484 : :
485 [ # # ]: 0 : if (bNotify)
486 [ # # ]: 0 : SendEvent();
487 : 0 : }
488 : :
489 : :
490 : : } } } // end of namespace ::sd::toolpanel::controls
491 : :
492 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|