tdf#129905 tdf#160365 sw: don't always draw text boundary on frames
[LibreOffice.git] / unotools / source / config / moduleoptions.cxx
blob01378438665ba3f3b3fa0a4c3e707950f3cc0945
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 <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!
52 e.g.:
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
90 namespace {
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 *//*-*************************************************************************************************************/
97 struct FactoryInfo
99 public:
101 // initialize empty struct
102 FactoryInfo()
104 free();
107 // easy way to reset struct member!
108 void free()
110 bInstalled = false;
111 sFactory.clear();
112 sTemplateFile.clear();
113 sDefaultFilter.clear();
114 nIcon = 0;
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 );
143 else
145 plProperties[nRealyChanged].Value <<= sTemplateFile;
148 ++nRealyChanged;
150 if( bChangedDefaultFilter )
152 plProperties[nRealyChanged].Name
153 = OUString::Concat(sNodeBase) + PROPERTYNAME_DEFAULTFILTER;
154 plProperties[nRealyChanged].Value <<= sDefaultFilter;
155 ++nRealyChanged;
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 );
163 return lProperties;
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 );
190 else
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;
214 private:
215 css::uno::Reference< css::util::XStringSubstitution > const & getStringSubstitution()
217 if ( !xSubstVars.is() )
219 xSubstVars.set( css::util::PathSubstitution::create(::comphelper::getProcessComponentContext()) );
221 return xSubstVars;
224 bool bInstalled;
225 OUString sFactory;
226 OUString sTemplateFile;
227 OUString sDefaultFilter;
228 sal_Int32 nIcon;
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
242 // public methods
244 public:
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;
255 // public interface
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();
273 // private methods
275 private:
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;
281 // private member
283 private:
284 o3tl::enumarray<SvtModuleOptions::EFactory, FactoryInfo> m_lFactories;
285 bool m_bReadOnlyStatesWellKnown;
288 /*-************************************************************************************************************
289 @short default ctor
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()
295 @threadsafe no
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 )
303 rFactory.free();
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
324 internal values.
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
329 at right position.
331 @seealso method impl_Read()
333 @param "lNames" is the list of set node entries which should be updated.
334 @threadsafe no
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
351 @threadsafe no
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;
360 OUString sBasePath;
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 :-)
374 if( nRealCount > 0 )
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"!)
393 @threadsafe no
394 *//*-*****************************************************************************************************/
395 bool SvtModuleOptions_Impl::IsModuleInstalled( SvtModuleOptions::EModule eModule ) const
397 switch( eModule )
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();
423 return false;
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;
449 OUString sShortName;
450 switch( eFactory )
452 case SvtModuleOptions::EFactory::WRITER : sShortName = "swriter";
453 break;
454 case SvtModuleOptions::EFactory::WRITERWEB: sShortName = "swriter/web";
455 break;
456 case SvtModuleOptions::EFactory::WRITERGLOBAL: sShortName = "swriter/GlobalDocument";
457 break;
458 case SvtModuleOptions::EFactory::CALC : sShortName = "scalc";
459 break;
460 case SvtModuleOptions::EFactory::DRAW : sShortName = "sdraw";
461 break;
462 case SvtModuleOptions::EFactory::IMPRESS : sShortName = "simpress";
463 break;
464 case SvtModuleOptions::EFactory::MATH : sShortName = "smath";
465 break;
466 case SvtModuleOptions::EFactory::CHART : sShortName = "schart";
467 break;
468 case SvtModuleOptions::EFactory::BASIC : sShortName = "sbasic";
469 break;
470 case SvtModuleOptions::EFactory::DATABASE : sShortName = "sdatabase";
471 break;
472 case SvtModuleOptions::EFactory::STARTMODULE : sShortName = "startmodule";
473 break;
474 default:
475 OSL_FAIL( "unknown factory" );
476 break;
479 return sShortName;
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();
494 OUString sURL;
495 switch( eFactory )
497 case SvtModuleOptions::EFactory::WRITER : sURL = "private:factory/swriter";
498 break;
499 case SvtModuleOptions::EFactory::WRITERWEB : sURL = "private:factory/swriter/web";
500 break;
501 case SvtModuleOptions::EFactory::WRITERGLOBAL : sURL = "private:factory/swriter/GlobalDocument";
502 break;
503 case SvtModuleOptions::EFactory::CALC : sURL = "private:factory/scalc";
504 break;
505 case SvtModuleOptions::EFactory::DRAW : sURL = "private:factory/sdraw";
506 break;
507 case SvtModuleOptions::EFactory::IMPRESS : sURL = "private:factory/simpress?slot=6686";
508 break;
509 case SvtModuleOptions::EFactory::MATH : sURL = "private:factory/smath";
510 break;
511 case SvtModuleOptions::EFactory::CHART : sURL = "private:factory/schart";
512 break;
513 case SvtModuleOptions::EFactory::BASIC : sURL = "private:factory/sbasic";
514 break;
515 case SvtModuleOptions::EFactory::DATABASE : sURL = "private:factory/sdatabase?Interactive";
516 break;
517 default:
518 OSL_FAIL( "unknown factory" );
519 break;
521 return sURL;
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 );
543 SetModified();
546 void SvtModuleOptions_Impl::SetFactoryDefaultFilter( SvtModuleOptions::EFactory eFactory,
547 const OUString& sFilter )
549 m_lFactories[eFactory].setDefaultFilter( sFilter );
550 SetModified();
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.
559 @seealso ctor
560 @return List of all relative addressed properties of given set entry names.
562 @onerror List will be empty.
563 @threadsafe no
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;
583 return lPropNames;
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.
600 @threadsafe no
601 *//*-*************************************************************************************************************/
602 bool SvtModuleOptions_Impl::ClassifyFactoryByName( std::u16string_view sName, SvtModuleOptions::EFactory& eFactory )
604 bool bState;
606 eFactory = SvtModuleOptions::EFactory::WRITER;
607 bState = ( sName == FACTORYNAME_WRITER );
609 if( !bState )
611 eFactory = SvtModuleOptions::EFactory::WRITERWEB;
612 bState = ( sName == FACTORYNAME_WRITERWEB );
614 // no else!
615 if( !bState )
617 eFactory = SvtModuleOptions::EFactory::WRITERGLOBAL;
618 bState = ( sName == FACTORYNAME_WRITERGLOBAL );
620 // no else!
621 if( !bState )
623 eFactory = SvtModuleOptions::EFactory::CALC;
624 bState = ( sName == FACTORYNAME_CALC );
626 // no else!
627 if( !bState )
629 eFactory = SvtModuleOptions::EFactory::DRAW;
630 bState = ( sName == FACTORYNAME_DRAW );
632 // no else!
633 if( !bState )
635 eFactory = SvtModuleOptions::EFactory::IMPRESS;
636 bState = ( sName == FACTORYNAME_IMPRESS );
638 // no else!
639 if( !bState )
641 eFactory = SvtModuleOptions::EFactory::MATH;
642 bState = ( sName == FACTORYNAME_MATH );
644 // no else!
645 if( !bState )
647 eFactory = SvtModuleOptions::EFactory::CHART;
648 bState = ( sName == FACTORYNAME_CHART );
650 // no else!
651 if( !bState )
653 eFactory = SvtModuleOptions::EFactory::DATABASE;
654 bState = ( sName == FACTORYNAME_DATABASE );
656 // no else!
657 if( !bState )
659 eFactory = SvtModuleOptions::EFactory::STARTMODULE;
660 bState = ( sName == FACTORYNAME_STARTMODULE);
662 // no else!
663 if( !bState )
665 eFactory = SvtModuleOptions::EFactory::BASIC;
666 bState = ( sName == FACTORYNAME_BASIC);
669 return bState;
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()".
678 @seealso ctor
679 @seealso method Notify()
681 @param "lFactories" is the list of set node entries which should be read.
682 @onerror We do nothing.
683 @threadsafe no
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 ) )
716 OUString sTemp;
717 sal_Int32 nTemp = 0;
719 pInfo = &(m_lFactories[eFactory]);
720 pInfo->free();
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)
739 return;
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))
753 continue;
755 FactoryInfo& rInfo = m_lFactories[eFactory];
756 rInfo.setDefaultFilterReadonly(lReadonlyStates[i]);
759 m_bReadOnlyStatesWellKnown = true;
762 namespace {
763 //global
764 std::weak_ptr<SvtModuleOptions_Impl> g_pModuleOptions;
766 std::mutex& impl_GetOwnStaticMutex()
768 static std::mutex s_Mutex;
769 return 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()
779 @threadsafe yes
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();
785 if( m_pImpl )
786 return;
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();
792 if( !m_pImpl )
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()
803 m_pImpl.reset();
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()
812 @threadsafe yes
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 ,
858 EFactory& eFactory )
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
922 switch( eModule )
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"; }
934 default:
935 OSL_FAIL( "unknown module" );
936 break;
939 return OUString();
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;
1005 xFilterCfg.set(
1006 xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", xContext), css::uno::UNO_QUERY);
1007 xTypeCfg.set(
1008 xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", xContext), css::uno::UNO_QUERY);
1010 catch(const css::uno::RuntimeException&)
1011 { throw; }
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)
1028 return eApp;
1030 catch(const css::uno::RuntimeException&)
1031 { throw; }
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())
1040 // no :-(
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)
1060 return eApp;
1062 catch(const css::uno::RuntimeException&)
1063 { throw; }
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);
1074 if (!xInfo.is())
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)
1083 return eApp;
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
1097 OUString aModule;
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);
1114 return aModule;
1117 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */