1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_unotools.hxx"
30 
31 #include <unotools/optionsdlg.hxx>
32 #include <unotools/configmgr.hxx>
33 #include <unotools/configitem.hxx>
34 #include <tools/debug.hxx>
35 #include <com/sun/star/uno/Any.hxx>
36 #include <com/sun/star/uno/Sequence.hxx>
37 #include <osl/mutex.hxx>
38 #include <comphelper/stl_types.hxx>
39 
40 #include <hash_map>
41 #include "itemholder1.hxx"
42 
43 using namespace utl;
44 using namespace rtl;
45 using namespace com::sun::star::beans ;
46 using namespace com::sun::star::uno;
47 
48 #define CFG_FILENAME            OUString( RTL_CONSTASCII_USTRINGPARAM( "Office.OptionsDialog" ) )
49 #define ROOT_NODE               OUString( RTL_CONSTASCII_USTRINGPARAM( "OptionsDialogGroups" ) )
50 #define PAGES_NODE              OUString( RTL_CONSTASCII_USTRINGPARAM( "Pages" ) )
51 #define OPTIONS_NODE            OUString( RTL_CONSTASCII_USTRINGPARAM( "Options" ) )
52 #define PROPERTY_HIDE           OUString( RTL_CONSTASCII_USTRINGPARAM( "Hide" ) )
53 
54 static SvtOptionsDlgOptions_Impl*   pOptions = NULL;
55 static sal_Int32                    nRefCount = 0;
56 
57 class SvtOptionsDlgOptions_Impl : public utl::ConfigItem
58 {
59 private:
60     struct OUStringHashCode
61     {
62         size_t operator()( const ::rtl::OUString& sString ) const
63         {
64             return sString.hashCode();
65         }
66     };
67 
68     typedef std::hash_map< OUString, sal_Bool, OUStringHashCode, ::std::equal_to< OUString > > OptionNodeList;
69 
70     OUString        m_sPathDelimiter;
71     OptionNodeList  m_aOptionNodeList;
72 
73     enum NodeType{ NT_Group, NT_Page, NT_Option };
74     void            ReadNode( const OUString& _rNode, NodeType _eType );
75     sal_Bool        IsHidden( const OUString& _rPath ) const;
76 
77 public:
78                     SvtOptionsDlgOptions_Impl();
79 
80     virtual void    Notify( const com::sun::star::uno::Sequence< rtl::OUString >& aPropertyNames );
81     virtual void    Commit();
82 
83     static ::osl::Mutex & getInitMutex();
84 
85     sal_Bool        IsGroupHidden   (   const OUString& _rGroup ) const;
86     sal_Bool        IsPageHidden    (   const OUString& _rPage,
87                                         const OUString& _rGroup ) const;
88     sal_Bool        IsOptionHidden  (   const OUString& _rOption,
89                                         const OUString& _rPage,
90                                         const OUString& _rGroup ) const;
91 };
92 
93 ::osl::Mutex & SvtOptionsDlgOptions_Impl::getInitMutex()
94 {
95     static ::osl::Mutex *pMutex = 0;
96 
97     if( ! pMutex )
98     {
99         ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
100         if( ! pMutex )
101         {
102             static ::osl::Mutex mutex;
103             pMutex = &mutex;
104         }
105     }
106     return *pMutex;
107 }
108 
109 // -----------------------------------------------------------------------
110 
111 SvtOptionsDlgOptions_Impl::SvtOptionsDlgOptions_Impl()
112     : ConfigItem( OUString( CFG_FILENAME ) ),
113 
114     m_sPathDelimiter( RTL_CONSTASCII_USTRINGPARAM( "/" ) ),
115     m_aOptionNodeList( OptionNodeList() )
116 
117 {
118     OUString sRootNode( ROOT_NODE );
119     Sequence< OUString > aNodeSeq = GetNodeNames( sRootNode );
120     OUString sNode( sRootNode + m_sPathDelimiter );
121     sal_uInt32 nCount = aNodeSeq.getLength();
122     for ( sal_uInt32 n = 0; n < nCount; n++ )
123     {
124         OUString sSubNode( sNode + aNodeSeq[n] );
125         ReadNode( sSubNode, NT_Group );
126     }
127 }
128 
129 // -----------------------------------------------------------------------
130 
131 void SvtOptionsDlgOptions_Impl::Commit()
132 {
133     // nothing to commit
134 }
135 
136 // -----------------------------------------------------------------------
137 
138 void SvtOptionsDlgOptions_Impl::Notify( const Sequence< rtl::OUString >& )
139 {
140     // nothing to notify
141 }
142 
143 void SvtOptionsDlgOptions_Impl::ReadNode( const OUString& _rNode, NodeType _eType )
144 {
145     OUString sNode( _rNode + m_sPathDelimiter );
146     OUString sSet;
147     sal_Int32 nLen = 0;
148     switch ( _eType )
149     {
150         case NT_Group :
151         {
152             sSet = PAGES_NODE;
153             nLen = 2;
154             break;
155         }
156 
157         case NT_Page :
158         {
159             sSet = OPTIONS_NODE;
160             nLen = 2;
161             break;
162         }
163 
164         case NT_Option :
165         {
166             nLen = 1;
167             break;
168         }
169     }
170 
171     Sequence< OUString > lResult( nLen );
172     lResult[0] = OUString( sNode + PROPERTY_HIDE );
173     if ( _eType != NT_Option )
174         lResult[1] = OUString( sNode + sSet );
175 
176     Sequence< Any > aValues;
177     aValues = GetProperties( lResult );
178     sal_Bool bHide = sal_False;
179     if ( aValues[0] >>= bHide )
180         m_aOptionNodeList.insert( OptionNodeList::value_type( sNode, bHide ) );
181 
182     if ( _eType != NT_Option )
183     {
184         OUString sNodes( sNode + sSet );
185         Sequence< OUString > aNodes = GetNodeNames( sNodes );
186         if ( aNodes.getLength() > 0 )
187         {
188             for ( sal_uInt32 n = 0; n < (sal_uInt32)aNodes.getLength(); ++n )
189             {
190                 OUString sSubNodeName( sNodes + m_sPathDelimiter + aNodes[n] );
191                 ReadNode( sSubNodeName, _eType == NT_Group ? NT_Page : NT_Option );
192             }
193         }
194     }
195 }
196 
197 // -----------------------------------------------------------------------
198 
199 OUString getGroupPath( const OUString& _rGroup )
200 {
201     return OUString( ROOT_NODE + OUString('/') + _rGroup + OUString('/') );
202 }
203 OUString getPagePath( const OUString& _rPage )
204 {
205     return OUString( PAGES_NODE + OUString('/') + _rPage + OUString('/') );
206 }
207 OUString getOptionPath( const OUString& _rOption )
208 {
209     return OUString( OPTIONS_NODE + OUString('/') + _rOption + OUString('/') );
210 }
211 
212 // -----------------------------------------------------------------------
213 
214 sal_Bool SvtOptionsDlgOptions_Impl::IsHidden( const OUString& _rPath ) const
215 {
216     sal_Bool bRet = sal_False;
217     OptionNodeList::const_iterator pIter = m_aOptionNodeList.find( _rPath );
218     if ( pIter != m_aOptionNodeList.end() )
219         bRet = pIter->second;
220     return bRet;
221 }
222 
223 // -----------------------------------------------------------------------
224 
225 sal_Bool SvtOptionsDlgOptions_Impl::IsGroupHidden( const OUString& _rGroup ) const
226 {
227     return IsHidden( getGroupPath( _rGroup ) );
228 }
229 
230 // -----------------------------------------------------------------------
231 
232 sal_Bool SvtOptionsDlgOptions_Impl::IsPageHidden( const OUString& _rPage, const OUString& _rGroup ) const
233 {
234     return IsHidden( getGroupPath( _rGroup  ) + getPagePath( _rPage ) );
235 }
236 
237 // -----------------------------------------------------------------------
238 
239 sal_Bool SvtOptionsDlgOptions_Impl::IsOptionHidden(
240     const OUString& _rOption, const OUString& _rPage, const OUString& _rGroup ) const
241 {
242     return IsHidden( getGroupPath( _rGroup  ) + getPagePath( _rPage ) + getOptionPath( _rOption ) );
243 }
244 
245 // -----------------------------------------------------------------------
246 
247 SvtOptionsDialogOptions::SvtOptionsDialogOptions()
248 {
249     // Global access, must be guarded (multithreading)
250     ::osl::MutexGuard aGuard( SvtOptionsDlgOptions_Impl::getInitMutex() );
251     ++nRefCount;
252     if ( !pOptions )
253     {
254         pOptions = new SvtOptionsDlgOptions_Impl;
255 
256         ItemHolder1::holdConfigItem( E_OPTIONSDLGOPTIONS );
257     }
258     m_pImp = pOptions;
259 }
260 
261 // -----------------------------------------------------------------------
262 
263 SvtOptionsDialogOptions::~SvtOptionsDialogOptions()
264 {
265     // Global access, must be guarded (multithreading)
266     ::osl::MutexGuard aGuard( SvtOptionsDlgOptions_Impl::getInitMutex() );
267     if ( !--nRefCount )
268 	{
269 		if ( pOptions->IsModified() )
270 			pOptions->Commit();
271         DELETEZ( pOptions );
272 	}
273 }
274 
275 sal_Bool SvtOptionsDialogOptions::IsGroupHidden( const String& _rGroup ) const
276 {
277     return m_pImp->IsGroupHidden( _rGroup );
278 }
279 
280 sal_Bool SvtOptionsDialogOptions::IsPageHidden( const String& _rPage, const String& _rGroup ) const
281 {
282     return m_pImp->IsPageHidden( _rPage, _rGroup );
283 }
284 
285 sal_Bool SvtOptionsDialogOptions::IsOptionHidden(
286     const String& _rOption, const String& _rPage, const String& _rGroup ) const
287 {
288     return m_pImp->IsOptionHidden( _rOption, _rPage, _rGroup );
289 }
290 
291