nss: upgrade to release 3.73
[LibreOffice.git] / unotools / source / config / moduleoptions.cxx
blob8082749e998b1eee12c95e2307a3e37959a4679c
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/frame/XModel.hpp>
33 #include <com/sun/star/lang/XServiceInfo.hpp>
34 #include <com/sun/star/document/XTypeDetection.hpp>
35 #include <com/sun/star/util/PathSubstitution.hpp>
36 #include <com/sun/star/util/XStringSubstitution.hpp>
38 #include "itemholder1.hxx"
40 /*-************************************************************************************************************
41 @descr These values are used to define necessary keys from our configuration management to support
42 all functionality of these implementation.
43 It's a fast way to make changes if some keys change its name or location!
45 Property handle are necessary to specify right position in return list of configuration
46 for asked values. We ask it with a list of properties to get its values. The returned list
47 has the same order like our given name list!
48 e.g.:
49 NAMELIST[ PROPERTYHANDLE_xxx ] => VALUELIST[ PROPERTYHANDLE_xxx ]
50 *//*-*************************************************************************************************************/
51 #define ROOTNODE_FACTORIES "Setup/Office/Factories"
52 #define PATHSEPARATOR "/"
54 // Attention: The property "ooSetupFactoryEmptyDocumentURL" is read from configuration but not used! There is
55 // special code that uses hard coded strings to return them.
56 #define PROPERTYNAME_SHORTNAME "ooSetupFactoryShortName"
57 #define PROPERTYNAME_TEMPLATEFILE "ooSetupFactoryTemplateFile"
58 #define PROPERTYNAME_WINDOWATTRIBUTES "ooSetupFactoryWindowAttributes"
59 #define PROPERTYNAME_EMPTYDOCUMENTURL "ooSetupFactoryEmptyDocumentURL"
60 #define PROPERTYNAME_DEFAULTFILTER "ooSetupFactoryDefaultFilter"
61 #define PROPERTYNAME_ICON "ooSetupFactoryIcon"
63 #define PROPERTYHANDLE_SHORTNAME 0
64 #define PROPERTYHANDLE_TEMPLATEFILE 1
65 #define PROPERTYHANDLE_WINDOWATTRIBUTES 2
66 #define PROPERTYHANDLE_EMPTYDOCUMENTURL 3
67 #define PROPERTYHANDLE_DEFAULTFILTER 4
68 #define PROPERTYHANDLE_ICON 5
70 #define PROPERTYCOUNT 6
72 #define FACTORYNAME_WRITER "com.sun.star.text.TextDocument"
73 #define FACTORYNAME_WRITERWEB "com.sun.star.text.WebDocument"
74 #define FACTORYNAME_WRITERGLOBAL "com.sun.star.text.GlobalDocument"
75 #define FACTORYNAME_CALC "com.sun.star.sheet.SpreadsheetDocument"
76 #define FACTORYNAME_DRAW "com.sun.star.drawing.DrawingDocument"
77 #define FACTORYNAME_IMPRESS "com.sun.star.presentation.PresentationDocument"
78 #define FACTORYNAME_MATH "com.sun.star.formula.FormulaProperties"
79 #define FACTORYNAME_CHART "com.sun.star.chart2.ChartDocument"
80 #define FACTORYNAME_DATABASE "com.sun.star.sdb.OfficeDatabaseDocument"
81 #define FACTORYNAME_STARTMODULE "com.sun.star.frame.StartModule"
82 #define FACTORYNAME_BASIC "com.sun.star.script.BasicIDE"
84 #define FACTORYCOUNT 11
86 namespace {
88 /*-************************************************************************************************************
89 @descr This struct hold information about one factory. We declare a complete array which can hold infos
90 for all well known factories. Values of enum "EFactory" (see header!) are directly used as index!
91 So we can support a fast access on this information.
92 *//*-*************************************************************************************************************/
93 struct FactoryInfo
95 public:
97 // initialize empty struct
98 FactoryInfo()
100 free();
103 // easy way to reset struct member!
104 void free()
106 bInstalled = false;
107 sFactory.clear();
108 sTemplateFile.clear();
109 sDefaultFilter.clear();
110 nIcon = 0;
111 bChangedTemplateFile = false;
112 bChangedDefaultFilter = false;
113 bDefaultFilterReadonly = false;
116 // returns list of properties, which has changed only!
117 // We use given value of sNodeBase to build full qualified paths ...
118 // Last sign of it must be "/". because we use it directly, without any additional things!
119 css::uno::Sequence< css::beans::PropertyValue > getChangedProperties( const OUString& sNodeBase )
121 // a) reserve memory for max. count of changed properties
122 // b) add names and values of changed ones only and count it
123 // c) resize return list by using count
124 css::uno::Sequence< css::beans::PropertyValue > lProperties ( 4 );
125 sal_Int8 nRealyChanged = 0;
127 if( bChangedTemplateFile )
129 lProperties[nRealyChanged].Name = sNodeBase + PROPERTYNAME_TEMPLATEFILE;
131 if ( !sTemplateFile.isEmpty() )
133 lProperties[nRealyChanged].Value
134 <<= getStringSubstitution()
135 ->reSubstituteVariables( sTemplateFile );
137 else
139 lProperties[nRealyChanged].Value <<= sTemplateFile;
142 ++nRealyChanged;
144 if( bChangedDefaultFilter )
146 lProperties[nRealyChanged].Name = sNodeBase + PROPERTYNAME_DEFAULTFILTER;
147 lProperties[nRealyChanged].Value <<= sDefaultFilter;
148 ++nRealyChanged;
151 // Don't forget to reset changed flags! Otherwise we save it again and again and ...
152 bChangedTemplateFile = false;
153 bChangedDefaultFilter = false;
155 lProperties.realloc( nRealyChanged );
156 return lProperties;
159 // We must support setting AND marking of changed values.
160 // That's why we can't make our member public. We must use get/set/init methods
161 // to control access on it!
162 bool getInstalled () const { return bInstalled; };
163 const OUString& getFactory () const { return sFactory; };
164 const OUString& getTemplateFile () const { return sTemplateFile; };
165 const OUString& getDefaultFilter () const { return sDefaultFilter; };
166 bool isDefaultFilterReadonly() const { return bDefaultFilterReadonly; }
167 sal_Int32 getIcon () const { return nIcon; };
169 // If you call set-methods - we check for changes of values and mark it.
170 // But if you wish to set it without that... you must initialize it!
171 void initInstalled () { bInstalled = true; }
172 void initFactory ( const OUString& sNewFactory ) { sFactory = sNewFactory; }
173 void initDefaultFilter ( const OUString& sNewDefaultFilter ) { sDefaultFilter = sNewDefaultFilter; }
174 void setDefaultFilterReadonly( const bool bVal){bDefaultFilterReadonly = bVal;}
175 void initIcon ( sal_Int32 nNewIcon ) { nIcon = nNewIcon; }
177 void initTemplateFile( const OUString& sNewTemplateFile )
179 if ( !sNewTemplateFile.isEmpty() )
181 sTemplateFile= getStringSubstitution()->substituteVariables( sNewTemplateFile, false );
183 else
185 sTemplateFile = sNewTemplateFile;
189 void setTemplateFile( const OUString& sNewTemplateFile )
191 if( sTemplateFile != sNewTemplateFile )
193 sTemplateFile = sNewTemplateFile;
194 bChangedTemplateFile = true;
198 void setDefaultFilter( const OUString& sNewDefaultFilter )
200 if( sDefaultFilter != sNewDefaultFilter )
202 sDefaultFilter = sNewDefaultFilter;
203 bChangedDefaultFilter = true;
207 private:
208 css::uno::Reference< css::util::XStringSubstitution > const & getStringSubstitution()
210 if ( !xSubstVars.is() )
212 xSubstVars.set( css::util::PathSubstitution::create(::comphelper::getProcessComponentContext()) );
214 return xSubstVars;
217 bool bInstalled;
218 OUString sFactory;
219 OUString sTemplateFile;
220 OUString sDefaultFilter;
221 sal_Int32 nIcon;
223 bool bChangedTemplateFile :1;
224 bool bChangedDefaultFilter :1;
225 bool bDefaultFilterReadonly :1;
227 css::uno::Reference< css::util::XStringSubstitution > xSubstVars;
232 class SvtModuleOptions_Impl : public ::utl::ConfigItem
235 // public methods
237 public:
239 // constructor / destructor
241 SvtModuleOptions_Impl();
242 virtual ~SvtModuleOptions_Impl() override;
244 // override methods of baseclass
246 virtual void Notify( const css::uno::Sequence< OUString >& lPropertyNames ) override;
248 // public interface
250 bool IsModuleInstalled ( SvtModuleOptions::EModule eModule ) const;
251 css::uno::Sequence < OUString > GetAllServiceNames();
252 OUString const & GetFactoryName ( SvtModuleOptions::EFactory eFactory ) const;
253 OUString const & GetFactoryStandardTemplate( SvtModuleOptions::EFactory eFactory ) const;
254 static OUString GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory eFactory );
255 OUString const & GetFactoryDefaultFilter ( SvtModuleOptions::EFactory eFactory ) const;
256 bool IsDefaultFilterReadonly( SvtModuleOptions::EFactory eFactory ) const;
257 sal_Int32 GetFactoryIcon ( SvtModuleOptions::EFactory eFactory ) const;
258 static bool ClassifyFactoryByName ( const OUString& sName ,
259 SvtModuleOptions::EFactory& eFactory );
260 void SetFactoryStandardTemplate( SvtModuleOptions::EFactory eFactory ,
261 const OUString& sTemplate );
262 void SetFactoryDefaultFilter ( SvtModuleOptions::EFactory eFactory ,
263 const OUString& sFilter );
264 void MakeReadonlyStatesAvailable();
266 // private methods
268 private:
269 static css::uno::Sequence< OUString > impl_ExpandSetNames ( const css::uno::Sequence< OUString >& lSetNames );
270 void impl_Read ( const css::uno::Sequence< OUString >& lSetNames );
272 virtual void ImplCommit() override;
274 // private member
276 private:
277 o3tl::enumarray<SvtModuleOptions::EFactory, FactoryInfo> m_lFactories;
278 bool m_bReadOnlyStatesWellKnown;
281 /*-************************************************************************************************************
282 @short default ctor
283 @descr We open our configuration here and read all necessary values from it.
284 These values are cached till everyone call Commit(). Then we write changed ones back to cfg.
286 @seealso baseclass ConfigItem
287 @seealso method impl_Read()
288 @threadsafe no
289 *//*-*************************************************************************************************************/
290 SvtModuleOptions_Impl::SvtModuleOptions_Impl()
291 : ::utl::ConfigItem( ROOTNODE_FACTORIES )
292 , m_bReadOnlyStatesWellKnown( false )
294 // First initialize list of factory infos! Otherwise we couldn't guarantee right working of these class.
295 for( auto & rFactory : m_lFactories )
296 rFactory.free();
298 // Get name list of all existing set node names in configuration to read her properties in impl_Read().
299 // These list is a list of long names of our factories.
300 const css::uno::Sequence< OUString > lFactories = GetNodeNames( OUString() );
301 impl_Read( lFactories );
303 // Enable notification for changes by using configuration directly.
304 // So we can update our internal values immediately.
305 EnableNotification( lFactories );
308 SvtModuleOptions_Impl::~SvtModuleOptions_Impl()
310 assert(!IsModified()); // should have been committed
313 /*-************************************************************************************************************
314 @short called for notify of configmanager
315 @descr This method is called from the ConfigManager before application ends or from the
316 PropertyChangeListener if the sub tree broadcasts changes. You must update our
317 internal values.
319 @attention We are registered for pure set node names only. So we can use our internal method "impl_Read()" to
320 update our info list. Because - this method expand given name list to full qualified property list
321 and use it to read the values. These values are filled into our internal member list m_lFactories
322 at right position.
324 @seealso method impl_Read()
326 @param "lNames" is the list of set node entries which should be updated.
327 @threadsafe no
328 *//*-*************************************************************************************************************/
329 void SvtModuleOptions_Impl::Notify( const css::uno::Sequence< OUString >& )
331 OSL_FAIL( "SvtModuleOptions_Impl::Notify() Not implemented yet!" );
334 /*-****************************************************************************************************
335 @short write changes to configuration
336 @descr This method writes the changed values into the sub tree
337 and should always called in our destructor to guarantee consistency of config data.
339 @attention We clear complete set in configuration first and write it completely new! So we don't must
340 distinguish between existing, added or removed elements. Our internal cached values
341 are the only and right ones.
343 @seealso baseclass ConfigItem
344 @threadsafe no
345 *//*-*****************************************************************************************************/
346 void SvtModuleOptions_Impl::ImplCommit()
348 // Reserve memory for ALL possible factory properties!
349 // Step over all factories and get her really changed values only.
350 // Build list of these ones and use it for commit.
351 css::uno::Sequence< css::beans::PropertyValue > lCommitProperties( FACTORYCOUNT*PROPERTYCOUNT );
352 sal_Int32 nRealCount = 0;
353 OUString sBasePath;
354 for( FactoryInfo & rInfo : m_lFactories )
356 // These path is used to build full qualified property names...
357 // See pInfo->getChangedProperties() for further information
358 sBasePath = PATHSEPARATOR + rInfo.getFactory() + PATHSEPARATOR;
360 const css::uno::Sequence< css::beans::PropertyValue > lChangedProperties = rInfo.getChangedProperties ( sBasePath );
361 std::copy(lChangedProperties.begin(), lChangedProperties.end(), std::next(lCommitProperties.begin(), nRealCount));
362 nRealCount += lChangedProperties.getLength();
364 // Resize commit list to real size.
365 // If nothing to do - suppress calling of configuration...
366 // It could be too expensive :-)
367 if( nRealCount > 0 )
369 lCommitProperties.realloc( nRealCount );
370 SetSetProperties( OUString(), lCommitProperties );
374 /*-****************************************************************************************************
375 @short access method to get internal values
376 @descr These methods implement easy access to our internal values.
377 You give us right enum value to specify which module interest you ... we return right information.
379 @attention Some people use any value as enum ... but we support in header specified values only!
380 We use it directly as index in our internal list. If enum value isn't right - we crash with an
381 "index out of range"!!! Please use me right - otherwise there is no guarantee.
382 @param "eModule" , index in list - specify module
383 @return Queried information.
385 @onerror We return default values. (mostly "not installed"!)
386 @threadsafe no
387 *//*-*****************************************************************************************************/
388 bool SvtModuleOptions_Impl::IsModuleInstalled( SvtModuleOptions::EModule eModule ) const
390 switch( eModule )
392 case SvtModuleOptions::EModule::WRITER:
393 return m_lFactories[SvtModuleOptions::EFactory::WRITER].getInstalled();
394 case SvtModuleOptions::EModule::WEB:
395 return m_lFactories[SvtModuleOptions::EFactory::WRITERWEB].getInstalled();
396 case SvtModuleOptions::EModule::GLOBAL:
397 return m_lFactories[SvtModuleOptions::EFactory::WRITERGLOBAL].getInstalled();
398 case SvtModuleOptions::EModule::CALC:
399 return m_lFactories[SvtModuleOptions::EFactory::CALC].getInstalled();
400 case SvtModuleOptions::EModule::DRAW:
401 return m_lFactories[SvtModuleOptions::EFactory::DRAW].getInstalled();
402 case SvtModuleOptions::EModule::IMPRESS:
403 return m_lFactories[SvtModuleOptions::EFactory::IMPRESS].getInstalled();
404 case SvtModuleOptions::EModule::MATH:
405 return m_lFactories[SvtModuleOptions::EFactory::MATH].getInstalled();
406 case SvtModuleOptions::EModule::CHART:
407 return m_lFactories[SvtModuleOptions::EFactory::CHART].getInstalled();
408 case SvtModuleOptions::EModule::STARTMODULE:
409 return m_lFactories[SvtModuleOptions::EFactory::STARTMODULE].getInstalled();
410 case SvtModuleOptions::EModule::BASIC:
411 return true; // Couldn't be deselected by setup yet!
412 case SvtModuleOptions::EModule::DATABASE:
413 return m_lFactories[SvtModuleOptions::EFactory::DATABASE].getInstalled();
416 return false;
419 css::uno::Sequence < OUString > SvtModuleOptions_Impl::GetAllServiceNames()
421 std::vector<OUString> aVec;
423 for( const auto & rFactory : m_lFactories )
424 if( rFactory.getInstalled() )
425 aVec.push_back( rFactory.getFactory() );
427 return comphelper::containerToSequence(aVec);
430 OUString const & SvtModuleOptions_Impl::GetFactoryName( SvtModuleOptions::EFactory eFactory ) const
432 return m_lFactories[eFactory].getFactory();
435 OUString SvtModuleOptions::GetFactoryShortName(SvtModuleOptions::EFactory eFactory)
437 // Attention: Hard configured yet ... because it's not fine to make changes possible by xml file yet.
438 // But it's good to plan further possibilities!
440 //return m_lFactories[eFactory].sShortName;
442 OUString sShortName;
443 switch( eFactory )
445 case SvtModuleOptions::EFactory::WRITER : sShortName = "swriter";
446 break;
447 case SvtModuleOptions::EFactory::WRITERWEB: sShortName = "swriter/web";
448 break;
449 case SvtModuleOptions::EFactory::WRITERGLOBAL: sShortName = "swriter/GlobalDocument";
450 break;
451 case SvtModuleOptions::EFactory::CALC : sShortName = "scalc";
452 break;
453 case SvtModuleOptions::EFactory::DRAW : sShortName = "sdraw";
454 break;
455 case SvtModuleOptions::EFactory::IMPRESS : sShortName = "simpress";
456 break;
457 case SvtModuleOptions::EFactory::MATH : sShortName = "smath";
458 break;
459 case SvtModuleOptions::EFactory::CHART : sShortName = "schart";
460 break;
461 case SvtModuleOptions::EFactory::BASIC : sShortName = "sbasic";
462 break;
463 case SvtModuleOptions::EFactory::DATABASE : sShortName = "sdatabase";
464 break;
465 default:
466 OSL_FAIL( "unknown factory" );
467 break;
470 return sShortName;
473 OUString const & SvtModuleOptions_Impl::GetFactoryStandardTemplate( SvtModuleOptions::EFactory eFactory ) const
475 return m_lFactories[eFactory].getTemplateFile();
478 OUString SvtModuleOptions_Impl::GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory eFactory )
480 // Attention: Hard configured yet ... because it's not fine to make changes possible by xml file yet.
481 // But it's good to plan further possibilities!
483 //return m_lFactories[eFactory].getEmptyDocumentURL();
485 OUString sURL;
486 switch( eFactory )
488 case SvtModuleOptions::EFactory::WRITER : sURL = "private:factory/swriter";
489 break;
490 case SvtModuleOptions::EFactory::WRITERWEB : sURL = "private:factory/swriter/web";
491 break;
492 case SvtModuleOptions::EFactory::WRITERGLOBAL : sURL = "private:factory/swriter/GlobalDocument";
493 break;
494 case SvtModuleOptions::EFactory::CALC : sURL = "private:factory/scalc";
495 break;
496 case SvtModuleOptions::EFactory::DRAW : sURL = "private:factory/sdraw";
497 break;
498 case SvtModuleOptions::EFactory::IMPRESS : sURL = "private:factory/simpress?slot=6686";
499 break;
500 case SvtModuleOptions::EFactory::MATH : sURL = "private:factory/smath";
501 break;
502 case SvtModuleOptions::EFactory::CHART : sURL = "private:factory/schart";
503 break;
504 case SvtModuleOptions::EFactory::BASIC : sURL = "private:factory/sbasic";
505 break;
506 case SvtModuleOptions::EFactory::DATABASE : sURL = "private:factory/sdatabase?Interactive";
507 break;
508 default:
509 OSL_FAIL( "unknown factory" );
510 break;
512 return sURL;
515 OUString const & SvtModuleOptions_Impl::GetFactoryDefaultFilter( SvtModuleOptions::EFactory eFactory ) const
517 return m_lFactories[eFactory].getDefaultFilter();
520 bool SvtModuleOptions_Impl::IsDefaultFilterReadonly( SvtModuleOptions::EFactory eFactory ) const
522 return m_lFactories[eFactory].isDefaultFilterReadonly();
525 sal_Int32 SvtModuleOptions_Impl::GetFactoryIcon( SvtModuleOptions::EFactory eFactory ) const
527 return m_lFactories[eFactory].getIcon();
530 void SvtModuleOptions_Impl::SetFactoryStandardTemplate( SvtModuleOptions::EFactory eFactory ,
531 const OUString& sTemplate )
533 m_lFactories[eFactory].setTemplateFile( sTemplate );
534 SetModified();
537 void SvtModuleOptions_Impl::SetFactoryDefaultFilter( SvtModuleOptions::EFactory eFactory,
538 const OUString& sFilter )
540 m_lFactories[eFactory].setDefaultFilter( sFilter );
541 SetModified();
544 /*-************************************************************************************************************
545 @short return list of key names of our configuration management which represent our module tree
546 @descr You give use a list of current existing set node names .. and we expand it for all
547 well known properties which are necessary for this implementation.
548 These full expanded list should be used to get values of this properties.
550 @seealso ctor
551 @return List of all relative addressed properties of given set entry names.
553 @onerror List will be empty.
554 @threadsafe no
555 *//*-*************************************************************************************************************/
556 css::uno::Sequence< OUString > SvtModuleOptions_Impl::impl_ExpandSetNames( const css::uno::Sequence< OUString >& lSetNames )
558 sal_Int32 nCount = lSetNames.getLength();
559 css::uno::Sequence< OUString > lPropNames ( nCount*PROPERTYCOUNT );
560 OUString* pPropNames = lPropNames.getArray();
561 sal_Int32 nPropStart = 0;
563 for( const auto& rSetName : lSetNames )
565 pPropNames[nPropStart+PROPERTYHANDLE_SHORTNAME ] = rSetName + PATHSEPARATOR PROPERTYNAME_SHORTNAME;
566 pPropNames[nPropStart+PROPERTYHANDLE_TEMPLATEFILE ] = rSetName + PATHSEPARATOR PROPERTYNAME_TEMPLATEFILE;
567 pPropNames[nPropStart+PROPERTYHANDLE_WINDOWATTRIBUTES] = rSetName + PATHSEPARATOR PROPERTYNAME_WINDOWATTRIBUTES;
568 pPropNames[nPropStart+PROPERTYHANDLE_EMPTYDOCUMENTURL] = rSetName + PATHSEPARATOR PROPERTYNAME_EMPTYDOCUMENTURL;
569 pPropNames[nPropStart+PROPERTYHANDLE_DEFAULTFILTER ] = rSetName + PATHSEPARATOR PROPERTYNAME_DEFAULTFILTER;
570 pPropNames[nPropStart+PROPERTYHANDLE_ICON ] = rSetName + PATHSEPARATOR PROPERTYNAME_ICON;
571 nPropStart += PROPERTYCOUNT;
574 return lPropNames;
577 /*-************************************************************************************************************
578 @short helper to classify given factory by name
579 @descr Every factory has its own long and short name. So we can match right enum value for internal using.
581 @attention We change in/out parameter "eFactory" in every case! But you should use it only, if return value is sal_True!
582 Algorithm: Set out-parameter to probably value ... and check the longname.
583 If it matches with these factory - break operation and return true AND right set parameter.
584 Otherwise try next one and so on. If no factory was found return false. Out parameter eFactory
585 is set to last tried value but shouldn't be used! Because our return value is false!
586 @param "sLongName" , long name of factory, which should be classified
587 @return "eFactory" , right enum value, which match given long name
588 and true for successfully classification, false otherwise
590 @onerror We return false.
591 @threadsafe no
592 *//*-*************************************************************************************************************/
593 bool SvtModuleOptions_Impl::ClassifyFactoryByName( const OUString& sName, SvtModuleOptions::EFactory& eFactory )
595 bool bState;
597 eFactory = SvtModuleOptions::EFactory::WRITER;
598 bState = ( sName == FACTORYNAME_WRITER );
600 if( !bState )
602 eFactory = SvtModuleOptions::EFactory::WRITERWEB;
603 bState = ( sName == FACTORYNAME_WRITERWEB );
605 // no else!
606 if( !bState )
608 eFactory = SvtModuleOptions::EFactory::WRITERGLOBAL;
609 bState = ( sName == FACTORYNAME_WRITERGLOBAL );
611 // no else!
612 if( !bState )
614 eFactory = SvtModuleOptions::EFactory::CALC;
615 bState = ( sName == FACTORYNAME_CALC );
617 // no else!
618 if( !bState )
620 eFactory = SvtModuleOptions::EFactory::DRAW;
621 bState = ( sName == FACTORYNAME_DRAW );
623 // no else!
624 if( !bState )
626 eFactory = SvtModuleOptions::EFactory::IMPRESS;
627 bState = ( sName == FACTORYNAME_IMPRESS );
629 // no else!
630 if( !bState )
632 eFactory = SvtModuleOptions::EFactory::MATH;
633 bState = ( sName == FACTORYNAME_MATH );
635 // no else!
636 if( !bState )
638 eFactory = SvtModuleOptions::EFactory::CHART;
639 bState = ( sName == FACTORYNAME_CHART );
641 // no else!
642 if( !bState )
644 eFactory = SvtModuleOptions::EFactory::DATABASE;
645 bState = ( sName == FACTORYNAME_DATABASE );
647 // no else!
648 if( !bState )
650 eFactory = SvtModuleOptions::EFactory::STARTMODULE;
651 bState = ( sName == FACTORYNAME_STARTMODULE);
653 // no else!
654 if( !bState )
656 eFactory = SvtModuleOptions::EFactory::BASIC;
657 bState = ( sName == FACTORYNAME_BASIC);
660 return bState;
663 /*-************************************************************************************************************
664 @short read factory configuration
665 @descr Give us a list of pure factory names (long names!) which can be used as
666 direct set node names... and we read her property values and fill internal list.
667 These method can be used by initial reading at ctor and later updating by "Notify()".
669 @seealso ctor
670 @seealso method Notify()
672 @param "lFactories" is the list of set node entries which should be read.
673 @onerror We do nothing.
674 @threadsafe no
675 *//*-*************************************************************************************************************/
676 void SvtModuleOptions_Impl::impl_Read( const css::uno::Sequence< OUString >& lFactories )
678 // Expand every set node name in lFactories to full qualified paths to its properties
679 // and get right values from configuration.
680 const css::uno::Sequence< OUString > lProperties = impl_ExpandSetNames( lFactories );
681 const css::uno::Sequence< css::uno::Any > lValues = GetProperties( lProperties );
683 // Safe impossible cases.
684 // We need values from ALL configuration keys.
685 // Follow assignment use order of values in relation to our list of key names!
686 OSL_ENSURE( !(lProperties.getLength()!=lValues.getLength()), "SvtModuleOptions_Impl::impl_Read()\nI miss some values of configuration keys!" );
688 // Algorithm: We step over all given factory names and classify it. These enum value can be used as direct index
689 // in our member list m_lFactories! VAriable nPropertyStart marks start position of every factory
690 // and her properties in expanded property/value list. The defines PROPERTHANDLE_xxx are used as offset values
691 // added to nPropertyStart. So we can address every property relative in these lists.
692 // If we found any valid values ... we reset all existing information for corresponding m_lFactories-entry and
693 // use a pointer to these struct in memory directly to set new values.
694 // But we set it only, if bInstalled is true. Otherwise all other values of a factory can be undeclared .. They
695 // shouldn't be used then.
696 // Attention: If a propertyset of a factory will be ignored we must step to next start position of next factory infos!
697 // see "nPropertyStart += PROPERTYCOUNT" ...
699 sal_Int32 nPropertyStart = 0;
700 FactoryInfo* pInfo = nullptr;
701 SvtModuleOptions::EFactory eFactory;
703 for( const OUString& sFactoryName : lFactories )
705 if( ClassifyFactoryByName( sFactoryName, eFactory ) )
707 OUString sTemp;
708 sal_Int32 nTemp = 0;
710 pInfo = &(m_lFactories[eFactory]);
711 pInfo->free();
713 pInfo->initInstalled();
714 pInfo->initFactory ( sFactoryName );
716 if (lValues[nPropertyStart+PROPERTYHANDLE_TEMPLATEFILE] >>= sTemp)
717 pInfo->initTemplateFile( sTemp );
718 if (lValues[nPropertyStart+PROPERTYHANDLE_DEFAULTFILTER ] >>= sTemp)
719 pInfo->initDefaultFilter( sTemp );
720 if (lValues[nPropertyStart+PROPERTYHANDLE_ICON] >>= nTemp)
721 pInfo->initIcon( nTemp );
723 nPropertyStart += PROPERTYCOUNT;
727 void SvtModuleOptions_Impl::MakeReadonlyStatesAvailable()
729 if (m_bReadOnlyStatesWellKnown)
730 return;
732 css::uno::Sequence< OUString > lFactories = GetNodeNames(OUString());
733 std::transform(lFactories.begin(), lFactories.end(), lFactories.begin(),
734 [](const OUString& rFactory) -> OUString {
735 return rFactory + PATHSEPARATOR PROPERTYNAME_DEFAULTFILTER;
738 css::uno::Sequence< sal_Bool > lReadonlyStates = GetReadOnlyStates(lFactories);
739 sal_Int32 c = lFactories.getLength();
740 for (sal_Int32 i=0; i<c; ++i)
742 OUString& rFactoryName = lFactories[i];
743 SvtModuleOptions::EFactory eFactory;
745 if (!ClassifyFactoryByName(rFactoryName, eFactory))
746 continue;
748 FactoryInfo& rInfo = m_lFactories[eFactory];
749 rInfo.setDefaultFilterReadonly(lReadonlyStates[i]);
752 m_bReadOnlyStatesWellKnown = true;
755 namespace {
756 //global
757 std::weak_ptr<SvtModuleOptions_Impl> g_pModuleOptions;
760 /*-************************************************************************************************************
761 @short standard constructor and destructor
762 @descr This will initialize an instance with default values. We initialize/deinitialize our static data
763 container and create a static mutex, which is used for threadsafe code in further time of this object.
765 @seealso method impl_GetOwnStaticMutex()
766 @threadsafe yes
767 *//*-*************************************************************************************************************/
768 SvtModuleOptions::SvtModuleOptions()
770 // Global access, must be guarded (multithreading!)
771 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
773 m_pImpl = g_pModuleOptions.lock();
774 if( !m_pImpl )
776 m_pImpl = std::make_shared<SvtModuleOptions_Impl>();
777 g_pModuleOptions = m_pImpl;
778 ItemHolder1::holdConfigItem(EItem::ModuleOptions);
782 SvtModuleOptions::~SvtModuleOptions()
784 // Global access, must be guarded (multithreading!)
785 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
787 m_pImpl.reset();
790 /*-************************************************************************************************************
791 @short access to configuration data
792 @descr This methods allow read/write access to configuration values.
793 They are threadsafe. All calls are forwarded to impl-data-container. See there for further information!
795 @seealso method impl_GetOwnStaticMutex()
796 @threadsafe yes
797 *//*-*************************************************************************************************************/
798 bool SvtModuleOptions::IsModuleInstalled( EModule eModule ) const
800 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
801 return m_pImpl->IsModuleInstalled( eModule );
804 OUString SvtModuleOptions::GetFactoryName( EFactory eFactory ) const
806 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
807 return m_pImpl->GetFactoryName( eFactory );
810 OUString SvtModuleOptions::GetFactoryStandardTemplate( EFactory eFactory ) const
812 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
813 return m_pImpl->GetFactoryStandardTemplate( eFactory );
816 OUString SvtModuleOptions::GetFactoryEmptyDocumentURL( EFactory eFactory ) const
818 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
819 return SvtModuleOptions_Impl::GetFactoryEmptyDocumentURL( eFactory );
822 OUString SvtModuleOptions::GetFactoryDefaultFilter( EFactory eFactory ) const
824 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
825 return m_pImpl->GetFactoryDefaultFilter( eFactory );
828 bool SvtModuleOptions::IsDefaultFilterReadonly( EFactory eFactory ) const
830 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
831 m_pImpl->MakeReadonlyStatesAvailable();
832 return m_pImpl->IsDefaultFilterReadonly( eFactory );
835 sal_Int32 SvtModuleOptions::GetFactoryIcon( EFactory eFactory ) const
837 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
838 return m_pImpl->GetFactoryIcon( eFactory );
841 bool SvtModuleOptions::ClassifyFactoryByName( const OUString& sName ,
842 EFactory& eFactory )
844 // We don't need any mutex here ... because we don't use any member here!
845 return SvtModuleOptions_Impl::ClassifyFactoryByName( sName, eFactory );
848 void SvtModuleOptions::SetFactoryStandardTemplate( EFactory eFactory ,
849 const OUString& sTemplate )
851 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
852 m_pImpl->SetFactoryStandardTemplate( eFactory, sTemplate );
855 void SvtModuleOptions::SetFactoryDefaultFilter( EFactory eFactory,
856 const OUString& sFilter )
858 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
859 m_pImpl->SetFactoryDefaultFilter( eFactory, sFilter );
862 bool SvtModuleOptions::IsMath() const
864 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
865 return m_pImpl->IsModuleInstalled( EModule::MATH );
868 bool SvtModuleOptions::IsChart() const
870 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
871 return m_pImpl->IsModuleInstalled( EModule::CHART );
874 bool SvtModuleOptions::IsCalc() const
876 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
877 return m_pImpl->IsModuleInstalled( EModule::CALC );
880 bool SvtModuleOptions::IsDraw() const
882 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
883 return m_pImpl->IsModuleInstalled( EModule::DRAW );
886 bool SvtModuleOptions::IsWriter() const
888 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
889 return m_pImpl->IsModuleInstalled( EModule::WRITER );
892 bool SvtModuleOptions::IsImpress() const
894 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
895 return m_pImpl->IsModuleInstalled( EModule::IMPRESS );
898 bool SvtModuleOptions::IsDataBase() const
900 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
901 return m_pImpl->IsModuleInstalled( EModule::DATABASE );
904 namespace
906 class theModuleOptionsMutex : public rtl::Static<osl::Mutex, theModuleOptionsMutex> {};
908 /*-****************************************************************************************************
909 @short return a reference to a static mutex
910 @descr These class is threadsafe.
911 We create a static mutex only for one time and use it to protect our refcount and container
912 member!
913 @return A reference to a static mutex member.
914 @threadsafe yes
915 *//*-*****************************************************************************************************/
916 ::osl::Mutex& SvtModuleOptions::impl_GetOwnStaticMutex()
918 return theModuleOptionsMutex::get();
921 OUString SvtModuleOptions::GetModuleName( EModule eModule ) const
923 switch( eModule )
925 case SvtModuleOptions::EModule::WRITER : { return "Writer"; }
926 case SvtModuleOptions::EModule::WEB : { return "Web"; }
927 case SvtModuleOptions::EModule::GLOBAL : { return "Global"; }
928 case SvtModuleOptions::EModule::CALC : { return "Calc"; }
929 case SvtModuleOptions::EModule::DRAW : { return "Draw"; }
930 case SvtModuleOptions::EModule::IMPRESS : { return "Impress"; }
931 case SvtModuleOptions::EModule::MATH : { return "Math"; }
932 case SvtModuleOptions::EModule::CHART : { return "Chart"; }
933 case SvtModuleOptions::EModule::BASIC : { return "Basic"; }
934 case SvtModuleOptions::EModule::DATABASE : { return "Database"; }
935 default:
936 OSL_FAIL( "unknown module" );
937 break;
940 return OUString();
943 SvtModuleOptions::EFactory SvtModuleOptions::ClassifyFactoryByShortName(const OUString& sName)
945 if ( sName == "swriter" )
946 return EFactory::WRITER;
947 if (sName.equalsIgnoreAsciiCase("swriter/Web")) // sometimes they are registered for swriter/web :-(
948 return EFactory::WRITERWEB;
949 if (sName.equalsIgnoreAsciiCase("swriter/GlobalDocument")) // sometimes they are registered for swriter/globaldocument :-(
950 return EFactory::WRITERGLOBAL;
951 if ( sName == "scalc" )
952 return EFactory::CALC;
953 if ( sName == "sdraw" )
954 return EFactory::DRAW;
955 if ( sName == "simpress" )
956 return EFactory::IMPRESS;
957 if ( sName == "schart" )
958 return EFactory::CHART;
959 if ( sName == "smath" )
960 return EFactory::MATH;
961 if ( sName == "sbasic" )
962 return EFactory::BASIC;
963 if ( sName == "sdatabase" )
964 return EFactory::DATABASE;
966 return EFactory::UNKNOWN_FACTORY;
969 SvtModuleOptions::EFactory SvtModuleOptions::ClassifyFactoryByServiceName(const OUString& sName)
971 if (sName == FACTORYNAME_WRITERGLOBAL)
972 return EFactory::WRITERGLOBAL;
973 if (sName == FACTORYNAME_WRITERWEB)
974 return EFactory::WRITERWEB;
975 if (sName == FACTORYNAME_WRITER)
976 return EFactory::WRITER;
977 if (sName == FACTORYNAME_CALC)
978 return EFactory::CALC;
979 if (sName == FACTORYNAME_DRAW)
980 return EFactory::DRAW;
981 if (sName == FACTORYNAME_IMPRESS)
982 return EFactory::IMPRESS;
983 if (sName == FACTORYNAME_MATH)
984 return EFactory::MATH;
985 if (sName == FACTORYNAME_CHART)
986 return EFactory::CHART;
987 if (sName == FACTORYNAME_DATABASE)
988 return EFactory::DATABASE;
989 if (sName == FACTORYNAME_STARTMODULE)
990 return EFactory::STARTMODULE;
991 if (sName == FACTORYNAME_BASIC)
992 return EFactory::BASIC;
994 return EFactory::UNKNOWN_FACTORY;
997 SvtModuleOptions::EFactory SvtModuleOptions::ClassifyFactoryByURL(const OUString& sURL ,
998 const css::uno::Sequence< css::beans::PropertyValue >& lMediaDescriptor)
1000 css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1002 css::uno::Reference< css::container::XNameAccess > xFilterCfg;
1003 css::uno::Reference< css::container::XNameAccess > xTypeCfg;
1006 xFilterCfg.set(
1007 xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", xContext), css::uno::UNO_QUERY);
1008 xTypeCfg.set(
1009 xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", xContext), css::uno::UNO_QUERY);
1011 catch(const css::uno::RuntimeException&)
1012 { throw; }
1013 catch(const css::uno::Exception&)
1014 { return EFactory::UNKNOWN_FACTORY; }
1016 ::comphelper::SequenceAsHashMap stlDesc(lMediaDescriptor);
1018 // is there already a filter inside the descriptor?
1019 OUString sFilterName = stlDesc.getUnpackedValueOrDefault("FilterName", OUString());
1020 if (!sFilterName.isEmpty())
1024 ::comphelper::SequenceAsHashMap stlFilterProps (xFilterCfg->getByName(sFilterName));
1025 OUString sDocumentService = stlFilterProps.getUnpackedValueOrDefault("DocumentService", OUString());
1026 SvtModuleOptions::EFactory eApp = SvtModuleOptions::ClassifyFactoryByServiceName(sDocumentService);
1028 if (eApp != EFactory::UNKNOWN_FACTORY)
1029 return eApp;
1031 catch(const css::uno::RuntimeException&)
1032 { throw; }
1033 catch(const css::uno::Exception&)
1034 { /* do nothing here ... may the following code can help!*/ }
1037 // is there already a type inside the descriptor?
1038 OUString sTypeName = stlDesc.getUnpackedValueOrDefault("TypeName", OUString());
1039 if (sTypeName.isEmpty())
1041 // no :-(
1042 // start flat detection of URL
1043 css::uno::Reference< css::document::XTypeDetection > xDetect(xTypeCfg, css::uno::UNO_QUERY);
1044 sTypeName = xDetect->queryTypeByURL(sURL);
1047 if (sTypeName.isEmpty())
1048 return EFactory::UNKNOWN_FACTORY;
1050 // yes - there is a type info
1051 // Try to find the preferred filter.
1054 ::comphelper::SequenceAsHashMap stlTypeProps (xTypeCfg->getByName(sTypeName));
1055 OUString sPreferredFilter = stlTypeProps.getUnpackedValueOrDefault("PreferredFilter", OUString());
1056 ::comphelper::SequenceAsHashMap stlFilterProps (xFilterCfg->getByName(sPreferredFilter));
1057 OUString sDocumentService = stlFilterProps.getUnpackedValueOrDefault("DocumentService", OUString());
1058 SvtModuleOptions::EFactory eApp = SvtModuleOptions::ClassifyFactoryByServiceName(sDocumentService);
1060 if (eApp != EFactory::UNKNOWN_FACTORY)
1061 return eApp;
1063 catch(const css::uno::RuntimeException&)
1064 { throw; }
1065 catch(const css::uno::Exception&)
1066 { /* do nothing here ... may the following code can help!*/ }
1068 // no filter/no type/no detection result => no fun :-)
1069 return EFactory::UNKNOWN_FACTORY;
1072 SvtModuleOptions::EFactory SvtModuleOptions::ClassifyFactoryByModel(const css::uno::Reference< css::frame::XModel >& xModel)
1074 css::uno::Reference< css::lang::XServiceInfo > xInfo(xModel, css::uno::UNO_QUERY);
1075 if (!xInfo.is())
1076 return EFactory::UNKNOWN_FACTORY;
1078 const css::uno::Sequence< OUString > lServices = xInfo->getSupportedServiceNames();
1080 for (const OUString& rService : lServices)
1082 SvtModuleOptions::EFactory eApp = SvtModuleOptions::ClassifyFactoryByServiceName(rService);
1083 if (eApp != EFactory::UNKNOWN_FACTORY)
1084 return eApp;
1087 return EFactory::UNKNOWN_FACTORY;
1090 css::uno::Sequence < OUString > SvtModuleOptions::GetAllServiceNames()
1092 ::osl::MutexGuard aGuard( impl_GetOwnStaticMutex() );
1093 return m_pImpl->GetAllServiceNames();
1096 OUString SvtModuleOptions::GetDefaultModuleName() const
1098 OUString aModule;
1099 if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::WRITER))
1100 aModule = GetFactoryShortName(SvtModuleOptions::EFactory::WRITER);
1101 else if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::CALC))
1102 aModule = GetFactoryShortName(SvtModuleOptions::EFactory::CALC);
1103 else if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::IMPRESS))
1104 aModule = GetFactoryShortName(SvtModuleOptions::EFactory::IMPRESS);
1105 else if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::DATABASE))
1106 aModule = GetFactoryShortName(SvtModuleOptions::EFactory::DATABASE);
1107 else if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::DRAW))
1108 aModule = GetFactoryShortName(SvtModuleOptions::EFactory::DRAW);
1109 else if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::WEB))
1110 aModule = GetFactoryShortName(SvtModuleOptions::EFactory::WRITERWEB);
1111 else if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::GLOBAL))
1112 aModule = GetFactoryShortName(SvtModuleOptions::EFactory::WRITERGLOBAL);
1113 else if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::MATH))
1114 aModule = GetFactoryShortName(SvtModuleOptions::EFactory::MATH);
1115 return aModule;
1118 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */