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 <unotools/moduleoptions.hxx>
21 #include <comphelper/sequenceashashmap.hxx>
22 #include <unotools/configitem.hxx>
23 #include <comphelper/processfactory.hxx>
24 #include <comphelper/sequence.hxx>
25 #include <osl/diagnose.h>
26 #include <o3tl/enumarray.hxx>
27 #include <rtl/instance.hxx>
28 #include <com/sun/star/uno/Any.hxx>
29 #include <com/sun/star/uno/Sequence.hxx>
30 #include <com/sun/star/beans/PropertyValue.hpp>
31 #include <com/sun/star/container/XNameAccess.hpp>
32 #include <com/sun/star/lang/XServiceInfo.hpp>
33 #include <com/sun/star/document/XTypeDetection.hpp>
34 #include <com/sun/star/util/PathSubstitution.hpp>
35 #include <com/sun/star/util/XStringSubstitution.hpp>
37 #include "itemholder1.hxx"
39 /*-************************************************************************************************************
40 @descr These values are used to define necessary keys from our configuration management to support
41 all functionality of these implementation.
42 It's a fast way to make changes if some keys change its name or location!
44 Property handle are necessary to specify right position in return list of configuration
45 for asked values. We ask it with a list of properties to get its values. The returned list
46 has the same order like our given name list!
48 NAMELIST[ PROPERTYHANDLE_xxx ] => VALUELIST[ PROPERTYHANDLE_xxx ]
49 *//*-*************************************************************************************************************/
50 #define ROOTNODE_FACTORIES "Setup/Office/Factories"
51 #define PATHSEPARATOR "/"
53 // Attention: The property "ooSetupFactoryEmptyDocumentURL" is read from configuration but not used! There is
54 // special code that uses hard coded strings to return them.
55 #define PROPERTYNAME_SHORTNAME "ooSetupFactoryShortName"
56 #define PROPERTYNAME_TEMPLATEFILE "ooSetupFactoryTemplateFile"
57 #define PROPERTYNAME_WINDOWATTRIBUTES "ooSetupFactoryWindowAttributes"
58 #define PROPERTYNAME_EMPTYDOCUMENTURL "ooSetupFactoryEmptyDocumentURL"
59 #define PROPERTYNAME_DEFAULTFILTER "ooSetupFactoryDefaultFilter"
60 #define PROPERTYNAME_ICON "ooSetupFactoryIcon"
62 #define PROPERTYHANDLE_SHORTNAME 0
63 #define PROPERTYHANDLE_TEMPLATEFILE 1
64 #define PROPERTYHANDLE_WINDOWATTRIBUTES 2
65 #define PROPERTYHANDLE_EMPTYDOCUMENTURL 3
66 #define PROPERTYHANDLE_DEFAULTFILTER 4
67 #define PROPERTYHANDLE_ICON 5
69 #define PROPERTYCOUNT 6
71 #define FACTORYNAME_WRITER "com.sun.star.text.TextDocument"
72 #define FACTORYNAME_WRITERWEB "com.sun.star.text.WebDocument"
73 #define FACTORYNAME_WRITERGLOBAL "com.sun.star.text.GlobalDocument"
74 #define FACTORYNAME_CALC "com.sun.star.sheet.SpreadsheetDocument"
75 #define FACTORYNAME_DRAW "com.sun.star.drawing.DrawingDocument"
76 #define FACTORYNAME_IMPRESS "com.sun.star.presentation.PresentationDocument"
77 #define FACTORYNAME_MATH "com.sun.star.formula.FormulaProperties"
78 #define FACTORYNAME_CHART "com.sun.star.chart2.ChartDocument"
79 #define FACTORYNAME_DATABASE "com.sun.star.sdb.OfficeDatabaseDocument"
80 #define FACTORYNAME_STARTMODULE "com.sun.star.frame.StartModule"
81 #define FACTORYNAME_BASIC "com.sun.star.script.BasicIDE"
83 #define FACTORYCOUNT 11
85 /*-************************************************************************************************************
86 @descr This struct hold information about one factory. We declare a complete array which can hold infos
87 for all well known factories. Values of enum "EFactory" (see header!) are directly used as index!
88 So we can support a fast access on this information.
89 *//*-*************************************************************************************************************/
94 // initialize empty struct
100 // easy way to reset struct member!
105 sTemplateFile
.clear();
106 sDefaultFilter
.clear();
108 bChangedTemplateFile
= false;
109 bChangedDefaultFilter
= false;
110 bDefaultFilterReadonly
= false;
113 // returns list of properties, which has changed only!
114 // We use given value of sNodeBase to build full qualified paths ...
115 // Last sign of it must be "/". because we use it directly, without any additional things!
116 css::uno::Sequence
< css::beans::PropertyValue
> getChangedProperties( const OUString
& sNodeBase
)
118 // a) reserve memory for max. count of changed properties
119 // b) add names and values of changed ones only and count it
120 // c) resize return list by using count
121 css::uno::Sequence
< css::beans::PropertyValue
> lProperties ( 4 );
122 sal_Int8 nRealyChanged
= 0;
124 if( bChangedTemplateFile
)
126 lProperties
[nRealyChanged
].Name
= sNodeBase
+ PROPERTYNAME_TEMPLATEFILE
;
128 if ( !sTemplateFile
.isEmpty() )
130 lProperties
[nRealyChanged
].Value
131 <<= getStringSubstitution()
132 ->reSubstituteVariables( sTemplateFile
);
136 lProperties
[nRealyChanged
].Value
<<= sTemplateFile
;
141 if( bChangedDefaultFilter
)
143 lProperties
[nRealyChanged
].Name
= sNodeBase
+ PROPERTYNAME_DEFAULTFILTER
;
144 lProperties
[nRealyChanged
].Value
<<= sDefaultFilter
;
148 // Don't forget to reset changed flags! Otherwise we save it again and again and ...
149 bChangedTemplateFile
= false;
150 bChangedDefaultFilter
= false;
152 lProperties
.realloc( nRealyChanged
);
156 // We must support setting AND marking of changed values.
157 // That's why we can't make our member public. We must use get/set/init methods
158 // to control access on it!
159 bool getInstalled () const { return bInstalled
; };
160 const OUString
& getFactory () const { return sFactory
; };
161 const OUString
& getTemplateFile () const { return sTemplateFile
; };
162 const OUString
& getDefaultFilter () const { return sDefaultFilter
; };
163 bool isDefaultFilterReadonly() const { return bDefaultFilterReadonly
; }
164 sal_Int32
getIcon () const { return nIcon
; };
166 // If you call set-methods - we check for changes of values and mark it.
167 // But if you wish to set it without that... you must initialize it!
168 void initInstalled () { bInstalled
= true; }
169 void initFactory ( const OUString
& sNewFactory
) { sFactory
= sNewFactory
; }
170 void initDefaultFilter ( const OUString
& sNewDefaultFilter
) { sDefaultFilter
= sNewDefaultFilter
; }
171 void setDefaultFilterReadonly( const bool bVal
){bDefaultFilterReadonly
= bVal
;}
172 void initIcon ( sal_Int32 nNewIcon
) { nIcon
= nNewIcon
; }
174 void initTemplateFile( const OUString
& sNewTemplateFile
)
176 if ( !sNewTemplateFile
.isEmpty() )
178 sTemplateFile
= getStringSubstitution()->substituteVariables( sNewTemplateFile
, false );
182 sTemplateFile
= sNewTemplateFile
;
186 void setTemplateFile( const OUString
& sNewTemplateFile
)
188 if( sTemplateFile
!= sNewTemplateFile
)
190 sTemplateFile
= sNewTemplateFile
;
191 bChangedTemplateFile
= true;
195 void setDefaultFilter( const OUString
& sNewDefaultFilter
)
197 if( sDefaultFilter
!= sNewDefaultFilter
)
199 sDefaultFilter
= sNewDefaultFilter
;
200 bChangedDefaultFilter
= true;
205 css::uno::Reference
< css::util::XStringSubstitution
> const & getStringSubstitution()
207 if ( !xSubstVars
.is() )
209 xSubstVars
.set( css::util::PathSubstitution::create(::comphelper::getProcessComponentContext()) );
216 OUString sTemplateFile
;
217 OUString sDefaultFilter
;
220 bool bChangedTemplateFile
:1;
221 bool bChangedDefaultFilter
:1;
222 bool bDefaultFilterReadonly
:1;
224 css::uno::Reference
< css::util::XStringSubstitution
> xSubstVars
;
227 class SvtModuleOptions_Impl
: public ::utl::ConfigItem
234 // constructor / destructor
236 SvtModuleOptions_Impl();
237 virtual ~SvtModuleOptions_Impl() override
;
239 // override methods of baseclass
241 virtual void Notify( const css::uno::Sequence
< OUString
>& lPropertyNames
) override
;
245 bool IsModuleInstalled ( SvtModuleOptions::EModule eModule
) const;
246 css::uno::Sequence
< OUString
> GetAllServiceNames();
247 OUString
const & GetFactoryName ( SvtModuleOptions::EFactory eFactory
) const;
248 OUString
const & GetFactoryStandardTemplate( SvtModuleOptions::EFactory eFactory
) const;
249 static OUString
GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory eFactory
);
250 OUString
const & GetFactoryDefaultFilter ( SvtModuleOptions::EFactory eFactory
) const;
251 bool IsDefaultFilterReadonly( SvtModuleOptions::EFactory eFactory
) const;
252 sal_Int32
GetFactoryIcon ( SvtModuleOptions::EFactory eFactory
) const;
253 static bool ClassifyFactoryByName ( const OUString
& sName
,
254 SvtModuleOptions::EFactory
& eFactory
);
255 void SetFactoryStandardTemplate( SvtModuleOptions::EFactory eFactory
,
256 const OUString
& sTemplate
);
257 void SetFactoryDefaultFilter ( SvtModuleOptions::EFactory eFactory
,
258 const OUString
& sFilter
);
259 void MakeReadonlyStatesAvailable();
264 static css::uno::Sequence
< OUString
> impl_ExpandSetNames ( const css::uno::Sequence
< OUString
>& lSetNames
);
265 void impl_Read ( const css::uno::Sequence
< OUString
>& lSetNames
);
267 virtual void ImplCommit() override
;
272 o3tl::enumarray
<SvtModuleOptions::EFactory
, FactoryInfo
> m_lFactories
;
273 bool m_bReadOnlyStatesWellKnown
;
276 /*-************************************************************************************************************
278 @descr We open our configuration here and read all necessary values from it.
279 These values are cached till everyone call Commit(). Then we write changed ones back to cfg.
281 @seealso baseclass ConfigItem
282 @seealso method impl_Read()
284 *//*-*************************************************************************************************************/
285 SvtModuleOptions_Impl::SvtModuleOptions_Impl()
286 : ::utl::ConfigItem( ROOTNODE_FACTORIES
)
287 , m_bReadOnlyStatesWellKnown( false )
289 // First initialize list of factory infos! Otherwise we couldn't guarantee right working of these class.
290 for( auto & rFactory
: m_lFactories
)
293 // Get name list of all existing set node names in configuration to read her properties in impl_Read().
294 // These list is a list of long names of our factories.
295 const css::uno::Sequence
< OUString
> lFactories
= GetNodeNames( OUString() );
296 impl_Read( lFactories
);
298 // Enable notification for changes by using configuration directly.
299 // So we can update our internal values immediately.
300 EnableNotification( lFactories
);
303 SvtModuleOptions_Impl::~SvtModuleOptions_Impl()
305 assert(!IsModified()); // should have been committed
308 /*-************************************************************************************************************
309 @short called for notify of configmanager
310 @descr This method is called from the ConfigManager before application ends or from the
311 PropertyChangeListener if the sub tree broadcasts changes. You must update our
314 @attention We are registered for pure set node names only. So we can use our internal method "impl_Read()" to
315 update our info list. Because - this method expand given name list to full qualified property list
316 and use it to read the values. These values are filled into our internal member list m_lFactories
319 @seealso method impl_Read()
321 @param "lNames" is the list of set node entries which should be updated.
323 *//*-*************************************************************************************************************/
324 void SvtModuleOptions_Impl::Notify( const css::uno::Sequence
< OUString
>& )
326 OSL_FAIL( "SvtModuleOptions_Impl::Notify() Not implemented yet!" );
329 /*-****************************************************************************************************
330 @short write changes to configuration
331 @descr This method writes the changed values into the sub tree
332 and should always called in our destructor to guarantee consistency of config data.
334 @attention We clear complete set in configuration first and write it completely new! So we don't must
335 distinguish between existing, added or removed elements. Our internal cached values
336 are the only and right ones.
338 @seealso baseclass ConfigItem
340 *//*-*****************************************************************************************************/
341 void SvtModuleOptions_Impl::ImplCommit()
343 // Reserve memory for ALL possible factory properties!
344 // Step over all factories and get her really changed values only.
345 // Build list of these ones and use it for commit.
346 css::uno::Sequence
< css::beans::PropertyValue
> lCommitProperties( FACTORYCOUNT
*PROPERTYCOUNT
);
347 sal_Int32 nRealCount
= 0;
349 for( FactoryInfo
& rInfo
: m_lFactories
)
351 // These path is used to build full qualified property names...
352 // See pInfo->getChangedProperties() for further information
353 sBasePath
= PATHSEPARATOR
+ rInfo
.getFactory() + PATHSEPARATOR
;
355 const css::uno::Sequence
< css::beans::PropertyValue
> lChangedProperties
= rInfo
.getChangedProperties ( sBasePath
);
356 std::copy(lChangedProperties
.begin(), lChangedProperties
.end(), std::next(lCommitProperties
.begin(), nRealCount
));
357 nRealCount
+= lChangedProperties
.getLength();
359 // Resize commit list to real size.
360 // If nothing to do - suppress calling of configuration...
361 // It could be too expensive :-)
364 lCommitProperties
.realloc( nRealCount
);
365 SetSetProperties( OUString(), lCommitProperties
);
369 /*-****************************************************************************************************
370 @short access method to get internal values
371 @descr These methods implement easy access to our internal values.
372 You give us right enum value to specify which module interest you ... we return right information.
374 @attention Some people use any value as enum ... but we support in header specified values only!
375 We use it directly as index in our internal list. If enum value isn't right - we crash with an
376 "index out of range"!!! Please use me right - otherwise there is no guarantee.
377 @param "eModule" , index in list - specify module
378 @return Queried information.
380 @onerror We return default values. (mostly "not installed"!)
382 *//*-*****************************************************************************************************/
383 bool SvtModuleOptions_Impl::IsModuleInstalled( SvtModuleOptions::EModule eModule
) const
387 case SvtModuleOptions::EModule::WRITER
:
388 return m_lFactories
[SvtModuleOptions::EFactory::WRITER
].getInstalled();
389 case SvtModuleOptions::EModule::WEB
:
390 return m_lFactories
[SvtModuleOptions::EFactory::WRITERWEB
].getInstalled();
391 case SvtModuleOptions::EModule::GLOBAL
:
392 return m_lFactories
[SvtModuleOptions::EFactory::WRITERGLOBAL
].getInstalled();
393 case SvtModuleOptions::EModule::CALC
:
394 return m_lFactories
[SvtModuleOptions::EFactory::CALC
].getInstalled();
395 case SvtModuleOptions::EModule::DRAW
:
396 return m_lFactories
[SvtModuleOptions::EFactory::DRAW
].getInstalled();
397 case SvtModuleOptions::EModule::IMPRESS
:
398 return m_lFactories
[SvtModuleOptions::EFactory::IMPRESS
].getInstalled();
399 case SvtModuleOptions::EModule::MATH
:
400 return m_lFactories
[SvtModuleOptions::EFactory::MATH
].getInstalled();
401 case SvtModuleOptions::EModule::CHART
:
402 return m_lFactories
[SvtModuleOptions::EFactory::CHART
].getInstalled();
403 case SvtModuleOptions::EModule::STARTMODULE
:
404 return m_lFactories
[SvtModuleOptions::EFactory::STARTMODULE
].getInstalled();
405 case SvtModuleOptions::EModule::BASIC
:
406 return true; // Couldn't be deselected by setup yet!
407 case SvtModuleOptions::EModule::DATABASE
:
408 return m_lFactories
[SvtModuleOptions::EFactory::DATABASE
].getInstalled();
414 css::uno::Sequence
< OUString
> SvtModuleOptions_Impl::GetAllServiceNames()
416 std::vector
<OUString
> aVec
;
418 for( const auto & rFactory
: m_lFactories
)
419 if( rFactory
.getInstalled() )
420 aVec
.push_back( rFactory
.getFactory() );
422 return comphelper::containerToSequence(aVec
);
425 OUString
const & SvtModuleOptions_Impl::GetFactoryName( SvtModuleOptions::EFactory eFactory
) const
427 return m_lFactories
[eFactory
].getFactory();
430 OUString
SvtModuleOptions::GetFactoryShortName(SvtModuleOptions::EFactory eFactory
)
432 // Attention: Hard configured yet ... because it's not fine to make changes possible by xml file yet.
433 // But it's good to plan further possibilities!
435 //return m_lFactories[eFactory].sShortName;
440 case SvtModuleOptions::EFactory::WRITER
: sShortName
= "swriter";
442 case SvtModuleOptions::EFactory::WRITERWEB
: sShortName
= "swriter/web";
444 case SvtModuleOptions::EFactory::WRITERGLOBAL
: sShortName
= "swriter/GlobalDocument";
446 case SvtModuleOptions::EFactory::CALC
: sShortName
= "scalc";
448 case SvtModuleOptions::EFactory::DRAW
: sShortName
= "sdraw";
450 case SvtModuleOptions::EFactory::IMPRESS
: sShortName
= "simpress";
452 case SvtModuleOptions::EFactory::MATH
: sShortName
= "smath";
454 case SvtModuleOptions::EFactory::CHART
: sShortName
= "schart";
456 case SvtModuleOptions::EFactory::BASIC
: sShortName
= "sbasic";
458 case SvtModuleOptions::EFactory::DATABASE
: sShortName
= "sdatabase";
461 OSL_FAIL( "unknown factory" );
468 OUString
const & SvtModuleOptions_Impl::GetFactoryStandardTemplate( SvtModuleOptions::EFactory eFactory
) const
470 return m_lFactories
[eFactory
].getTemplateFile();
473 OUString
SvtModuleOptions_Impl::GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory eFactory
)
475 // Attention: Hard configured yet ... because it's not fine to make changes possible by xml file yet.
476 // But it's good to plan further possibilities!
478 //return m_lFactories[eFactory].getEmptyDocumentURL();
483 case SvtModuleOptions::EFactory::WRITER
: sURL
= "private:factory/swriter";
485 case SvtModuleOptions::EFactory::WRITERWEB
: sURL
= "private:factory/swriter/web";
487 case SvtModuleOptions::EFactory::WRITERGLOBAL
: sURL
= "private:factory/swriter/GlobalDocument";
489 case SvtModuleOptions::EFactory::CALC
: sURL
= "private:factory/scalc";
491 case SvtModuleOptions::EFactory::DRAW
: sURL
= "private:factory/sdraw";
493 case SvtModuleOptions::EFactory::IMPRESS
: sURL
= "private:factory/simpress?slot=6686";
495 case SvtModuleOptions::EFactory::MATH
: sURL
= "private:factory/smath";
497 case SvtModuleOptions::EFactory::CHART
: sURL
= "private:factory/schart";
499 case SvtModuleOptions::EFactory::BASIC
: sURL
= "private:factory/sbasic";
501 case SvtModuleOptions::EFactory::DATABASE
: sURL
= "private:factory/sdatabase?Interactive";
504 OSL_FAIL( "unknown factory" );
510 OUString
const & SvtModuleOptions_Impl::GetFactoryDefaultFilter( SvtModuleOptions::EFactory eFactory
) const
512 return m_lFactories
[eFactory
].getDefaultFilter();
515 bool SvtModuleOptions_Impl::IsDefaultFilterReadonly( SvtModuleOptions::EFactory eFactory
) const
517 return m_lFactories
[eFactory
].isDefaultFilterReadonly();
520 sal_Int32
SvtModuleOptions_Impl::GetFactoryIcon( SvtModuleOptions::EFactory eFactory
) const
522 return m_lFactories
[eFactory
].getIcon();
525 void SvtModuleOptions_Impl::SetFactoryStandardTemplate( SvtModuleOptions::EFactory eFactory
,
526 const OUString
& sTemplate
)
528 m_lFactories
[eFactory
].setTemplateFile( sTemplate
);
532 void SvtModuleOptions_Impl::SetFactoryDefaultFilter( SvtModuleOptions::EFactory eFactory
,
533 const OUString
& sFilter
)
535 m_lFactories
[eFactory
].setDefaultFilter( sFilter
);
539 /*-************************************************************************************************************
540 @short return list of key names of our configuration management which represent our module tree
541 @descr You give use a list of current existing set node names .. and we expand it for all
542 well known properties which are necessary for this implementation.
543 These full expanded list should be used to get values of this properties.
546 @return List of all relative addressed properties of given set entry names.
548 @onerror List will be empty.
550 *//*-*************************************************************************************************************/
551 css::uno::Sequence
< OUString
> SvtModuleOptions_Impl::impl_ExpandSetNames( const css::uno::Sequence
< OUString
>& lSetNames
)
553 sal_Int32 nCount
= lSetNames
.getLength();
554 css::uno::Sequence
< OUString
> lPropNames ( nCount
*PROPERTYCOUNT
);
555 OUString
* pPropNames
= lPropNames
.getArray();
556 sal_Int32 nPropStart
= 0;
558 for( const auto& rSetName
: lSetNames
)
560 pPropNames
[nPropStart
+PROPERTYHANDLE_SHORTNAME
] = rSetName
+ PATHSEPARATOR PROPERTYNAME_SHORTNAME
;
561 pPropNames
[nPropStart
+PROPERTYHANDLE_TEMPLATEFILE
] = rSetName
+ PATHSEPARATOR PROPERTYNAME_TEMPLATEFILE
;
562 pPropNames
[nPropStart
+PROPERTYHANDLE_WINDOWATTRIBUTES
] = rSetName
+ PATHSEPARATOR PROPERTYNAME_WINDOWATTRIBUTES
;
563 pPropNames
[nPropStart
+PROPERTYHANDLE_EMPTYDOCUMENTURL
] = rSetName
+ PATHSEPARATOR PROPERTYNAME_EMPTYDOCUMENTURL
;
564 pPropNames
[nPropStart
+PROPERTYHANDLE_DEFAULTFILTER
] = rSetName
+ PATHSEPARATOR PROPERTYNAME_DEFAULTFILTER
;
565 pPropNames
[nPropStart
+PROPERTYHANDLE_ICON
] = rSetName
+ PATHSEPARATOR PROPERTYNAME_ICON
;
566 nPropStart
+= PROPERTYCOUNT
;
572 /*-************************************************************************************************************
573 @short helper to classify given factory by name
574 @descr Every factory has its own long and short name. So we can match right enum value for internal using.
576 @attention We change in/out parameter "eFactory" in every case! But you should use it only, if return value is sal_True!
577 Algorithm: Set out-parameter to probably value ... and check the longname.
578 If it matches with these factory - break operation and return true AND right set parameter.
579 Otherwise try next one and so on. If no factory was found return false. Out parameter eFactory
580 is set to last tried value but shouldn't be used! Because our return value is false!
581 @param "sLongName" , long name of factory, which should be classified
582 @return "eFactory" , right enum value, which match given long name
583 and true for successfully classification, false otherwise
585 @onerror We return false.
587 *//*-*************************************************************************************************************/
588 bool SvtModuleOptions_Impl::ClassifyFactoryByName( const OUString
& sName
, SvtModuleOptions::EFactory
& eFactory
)
592 eFactory
= SvtModuleOptions::EFactory::WRITER
;
593 bState
= ( sName
== FACTORYNAME_WRITER
);
597 eFactory
= SvtModuleOptions::EFactory::WRITERWEB
;
598 bState
= ( sName
== FACTORYNAME_WRITERWEB
);
603 eFactory
= SvtModuleOptions::EFactory::WRITERGLOBAL
;
604 bState
= ( sName
== FACTORYNAME_WRITERGLOBAL
);
609 eFactory
= SvtModuleOptions::EFactory::CALC
;
610 bState
= ( sName
== FACTORYNAME_CALC
);
615 eFactory
= SvtModuleOptions::EFactory::DRAW
;
616 bState
= ( sName
== FACTORYNAME_DRAW
);
621 eFactory
= SvtModuleOptions::EFactory::IMPRESS
;
622 bState
= ( sName
== FACTORYNAME_IMPRESS
);
627 eFactory
= SvtModuleOptions::EFactory::MATH
;
628 bState
= ( sName
== FACTORYNAME_MATH
);
633 eFactory
= SvtModuleOptions::EFactory::CHART
;
634 bState
= ( sName
== FACTORYNAME_CHART
);
639 eFactory
= SvtModuleOptions::EFactory::DATABASE
;
640 bState
= ( sName
== FACTORYNAME_DATABASE
);
645 eFactory
= SvtModuleOptions::EFactory::STARTMODULE
;
646 bState
= ( sName
== FACTORYNAME_STARTMODULE
);
651 eFactory
= SvtModuleOptions::EFactory::BASIC
;
652 bState
= ( sName
== FACTORYNAME_BASIC
);
658 /*-************************************************************************************************************
659 @short read factory configuration
660 @descr Give us a list of pure factory names (long names!) which can be used as
661 direct set node names... and we read her property values and fill internal list.
662 These method can be used by initial reading at ctor and later updating by "Notify()".
665 @seealso method Notify()
667 @param "lFactories" is the list of set node entries which should be read.
668 @onerror We do nothing.
670 *//*-*************************************************************************************************************/
671 void SvtModuleOptions_Impl::impl_Read( const css::uno::Sequence
< OUString
>& lFactories
)
673 // Expand every set node name in lFactories to full qualified paths to its properties
674 // and get right values from configuration.
675 const css::uno::Sequence
< OUString
> lProperties
= impl_ExpandSetNames( lFactories
);
676 const css::uno::Sequence
< css::uno::Any
> lValues
= GetProperties( lProperties
);
678 // Safe impossible cases.
679 // We need values from ALL configuration keys.
680 // Follow assignment use order of values in relation to our list of key names!
681 OSL_ENSURE( !(lProperties
.getLength()!=lValues
.getLength()), "SvtModuleOptions_Impl::impl_Read()\nI miss some values of configuration keys!" );
683 // Algorithm: We step over all given factory names and classify it. These enum value can be used as direct index
684 // in our member list m_lFactories! VAriable nPropertyStart marks start position of every factory
685 // and her properties in expanded property/value list. The defines PROPERTHANDLE_xxx are used as offset values
686 // added to nPropertyStart. So we can address every property relative in these lists.
687 // If we found any valid values ... we reset all existing information for corresponding m_lFactories-entry and
688 // use a pointer to these struct in memory directly to set new values.
689 // But we set it only, if bInstalled is true. Otherwise all other values of a factory can be undeclared .. They
690 // shouldn't be used then.
691 // Attention: If a propertyset of a factory will be ignored we must step to next start position of next factory infos!
692 // see "nPropertyStart += PROPERTYCOUNT" ...
694 sal_Int32 nPropertyStart
= 0;
695 FactoryInfo
* pInfo
= nullptr;
696 SvtModuleOptions::EFactory eFactory
;
698 for( const OUString
& sFactoryName
: lFactories
)
700 if( ClassifyFactoryByName( sFactoryName
, eFactory
) )
705 pInfo
= &(m_lFactories
[eFactory
]);
708 pInfo
->initInstalled();
709 pInfo
->initFactory ( sFactoryName
);
711 if (lValues
[nPropertyStart
+PROPERTYHANDLE_TEMPLATEFILE
] >>= sTemp
)
712 pInfo
->initTemplateFile( sTemp
);
713 if (lValues
[nPropertyStart
+PROPERTYHANDLE_DEFAULTFILTER
] >>= sTemp
)
714 pInfo
->initDefaultFilter( sTemp
);
715 if (lValues
[nPropertyStart
+PROPERTYHANDLE_ICON
] >>= nTemp
)
716 pInfo
->initIcon( nTemp
);
718 nPropertyStart
+= PROPERTYCOUNT
;
722 void SvtModuleOptions_Impl::MakeReadonlyStatesAvailable()
724 if (m_bReadOnlyStatesWellKnown
)
727 css::uno::Sequence
< OUString
> lFactories
= GetNodeNames(OUString());
728 std::transform(lFactories
.begin(), lFactories
.end(), lFactories
.begin(),
729 [](const OUString
& rFactory
) -> OUString
{
730 return rFactory
+ PATHSEPARATOR PROPERTYNAME_DEFAULTFILTER
;
733 css::uno::Sequence
< sal_Bool
> lReadonlyStates
= GetReadOnlyStates(lFactories
);
734 sal_Int32 c
= lFactories
.getLength();
735 for (sal_Int32 i
=0; i
<c
; ++i
)
737 OUString
& rFactoryName
= lFactories
[i
];
738 SvtModuleOptions::EFactory eFactory
;
740 if (!ClassifyFactoryByName(rFactoryName
, eFactory
))
743 FactoryInfo
& rInfo
= m_lFactories
[eFactory
];
744 rInfo
.setDefaultFilterReadonly(lReadonlyStates
[i
]);
747 m_bReadOnlyStatesWellKnown
= true;
752 std::weak_ptr
<SvtModuleOptions_Impl
> g_pModuleOptions
;
755 /*-************************************************************************************************************
756 @short standard constructor and destructor
757 @descr This will initialize an instance with default values. We initialize/deinitialize our static data
758 container and create a static mutex, which is used for threadsafe code in further time of this object.
760 @seealso method impl_GetOwnStaticMutex()
762 *//*-*************************************************************************************************************/
763 SvtModuleOptions::SvtModuleOptions()
765 // Global access, must be guarded (multithreading!)
766 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
768 m_pImpl
= g_pModuleOptions
.lock();
771 m_pImpl
= std::make_shared
<SvtModuleOptions_Impl
>();
772 g_pModuleOptions
= m_pImpl
;
773 ItemHolder1::holdConfigItem(EItem::ModuleOptions
);
777 SvtModuleOptions::~SvtModuleOptions()
779 // Global access, must be guarded (multithreading!)
780 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
785 /*-************************************************************************************************************
786 @short access to configuration data
787 @descr This methods allow read/write access to configuration values.
788 They are threadsafe. All calls are forwarded to impl-data-container. See there for further information!
790 @seealso method impl_GetOwnStaticMutex()
792 *//*-*************************************************************************************************************/
793 bool SvtModuleOptions::IsModuleInstalled( EModule eModule
) const
795 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
796 return m_pImpl
->IsModuleInstalled( eModule
);
799 OUString
SvtModuleOptions::GetFactoryName( EFactory eFactory
) const
801 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
802 return m_pImpl
->GetFactoryName( eFactory
);
805 OUString
SvtModuleOptions::GetFactoryStandardTemplate( EFactory eFactory
) const
807 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
808 return m_pImpl
->GetFactoryStandardTemplate( eFactory
);
811 OUString
SvtModuleOptions::GetFactoryEmptyDocumentURL( EFactory eFactory
) const
813 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
814 return SvtModuleOptions_Impl::GetFactoryEmptyDocumentURL( eFactory
);
817 OUString
SvtModuleOptions::GetFactoryDefaultFilter( EFactory eFactory
) const
819 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
820 return m_pImpl
->GetFactoryDefaultFilter( eFactory
);
823 bool SvtModuleOptions::IsDefaultFilterReadonly( EFactory eFactory
) const
825 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
826 m_pImpl
->MakeReadonlyStatesAvailable();
827 return m_pImpl
->IsDefaultFilterReadonly( eFactory
);
830 sal_Int32
SvtModuleOptions::GetFactoryIcon( EFactory eFactory
) const
832 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
833 return m_pImpl
->GetFactoryIcon( eFactory
);
836 bool SvtModuleOptions::ClassifyFactoryByName( const OUString
& sName
,
839 // We don't need any mutex here ... because we don't use any member here!
840 return SvtModuleOptions_Impl::ClassifyFactoryByName( sName
, eFactory
);
843 void SvtModuleOptions::SetFactoryStandardTemplate( EFactory eFactory
,
844 const OUString
& sTemplate
)
846 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
847 m_pImpl
->SetFactoryStandardTemplate( eFactory
, sTemplate
);
850 void SvtModuleOptions::SetFactoryDefaultFilter( EFactory eFactory
,
851 const OUString
& sFilter
)
853 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
854 m_pImpl
->SetFactoryDefaultFilter( eFactory
, sFilter
);
857 bool SvtModuleOptions::IsMath() const
859 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
860 return m_pImpl
->IsModuleInstalled( EModule::MATH
);
863 bool SvtModuleOptions::IsChart() const
865 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
866 return m_pImpl
->IsModuleInstalled( EModule::CHART
);
869 bool SvtModuleOptions::IsCalc() const
871 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
872 return m_pImpl
->IsModuleInstalled( EModule::CALC
);
875 bool SvtModuleOptions::IsDraw() const
877 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
878 return m_pImpl
->IsModuleInstalled( EModule::DRAW
);
881 bool SvtModuleOptions::IsWriter() const
883 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
884 return m_pImpl
->IsModuleInstalled( EModule::WRITER
);
887 bool SvtModuleOptions::IsImpress() const
889 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
890 return m_pImpl
->IsModuleInstalled( EModule::IMPRESS
);
893 bool SvtModuleOptions::IsDataBase() const
895 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
896 return m_pImpl
->IsModuleInstalled( EModule::DATABASE
);
901 class theModuleOptionsMutex
: public rtl::Static
<osl::Mutex
, theModuleOptionsMutex
> {};
903 /*-****************************************************************************************************
904 @short return a reference to a static mutex
905 @descr These class is threadsafe.
906 We create a static mutex only for one time and use it to protect our refcount and container
908 @return A reference to a static mutex member.
910 *//*-*****************************************************************************************************/
911 ::osl::Mutex
& SvtModuleOptions::impl_GetOwnStaticMutex()
913 return theModuleOptionsMutex::get();
916 OUString
SvtModuleOptions::GetModuleName( EModule eModule
) const
920 case SvtModuleOptions::EModule::WRITER
: { return "Writer"; }
921 case SvtModuleOptions::EModule::WEB
: { return "Web"; }
922 case SvtModuleOptions::EModule::GLOBAL
: { return "Global"; }
923 case SvtModuleOptions::EModule::CALC
: { return "Calc"; }
924 case SvtModuleOptions::EModule::DRAW
: { return "Draw"; }
925 case SvtModuleOptions::EModule::IMPRESS
: { return "Impress"; }
926 case SvtModuleOptions::EModule::MATH
: { return "Math"; }
927 case SvtModuleOptions::EModule::CHART
: { return "Chart"; }
928 case SvtModuleOptions::EModule::BASIC
: { return "Basic"; }
929 case SvtModuleOptions::EModule::DATABASE
: { return "Database"; }
931 OSL_FAIL( "unknown module" );
938 SvtModuleOptions::EFactory
SvtModuleOptions::ClassifyFactoryByShortName(const OUString
& sName
)
940 if ( sName
== "swriter" )
941 return EFactory::WRITER
;
942 if (sName
.equalsIgnoreAsciiCase("swriter/Web")) // sometimes they are registered for swriter/web :-(
943 return EFactory::WRITERWEB
;
944 if (sName
.equalsIgnoreAsciiCase("swriter/GlobalDocument")) // sometimes they are registered for swriter/globaldocument :-(
945 return EFactory::WRITERGLOBAL
;
946 if ( sName
== "scalc" )
947 return EFactory::CALC
;
948 if ( sName
== "sdraw" )
949 return EFactory::DRAW
;
950 if ( sName
== "simpress" )
951 return EFactory::IMPRESS
;
952 if ( sName
== "schart" )
953 return EFactory::CHART
;
954 if ( sName
== "smath" )
955 return EFactory::MATH
;
956 if ( sName
== "sbasic" )
957 return EFactory::BASIC
;
958 if ( sName
== "sdatabase" )
959 return EFactory::DATABASE
;
961 return EFactory::UNKNOWN_FACTORY
;
964 SvtModuleOptions::EFactory
SvtModuleOptions::ClassifyFactoryByServiceName(const OUString
& sName
)
966 if (sName
== FACTORYNAME_WRITERGLOBAL
)
967 return EFactory::WRITERGLOBAL
;
968 if (sName
== FACTORYNAME_WRITERWEB
)
969 return EFactory::WRITERWEB
;
970 if (sName
== FACTORYNAME_WRITER
)
971 return EFactory::WRITER
;
972 if (sName
== FACTORYNAME_CALC
)
973 return EFactory::CALC
;
974 if (sName
== FACTORYNAME_DRAW
)
975 return EFactory::DRAW
;
976 if (sName
== FACTORYNAME_IMPRESS
)
977 return EFactory::IMPRESS
;
978 if (sName
== FACTORYNAME_MATH
)
979 return EFactory::MATH
;
980 if (sName
== FACTORYNAME_CHART
)
981 return EFactory::CHART
;
982 if (sName
== FACTORYNAME_DATABASE
)
983 return EFactory::DATABASE
;
984 if (sName
== FACTORYNAME_STARTMODULE
)
985 return EFactory::STARTMODULE
;
986 if (sName
== FACTORYNAME_BASIC
)
987 return EFactory::BASIC
;
989 return EFactory::UNKNOWN_FACTORY
;
992 SvtModuleOptions::EFactory
SvtModuleOptions::ClassifyFactoryByURL(const OUString
& sURL
,
993 const css::uno::Sequence
< css::beans::PropertyValue
>& lMediaDescriptor
)
995 css::uno::Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
997 css::uno::Reference
< css::container::XNameAccess
> xFilterCfg
;
998 css::uno::Reference
< css::container::XNameAccess
> xTypeCfg
;
1002 xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", xContext
), css::uno::UNO_QUERY
);
1004 xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", xContext
), css::uno::UNO_QUERY
);
1006 catch(const css::uno::RuntimeException
&)
1008 catch(const css::uno::Exception
&)
1009 { return EFactory::UNKNOWN_FACTORY
; }
1011 ::comphelper::SequenceAsHashMap
stlDesc(lMediaDescriptor
);
1013 // is there already a filter inside the descriptor?
1014 OUString sFilterName
= stlDesc
.getUnpackedValueOrDefault("FilterName", OUString());
1015 if (!sFilterName
.isEmpty())
1019 ::comphelper::SequenceAsHashMap
stlFilterProps (xFilterCfg
->getByName(sFilterName
));
1020 OUString sDocumentService
= stlFilterProps
.getUnpackedValueOrDefault("DocumentService", OUString());
1021 SvtModuleOptions::EFactory eApp
= SvtModuleOptions::ClassifyFactoryByServiceName(sDocumentService
);
1023 if (eApp
!= EFactory::UNKNOWN_FACTORY
)
1026 catch(const css::uno::RuntimeException
&)
1028 catch(const css::uno::Exception
&)
1029 { /* do nothing here ... may the following code can help!*/ }
1032 // is there already a type inside the descriptor?
1033 OUString sTypeName
= stlDesc
.getUnpackedValueOrDefault("TypeName", OUString());
1034 if (sTypeName
.isEmpty())
1037 // start flat detection of URL
1038 css::uno::Reference
< css::document::XTypeDetection
> xDetect(xTypeCfg
, css::uno::UNO_QUERY
);
1039 sTypeName
= xDetect
->queryTypeByURL(sURL
);
1042 if (sTypeName
.isEmpty())
1043 return EFactory::UNKNOWN_FACTORY
;
1045 // yes - there is a type info
1046 // Try to find the preferred filter.
1049 ::comphelper::SequenceAsHashMap
stlTypeProps (xTypeCfg
->getByName(sTypeName
));
1050 OUString sPreferredFilter
= stlTypeProps
.getUnpackedValueOrDefault("PreferredFilter", OUString());
1051 ::comphelper::SequenceAsHashMap
stlFilterProps (xFilterCfg
->getByName(sPreferredFilter
));
1052 OUString sDocumentService
= stlFilterProps
.getUnpackedValueOrDefault("DocumentService", OUString());
1053 SvtModuleOptions::EFactory eApp
= SvtModuleOptions::ClassifyFactoryByServiceName(sDocumentService
);
1055 if (eApp
!= EFactory::UNKNOWN_FACTORY
)
1058 catch(const css::uno::RuntimeException
&)
1060 catch(const css::uno::Exception
&)
1061 { /* do nothing here ... may the following code can help!*/ }
1063 // no filter/no type/no detection result => no fun :-)
1064 return EFactory::UNKNOWN_FACTORY
;
1067 SvtModuleOptions::EFactory
SvtModuleOptions::ClassifyFactoryByModel(const css::uno::Reference
< css::frame::XModel
>& xModel
)
1069 css::uno::Reference
< css::lang::XServiceInfo
> xInfo(xModel
, css::uno::UNO_QUERY
);
1071 return EFactory::UNKNOWN_FACTORY
;
1073 const css::uno::Sequence
< OUString
> lServices
= xInfo
->getSupportedServiceNames();
1075 for (const OUString
& rService
: lServices
)
1077 SvtModuleOptions::EFactory eApp
= SvtModuleOptions::ClassifyFactoryByServiceName(rService
);
1078 if (eApp
!= EFactory::UNKNOWN_FACTORY
)
1082 return EFactory::UNKNOWN_FACTORY
;
1085 css::uno::Sequence
< OUString
> SvtModuleOptions::GetAllServiceNames()
1087 ::osl::MutexGuard
aGuard( impl_GetOwnStaticMutex() );
1088 return m_pImpl
->GetAllServiceNames();
1091 OUString
SvtModuleOptions::GetDefaultModuleName() const
1094 if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::WRITER
))
1095 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::WRITER
);
1096 else if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::CALC
))
1097 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::CALC
);
1098 else if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::IMPRESS
))
1099 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::IMPRESS
);
1100 else if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::DATABASE
))
1101 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::DATABASE
);
1102 else if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::DRAW
))
1103 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::DRAW
);
1104 else if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::WEB
))
1105 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::WRITERWEB
);
1106 else if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::GLOBAL
))
1107 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::WRITERGLOBAL
);
1108 else if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::MATH
))
1109 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::MATH
);
1113 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */