Version 4.0.0.1, tag libreoffice-4.0.0.1
[LibreOffice.git] / unotools / source / config / historyoptions.cxx
blobaed1f4ba13c86bb40c8c2471c0b65456f4dab0c4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
27 #include <cassert>
28 #include <deque>
29 #include <algorithm>
31 #include <rtl/logfile.hxx>
32 #include "itemholder1.hxx"
34 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/container/XNameAccess.hpp>
38 #include <com/sun/star/container/XNameContainer.hpp>
40 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
42 #include <comphelper/configurationhelper.hxx>
44 #include <comphelper/processfactory.hxx>
46 using namespace ::std ;
47 using namespace ::utl ;
48 using namespace ::rtl ;
49 using namespace ::osl ;
50 using namespace ::com::sun::star::uno ;
51 using namespace ::com::sun::star::beans ;
53 namespace {
54 static const ::sal_Int32 s_nOffsetURL = 0;
55 static const ::sal_Int32 s_nOffsetFilter = 1;
56 static const ::sal_Int32 s_nOffsetTitle = 2;
57 static const ::sal_Int32 s_nOffsetPassword = 3;
59 const char s_sCommonHistory[] = "org.openoffice.Office.Common/History";
60 const char s_sHistories[] = "org.openoffice.Office.Histories/Histories";
61 const char s_sPickListSize[] = "PickListSize";
62 const char s_sURLHistorySize[] = "Size";
63 const char s_sHelpBookmarksSize[] = "HelpBookmarkSize";
64 const char s_sPickList[] = "PickList";
65 const char s_sURLHistory[] = "URLHistory";
66 const char s_sHelpBookmarks[] = "HelpBookmarks";
67 const char s_sItemList[] = "ItemList";
68 const char s_sOrderList[] = "OrderList";
69 const char s_sHistoryItemRef[] = "HistoryItemRef";
70 const char s_sFilter[] = "Filter";
71 const char s_sTitle[] = "Title";
72 const char s_sPassword[] = "Password";
75 struct IMPL_THistoryItem
77 IMPL_THistoryItem()
81 IMPL_THistoryItem( const OUString& sNewURL ,
82 const OUString& sNewFilter ,
83 const OUString& sNewTitle ,
84 const OUString& sNewPassword )
86 sURL = sNewURL ;
87 sFilter = sNewFilter ;
88 sTitle = sNewTitle ;
89 sPassword = sNewPassword ;
92 sal_Bool operator==( const OUString& sSearchedURL ) const
94 return( sURL == sSearchedURL );
97 OUString sURL ;
98 OUString sFilter ;
99 OUString sTitle ;
100 OUString sPassword ;
103 //*****************************************************************************************************************
104 // class SvtHistoryOptions_Impl
105 // redesigned
106 //*****************************************************************************************************************
107 class SvtHistoryOptions_Impl
109 public:
110 SvtHistoryOptions_Impl();
111 ~SvtHistoryOptions_Impl();
113 sal_uInt32 GetSize( EHistoryType eHistory );
114 void Clear( EHistoryType eHistory );
115 Sequence< Sequence< PropertyValue > > GetList( EHistoryType eHistory );
116 void AppendItem( EHistoryType eHistory ,
117 const OUString& sURL ,
118 const OUString& sFilter ,
119 const OUString& sTitle ,
120 const OUString& sPassword );
122 private:
123 void impl_truncateList (EHistoryType eHistory, sal_uInt32 nSize);
125 private:
126 css::uno::Reference< css::container::XNameAccess > m_xCfg;
127 css::uno::Reference< css::container::XNameAccess > m_xCommonXCU;
130 //*****************************************************************************************************************
131 // constructor
132 //*****************************************************************************************************************
133 SvtHistoryOptions_Impl::SvtHistoryOptions_Impl()
137 m_xCfg = Reference< css::container::XNameAccess > (
138 ::comphelper::ConfigurationHelper::openConfig(
139 ::comphelper::getProcessComponentContext(),
140 rtl::OUString(s_sHistories),
141 ::comphelper::ConfigurationHelper::E_STANDARD),
142 css::uno::UNO_QUERY );
144 m_xCommonXCU = Reference< css::container::XNameAccess > (
145 ::comphelper::ConfigurationHelper::openConfig(
146 ::comphelper::getProcessComponentContext(),
147 rtl::OUString(s_sCommonHistory),
148 ::comphelper::ConfigurationHelper::E_STANDARD),
149 css::uno::UNO_QUERY );
151 catch(const css::uno::Exception& ex)
153 m_xCfg.clear();
154 m_xCommonXCU.clear();
156 SAL_WARN("unotools", "Caught unexpected: " << ex.Message);
160 //*****************************************************************************************************************
161 // destructor
162 //*****************************************************************************************************************
163 SvtHistoryOptions_Impl::~SvtHistoryOptions_Impl()
167 //*****************************************************************************************************************
168 // public method
169 // Attention: We return the max. size of our internal lists - That is the capacity not the size!
170 //*****************************************************************************************************************
171 sal_uInt32 SvtHistoryOptions_Impl::GetSize( EHistoryType eHistory )
173 css::uno::Reference< css::beans::XPropertySet > xListAccess(m_xCommonXCU, css::uno::UNO_QUERY);
175 if (!xListAccess.is())
176 return 0;
178 sal_uInt32 nSize = 0 ;
182 switch( eHistory )
184 case ePICKLIST:
185 xListAccess->getPropertyValue(rtl::OUString(s_sPickListSize)) >>= nSize;
186 break;
188 case eHISTORY:
189 xListAccess->getPropertyValue(rtl::OUString(s_sURLHistorySize)) >>= nSize;
190 break;
192 case eHELPBOOKMARKS:
193 xListAccess->getPropertyValue(rtl::OUString(s_sHelpBookmarksSize)) >>= nSize;
194 break;
196 default:
197 break;
200 catch(const css::uno::Exception& ex)
202 SAL_WARN("unotools", "Caught unexpected: " << ex.Message);
205 return nSize;
208 //*****************************************************************************************************************
209 void SvtHistoryOptions_Impl::impl_truncateList ( EHistoryType eHistory, sal_uInt32 nSize )
211 css::uno::Reference< css::container::XNameAccess > xList;
212 css::uno::Reference< css::container::XNameContainer > xItemList;
213 css::uno::Reference< css::container::XNameContainer > xOrderList;
214 css::uno::Reference< css::beans::XPropertySet > xSet;
218 switch( eHistory )
220 case ePICKLIST:
221 m_xCfg->getByName(rtl::OUString(s_sPickList)) >>= xList;
222 break;
224 case eHISTORY:
225 m_xCfg->getByName(rtl::OUString(s_sURLHistory)) >>= xList;
226 break;
228 case eHELPBOOKMARKS:
229 m_xCfg->getByName(rtl::OUString(s_sHelpBookmarks)) >>= xList;
230 break;
232 default:
233 break;
236 // If too much items in current list ...
237 // truncate the oldest items BEFORE you set the new one.
238 if ( ! xList.is())
239 return;
241 xList->getByName(rtl::OUString(s_sOrderList)) >>= xOrderList;
242 xList->getByName(rtl::OUString(s_sItemList)) >>= xItemList;
244 const sal_uInt32 nLength = xOrderList->getElementNames().getLength();
245 if (nSize < nLength)
247 for (sal_uInt32 i=nLength-1; i>=nSize; --i)
249 ::rtl::OUString sTmp;
250 const ::rtl::OUString sRemove = ::rtl::OUString::valueOf((sal_Int32)i);
251 xOrderList->getByName(sRemove) >>= xSet;
252 xSet->getPropertyValue(rtl::OUString(s_sHistoryItemRef)) >>= sTmp;
253 xItemList->removeByName(sTmp);
254 xOrderList->removeByName(sRemove);
257 ::comphelper::ConfigurationHelper::flush(m_xCfg);
260 catch(const css::uno::Exception& ex)
262 SAL_WARN("unotools", "Caught unexpected: " << ex.Message);
266 //*****************************************************************************************************************
267 // public method
268 // Clear specified history list
269 //*****************************************************************************************************************
270 void SvtHistoryOptions_Impl::Clear( EHistoryType eHistory )
272 css::uno::Reference< css::container::XNameAccess > xListAccess;
273 css::uno::Reference< css::container::XNameContainer > xNode;
274 Sequence< ::rtl::OUString > lOrders;
278 switch( eHistory )
280 case ePICKLIST:
282 m_xCfg->getByName(rtl::OUString(s_sPickList)) >>= xListAccess;
283 break;
286 case eHISTORY:
288 m_xCfg->getByName(rtl::OUString(s_sURLHistory)) >>= xListAccess;
289 break;
292 case eHELPBOOKMARKS:
294 m_xCfg->getByName(rtl::OUString(s_sHelpBookmarks)) >>= xListAccess;
295 break;
298 default:
299 break;
302 if (xListAccess.is())
304 // clear ItemList
305 xListAccess->getByName(rtl::OUString(s_sItemList)) >>= xNode ;
306 lOrders = xNode->getElementNames();
307 const sal_Int32 nLength = lOrders.getLength();
308 for(sal_Int32 i=0; i<nLength; ++i)
309 xNode->removeByName(lOrders[i]);
311 // clear OrderList
312 xListAccess->getByName(rtl::OUString(s_sOrderList)) >>= xNode ;
313 lOrders = xNode->getElementNames();
314 for(sal_Int32 j=0; j<nLength; ++j)
315 xNode->removeByName(lOrders[j]);
317 ::comphelper::ConfigurationHelper::flush(m_xCfg);
320 catch(const css::uno::Exception& ex)
322 SAL_WARN("unotools", "Caught unexpected: " << ex.Message);
326 //*****************************************************************************************************************
327 // public method
328 // get a sequence list from the items
329 //*****************************************************************************************************************
330 Sequence< Sequence< PropertyValue > > SvtHistoryOptions_Impl::GetList( EHistoryType eHistory )
332 impl_truncateList (eHistory, GetSize (eHistory));
334 Sequence< Sequence< PropertyValue > > seqReturn; // Set default return value.
335 Sequence< PropertyValue > seqProperties( 4 );
336 Sequence< ::rtl::OUString > lOrders;
338 css::uno::Reference< css::container::XNameAccess > xListAccess;
339 css::uno::Reference< css::container::XNameAccess > xItemList;
340 css::uno::Reference< css::container::XNameAccess > xOrderList;
341 css::uno::Reference< css::beans::XPropertySet > xSet;
343 seqProperties[s_nOffsetURL ].Name = HISTORY_PROPERTYNAME_URL;
344 seqProperties[s_nOffsetFilter ].Name = HISTORY_PROPERTYNAME_FILTER;
345 seqProperties[s_nOffsetTitle ].Name = HISTORY_PROPERTYNAME_TITLE;
346 seqProperties[s_nOffsetPassword ].Name = HISTORY_PROPERTYNAME_PASSWORD;
350 switch( eHistory )
352 case ePICKLIST:
354 m_xCfg->getByName(rtl::OUString(s_sPickList)) >>= xListAccess;
355 break;
358 case eHISTORY:
360 m_xCfg->getByName(rtl::OUString(s_sURLHistory)) >>= xListAccess;
361 break;
364 case eHELPBOOKMARKS:
366 m_xCfg->getByName(rtl::OUString(s_sHelpBookmarks)) >>= xListAccess;
367 break;
370 default:
371 break;
374 if (xListAccess.is())
376 xListAccess->getByName(rtl::OUString(s_sItemList)) >>= xItemList;
377 xListAccess->getByName(rtl::OUString(s_sOrderList)) >>= xOrderList;
379 const sal_Int32 nLength = xOrderList->getElementNames().getLength();
380 Sequence< Sequence< PropertyValue > > aRet(nLength);
381 sal_Int32 nCount = 0;
383 for(sal_Int32 nItem=0; nItem<nLength; ++nItem)
387 ::rtl::OUString sUrl;
388 xOrderList->getByName(::rtl::OUString::valueOf(nItem)) >>= xSet;
389 xSet->getPropertyValue(rtl::OUString(s_sHistoryItemRef)) >>= sUrl;
391 xItemList->getByName(sUrl) >>= xSet;
392 seqProperties[s_nOffsetURL ].Value <<= sUrl;
393 xSet->getPropertyValue(rtl::OUString(s_sFilter)) >>= seqProperties[s_nOffsetFilter ].Value;
394 xSet->getPropertyValue(rtl::OUString(s_sTitle)) >>= seqProperties[s_nOffsetTitle ].Value;
395 xSet->getPropertyValue(rtl::OUString(s_sPassword)) >>= seqProperties[s_nOffsetPassword ].Value;
396 aRet[nCount++] = seqProperties;
398 catch(const css::uno::Exception& ex)
400 // <https://bugs.freedesktop.org/show_bug.cgi?id=46074>
401 // "FILEOPEN: No Recent Documents..." discusses a problem
402 // with corrupted /org.openoffice.Office/Histories/Histories
403 // configuration items; to work around that problem, simply
404 // ignore such corrupted individual items here, so that at
405 // least newly added items are successfully reported back
406 // from this function:
407 SAL_WARN("unotools", "Caught unexpected: " << ex.Message);
410 assert(nCount <= nLength);
411 aRet.realloc(nCount);
412 seqReturn = aRet;
415 catch(const css::uno::Exception& ex)
417 SAL_WARN("unotools", "Caught unexpected: " << ex.Message);
420 return seqReturn;
423 //*****************************************************************************************************************
424 // public method
425 // implements a deque in XML
426 //*****************************************************************************************************************
427 void SvtHistoryOptions_Impl::AppendItem( EHistoryType eHistory ,
428 const OUString& sURL ,
429 const OUString& sFilter ,
430 const OUString& sTitle ,
431 const OUString& sPassword )
433 impl_truncateList (eHistory, GetSize (eHistory));
435 css::uno::Reference< css::container::XNameAccess > xListAccess;
436 sal_Int32 nMaxSize = 0;
438 switch(eHistory)
440 case ePICKLIST:
442 m_xCfg->getByName(rtl::OUString(s_sPickList)) >>= xListAccess;
443 nMaxSize = GetSize(ePICKLIST);
445 break;
446 case eHISTORY:
448 m_xCfg->getByName(rtl::OUString(s_sURLHistory)) >>= xListAccess;
449 nMaxSize = GetSize(eHISTORY);
451 break;
452 case eHELPBOOKMARKS:
454 m_xCfg->getByName(rtl::OUString(s_sHelpBookmarks)) >>= xListAccess;
455 nMaxSize = GetSize(eHELPBOOKMARKS);
457 break;
458 default:
459 break;
462 if (nMaxSize==0)
463 return;
465 css::uno::Reference< css::container::XNameContainer > xItemList;
466 css::uno::Reference< css::container::XNameContainer > xOrderList;
467 css::uno::Reference< css::beans::XPropertySet > xSet;
471 xListAccess->getByName(rtl::OUString(s_sItemList)) >>= xItemList;
472 xListAccess->getByName(rtl::OUString(s_sOrderList)) >>= xOrderList;
473 sal_Int32 nLength = xOrderList->getElementNames().getLength();
475 rtl::OUString sHistoryItemRef(s_sHistoryItemRef);
476 // The item to be appended is already existing!
477 if (xItemList->hasByName(sURL))
479 for (sal_Int32 i=0; i<nLength; ++i)
481 ::rtl::OUString sTmp;
482 xOrderList->getByName(::rtl::OUString::valueOf(i)) >>= xSet;
483 xSet->getPropertyValue(sHistoryItemRef) >>= sTmp;
485 if(sURL == sTmp)
487 ::rtl::OUString sFind;
488 xOrderList->getByName( ::rtl::OUString::valueOf(i) ) >>= xSet;
489 xSet->getPropertyValue(sHistoryItemRef) >>= sFind;
490 for (sal_Int32 j=i-1; j>=0; --j)
492 css::uno::Reference< css::beans::XPropertySet > xPrevSet;
493 css::uno::Reference< css::beans::XPropertySet > xNextSet;
494 xOrderList->getByName( ::rtl::OUString::valueOf(j+1) ) >>= xPrevSet;
495 xOrderList->getByName( ::rtl::OUString::valueOf(j) ) >>= xNextSet;
497 ::rtl::OUString sTemp;
498 xNextSet->getPropertyValue(sHistoryItemRef) >>= sTemp;
499 xPrevSet->setPropertyValue(sHistoryItemRef, css::uno::makeAny(sTemp));
501 xOrderList->getByName( ::rtl::OUString::valueOf((sal_Int32)0) ) >>= xSet;
502 xSet->setPropertyValue(sHistoryItemRef, css::uno::makeAny(sFind));
504 ::comphelper::ConfigurationHelper::flush(m_xCfg);
505 break;
510 // The item to be appended is not existing!
511 else
513 css::uno::Reference< css::lang::XSingleServiceFactory > xFac;
514 css::uno::Reference< css::uno::XInterface > xInst;
515 css::uno::Reference< css::beans::XPropertySet > xPrevSet;
516 css::uno::Reference< css::beans::XPropertySet > xNextSet;
518 // Append new item to OrderList.
519 if ( nLength == nMaxSize )
521 ::rtl::OUString sRemove;
522 xOrderList->getByName(::rtl::OUString::valueOf(nLength-1)) >>= xSet;
523 xSet->getPropertyValue(sHistoryItemRef) >>= sRemove;
526 xItemList->removeByName(sRemove);
528 catch (css::container::NoSuchElementException &)
530 // <https://bugs.freedesktop.org/show_bug.cgi?id=46074>
531 // "FILEOPEN: No Recent Documents..." discusses a problem
532 // with corrupted /org.openoffice.Office/Histories/Histories
533 // configuration items; to work around that problem, simply
534 // ignore such corrupted individual items here, so that at
535 // least newly added items are successfully added:
536 if (!sRemove.isEmpty())
538 throw;
542 if ( nLength != nMaxSize )
544 xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xOrderList, css::uno::UNO_QUERY);
545 xInst = xFac->createInstance();
546 ::rtl::OUString sPush = ::rtl::OUString::valueOf(nLength++);
547 xOrderList->insertByName(sPush, css::uno::makeAny(xInst));
549 for (sal_Int32 j=nLength-1; j>0; --j)
551 xOrderList->getByName( ::rtl::OUString::valueOf(j) ) >>= xPrevSet;
552 xOrderList->getByName( ::rtl::OUString::valueOf(j-1) ) >>= xNextSet;
553 ::rtl::OUString sTemp;
554 xNextSet->getPropertyValue(sHistoryItemRef) >>= sTemp;
555 xPrevSet->setPropertyValue(sHistoryItemRef, css::uno::makeAny(sTemp));
557 xOrderList->getByName( ::rtl::OUString::valueOf((sal_Int32)0) ) >>= xSet;
558 xSet->setPropertyValue(sHistoryItemRef, css::uno::makeAny(sURL));
560 // Append the item to ItemList.
561 xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xItemList, css::uno::UNO_QUERY);
562 xInst = xFac->createInstance();
563 xItemList->insertByName(sURL, css::uno::makeAny(xInst));
564 xSet = css::uno::Reference< css::beans::XPropertySet >(xInst, css::uno::UNO_QUERY);
565 xSet->setPropertyValue(rtl::OUString(s_sFilter), css::uno::makeAny(sFilter));
566 xSet->setPropertyValue(rtl::OUString(s_sTitle), css::uno::makeAny(sTitle));
567 xSet->setPropertyValue(rtl::OUString(s_sPassword), css::uno::makeAny(sPassword));
569 ::comphelper::ConfigurationHelper::flush(m_xCfg);
572 catch(const css::uno::Exception& ex)
574 SAL_WARN("unotools", "Caught unexpected: " << ex.Message);
578 //*****************************************************************************************************************
579 // initialize static member
580 // DON'T DO IT IN YOUR HEADER!
581 // see definition for further informations
582 //*****************************************************************************************************************
583 SvtHistoryOptions_Impl* SvtHistoryOptions::m_pDataContainer = NULL ;
584 sal_Int32 SvtHistoryOptions::m_nRefCount = 0 ;
586 //*****************************************************************************************************************
587 // constructor
588 //*****************************************************************************************************************
589 SvtHistoryOptions::SvtHistoryOptions()
591 // Global access, must be guarded (multithreading!).
592 MutexGuard aGuard( GetOwnStaticMutex() );
593 // Increase ouer refcount ...
594 ++m_nRefCount;
595 // ... and initialize ouer data container only if it not already exist!
596 if( m_pDataContainer == NULL )
598 RTL_LOGFILE_CONTEXT(aLog, "unotools ( ??? ) ::SvtHistoryOptions_Impl::ctor()");
599 m_pDataContainer = new SvtHistoryOptions_Impl;
601 ItemHolder1::holdConfigItem(E_HISTORYOPTIONS);
605 //*****************************************************************************************************************
606 // destructor
607 //*****************************************************************************************************************
608 SvtHistoryOptions::~SvtHistoryOptions()
610 // Global access, must be guarded (multithreading!)
611 MutexGuard aGuard( GetOwnStaticMutex() );
612 // Decrease ouer refcount.
613 --m_nRefCount;
614 // If last instance was deleted ...
615 // we must destroy ouer static data container!
616 if( m_nRefCount <= 0 )
618 delete m_pDataContainer;
619 m_pDataContainer = NULL;
623 //*****************************************************************************************************************
624 // public method
625 //*****************************************************************************************************************
626 sal_uInt32 SvtHistoryOptions::GetSize( EHistoryType eHistory ) const
628 MutexGuard aGuard( GetOwnStaticMutex() );
629 return m_pDataContainer->GetSize( eHistory );
632 //*****************************************************************************************************************
633 // public method
634 //*****************************************************************************************************************
635 void SvtHistoryOptions::Clear( EHistoryType eHistory )
637 MutexGuard aGuard( GetOwnStaticMutex() );
638 m_pDataContainer->Clear( eHistory );
641 //*****************************************************************************************************************
642 // public method
643 //*****************************************************************************************************************
644 Sequence< Sequence< PropertyValue > > SvtHistoryOptions::GetList( EHistoryType eHistory ) const
646 MutexGuard aGuard( GetOwnStaticMutex() );
647 return m_pDataContainer->GetList( eHistory );
650 //*****************************************************************************************************************
651 // public method
652 //*****************************************************************************************************************
653 void SvtHistoryOptions::AppendItem( EHistoryType eHistory ,
654 const OUString& sURL ,
655 const OUString& sFilter ,
656 const OUString& sTitle ,
657 const OUString& sPassword )
659 MutexGuard aGuard( GetOwnStaticMutex() );
660 m_pDataContainer->AppendItem( eHistory, sURL, sFilter, sTitle, sPassword );
663 namespace
665 class theHistoryOptionsMutex : public rtl::Static<osl::Mutex, theHistoryOptionsMutex>{};
668 //*****************************************************************************************************************
669 // private method
670 //*****************************************************************************************************************
671 Mutex& SvtHistoryOptions::GetOwnStaticMutex()
673 return theHistoryOptionsMutex::get();
676 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */