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 .
21 #include <unotools/historyoptions.hxx>
22 #include <unotools/configmgr.hxx>
23 #include <unotools/configitem.hxx>
24 #include <com/sun/star/uno/Any.hxx>
25 #include <com/sun/star/uno/Sequence.hxx>
31 #include <rtl/logfile.hxx>
32 #include "itemholder1.hxx"
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/container/XNameAccess.hpp>
36 #include <com/sun/star/container/XNameContainer.hpp>
37 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
38 #include <comphelper/configurationhelper.hxx>
39 #include <comphelper/processfactory.hxx>
41 using namespace ::std
;
42 using namespace ::utl
;
43 using namespace ::rtl
;
44 using namespace ::osl
;
45 using namespace ::com::sun::star::uno
;
46 using namespace ::com::sun::star::beans
;
49 static const ::sal_Int32 s_nOffsetURL
= 0;
50 static const ::sal_Int32 s_nOffsetFilter
= 1;
51 static const ::sal_Int32 s_nOffsetTitle
= 2;
52 static const ::sal_Int32 s_nOffsetPassword
= 3;
54 const char s_sCommonHistory
[] = "org.openoffice.Office.Common/History";
55 const char s_sHistories
[] = "org.openoffice.Office.Histories/Histories";
56 const char s_sPickListSize
[] = "PickListSize";
57 const char s_sURLHistorySize
[] = "Size";
58 const char s_sHelpBookmarksSize
[] = "HelpBookmarkSize";
59 const char s_sPickList
[] = "PickList";
60 const char s_sURLHistory
[] = "URLHistory";
61 const char s_sHelpBookmarks
[] = "HelpBookmarks";
62 const char s_sItemList
[] = "ItemList";
63 const char s_sOrderList
[] = "OrderList";
64 const char s_sHistoryItemRef
[] = "HistoryItemRef";
65 const char s_sFilter
[] = "Filter";
66 const char s_sTitle
[] = "Title";
67 const char s_sPassword
[] = "Password";
70 struct IMPL_THistoryItem
76 IMPL_THistoryItem( const OUString
& sNewURL
,
77 const OUString
& sNewFilter
,
78 const OUString
& sNewTitle
,
79 const OUString
& sNewPassword
)
82 sFilter
= sNewFilter
;
84 sPassword
= sNewPassword
;
87 sal_Bool
operator==( const OUString
& sSearchedURL
) const
89 return( sURL
== sSearchedURL
);
98 //*****************************************************************************************************************
99 // class SvtHistoryOptions_Impl
101 //*****************************************************************************************************************
102 class SvtHistoryOptions_Impl
105 SvtHistoryOptions_Impl();
106 ~SvtHistoryOptions_Impl();
108 sal_uInt32
GetSize( EHistoryType eHistory
);
109 void Clear( EHistoryType eHistory
);
110 Sequence
< Sequence
< PropertyValue
> > GetList( EHistoryType eHistory
);
111 void AppendItem( EHistoryType eHistory
,
112 const OUString
& sURL
,
113 const OUString
& sFilter
,
114 const OUString
& sTitle
,
115 const OUString
& sPassword
);
118 void impl_truncateList (EHistoryType eHistory
, sal_uInt32 nSize
);
121 css::uno::Reference
< css::container::XNameAccess
> m_xCfg
;
122 css::uno::Reference
< css::container::XNameAccess
> m_xCommonXCU
;
125 //*****************************************************************************************************************
127 //*****************************************************************************************************************
128 SvtHistoryOptions_Impl::SvtHistoryOptions_Impl()
132 m_xCfg
= Reference
< css::container::XNameAccess
> (
133 ::comphelper::ConfigurationHelper::openConfig(
134 ::comphelper::getProcessComponentContext(),
135 OUString(s_sHistories
),
136 ::comphelper::ConfigurationHelper::E_STANDARD
),
137 css::uno::UNO_QUERY
);
139 m_xCommonXCU
= Reference
< css::container::XNameAccess
> (
140 ::comphelper::ConfigurationHelper::openConfig(
141 ::comphelper::getProcessComponentContext(),
142 OUString(s_sCommonHistory
),
143 ::comphelper::ConfigurationHelper::E_STANDARD
),
144 css::uno::UNO_QUERY
);
146 catch(const css::uno::Exception
& ex
)
149 m_xCommonXCU
.clear();
151 SAL_WARN("unotools.config", "Caught unexpected: " << ex
.Message
);
155 //*****************************************************************************************************************
157 //*****************************************************************************************************************
158 SvtHistoryOptions_Impl::~SvtHistoryOptions_Impl()
162 //*****************************************************************************************************************
164 // Attention: We return the max. size of our internal lists - That is the capacity not the size!
165 //*****************************************************************************************************************
166 sal_uInt32
SvtHistoryOptions_Impl::GetSize( EHistoryType eHistory
)
168 css::uno::Reference
< css::beans::XPropertySet
> xListAccess(m_xCommonXCU
, css::uno::UNO_QUERY
);
170 if (!xListAccess
.is())
173 sal_uInt32 nSize
= 0 ;
180 xListAccess
->getPropertyValue(OUString(s_sPickListSize
)) >>= nSize
;
184 xListAccess
->getPropertyValue(OUString(s_sURLHistorySize
)) >>= nSize
;
188 xListAccess
->getPropertyValue(OUString(s_sHelpBookmarksSize
)) >>= nSize
;
195 catch(const css::uno::Exception
& ex
)
197 SAL_WARN("unotools.config", "Caught unexpected: " << ex
.Message
);
203 //*****************************************************************************************************************
204 void SvtHistoryOptions_Impl::impl_truncateList ( EHistoryType eHistory
, sal_uInt32 nSize
)
206 css::uno::Reference
< css::container::XNameAccess
> xList
;
207 css::uno::Reference
< css::container::XNameContainer
> xItemList
;
208 css::uno::Reference
< css::container::XNameContainer
> xOrderList
;
209 css::uno::Reference
< css::beans::XPropertySet
> xSet
;
216 m_xCfg
->getByName(OUString(s_sPickList
)) >>= xList
;
220 m_xCfg
->getByName(OUString(s_sURLHistory
)) >>= xList
;
224 m_xCfg
->getByName(OUString(s_sHelpBookmarks
)) >>= xList
;
231 // If too much items in current list ...
232 // truncate the oldest items BEFORE you set the new one.
236 xList
->getByName(OUString(s_sOrderList
)) >>= xOrderList
;
237 xList
->getByName(OUString(s_sItemList
)) >>= xItemList
;
239 const sal_uInt32 nLength
= xOrderList
->getElementNames().getLength();
242 for (sal_uInt32 i
=nLength
-1; i
>=nSize
; --i
)
245 const OUString sRemove
= OUString::valueOf((sal_Int32
)i
);
246 xOrderList
->getByName(sRemove
) >>= xSet
;
247 xSet
->getPropertyValue(OUString(s_sHistoryItemRef
)) >>= sTmp
;
248 xItemList
->removeByName(sTmp
);
249 xOrderList
->removeByName(sRemove
);
252 ::comphelper::ConfigurationHelper::flush(m_xCfg
);
255 catch(const css::uno::Exception
& ex
)
257 SAL_WARN("unotools.config", "Caught unexpected: " << ex
.Message
);
261 //*****************************************************************************************************************
263 // Clear specified history list
264 //*****************************************************************************************************************
265 void SvtHistoryOptions_Impl::Clear( EHistoryType eHistory
)
267 css::uno::Reference
< css::container::XNameAccess
> xListAccess
;
268 css::uno::Reference
< css::container::XNameContainer
> xNode
;
269 Sequence
< OUString
> lOrders
;
277 m_xCfg
->getByName(OUString(s_sPickList
)) >>= xListAccess
;
283 m_xCfg
->getByName(OUString(s_sURLHistory
)) >>= xListAccess
;
289 m_xCfg
->getByName(OUString(s_sHelpBookmarks
)) >>= xListAccess
;
297 if (xListAccess
.is())
300 xListAccess
->getByName(OUString(s_sItemList
)) >>= xNode
;
301 lOrders
= xNode
->getElementNames();
302 const sal_Int32 nLength
= lOrders
.getLength();
303 for(sal_Int32 i
=0; i
<nLength
; ++i
)
304 xNode
->removeByName(lOrders
[i
]);
307 xListAccess
->getByName(OUString(s_sOrderList
)) >>= xNode
;
308 lOrders
= xNode
->getElementNames();
309 for(sal_Int32 j
=0; j
<nLength
; ++j
)
310 xNode
->removeByName(lOrders
[j
]);
312 ::comphelper::ConfigurationHelper::flush(m_xCfg
);
315 catch(const css::uno::Exception
& ex
)
317 SAL_WARN("unotools.config", "Caught unexpected: " << ex
.Message
);
321 //*****************************************************************************************************************
323 // get a sequence list from the items
324 //*****************************************************************************************************************
325 Sequence
< Sequence
< PropertyValue
> > SvtHistoryOptions_Impl::GetList( EHistoryType eHistory
)
327 impl_truncateList (eHistory
, GetSize (eHistory
));
329 Sequence
< Sequence
< PropertyValue
> > seqReturn
; // Set default return value.
330 Sequence
< PropertyValue
> seqProperties( 4 );
331 Sequence
< OUString
> lOrders
;
333 css::uno::Reference
< css::container::XNameAccess
> xListAccess
;
334 css::uno::Reference
< css::container::XNameAccess
> xItemList
;
335 css::uno::Reference
< css::container::XNameAccess
> xOrderList
;
336 css::uno::Reference
< css::beans::XPropertySet
> xSet
;
338 seqProperties
[s_nOffsetURL
].Name
= HISTORY_PROPERTYNAME_URL
;
339 seqProperties
[s_nOffsetFilter
].Name
= HISTORY_PROPERTYNAME_FILTER
;
340 seqProperties
[s_nOffsetTitle
].Name
= HISTORY_PROPERTYNAME_TITLE
;
341 seqProperties
[s_nOffsetPassword
].Name
= HISTORY_PROPERTYNAME_PASSWORD
;
349 m_xCfg
->getByName(OUString(s_sPickList
)) >>= xListAccess
;
355 m_xCfg
->getByName(OUString(s_sURLHistory
)) >>= xListAccess
;
361 m_xCfg
->getByName(OUString(s_sHelpBookmarks
)) >>= xListAccess
;
369 if (xListAccess
.is())
371 xListAccess
->getByName(OUString(s_sItemList
)) >>= xItemList
;
372 xListAccess
->getByName(OUString(s_sOrderList
)) >>= xOrderList
;
374 const sal_Int32 nLength
= xOrderList
->getElementNames().getLength();
375 Sequence
< Sequence
< PropertyValue
> > aRet(nLength
);
376 sal_Int32 nCount
= 0;
378 for(sal_Int32 nItem
=0; nItem
<nLength
; ++nItem
)
383 xOrderList
->getByName(OUString::valueOf(nItem
)) >>= xSet
;
384 xSet
->getPropertyValue(OUString(s_sHistoryItemRef
)) >>= sUrl
;
386 xItemList
->getByName(sUrl
) >>= xSet
;
387 seqProperties
[s_nOffsetURL
].Value
<<= sUrl
;
388 xSet
->getPropertyValue(OUString(s_sFilter
)) >>= seqProperties
[s_nOffsetFilter
].Value
;
389 xSet
->getPropertyValue(OUString(s_sTitle
)) >>= seqProperties
[s_nOffsetTitle
].Value
;
390 xSet
->getPropertyValue(OUString(s_sPassword
)) >>= seqProperties
[s_nOffsetPassword
].Value
;
391 aRet
[nCount
++] = seqProperties
;
393 catch(const css::uno::Exception
& ex
)
395 // <https://bugs.freedesktop.org/show_bug.cgi?id=46074>
396 // "FILEOPEN: No Recent Documents..." discusses a problem
397 // with corrupted /org.openoffice.Office/Histories/Histories
398 // configuration items; to work around that problem, simply
399 // ignore such corrupted individual items here, so that at
400 // least newly added items are successfully reported back
401 // from this function:
402 SAL_WARN("unotools.config", "Caught unexpected: " << ex
.Message
);
405 assert(nCount
<= nLength
);
406 aRet
.realloc(nCount
);
410 catch(const css::uno::Exception
& ex
)
412 SAL_WARN("unotools.config", "Caught unexpected: " << ex
.Message
);
418 //*****************************************************************************************************************
420 // implements a deque in XML
421 //*****************************************************************************************************************
422 void SvtHistoryOptions_Impl::AppendItem( EHistoryType eHistory
,
423 const OUString
& sURL
,
424 const OUString
& sFilter
,
425 const OUString
& sTitle
,
426 const OUString
& sPassword
)
428 impl_truncateList (eHistory
, GetSize (eHistory
));
430 css::uno::Reference
< css::container::XNameAccess
> xListAccess
;
431 sal_Int32 nMaxSize
= 0;
437 m_xCfg
->getByName(OUString(s_sPickList
)) >>= xListAccess
;
438 nMaxSize
= GetSize(ePICKLIST
);
443 m_xCfg
->getByName(OUString(s_sURLHistory
)) >>= xListAccess
;
444 nMaxSize
= GetSize(eHISTORY
);
449 m_xCfg
->getByName(OUString(s_sHelpBookmarks
)) >>= xListAccess
;
450 nMaxSize
= GetSize(eHELPBOOKMARKS
);
460 css::uno::Reference
< css::container::XNameContainer
> xItemList
;
461 css::uno::Reference
< css::container::XNameContainer
> xOrderList
;
462 css::uno::Reference
< css::beans::XPropertySet
> xSet
;
466 xListAccess
->getByName(OUString(s_sItemList
)) >>= xItemList
;
467 xListAccess
->getByName(OUString(s_sOrderList
)) >>= xOrderList
;
468 sal_Int32 nLength
= xOrderList
->getElementNames().getLength();
470 OUString
sHistoryItemRef(s_sHistoryItemRef
);
471 // The item to be appended is already existing!
472 if (xItemList
->hasByName(sURL
))
474 for (sal_Int32 i
=0; i
<nLength
; ++i
)
477 xOrderList
->getByName(OUString::valueOf(i
)) >>= xSet
;
478 xSet
->getPropertyValue(sHistoryItemRef
) >>= sTmp
;
483 xOrderList
->getByName( OUString::valueOf(i
) ) >>= xSet
;
484 xSet
->getPropertyValue(sHistoryItemRef
) >>= sFind
;
485 for (sal_Int32 j
=i
-1; j
>=0; --j
)
487 css::uno::Reference
< css::beans::XPropertySet
> xPrevSet
;
488 css::uno::Reference
< css::beans::XPropertySet
> xNextSet
;
489 xOrderList
->getByName( OUString::valueOf(j
+1) ) >>= xPrevSet
;
490 xOrderList
->getByName( OUString::valueOf(j
) ) >>= xNextSet
;
493 xNextSet
->getPropertyValue(sHistoryItemRef
) >>= sTemp
;
494 xPrevSet
->setPropertyValue(sHistoryItemRef
, css::uno::makeAny(sTemp
));
496 xOrderList
->getByName( OUString::valueOf((sal_Int32
)0) ) >>= xSet
;
497 xSet
->setPropertyValue(sHistoryItemRef
, css::uno::makeAny(sFind
));
499 ::comphelper::ConfigurationHelper::flush(m_xCfg
);
505 // The item to be appended is not existing!
508 css::uno::Reference
< css::lang::XSingleServiceFactory
> xFac
;
509 css::uno::Reference
< css::uno::XInterface
> xInst
;
510 css::uno::Reference
< css::beans::XPropertySet
> xPrevSet
;
511 css::uno::Reference
< css::beans::XPropertySet
> xNextSet
;
513 // Append new item to OrderList.
514 if ( nLength
== nMaxSize
)
517 xOrderList
->getByName(OUString::valueOf(nLength
-1)) >>= xSet
;
518 xSet
->getPropertyValue(sHistoryItemRef
) >>= sRemove
;
521 xItemList
->removeByName(sRemove
);
523 catch (css::container::NoSuchElementException
&)
525 // <https://bugs.freedesktop.org/show_bug.cgi?id=46074>
526 // "FILEOPEN: No Recent Documents..." discusses a problem
527 // with corrupted /org.openoffice.Office/Histories/Histories
528 // configuration items; to work around that problem, simply
529 // ignore such corrupted individual items here, so that at
530 // least newly added items are successfully added:
531 if (!sRemove
.isEmpty())
537 if ( nLength
!= nMaxSize
)
539 xFac
= css::uno::Reference
< css::lang::XSingleServiceFactory
>(xOrderList
, css::uno::UNO_QUERY
);
540 xInst
= xFac
->createInstance();
541 OUString sPush
= OUString::valueOf(nLength
++);
542 xOrderList
->insertByName(sPush
, css::uno::makeAny(xInst
));
544 for (sal_Int32 j
=nLength
-1; j
>0; --j
)
546 xOrderList
->getByName( OUString::valueOf(j
) ) >>= xPrevSet
;
547 xOrderList
->getByName( OUString::valueOf(j
-1) ) >>= xNextSet
;
549 xNextSet
->getPropertyValue(sHistoryItemRef
) >>= sTemp
;
550 xPrevSet
->setPropertyValue(sHistoryItemRef
, css::uno::makeAny(sTemp
));
552 xOrderList
->getByName( OUString::valueOf((sal_Int32
)0) ) >>= xSet
;
553 xSet
->setPropertyValue(sHistoryItemRef
, css::uno::makeAny(sURL
));
555 // Append the item to ItemList.
556 xFac
= css::uno::Reference
< css::lang::XSingleServiceFactory
>(xItemList
, css::uno::UNO_QUERY
);
557 xInst
= xFac
->createInstance();
558 xItemList
->insertByName(sURL
, css::uno::makeAny(xInst
));
559 xSet
= css::uno::Reference
< css::beans::XPropertySet
>(xInst
, css::uno::UNO_QUERY
);
560 xSet
->setPropertyValue(OUString(s_sFilter
), css::uno::makeAny(sFilter
));
561 xSet
->setPropertyValue(OUString(s_sTitle
), css::uno::makeAny(sTitle
));
562 xSet
->setPropertyValue(OUString(s_sPassword
), css::uno::makeAny(sPassword
));
564 ::comphelper::ConfigurationHelper::flush(m_xCfg
);
567 catch(const css::uno::Exception
& ex
)
569 SAL_WARN("unotools.config", "Caught unexpected: " << ex
.Message
);
573 //*****************************************************************************************************************
574 // initialize static member
575 // DON'T DO IT IN YOUR HEADER!
576 // see definition for further information
577 //*****************************************************************************************************************
578 SvtHistoryOptions_Impl
* SvtHistoryOptions::m_pDataContainer
= NULL
;
579 sal_Int32
SvtHistoryOptions::m_nRefCount
= 0 ;
581 //*****************************************************************************************************************
583 //*****************************************************************************************************************
584 SvtHistoryOptions::SvtHistoryOptions()
586 // Global access, must be guarded (multithreading!).
587 MutexGuard
aGuard( GetOwnStaticMutex() );
588 // Increase ouer refcount ...
590 // ... and initialize ouer data container only if it not already exist!
591 if( m_pDataContainer
== NULL
)
593 RTL_LOGFILE_CONTEXT(aLog
, "unotools ( ??? ) ::SvtHistoryOptions_Impl::ctor()");
594 m_pDataContainer
= new SvtHistoryOptions_Impl
;
596 ItemHolder1::holdConfigItem(E_HISTORYOPTIONS
);
600 //*****************************************************************************************************************
602 //*****************************************************************************************************************
603 SvtHistoryOptions::~SvtHistoryOptions()
605 // Global access, must be guarded (multithreading!)
606 MutexGuard
aGuard( GetOwnStaticMutex() );
607 // Decrease ouer refcount.
609 // If last instance was deleted ...
610 // we must destroy ouer static data container!
611 if( m_nRefCount
<= 0 )
613 delete m_pDataContainer
;
614 m_pDataContainer
= NULL
;
618 //*****************************************************************************************************************
620 //*****************************************************************************************************************
621 sal_uInt32
SvtHistoryOptions::GetSize( EHistoryType eHistory
) const
623 MutexGuard
aGuard( GetOwnStaticMutex() );
624 return m_pDataContainer
->GetSize( eHistory
);
627 //*****************************************************************************************************************
629 //*****************************************************************************************************************
630 void SvtHistoryOptions::Clear( EHistoryType eHistory
)
632 MutexGuard
aGuard( GetOwnStaticMutex() );
633 m_pDataContainer
->Clear( eHistory
);
636 //*****************************************************************************************************************
638 //*****************************************************************************************************************
639 Sequence
< Sequence
< PropertyValue
> > SvtHistoryOptions::GetList( EHistoryType eHistory
) const
641 MutexGuard
aGuard( GetOwnStaticMutex() );
642 return m_pDataContainer
->GetList( eHistory
);
645 //*****************************************************************************************************************
647 //*****************************************************************************************************************
648 void SvtHistoryOptions::AppendItem( EHistoryType eHistory
,
649 const OUString
& sURL
,
650 const OUString
& sFilter
,
651 const OUString
& sTitle
,
652 const OUString
& sPassword
)
654 MutexGuard
aGuard( GetOwnStaticMutex() );
655 m_pDataContainer
->AppendItem( eHistory
, sURL
, sFilter
, sTitle
, sPassword
);
660 class theHistoryOptionsMutex
: public rtl::Static
<osl::Mutex
, theHistoryOptionsMutex
>{};
663 //*****************************************************************************************************************
665 //*****************************************************************************************************************
666 Mutex
& SvtHistoryOptions::GetOwnStaticMutex()
668 return theHistoryOptionsMutex::get();
671 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */