Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / unotools / source / config / moduleoptions.cxx
blobc6442a16ab9e041ed0f0be64275884bc7792d404
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
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!
47 e.g.:
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 *//*-*************************************************************************************************************/
90 struct FactoryInfo
92 public:
94 // initialize empty struct
95 FactoryInfo()
97 free();
100 // easy way to reset struct member!
101 void free()
103 bInstalled = false;
104 sFactory.clear();
105 sTemplateFile.clear();
106 sDefaultFilter.clear();
107 nIcon = 0;
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 );
134 else
136 lProperties[nRealyChanged].Value <<= sTemplateFile;
139 ++nRealyChanged;
141 if( bChangedDefaultFilter )
143 lProperties[nRealyChanged].Name = sNodeBase + PROPERTYNAME_DEFAULTFILTER;
144 lProperties[nRealyChanged].Value <<= sDefaultFilter;
145 ++nRealyChanged;
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 );
153 return lProperties;
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 );
180 else
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;
204 private:
205 css::uno::Reference< css::util::XStringSubstitution > const & getStringSubstitution()
207 if ( !xSubstVars.is() )
209 xSubstVars.set( css::util::PathSubstitution::create(::comphelper::getProcessComponentContext()) );
211 return xSubstVars;
214 bool bInstalled;
215 OUString sFactory;
216 OUString sTemplateFile;
217 OUString sDefaultFilter;
218 sal_Int32 nIcon;
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
230 // public methods
232 public:
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;
243 // public interface
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();
261 // private methods
263 private:
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;
269 // private member
271 private:
272 o3tl::enumarray<SvtModuleOptions::EFactory, FactoryInfo> m_lFactories;
273 bool m_bReadOnlyStatesWellKnown;
276 /*-************************************************************************************************************
277 @short default ctor
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()
283 @threadsafe no
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 )
291 rFactory.free();
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
312 internal values.
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
317 at right position.
319 @seealso method impl_Read()
321 @param "lNames" is the list of set node entries which should be updated.
322 @threadsafe no
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
339 @threadsafe no
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;
348 OUString sBasePath;
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 :-)
362 if( nRealCount > 0 )
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"!)
381 @threadsafe no
382 *//*-*****************************************************************************************************/
383 bool SvtModuleOptions_Impl::IsModuleInstalled( SvtModuleOptions::EModule eModule ) const
385 switch( eModule )
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();
411 return false;
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;
437 OUString sShortName;
438 switch( eFactory )
440 case SvtModuleOptions::EFactory::WRITER : sShortName = "swriter";
441 break;
442 case SvtModuleOptions::EFactory::WRITERWEB: sShortName = "swriter/web";
443 break;
444 case SvtModuleOptions::EFactory::WRITERGLOBAL: sShortName = "swriter/GlobalDocument";
445 break;
446 case SvtModuleOptions::EFactory::CALC : sShortName = "scalc";
447 break;
448 case SvtModuleOptions::EFactory::DRAW : sShortName = "sdraw";
449 break;
450 case SvtModuleOptions::EFactory::IMPRESS : sShortName = "simpress";
451 break;
452 case SvtModuleOptions::EFactory::MATH : sShortName = "smath";
453 break;
454 case SvtModuleOptions::EFactory::CHART : sShortName = "schart";
455 break;
456 case SvtModuleOptions::EFactory::BASIC : sShortName = "sbasic";
457 break;
458 case SvtModuleOptions::EFactory::DATABASE : sShortName = "sdatabase";
459 break;
460 default:
461 OSL_FAIL( "unknown factory" );
462 break;
465 return sShortName;
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();
480 OUString sURL;
481 switch( eFactory )
483 case SvtModuleOptions::EFactory::WRITER : sURL = "private:factory/swriter";
484 break;
485 case SvtModuleOptions::EFactory::WRITERWEB : sURL = "private:factory/swriter/web";
486 break;
487 case SvtModuleOptions::EFactory::WRITERGLOBAL : sURL = "private:factory/swriter/GlobalDocument";
488 break;
489 case SvtModuleOptions::EFactory::CALC : sURL = "private:factory/scalc";
490 break;
491 case SvtModuleOptions::EFactory::DRAW : sURL = "private:factory/sdraw";
492 break;
493 case SvtModuleOptions::EFactory::IMPRESS : sURL = "private:factory/simpress?slot=6686";
494 break;
495 case SvtModuleOptions::EFactory::MATH : sURL = "private:factory/smath";
496 break;
497 case SvtModuleOptions::EFactory::CHART : sURL = "private:factory/schart";
498 break;
499 case SvtModuleOptions::EFactory::BASIC : sURL = "private:factory/sbasic";
500 break;
501 case SvtModuleOptions::EFactory::DATABASE : sURL = "private:factory/sdatabase?Interactive";
502 break;
503 default:
504 OSL_FAIL( "unknown factory" );
505 break;
507 return sURL;
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 );
529 SetModified();
532 void SvtModuleOptions_Impl::SetFactoryDefaultFilter( SvtModuleOptions::EFactory eFactory,
533 const OUString& sFilter )
535 m_lFactories[eFactory].setDefaultFilter( sFilter );
536 SetModified();
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.
545 @seealso ctor
546 @return List of all relative addressed properties of given set entry names.
548 @onerror List will be empty.
549 @threadsafe no
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;
569 return lPropNames;
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.
586 @threadsafe no
587 *//*-*************************************************************************************************************/
588 bool SvtModuleOptions_Impl::ClassifyFactoryByName( const OUString& sName, SvtModuleOptions::EFactory& eFactory )
590 bool bState;
592 eFactory = SvtModuleOptions::EFactory::WRITER;
593 bState = ( sName == FACTORYNAME_WRITER );
595 if( !bState )
597 eFactory = SvtModuleOptions::EFactory::WRITERWEB;
598 bState = ( sName == FACTORYNAME_WRITERWEB );
600 // no else!
601 if( !bState )
603 eFactory = SvtModuleOptions::EFactory::WRITERGLOBAL;
604 bState = ( sName == FACTORYNAME_WRITERGLOBAL );
606 // no else!
607 if( !bState )
609 eFactory = SvtModuleOptions::EFactory::CALC;
610 bState = ( sName == FACTORYNAME_CALC );
612 // no else!
613 if( !bState )
615 eFactory = SvtModuleOptions::EFactory::DRAW;
616 bState = ( sName == FACTORYNAME_DRAW );
618 // no else!
619 if( !bState )
621 eFactory = SvtModuleOptions::EFactory::IMPRESS;
622 bState = ( sName == FACTORYNAME_IMPRESS );
624 // no else!
625 if( !bState )
627 eFactory = SvtModuleOptions::EFactory::MATH;
628 bState = ( sName == FACTORYNAME_MATH );
630 // no else!
631 if( !bState )
633 eFactory = SvtModuleOptions::EFactory::CHART;
634 bState = ( sName == FACTORYNAME_CHART );
636 // no else!
637 if( !bState )
639 eFactory = SvtModuleOptions::EFactory::DATABASE;
640 bState = ( sName == FACTORYNAME_DATABASE );
642 // no else!
643 if( !bState )
645 eFactory = SvtModuleOptions::EFactory::STARTMODULE;
646 bState = ( sName == FACTORYNAME_STARTMODULE);
648 // no else!
649 if( !bState )
651 eFactory = SvtModuleOptions::EFactory::BASIC;
652 bState = ( sName == FACTORYNAME_BASIC);
655 return bState;
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()".
664 @seealso ctor
665 @seealso method Notify()
667 @param "lFactories" is the list of set node entries which should be read.
668 @onerror We do nothing.
669 @threadsafe no
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 ) )
702 OUString sTemp;
703 sal_Int32 nTemp = 0;
705 pInfo = &(m_lFactories[eFactory]);
706 pInfo->free();
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)
725 return;
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))
741 continue;
743 FactoryInfo& rInfo = m_lFactories[eFactory];
744 rInfo.setDefaultFilterReadonly(lReadonlyStates[i]);
747 m_bReadOnlyStatesWellKnown = true;
750 namespace {
751 //global
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()
761 @threadsafe yes
762 *//*-*************************************************************************************************************/
763 SvtModuleOptions::SvtModuleOptions()
765 // Global access, must be guarded (multithreading!)
766 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
768 m_pImpl = g_pModuleOptions.lock();
769 if( !m_pImpl )
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() );
782 m_pImpl.reset();
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()
791 @threadsafe yes
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 ,
837 EFactory& eFactory )
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 );
899 namespace
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
907 member!
908 @return A reference to a static mutex member.
909 @threadsafe yes
910 *//*-*****************************************************************************************************/
911 ::osl::Mutex& SvtModuleOptions::impl_GetOwnStaticMutex()
913 return theModuleOptionsMutex::get();
916 OUString SvtModuleOptions::GetModuleName( EModule eModule ) const
918 switch( eModule )
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"; }
930 default:
931 OSL_FAIL( "unknown module" );
932 break;
935 return OUString();
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;
1001 xFilterCfg.set(
1002 xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", xContext), css::uno::UNO_QUERY);
1003 xTypeCfg.set(
1004 xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", xContext), css::uno::UNO_QUERY);
1006 catch(const css::uno::RuntimeException&)
1007 { throw; }
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)
1024 return eApp;
1026 catch(const css::uno::RuntimeException&)
1027 { throw; }
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())
1036 // no :-(
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)
1056 return eApp;
1058 catch(const css::uno::RuntimeException&)
1059 { throw; }
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);
1070 if (!xInfo.is())
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)
1079 return eApp;
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
1093 OUString aModule;
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);
1110 return aModule;
1113 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */