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 <sal/config.h>
22 #include <string_view>
24 #include <unotools/moduleoptions.hxx>
25 #include <comphelper/sequenceashashmap.hxx>
26 #include <unotools/configitem.hxx>
27 #include <comphelper/processfactory.hxx>
28 #include <comphelper/sequence.hxx>
29 #include <osl/diagnose.h>
30 #include <o3tl/enumarray.hxx>
31 #include <o3tl/string_view.hxx>
32 #include <com/sun/star/uno/Any.hxx>
33 #include <com/sun/star/uno/Sequence.hxx>
34 #include <com/sun/star/beans/PropertyValue.hpp>
35 #include <com/sun/star/container/XNameAccess.hpp>
36 #include <com/sun/star/frame/XModel.hpp>
37 #include <com/sun/star/lang/XServiceInfo.hpp>
38 #include <com/sun/star/document/XTypeDetection.hpp>
39 #include <com/sun/star/util/PathSubstitution.hpp>
40 #include <com/sun/star/util/XStringSubstitution.hpp>
42 #include "itemholder1.hxx"
44 /*-************************************************************************************************************
45 @descr These values are used to define necessary keys from our configuration management to support
46 all functionality of these implementation.
47 It's a fast way to make changes if some keys change its name or location!
49 Property handle are necessary to specify right position in return list of configuration
50 for asked values. We ask it with a list of properties to get its values. The returned list
51 has the same order like our given name list!
53 NAMELIST[ PROPERTYHANDLE_xxx ] => VALUELIST[ PROPERTYHANDLE_xxx ]
54 *//*-*************************************************************************************************************/
55 constexpr OUStringLiteral ROOTNODE_FACTORIES
= u
"Setup/Office/Factories";
56 #define PATHSEPARATOR "/"
58 // Attention: The property "ooSetupFactoryEmptyDocumentURL" is read from configuration but not used! There is
59 // special code that uses hard coded strings to return them.
60 #define PROPERTYNAME_SHORTNAME "ooSetupFactoryShortName"
61 #define PROPERTYNAME_TEMPLATEFILE "ooSetupFactoryTemplateFile"
62 #define PROPERTYNAME_WINDOWATTRIBUTES "ooSetupFactoryWindowAttributes"
63 #define PROPERTYNAME_EMPTYDOCUMENTURL "ooSetupFactoryEmptyDocumentURL"
64 #define PROPERTYNAME_DEFAULTFILTER "ooSetupFactoryDefaultFilter"
65 #define PROPERTYNAME_ICON "ooSetupFactoryIcon"
67 #define PROPERTYHANDLE_SHORTNAME 0
68 #define PROPERTYHANDLE_TEMPLATEFILE 1
69 #define PROPERTYHANDLE_WINDOWATTRIBUTES 2
70 #define PROPERTYHANDLE_EMPTYDOCUMENTURL 3
71 #define PROPERTYHANDLE_DEFAULTFILTER 4
72 #define PROPERTYHANDLE_ICON 5
74 #define PROPERTYCOUNT 6
76 constexpr OUString FACTORYNAME_WRITER
= u
"com.sun.star.text.TextDocument"_ustr
;
77 constexpr OUString FACTORYNAME_WRITERWEB
= u
"com.sun.star.text.WebDocument"_ustr
;
78 constexpr OUString FACTORYNAME_WRITERGLOBAL
= u
"com.sun.star.text.GlobalDocument"_ustr
;
79 constexpr OUString FACTORYNAME_CALC
= u
"com.sun.star.sheet.SpreadsheetDocument"_ustr
;
80 constexpr OUString FACTORYNAME_DRAW
= u
"com.sun.star.drawing.DrawingDocument"_ustr
;
81 constexpr OUString FACTORYNAME_IMPRESS
= u
"com.sun.star.presentation.PresentationDocument"_ustr
;
82 constexpr OUString FACTORYNAME_MATH
= u
"com.sun.star.formula.FormulaProperties"_ustr
;
83 constexpr OUString FACTORYNAME_CHART
= u
"com.sun.star.chart2.ChartDocument"_ustr
;
84 constexpr OUString FACTORYNAME_DATABASE
= u
"com.sun.star.sdb.OfficeDatabaseDocument"_ustr
;
85 constexpr OUString FACTORYNAME_STARTMODULE
= u
"com.sun.star.frame.StartModule"_ustr
;
86 constexpr OUString FACTORYNAME_BASIC
= u
"com.sun.star.script.BasicIDE"_ustr
;
88 #define FACTORYCOUNT 11
92 /*-************************************************************************************************************
93 @descr This struct hold information about one factory. We declare a complete array which can hold infos
94 for all well known factories. Values of enum "EFactory" (see header!) are directly used as index!
95 So we can support a fast access on this information.
96 *//*-*************************************************************************************************************/
101 // initialize empty struct
107 // easy way to reset struct member!
112 sTemplateFile
.clear();
113 sDefaultFilter
.clear();
115 bChangedTemplateFile
= false;
116 bChangedDefaultFilter
= false;
117 bDefaultFilterReadonly
= false;
120 // returns list of properties, which has changed only!
121 // We use given value of sNodeBase to build full qualified paths ...
122 // Last sign of it must be "/". because we use it directly, without any additional things!
123 css::uno::Sequence
< css::beans::PropertyValue
> getChangedProperties( std::u16string_view sNodeBase
)
125 // a) reserve memory for max. count of changed properties
126 // b) add names and values of changed ones only and count it
127 // c) resize return list by using count
128 css::uno::Sequence
< css::beans::PropertyValue
> lProperties ( 4 );
129 auto plProperties
= lProperties
.getArray();
130 sal_Int8 nRealyChanged
= 0;
132 if( bChangedTemplateFile
)
134 plProperties
[nRealyChanged
].Name
135 = OUString::Concat(sNodeBase
) + PROPERTYNAME_TEMPLATEFILE
;
137 if ( !sTemplateFile
.isEmpty() )
139 plProperties
[nRealyChanged
].Value
140 <<= getStringSubstitution()
141 ->reSubstituteVariables( sTemplateFile
);
145 plProperties
[nRealyChanged
].Value
<<= sTemplateFile
;
150 if( bChangedDefaultFilter
)
152 plProperties
[nRealyChanged
].Name
153 = OUString::Concat(sNodeBase
) + PROPERTYNAME_DEFAULTFILTER
;
154 plProperties
[nRealyChanged
].Value
<<= sDefaultFilter
;
158 // Don't forget to reset changed flags! Otherwise we save it again and again and ...
159 bChangedTemplateFile
= false;
160 bChangedDefaultFilter
= false;
162 lProperties
.realloc( nRealyChanged
);
166 // We must support setting AND marking of changed values.
167 // That's why we can't make our member public. We must use get/set/init methods
168 // to control access on it!
169 bool getInstalled () const { return bInstalled
; };
170 const OUString
& getFactory () const { return sFactory
; };
171 const OUString
& getTemplateFile () const { return sTemplateFile
; };
172 const OUString
& getDefaultFilter () const { return sDefaultFilter
; };
173 bool isDefaultFilterReadonly() const { return bDefaultFilterReadonly
; }
174 sal_Int32
getIcon () const { return nIcon
; };
176 // If you call set-methods - we check for changes of values and mark it.
177 // But if you wish to set it without that... you must initialize it!
178 void initInstalled () { bInstalled
= true; }
179 void initFactory ( const OUString
& sNewFactory
) { sFactory
= sNewFactory
; }
180 void initDefaultFilter ( const OUString
& sNewDefaultFilter
) { sDefaultFilter
= sNewDefaultFilter
; }
181 void setDefaultFilterReadonly( const bool bVal
){bDefaultFilterReadonly
= bVal
;}
182 void initIcon ( sal_Int32 nNewIcon
) { nIcon
= nNewIcon
; }
184 void initTemplateFile( const OUString
& sNewTemplateFile
)
186 if ( !sNewTemplateFile
.isEmpty() )
188 sTemplateFile
= getStringSubstitution()->substituteVariables( sNewTemplateFile
, false );
192 sTemplateFile
= sNewTemplateFile
;
196 void setTemplateFile( const OUString
& sNewTemplateFile
)
198 if( sTemplateFile
!= sNewTemplateFile
)
200 sTemplateFile
= sNewTemplateFile
;
201 bChangedTemplateFile
= true;
205 void setDefaultFilter( const OUString
& sNewDefaultFilter
)
207 if( sDefaultFilter
!= sNewDefaultFilter
)
209 sDefaultFilter
= sNewDefaultFilter
;
210 bChangedDefaultFilter
= true;
215 css::uno::Reference
< css::util::XStringSubstitution
> const & getStringSubstitution()
217 if ( !xSubstVars
.is() )
219 xSubstVars
.set( css::util::PathSubstitution::create(::comphelper::getProcessComponentContext()) );
226 OUString sTemplateFile
;
227 OUString sDefaultFilter
;
230 bool bChangedTemplateFile
:1;
231 bool bChangedDefaultFilter
:1;
232 bool bDefaultFilterReadonly
:1;
234 css::uno::Reference
< css::util::XStringSubstitution
> xSubstVars
;
239 class SvtModuleOptions_Impl
: public ::utl::ConfigItem
246 // constructor / destructor
248 SvtModuleOptions_Impl();
249 virtual ~SvtModuleOptions_Impl() override
;
251 // override methods of baseclass
253 virtual void Notify( const css::uno::Sequence
< OUString
>& lPropertyNames
) override
;
257 bool IsModuleInstalled ( SvtModuleOptions::EModule eModule
) const;
258 css::uno::Sequence
< OUString
> GetAllServiceNames();
259 OUString
const & GetFactoryName ( SvtModuleOptions::EFactory eFactory
) const;
260 OUString
const & GetFactoryStandardTemplate( SvtModuleOptions::EFactory eFactory
) const;
261 static OUString
GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory eFactory
);
262 OUString
const & GetFactoryDefaultFilter ( SvtModuleOptions::EFactory eFactory
) const;
263 bool IsDefaultFilterReadonly( SvtModuleOptions::EFactory eFactory
) const;
264 sal_Int32
GetFactoryIcon ( SvtModuleOptions::EFactory eFactory
) const;
265 static bool ClassifyFactoryByName ( std::u16string_view sName
,
266 SvtModuleOptions::EFactory
& eFactory
);
267 void SetFactoryStandardTemplate( SvtModuleOptions::EFactory eFactory
,
268 const OUString
& sTemplate
);
269 void SetFactoryDefaultFilter ( SvtModuleOptions::EFactory eFactory
,
270 const OUString
& sFilter
);
271 void MakeReadonlyStatesAvailable();
276 static css::uno::Sequence
< OUString
> impl_ExpandSetNames ( const css::uno::Sequence
< OUString
>& lSetNames
);
277 void impl_Read ( const css::uno::Sequence
< OUString
>& lSetNames
);
279 virtual void ImplCommit() override
;
284 o3tl::enumarray
<SvtModuleOptions::EFactory
, FactoryInfo
> m_lFactories
;
285 bool m_bReadOnlyStatesWellKnown
;
288 /*-************************************************************************************************************
290 @descr We open our configuration here and read all necessary values from it.
291 These values are cached till everyone call Commit(). Then we write changed ones back to cfg.
293 @seealso baseclass ConfigItem
294 @seealso method impl_Read()
296 *//*-*************************************************************************************************************/
297 SvtModuleOptions_Impl::SvtModuleOptions_Impl()
298 : ::utl::ConfigItem( ROOTNODE_FACTORIES
)
299 , m_bReadOnlyStatesWellKnown( false )
301 // First initialize list of factory infos! Otherwise we couldn't guarantee right working of these class.
302 for( auto & rFactory
: m_lFactories
)
305 // Get name list of all existing set node names in configuration to read her properties in impl_Read().
306 // These list is a list of long names of our factories.
307 const css::uno::Sequence
< OUString
> lFactories
= GetNodeNames( OUString() );
308 impl_Read( lFactories
);
310 // Enable notification for changes by using configuration directly.
311 // So we can update our internal values immediately.
312 EnableNotification( lFactories
);
315 SvtModuleOptions_Impl::~SvtModuleOptions_Impl()
317 assert(!IsModified()); // should have been committed
320 /*-************************************************************************************************************
321 @short called for notify of configmanager
322 @descr This method is called from the ConfigManager before application ends or from the
323 PropertyChangeListener if the sub tree broadcasts changes. You must update our
326 @attention We are registered for pure set node names only. So we can use our internal method "impl_Read()" to
327 update our info list. Because - this method expand given name list to full qualified property list
328 and use it to read the values. These values are filled into our internal member list m_lFactories
331 @seealso method impl_Read()
333 @param "lNames" is the list of set node entries which should be updated.
335 *//*-*************************************************************************************************************/
336 void SvtModuleOptions_Impl::Notify( const css::uno::Sequence
< OUString
>& )
338 OSL_FAIL( "SvtModuleOptions_Impl::Notify() Not implemented yet!" );
341 /*-****************************************************************************************************
342 @short write changes to configuration
343 @descr This method writes the changed values into the sub tree
344 and should always called in our destructor to guarantee consistency of config data.
346 @attention We clear complete set in configuration first and write it completely new! So we don't must
347 distinguish between existing, added or removed elements. Our internal cached values
348 are the only and right ones.
350 @seealso baseclass ConfigItem
352 *//*-*****************************************************************************************************/
353 void SvtModuleOptions_Impl::ImplCommit()
355 // Reserve memory for ALL possible factory properties!
356 // Step over all factories and get her really changed values only.
357 // Build list of these ones and use it for commit.
358 css::uno::Sequence
< css::beans::PropertyValue
> lCommitProperties( FACTORYCOUNT
*PROPERTYCOUNT
);
359 sal_Int32 nRealCount
= 0;
361 for( FactoryInfo
& rInfo
: m_lFactories
)
363 // These path is used to build full qualified property names...
364 // See pInfo->getChangedProperties() for further information
365 sBasePath
= PATHSEPARATOR
+ rInfo
.getFactory() + PATHSEPARATOR
;
367 const css::uno::Sequence
< css::beans::PropertyValue
> lChangedProperties
= rInfo
.getChangedProperties ( sBasePath
);
368 std::copy(lChangedProperties
.begin(), lChangedProperties
.end(), std::next(lCommitProperties
.getArray(), nRealCount
));
369 nRealCount
+= lChangedProperties
.getLength();
371 // Resize commit list to real size.
372 // If nothing to do - suppress calling of configuration...
373 // It could be too expensive :-)
376 lCommitProperties
.realloc( nRealCount
);
377 SetSetProperties( OUString(), lCommitProperties
);
381 /*-****************************************************************************************************
382 @short access method to get internal values
383 @descr These methods implement easy access to our internal values.
384 You give us right enum value to specify which module interest you ... we return right information.
386 @attention Some people use any value as enum ... but we support in header specified values only!
387 We use it directly as index in our internal list. If enum value isn't right - we crash with an
388 "index out of range"!!! Please use me right - otherwise there is no guarantee.
389 @param "eModule" , index in list - specify module
390 @return Queried information.
392 @onerror We return default values. (mostly "not installed"!)
394 *//*-*****************************************************************************************************/
395 bool SvtModuleOptions_Impl::IsModuleInstalled( SvtModuleOptions::EModule eModule
) const
399 case SvtModuleOptions::EModule::WRITER
:
400 return m_lFactories
[SvtModuleOptions::EFactory::WRITER
].getInstalled();
401 case SvtModuleOptions::EModule::WEB
:
402 return m_lFactories
[SvtModuleOptions::EFactory::WRITERWEB
].getInstalled();
403 case SvtModuleOptions::EModule::GLOBAL
:
404 return m_lFactories
[SvtModuleOptions::EFactory::WRITERGLOBAL
].getInstalled();
405 case SvtModuleOptions::EModule::CALC
:
406 return m_lFactories
[SvtModuleOptions::EFactory::CALC
].getInstalled();
407 case SvtModuleOptions::EModule::DRAW
:
408 return m_lFactories
[SvtModuleOptions::EFactory::DRAW
].getInstalled();
409 case SvtModuleOptions::EModule::IMPRESS
:
410 return m_lFactories
[SvtModuleOptions::EFactory::IMPRESS
].getInstalled();
411 case SvtModuleOptions::EModule::MATH
:
412 return m_lFactories
[SvtModuleOptions::EFactory::MATH
].getInstalled();
413 case SvtModuleOptions::EModule::CHART
:
414 return m_lFactories
[SvtModuleOptions::EFactory::CHART
].getInstalled();
415 case SvtModuleOptions::EModule::STARTMODULE
:
416 return m_lFactories
[SvtModuleOptions::EFactory::STARTMODULE
].getInstalled();
417 case SvtModuleOptions::EModule::BASIC
:
418 return true; // Couldn't be deselected by setup yet!
419 case SvtModuleOptions::EModule::DATABASE
:
420 return m_lFactories
[SvtModuleOptions::EFactory::DATABASE
].getInstalled();
426 css::uno::Sequence
< OUString
> SvtModuleOptions_Impl::GetAllServiceNames()
428 std::vector
<OUString
> aVec
;
430 for( const auto & rFactory
: m_lFactories
)
431 if( rFactory
.getInstalled() )
432 aVec
.push_back( rFactory
.getFactory() );
434 return comphelper::containerToSequence(aVec
);
437 OUString
const & SvtModuleOptions_Impl::GetFactoryName( SvtModuleOptions::EFactory eFactory
) const
439 return m_lFactories
[eFactory
].getFactory();
442 OUString
SvtModuleOptions::GetFactoryShortName(SvtModuleOptions::EFactory eFactory
)
444 // Attention: Hard configured yet ... because it's not fine to make changes possible by xml file yet.
445 // But it's good to plan further possibilities!
447 //return m_lFactories[eFactory].sShortName;
452 case SvtModuleOptions::EFactory::WRITER
: sShortName
= "swriter";
454 case SvtModuleOptions::EFactory::WRITERWEB
: sShortName
= "swriter/web";
456 case SvtModuleOptions::EFactory::WRITERGLOBAL
: sShortName
= "swriter/GlobalDocument";
458 case SvtModuleOptions::EFactory::CALC
: sShortName
= "scalc";
460 case SvtModuleOptions::EFactory::DRAW
: sShortName
= "sdraw";
462 case SvtModuleOptions::EFactory::IMPRESS
: sShortName
= "simpress";
464 case SvtModuleOptions::EFactory::MATH
: sShortName
= "smath";
466 case SvtModuleOptions::EFactory::CHART
: sShortName
= "schart";
468 case SvtModuleOptions::EFactory::BASIC
: sShortName
= "sbasic";
470 case SvtModuleOptions::EFactory::DATABASE
: sShortName
= "sdatabase";
472 case SvtModuleOptions::EFactory::STARTMODULE
: sShortName
= "startmodule";
475 OSL_FAIL( "unknown factory" );
482 OUString
const & SvtModuleOptions_Impl::GetFactoryStandardTemplate( SvtModuleOptions::EFactory eFactory
) const
484 return m_lFactories
[eFactory
].getTemplateFile();
487 OUString
SvtModuleOptions_Impl::GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory eFactory
)
489 // Attention: Hard configured yet ... because it's not fine to make changes possible by xml file yet.
490 // But it's good to plan further possibilities!
492 //return m_lFactories[eFactory].getEmptyDocumentURL();
497 case SvtModuleOptions::EFactory::WRITER
: sURL
= "private:factory/swriter";
499 case SvtModuleOptions::EFactory::WRITERWEB
: sURL
= "private:factory/swriter/web";
501 case SvtModuleOptions::EFactory::WRITERGLOBAL
: sURL
= "private:factory/swriter/GlobalDocument";
503 case SvtModuleOptions::EFactory::CALC
: sURL
= "private:factory/scalc";
505 case SvtModuleOptions::EFactory::DRAW
: sURL
= "private:factory/sdraw";
507 case SvtModuleOptions::EFactory::IMPRESS
: sURL
= "private:factory/simpress?slot=6686";
509 case SvtModuleOptions::EFactory::MATH
: sURL
= "private:factory/smath";
511 case SvtModuleOptions::EFactory::CHART
: sURL
= "private:factory/schart";
513 case SvtModuleOptions::EFactory::BASIC
: sURL
= "private:factory/sbasic";
515 case SvtModuleOptions::EFactory::DATABASE
: sURL
= "private:factory/sdatabase?Interactive";
518 OSL_FAIL( "unknown factory" );
524 OUString
const & SvtModuleOptions_Impl::GetFactoryDefaultFilter( SvtModuleOptions::EFactory eFactory
) const
526 return m_lFactories
[eFactory
].getDefaultFilter();
529 bool SvtModuleOptions_Impl::IsDefaultFilterReadonly( SvtModuleOptions::EFactory eFactory
) const
531 return m_lFactories
[eFactory
].isDefaultFilterReadonly();
534 sal_Int32
SvtModuleOptions_Impl::GetFactoryIcon( SvtModuleOptions::EFactory eFactory
) const
536 return m_lFactories
[eFactory
].getIcon();
539 void SvtModuleOptions_Impl::SetFactoryStandardTemplate( SvtModuleOptions::EFactory eFactory
,
540 const OUString
& sTemplate
)
542 m_lFactories
[eFactory
].setTemplateFile( sTemplate
);
546 void SvtModuleOptions_Impl::SetFactoryDefaultFilter( SvtModuleOptions::EFactory eFactory
,
547 const OUString
& sFilter
)
549 m_lFactories
[eFactory
].setDefaultFilter( sFilter
);
553 /*-************************************************************************************************************
554 @short return list of key names of our configuration management which represent our module tree
555 @descr You give use a list of current existing set node names .. and we expand it for all
556 well known properties which are necessary for this implementation.
557 These full expanded list should be used to get values of this properties.
560 @return List of all relative addressed properties of given set entry names.
562 @onerror List will be empty.
564 *//*-*************************************************************************************************************/
565 css::uno::Sequence
< OUString
> SvtModuleOptions_Impl::impl_ExpandSetNames( const css::uno::Sequence
< OUString
>& lSetNames
)
567 sal_Int32 nCount
= lSetNames
.getLength();
568 css::uno::Sequence
< OUString
> lPropNames ( nCount
*PROPERTYCOUNT
);
569 OUString
* pPropNames
= lPropNames
.getArray();
570 sal_Int32 nPropStart
= 0;
572 for( const auto& rSetName
: lSetNames
)
574 pPropNames
[nPropStart
+PROPERTYHANDLE_SHORTNAME
] = rSetName
+ PATHSEPARATOR PROPERTYNAME_SHORTNAME
;
575 pPropNames
[nPropStart
+PROPERTYHANDLE_TEMPLATEFILE
] = rSetName
+ PATHSEPARATOR PROPERTYNAME_TEMPLATEFILE
;
576 pPropNames
[nPropStart
+PROPERTYHANDLE_WINDOWATTRIBUTES
] = rSetName
+ PATHSEPARATOR PROPERTYNAME_WINDOWATTRIBUTES
;
577 pPropNames
[nPropStart
+PROPERTYHANDLE_EMPTYDOCUMENTURL
] = rSetName
+ PATHSEPARATOR PROPERTYNAME_EMPTYDOCUMENTURL
;
578 pPropNames
[nPropStart
+PROPERTYHANDLE_DEFAULTFILTER
] = rSetName
+ PATHSEPARATOR PROPERTYNAME_DEFAULTFILTER
;
579 pPropNames
[nPropStart
+PROPERTYHANDLE_ICON
] = rSetName
+ PATHSEPARATOR PROPERTYNAME_ICON
;
580 nPropStart
+= PROPERTYCOUNT
;
586 /*-************************************************************************************************************
587 @short helper to classify given factory by name
588 @descr Every factory has its own long and short name. So we can match right enum value for internal using.
590 @attention We change in/out parameter "eFactory" in every case! But you should use it only, if return value is sal_True!
591 Algorithm: Set out-parameter to probably value ... and check the longname.
592 If it matches with these factory - break operation and return true AND right set parameter.
593 Otherwise try next one and so on. If no factory was found return false. Out parameter eFactory
594 is set to last tried value but shouldn't be used! Because our return value is false!
595 @param "sLongName" , long name of factory, which should be classified
596 @return "eFactory" , right enum value, which match given long name
597 and true for successfully classification, false otherwise
599 @onerror We return false.
601 *//*-*************************************************************************************************************/
602 bool SvtModuleOptions_Impl::ClassifyFactoryByName( std::u16string_view sName
, SvtModuleOptions::EFactory
& eFactory
)
606 eFactory
= SvtModuleOptions::EFactory::WRITER
;
607 bState
= ( sName
== FACTORYNAME_WRITER
);
611 eFactory
= SvtModuleOptions::EFactory::WRITERWEB
;
612 bState
= ( sName
== FACTORYNAME_WRITERWEB
);
617 eFactory
= SvtModuleOptions::EFactory::WRITERGLOBAL
;
618 bState
= ( sName
== FACTORYNAME_WRITERGLOBAL
);
623 eFactory
= SvtModuleOptions::EFactory::CALC
;
624 bState
= ( sName
== FACTORYNAME_CALC
);
629 eFactory
= SvtModuleOptions::EFactory::DRAW
;
630 bState
= ( sName
== FACTORYNAME_DRAW
);
635 eFactory
= SvtModuleOptions::EFactory::IMPRESS
;
636 bState
= ( sName
== FACTORYNAME_IMPRESS
);
641 eFactory
= SvtModuleOptions::EFactory::MATH
;
642 bState
= ( sName
== FACTORYNAME_MATH
);
647 eFactory
= SvtModuleOptions::EFactory::CHART
;
648 bState
= ( sName
== FACTORYNAME_CHART
);
653 eFactory
= SvtModuleOptions::EFactory::DATABASE
;
654 bState
= ( sName
== FACTORYNAME_DATABASE
);
659 eFactory
= SvtModuleOptions::EFactory::STARTMODULE
;
660 bState
= ( sName
== FACTORYNAME_STARTMODULE
);
665 eFactory
= SvtModuleOptions::EFactory::BASIC
;
666 bState
= ( sName
== FACTORYNAME_BASIC
);
672 /*-************************************************************************************************************
673 @short read factory configuration
674 @descr Give us a list of pure factory names (long names!) which can be used as
675 direct set node names... and we read her property values and fill internal list.
676 These method can be used by initial reading at ctor and later updating by "Notify()".
679 @seealso method Notify()
681 @param "lFactories" is the list of set node entries which should be read.
682 @onerror We do nothing.
684 *//*-*************************************************************************************************************/
685 void SvtModuleOptions_Impl::impl_Read( const css::uno::Sequence
< OUString
>& lFactories
)
687 // Expand every set node name in lFactories to full qualified paths to its properties
688 // and get right values from configuration.
689 const css::uno::Sequence
< OUString
> lProperties
= impl_ExpandSetNames( lFactories
);
690 const css::uno::Sequence
< css::uno::Any
> lValues
= GetProperties( lProperties
);
692 // Safe impossible cases.
693 // We need values from ALL configuration keys.
694 // Follow assignment use order of values in relation to our list of key names!
695 OSL_ENSURE( !(lProperties
.getLength()!=lValues
.getLength()), "SvtModuleOptions_Impl::impl_Read()\nI miss some values of configuration keys!" );
697 // Algorithm: We step over all given factory names and classify it. These enum value can be used as direct index
698 // in our member list m_lFactories! VAriable nPropertyStart marks start position of every factory
699 // and her properties in expanded property/value list. The defines PROPERTHANDLE_xxx are used as offset values
700 // added to nPropertyStart. So we can address every property relative in these lists.
701 // If we found any valid values ... we reset all existing information for corresponding m_lFactories-entry and
702 // use a pointer to these struct in memory directly to set new values.
703 // But we set it only, if bInstalled is true. Otherwise all other values of a factory can be undeclared .. They
704 // shouldn't be used then.
705 // Attention: If a propertyset of a factory will be ignored we must step to next start position of next factory infos!
706 // see "nPropertyStart += PROPERTYCOUNT" ...
708 sal_Int32 nPropertyStart
= 0;
709 FactoryInfo
* pInfo
= nullptr;
710 SvtModuleOptions::EFactory eFactory
;
712 for( const OUString
& sFactoryName
: lFactories
)
714 if( ClassifyFactoryByName( sFactoryName
, eFactory
) )
719 pInfo
= &(m_lFactories
[eFactory
]);
722 pInfo
->initInstalled();
723 pInfo
->initFactory ( sFactoryName
);
725 if (lValues
[nPropertyStart
+PROPERTYHANDLE_TEMPLATEFILE
] >>= sTemp
)
726 pInfo
->initTemplateFile( sTemp
);
727 if (lValues
[nPropertyStart
+PROPERTYHANDLE_DEFAULTFILTER
] >>= sTemp
)
728 pInfo
->initDefaultFilter( sTemp
);
729 if (lValues
[nPropertyStart
+PROPERTYHANDLE_ICON
] >>= nTemp
)
730 pInfo
->initIcon( nTemp
);
732 nPropertyStart
+= PROPERTYCOUNT
;
736 void SvtModuleOptions_Impl::MakeReadonlyStatesAvailable()
738 if (m_bReadOnlyStatesWellKnown
)
741 css::uno::Sequence
< OUString
> lFactories
= GetNodeNames(OUString());
742 for (OUString
& rFactory
: asNonConstRange(lFactories
))
743 rFactory
+= PATHSEPARATOR PROPERTYNAME_DEFAULTFILTER
;
745 css::uno::Sequence
< sal_Bool
> lReadonlyStates
= GetReadOnlyStates(lFactories
);
746 sal_Int32 c
= lFactories
.getLength();
747 for (sal_Int32 i
=0; i
<c
; ++i
)
749 const OUString
& rFactoryName
= lFactories
[i
];
750 SvtModuleOptions::EFactory eFactory
;
752 if (!ClassifyFactoryByName(rFactoryName
, eFactory
))
755 FactoryInfo
& rInfo
= m_lFactories
[eFactory
];
756 rInfo
.setDefaultFilterReadonly(lReadonlyStates
[i
]);
759 m_bReadOnlyStatesWellKnown
= true;
764 std::weak_ptr
<SvtModuleOptions_Impl
> g_pModuleOptions
;
766 std::mutex
& impl_GetOwnStaticMutex()
768 static std::mutex s_Mutex
;
773 /*-************************************************************************************************************
774 @short standard constructor and destructor
775 @descr This will initialize an instance with default values. We initialize/deinitialize our static data
776 container and create a static mutex, which is used for threadsafe code in further time of this object.
778 @seealso method impl_GetOwnStaticMutex()
780 *//*-*************************************************************************************************************/
781 SvtModuleOptions::SvtModuleOptions()
783 // no need to take the mutex yet, shared_ptr/weak_ptr are thread-safe
784 m_pImpl
= g_pModuleOptions
.lock();
788 // take the mutex, so we don't accidentally create more than one
789 std::unique_lock
aGuard( impl_GetOwnStaticMutex() );
791 m_pImpl
= g_pModuleOptions
.lock();
794 m_pImpl
= std::make_shared
<SvtModuleOptions_Impl
>();
795 g_pModuleOptions
= m_pImpl
;
796 aGuard
.unlock(); // because holdConfigItem will call this constructor
797 ItemHolder1::holdConfigItem(EItem::ModuleOptions
);
801 SvtModuleOptions::~SvtModuleOptions()
806 /*-************************************************************************************************************
807 @short access to configuration data
808 @descr This methods allow read/write access to configuration values.
809 They are threadsafe. All calls are forwarded to impl-data-container. See there for further information!
811 @seealso method impl_GetOwnStaticMutex()
813 *//*-*************************************************************************************************************/
814 bool SvtModuleOptions::IsModuleInstalled( EModule eModule
) const
816 // doesn't need mutex, never modified
817 return m_pImpl
->IsModuleInstalled( eModule
);
820 const OUString
& SvtModuleOptions::GetFactoryName( EFactory eFactory
) const
822 // doesn't need mutex, never modified
823 return m_pImpl
->GetFactoryName( eFactory
);
826 OUString
SvtModuleOptions::GetFactoryStandardTemplate( EFactory eFactory
) const
828 std::unique_lock
aGuard( impl_GetOwnStaticMutex() );
829 return m_pImpl
->GetFactoryStandardTemplate( eFactory
);
832 OUString
SvtModuleOptions::GetFactoryEmptyDocumentURL( EFactory eFactory
) const
834 std::unique_lock
aGuard( impl_GetOwnStaticMutex() );
835 return SvtModuleOptions_Impl::GetFactoryEmptyDocumentURL( eFactory
);
838 OUString
SvtModuleOptions::GetFactoryDefaultFilter( EFactory eFactory
) const
840 std::unique_lock
aGuard( impl_GetOwnStaticMutex() );
841 return m_pImpl
->GetFactoryDefaultFilter( eFactory
);
844 bool SvtModuleOptions::IsDefaultFilterReadonly( EFactory eFactory
) const
846 std::unique_lock
aGuard( impl_GetOwnStaticMutex() );
847 m_pImpl
->MakeReadonlyStatesAvailable();
848 return m_pImpl
->IsDefaultFilterReadonly( eFactory
);
851 sal_Int32
SvtModuleOptions::GetFactoryIcon( EFactory eFactory
) const
853 std::unique_lock
aGuard( impl_GetOwnStaticMutex() );
854 return m_pImpl
->GetFactoryIcon( eFactory
);
857 bool SvtModuleOptions::ClassifyFactoryByName( std::u16string_view sName
,
860 // We don't need any mutex here ... because we don't use any member here!
861 return SvtModuleOptions_Impl::ClassifyFactoryByName( sName
, eFactory
);
864 void SvtModuleOptions::SetFactoryStandardTemplate( EFactory eFactory
,
865 const OUString
& sTemplate
)
867 std::unique_lock
aGuard( impl_GetOwnStaticMutex() );
868 m_pImpl
->SetFactoryStandardTemplate( eFactory
, sTemplate
);
871 void SvtModuleOptions::SetFactoryDefaultFilter( EFactory eFactory
,
872 const OUString
& sFilter
)
874 std::unique_lock
aGuard( impl_GetOwnStaticMutex() );
875 m_pImpl
->SetFactoryDefaultFilter( eFactory
, sFilter
);
878 bool SvtModuleOptions::IsMath() const
880 // doesn't need mutex, never modified
881 return m_pImpl
->IsModuleInstalled( EModule::MATH
);
884 bool SvtModuleOptions::IsChart() const
886 // doesn't need mutex, never modified
887 return m_pImpl
->IsModuleInstalled( EModule::CHART
);
890 bool SvtModuleOptions::IsCalc() const
892 // doesn't need mutex, never modified
893 return m_pImpl
->IsModuleInstalled( EModule::CALC
);
896 bool SvtModuleOptions::IsDraw() const
898 // doesn't need mutex, never modified
899 return m_pImpl
->IsModuleInstalled( EModule::DRAW
);
902 bool SvtModuleOptions::IsWriter() const
904 std::unique_lock
aGuard( impl_GetOwnStaticMutex() );
905 return m_pImpl
->IsModuleInstalled( EModule::WRITER
);
908 bool SvtModuleOptions::IsImpress() const
910 // doesn't need mutex, never modified
911 return m_pImpl
->IsModuleInstalled( EModule::IMPRESS
);
914 bool SvtModuleOptions::IsDataBase() const
916 // doesn't need mutex, never modified
917 return m_pImpl
->IsModuleInstalled( EModule::DATABASE
);
920 OUString
SvtModuleOptions::GetModuleName( EModule eModule
) const
924 case SvtModuleOptions::EModule::WRITER
: { return "Writer"; }
925 case SvtModuleOptions::EModule::WEB
: { return "Web"; }
926 case SvtModuleOptions::EModule::GLOBAL
: { return "Global"; }
927 case SvtModuleOptions::EModule::CALC
: { return "Calc"; }
928 case SvtModuleOptions::EModule::DRAW
: { return "Draw"; }
929 case SvtModuleOptions::EModule::IMPRESS
: { return "Impress"; }
930 case SvtModuleOptions::EModule::MATH
: { return "Math"; }
931 case SvtModuleOptions::EModule::CHART
: { return "Chart"; }
932 case SvtModuleOptions::EModule::BASIC
: { return "Basic"; }
933 case SvtModuleOptions::EModule::DATABASE
: { return "Database"; }
935 OSL_FAIL( "unknown module" );
942 SvtModuleOptions::EFactory
SvtModuleOptions::ClassifyFactoryByShortName(std::u16string_view sName
)
944 if ( sName
== u
"swriter" )
945 return EFactory::WRITER
;
946 if (o3tl::equalsIgnoreAsciiCase(sName
, u
"swriter/Web")) // sometimes they are registered for swriter/web :-(
947 return EFactory::WRITERWEB
;
948 if (o3tl::equalsIgnoreAsciiCase(sName
, u
"swriter/GlobalDocument")) // sometimes they are registered for swriter/globaldocument :-(
949 return EFactory::WRITERGLOBAL
;
950 if ( sName
== u
"scalc" )
951 return EFactory::CALC
;
952 if ( sName
== u
"sdraw" )
953 return EFactory::DRAW
;
954 if ( sName
== u
"simpress" )
955 return EFactory::IMPRESS
;
956 if ( sName
== u
"schart" )
957 return EFactory::CHART
;
958 if ( sName
== u
"smath" )
959 return EFactory::MATH
;
960 if ( sName
== u
"sbasic" )
961 return EFactory::BASIC
;
962 if ( sName
== u
"sdatabase" )
963 return EFactory::DATABASE
;
965 return EFactory::UNKNOWN_FACTORY
;
968 SvtModuleOptions::EFactory
SvtModuleOptions::ClassifyFactoryByServiceName(std::u16string_view sName
)
970 if (sName
== FACTORYNAME_WRITERGLOBAL
)
971 return EFactory::WRITERGLOBAL
;
972 if (sName
== FACTORYNAME_WRITERWEB
)
973 return EFactory::WRITERWEB
;
974 if (sName
== FACTORYNAME_WRITER
)
975 return EFactory::WRITER
;
976 if (sName
== FACTORYNAME_CALC
)
977 return EFactory::CALC
;
978 if (sName
== FACTORYNAME_DRAW
)
979 return EFactory::DRAW
;
980 if (sName
== FACTORYNAME_IMPRESS
)
981 return EFactory::IMPRESS
;
982 if (sName
== FACTORYNAME_MATH
)
983 return EFactory::MATH
;
984 if (sName
== FACTORYNAME_CHART
)
985 return EFactory::CHART
;
986 if (sName
== FACTORYNAME_DATABASE
)
987 return EFactory::DATABASE
;
988 if (sName
== FACTORYNAME_STARTMODULE
)
989 return EFactory::STARTMODULE
;
990 if (sName
== FACTORYNAME_BASIC
)
991 return EFactory::BASIC
;
993 return EFactory::UNKNOWN_FACTORY
;
996 SvtModuleOptions::EFactory
SvtModuleOptions::ClassifyFactoryByURL(const OUString
& sURL
,
997 const css::uno::Sequence
< css::beans::PropertyValue
>& lMediaDescriptor
)
999 css::uno::Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
1001 css::uno::Reference
< css::container::XNameAccess
> xFilterCfg
;
1002 css::uno::Reference
< css::container::XNameAccess
> xTypeCfg
;
1006 xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", xContext
), css::uno::UNO_QUERY
);
1008 xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", xContext
), css::uno::UNO_QUERY
);
1010 catch(const css::uno::RuntimeException
&)
1012 catch(const css::uno::Exception
&)
1013 { return EFactory::UNKNOWN_FACTORY
; }
1015 ::comphelper::SequenceAsHashMap
stlDesc(lMediaDescriptor
);
1017 // is there already a filter inside the descriptor?
1018 OUString sFilterName
= stlDesc
.getUnpackedValueOrDefault("FilterName", OUString());
1019 if (!sFilterName
.isEmpty())
1023 ::comphelper::SequenceAsHashMap
stlFilterProps (xFilterCfg
->getByName(sFilterName
));
1024 OUString sDocumentService
= stlFilterProps
.getUnpackedValueOrDefault("DocumentService", OUString());
1025 SvtModuleOptions::EFactory eApp
= SvtModuleOptions::ClassifyFactoryByServiceName(sDocumentService
);
1027 if (eApp
!= EFactory::UNKNOWN_FACTORY
)
1030 catch(const css::uno::RuntimeException
&)
1032 catch(const css::uno::Exception
&)
1033 { /* do nothing here ... may the following code can help!*/ }
1036 // is there already a type inside the descriptor?
1037 OUString sTypeName
= stlDesc
.getUnpackedValueOrDefault("TypeName", OUString());
1038 if (sTypeName
.isEmpty())
1041 // start flat detection of URL
1042 css::uno::Reference
< css::document::XTypeDetection
> xDetect(xTypeCfg
, css::uno::UNO_QUERY
);
1043 sTypeName
= xDetect
->queryTypeByURL(sURL
);
1046 if (sTypeName
.isEmpty())
1047 return EFactory::UNKNOWN_FACTORY
;
1049 // yes - there is a type info
1050 // Try to find the preferred filter.
1053 ::comphelper::SequenceAsHashMap
stlTypeProps (xTypeCfg
->getByName(sTypeName
));
1054 OUString sPreferredFilter
= stlTypeProps
.getUnpackedValueOrDefault("PreferredFilter", OUString());
1055 ::comphelper::SequenceAsHashMap
stlFilterProps (xFilterCfg
->getByName(sPreferredFilter
));
1056 OUString sDocumentService
= stlFilterProps
.getUnpackedValueOrDefault("DocumentService", OUString());
1057 SvtModuleOptions::EFactory eApp
= SvtModuleOptions::ClassifyFactoryByServiceName(sDocumentService
);
1059 if (eApp
!= EFactory::UNKNOWN_FACTORY
)
1062 catch(const css::uno::RuntimeException
&)
1064 catch(const css::uno::Exception
&)
1065 { /* do nothing here ... may the following code can help!*/ }
1067 // no filter/no type/no detection result => no fun :-)
1068 return EFactory::UNKNOWN_FACTORY
;
1071 SvtModuleOptions::EFactory
SvtModuleOptions::ClassifyFactoryByModel(const css::uno::Reference
< css::frame::XModel
>& xModel
)
1073 css::uno::Reference
< css::lang::XServiceInfo
> xInfo(xModel
, css::uno::UNO_QUERY
);
1075 return EFactory::UNKNOWN_FACTORY
;
1077 const css::uno::Sequence
< OUString
> lServices
= xInfo
->getSupportedServiceNames();
1079 for (const OUString
& rService
: lServices
)
1081 SvtModuleOptions::EFactory eApp
= SvtModuleOptions::ClassifyFactoryByServiceName(rService
);
1082 if (eApp
!= EFactory::UNKNOWN_FACTORY
)
1086 return EFactory::UNKNOWN_FACTORY
;
1089 css::uno::Sequence
< OUString
> SvtModuleOptions::GetAllServiceNames()
1091 std::unique_lock
aGuard( impl_GetOwnStaticMutex() );
1092 return m_pImpl
->GetAllServiceNames();
1095 OUString
SvtModuleOptions::GetDefaultModuleName() const
1098 if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::WRITER
))
1099 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::WRITER
);
1100 else if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::CALC
))
1101 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::CALC
);
1102 else if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::IMPRESS
))
1103 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::IMPRESS
);
1104 else if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::DATABASE
))
1105 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::DATABASE
);
1106 else if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::DRAW
))
1107 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::DRAW
);
1108 else if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::WEB
))
1109 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::WRITERWEB
);
1110 else if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::GLOBAL
))
1111 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::WRITERGLOBAL
);
1112 else if (m_pImpl
->IsModuleInstalled(SvtModuleOptions::EModule::MATH
))
1113 aModule
= GetFactoryShortName(SvtModuleOptions::EFactory::MATH
);
1117 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */