LibreOffice Module unotools (master) 1
moduleoptions.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21
22#include <string_view>
23
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>
41
42#include "itemholder1.hxx"
43
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!
48
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*//*-*************************************************************************************************************/
55constexpr OUStringLiteral ROOTNODE_FACTORIES = u"Setup/Office/Factories";
56#define PATHSEPARATOR "/"
57
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"
66
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
73
74#define PROPERTYCOUNT 6
75
76constexpr OUStringLiteral FACTORYNAME_WRITER = u"com.sun.star.text.TextDocument";
77constexpr OUStringLiteral FACTORYNAME_WRITERWEB = u"com.sun.star.text.WebDocument";
78constexpr OUStringLiteral FACTORYNAME_WRITERGLOBAL = u"com.sun.star.text.GlobalDocument";
79constexpr OUStringLiteral FACTORYNAME_CALC = u"com.sun.star.sheet.SpreadsheetDocument";
80constexpr OUStringLiteral FACTORYNAME_DRAW = u"com.sun.star.drawing.DrawingDocument";
81constexpr OUStringLiteral FACTORYNAME_IMPRESS = u"com.sun.star.presentation.PresentationDocument";
82constexpr OUStringLiteral FACTORYNAME_MATH = u"com.sun.star.formula.FormulaProperties";
83constexpr OUStringLiteral FACTORYNAME_CHART = u"com.sun.star.chart2.ChartDocument";
84constexpr OUStringLiteral FACTORYNAME_DATABASE = u"com.sun.star.sdb.OfficeDatabaseDocument";
85constexpr OUStringLiteral FACTORYNAME_STARTMODULE = u"com.sun.star.frame.StartModule";
86constexpr OUStringLiteral FACTORYNAME_BASIC = u"com.sun.star.script.BasicIDE";
87
88#define FACTORYCOUNT 11
89
90namespace {
91
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*//*-*************************************************************************************************************/
97struct FactoryInfo
98{
99 public:
100
101 // initialize empty struct
102 FactoryInfo()
103 {
104 free();
105 }
106
107 // easy way to reset struct member!
108 void free()
109 {
110 bInstalled = false;
111 sFactory.clear();
112 sTemplateFile.clear();
113 sDefaultFilter.clear();
114 nIcon = 0;
115 bChangedTemplateFile = false;
116 bChangedDefaultFilter = false;
117 bDefaultFilterReadonly = false;
118 }
119
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 )
124 {
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;
131
132 if( bChangedTemplateFile )
133 {
134 plProperties[nRealyChanged].Name
135 = OUString::Concat(sNodeBase) + PROPERTYNAME_TEMPLATEFILE;
136
137 if ( !sTemplateFile.isEmpty() )
138 {
139 plProperties[nRealyChanged].Value
140 <<= getStringSubstitution()
141 ->reSubstituteVariables( sTemplateFile );
142 }
143 else
144 {
145 plProperties[nRealyChanged].Value <<= sTemplateFile;
146 }
147
148 ++nRealyChanged;
149 }
150 if( bChangedDefaultFilter )
151 {
152 plProperties[nRealyChanged].Name
153 = OUString::Concat(sNodeBase) + PROPERTYNAME_DEFAULTFILTER;
154 plProperties[nRealyChanged].Value <<= sDefaultFilter;
155 ++nRealyChanged;
156 }
157
158 // Don't forget to reset changed flags! Otherwise we save it again and again and ...
159 bChangedTemplateFile = false;
160 bChangedDefaultFilter = false;
161
162 lProperties.realloc( nRealyChanged );
163 return lProperties;
164 }
165
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; };
175
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; }
183
184 void initTemplateFile( const OUString& sNewTemplateFile )
185 {
186 if ( !sNewTemplateFile.isEmpty() )
187 {
188 sTemplateFile= getStringSubstitution()->substituteVariables( sNewTemplateFile, false );
189 }
190 else
191 {
192 sTemplateFile = sNewTemplateFile;
193 }
194 }
195
196 void setTemplateFile( const OUString& sNewTemplateFile )
197 {
198 if( sTemplateFile != sNewTemplateFile )
199 {
200 sTemplateFile = sNewTemplateFile;
201 bChangedTemplateFile = true;
202 }
203 };
204
205 void setDefaultFilter( const OUString& sNewDefaultFilter )
206 {
207 if( sDefaultFilter != sNewDefaultFilter )
208 {
209 sDefaultFilter = sNewDefaultFilter;
210 bChangedDefaultFilter = true;
211 }
212 };
213
214 private:
215 css::uno::Reference< css::util::XStringSubstitution > const & getStringSubstitution()
216 {
217 if ( !xSubstVars.is() )
218 {
219 xSubstVars.set( css::util::PathSubstitution::create(::comphelper::getProcessComponentContext()) );
220 }
221 return xSubstVars;
222 }
223
224 bool bInstalled;
225 OUString sFactory;
226 OUString sTemplateFile;
227 OUString sDefaultFilter;
228 sal_Int32 nIcon;
229
230 bool bChangedTemplateFile :1;
231 bool bChangedDefaultFilter :1;
232 bool bDefaultFilterReadonly :1;
233
234 css::uno::Reference< css::util::XStringSubstitution > xSubstVars;
235};
236
237}
238
240{
241
242 // public methods
243
244 public:
245
246 // constructor / destructor
247
249 virtual ~SvtModuleOptions_Impl() override;
250
251 // override methods of baseclass
252
253 virtual void Notify( const css::uno::Sequence< OUString >& lPropertyNames ) override;
254
255 // public interface
256
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;
264 sal_Int32 GetFactoryIcon ( SvtModuleOptions::EFactory eFactory ) const;
265 static bool ClassifyFactoryByName ( std::u16string_view sName ,
266 SvtModuleOptions::EFactory& eFactory );
268 const OUString& sTemplate );
270 const OUString& sFilter );
272
273 // private methods
274
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 );
278
279 virtual void ImplCommit() override;
280
281 // private member
282
283 private:
286};
287
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.
292
293 @seealso baseclass ConfigItem
294 @seealso method impl_Read()
295 @threadsafe no
296*//*-*************************************************************************************************************/
298 : ::utl::ConfigItem( ROOTNODE_FACTORIES )
299 , m_bReadOnlyStatesWellKnown( false )
300{
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();
304
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 );
309
310 // Enable notification for changes by using configuration directly.
311 // So we can update our internal values immediately.
312 EnableNotification( lFactories );
313}
314
316{
317 assert(!IsModified()); // should have been committed
318}
319
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.
325
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.
330
331 @seealso method impl_Read()
332
333 @param "lNames" is the list of set node entries which should be updated.
334 @threadsafe no
335*//*-*************************************************************************************************************/
336void SvtModuleOptions_Impl::Notify( const css::uno::Sequence< OUString >& )
337{
338 OSL_FAIL( "SvtModuleOptions_Impl::Notify() Not implemented yet!" );
339}
340
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.
345
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.
349
350 @seealso baseclass ConfigItem
351 @threadsafe no
352*//*-*****************************************************************************************************/
354{
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 )
362 {
363 // These path is used to build full qualified property names...
364 // See pInfo->getChangedProperties() for further information
365 sBasePath = PATHSEPARATOR + rInfo.getFactory() + PATHSEPARATOR;
366
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();
370 }
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 )
375 {
376 lCommitProperties.realloc( nRealCount );
377 SetSetProperties( OUString(), lCommitProperties );
378 }
379}
380
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.
385
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.
391
392 @onerror We return default values. (mostly "not installed"!)
393 @threadsafe no
394*//*-*****************************************************************************************************/
396{
397 switch( eModule )
398 {
406 return m_lFactories[SvtModuleOptions::EFactory::CALC].getInstalled();
408 return m_lFactories[SvtModuleOptions::EFactory::DRAW].getInstalled();
412 return m_lFactories[SvtModuleOptions::EFactory::MATH].getInstalled();
414 return m_lFactories[SvtModuleOptions::EFactory::CHART].getInstalled();
418 return true; // Couldn't be deselected by setup yet!
421 }
422
423 return false;
424}
425
426css::uno::Sequence < OUString > SvtModuleOptions_Impl::GetAllServiceNames()
427{
428 std::vector<OUString> aVec;
429
430 for( const auto & rFactory : m_lFactories )
431 if( rFactory.getInstalled() )
432 aVec.push_back( rFactory.getFactory() );
433
435}
436
438{
439 return m_lFactories[eFactory].getFactory();
440}
441
443{
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!
446
447 //return m_lFactories[eFactory].sShortName;
448
449 OUString sShortName;
450 switch( eFactory )
451 {
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;
477 }
478
479 return sShortName;
480}
481
483{
484 return m_lFactories[eFactory].getTemplateFile();
485}
486
488{
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!
491
492 //return m_lFactories[eFactory].getEmptyDocumentURL();
493
494 OUString sURL;
495 switch( eFactory )
496 {
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;
520 }
521 return sURL;
522}
523
525{
526 return m_lFactories[eFactory].getDefaultFilter();
527}
528
530{
531 return m_lFactories[eFactory].isDefaultFilterReadonly();
532}
533
535{
536 return m_lFactories[eFactory].getIcon();
537}
538
540 const OUString& sTemplate )
541{
542 m_lFactories[eFactory].setTemplateFile( sTemplate );
543 SetModified();
544}
545
547 const OUString& sFilter )
548{
549 m_lFactories[eFactory].setDefaultFilter( sFilter );
550 SetModified();
551}
552
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.
558
559 @seealso ctor
560 @return List of all relative addressed properties of given set entry names.
561
562 @onerror List will be empty.
563 @threadsafe no
564*//*-*************************************************************************************************************/
565css::uno::Sequence< OUString > SvtModuleOptions_Impl::impl_ExpandSetNames( const css::uno::Sequence< OUString >& lSetNames )
566{
567 sal_Int32 nCount = lSetNames.getLength();
568 css::uno::Sequence< OUString > lPropNames ( nCount*PROPERTYCOUNT );
569 OUString* pPropNames = lPropNames.getArray();
570 sal_Int32 nPropStart = 0;
571
572 for( const auto& rSetName : lSetNames )
573 {
574 pPropNames[nPropStart+PROPERTYHANDLE_SHORTNAME ] = rSetName + PATHSEPARATOR PROPERTYNAME_SHORTNAME;
575 pPropNames[nPropStart+PROPERTYHANDLE_TEMPLATEFILE ] = rSetName + PATHSEPARATOR PROPERTYNAME_TEMPLATEFILE;
578 pPropNames[nPropStart+PROPERTYHANDLE_DEFAULTFILTER ] = rSetName + PATHSEPARATOR PROPERTYNAME_DEFAULTFILTER;
579 pPropNames[nPropStart+PROPERTYHANDLE_ICON ] = rSetName + PATHSEPARATOR PROPERTYNAME_ICON;
580 nPropStart += PROPERTYCOUNT;
581 }
582
583 return lPropNames;
584}
585
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.
589
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
598
599 @onerror We return false.
600 @threadsafe no
601*//*-*************************************************************************************************************/
603{
604 bool bState;
605
607 bState = ( sName == FACTORYNAME_WRITER );
608
609 if( !bState )
610 {
612 bState = ( sName == FACTORYNAME_WRITERWEB );
613 }
614 // no else!
615 if( !bState )
616 {
618 bState = ( sName == FACTORYNAME_WRITERGLOBAL );
619 }
620 // no else!
621 if( !bState )
622 {
624 bState = ( sName == FACTORYNAME_CALC );
625 }
626 // no else!
627 if( !bState )
628 {
630 bState = ( sName == FACTORYNAME_DRAW );
631 }
632 // no else!
633 if( !bState )
634 {
636 bState = ( sName == FACTORYNAME_IMPRESS );
637 }
638 // no else!
639 if( !bState )
640 {
642 bState = ( sName == FACTORYNAME_MATH );
643 }
644 // no else!
645 if( !bState )
646 {
648 bState = ( sName == FACTORYNAME_CHART );
649 }
650 // no else!
651 if( !bState )
652 {
654 bState = ( sName == FACTORYNAME_DATABASE );
655 }
656 // no else!
657 if( !bState )
658 {
660 bState = ( sName == FACTORYNAME_STARTMODULE);
661 }
662 // no else!
663 if( !bState )
664 {
666 bState = ( sName == FACTORYNAME_BASIC);
667 }
668
669 return bState;
670}
671
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()".
677
678 @seealso ctor
679 @seealso method Notify()
680
681 @param "lFactories" is the list of set node entries which should be read.
682 @onerror We do nothing.
683 @threadsafe no
684*//*-*************************************************************************************************************/
685void SvtModuleOptions_Impl::impl_Read( const css::uno::Sequence< OUString >& lFactories )
686{
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 );
691
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!" );
696
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" ...
707
708 sal_Int32 nPropertyStart = 0;
709 FactoryInfo* pInfo = nullptr;
711
712 for( const OUString& sFactoryName : lFactories )
713 {
714 if( ClassifyFactoryByName( sFactoryName, eFactory ) )
715 {
716 OUString sTemp;
717 sal_Int32 nTemp = 0;
718
719 pInfo = &(m_lFactories[eFactory]);
720 pInfo->free();
721
722 pInfo->initInstalled();
723 pInfo->initFactory ( sFactoryName );
724
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 );
731 }
732 nPropertyStart += PROPERTYCOUNT;
733 }
734}
735
737{
739 return;
740
741 css::uno::Sequence< OUString > lFactories = GetNodeNames(OUString());
742 for (OUString& rFactory : asNonConstRange(lFactories))
744
745 css::uno::Sequence< sal_Bool > lReadonlyStates = GetReadOnlyStates(lFactories);
746 sal_Int32 c = lFactories.getLength();
747 for (sal_Int32 i=0; i<c; ++i)
748 {
749 const OUString& rFactoryName = std::as_const(lFactories)[i];
751
752 if (!ClassifyFactoryByName(rFactoryName, eFactory))
753 continue;
754
755 FactoryInfo& rInfo = m_lFactories[eFactory];
756 rInfo.setDefaultFilterReadonly(lReadonlyStates[i]);
757 }
758
760}
761
762namespace {
763 //global
764 std::weak_ptr<SvtModuleOptions_Impl> g_pModuleOptions;
765
766std::mutex& impl_GetOwnStaticMutex()
767{
768 static std::mutex s_Mutex;
769 return s_Mutex;
770}
771}
772
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.
777
778 @seealso method impl_GetOwnStaticMutex()
779 @threadsafe yes
780*//*-*************************************************************************************************************/
782{
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;
787
788 // take the mutex, so we don't accidentally create more than one
789 std::unique_lock aGuard( impl_GetOwnStaticMutex() );
790
791 m_pImpl = g_pModuleOptions.lock();
792 if( !m_pImpl )
793 {
794 m_pImpl = std::make_shared<SvtModuleOptions_Impl>();
795 g_pModuleOptions = m_pImpl;
796 aGuard.unlock(); // because holdConfigItem will call this constructor
798 }
799}
800
802{
803 m_pImpl.reset();
804}
805
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!
810
811 @seealso method impl_GetOwnStaticMutex()
812 @threadsafe yes
813*//*-*************************************************************************************************************/
815{
816 // doesn't need mutex, never modified
817 return m_pImpl->IsModuleInstalled( eModule );
818}
819
820const OUString & SvtModuleOptions::GetFactoryName( EFactory eFactory ) const
821{
822 // doesn't need mutex, never modified
823 return m_pImpl->GetFactoryName( eFactory );
824}
825
827{
828 std::unique_lock aGuard( impl_GetOwnStaticMutex() );
829 return m_pImpl->GetFactoryStandardTemplate( eFactory );
830}
831
833{
834 std::unique_lock aGuard( impl_GetOwnStaticMutex() );
836}
837
839{
840 std::unique_lock aGuard( impl_GetOwnStaticMutex() );
841 return m_pImpl->GetFactoryDefaultFilter( eFactory );
842}
843
845{
846 std::unique_lock aGuard( impl_GetOwnStaticMutex() );
847 m_pImpl->MakeReadonlyStatesAvailable();
848 return m_pImpl->IsDefaultFilterReadonly( eFactory );
849}
850
852{
853 std::unique_lock aGuard( impl_GetOwnStaticMutex() );
854 return m_pImpl->GetFactoryIcon( eFactory );
855}
856
857bool SvtModuleOptions::ClassifyFactoryByName( std::u16string_view sName ,
858 EFactory& eFactory )
859{
860 // We don't need any mutex here ... because we don't use any member here!
862}
863
865 const OUString& sTemplate )
866{
867 std::unique_lock aGuard( impl_GetOwnStaticMutex() );
868 m_pImpl->SetFactoryStandardTemplate( eFactory, sTemplate );
869}
870
872 const OUString& sFilter )
873{
874 std::unique_lock aGuard( impl_GetOwnStaticMutex() );
875 m_pImpl->SetFactoryDefaultFilter( eFactory, sFilter );
876}
877
879{
880 // doesn't need mutex, never modified
881 return m_pImpl->IsModuleInstalled( EModule::MATH );
882}
883
885{
886 // doesn't need mutex, never modified
887 return m_pImpl->IsModuleInstalled( EModule::CHART );
888}
889
891{
892 // doesn't need mutex, never modified
893 return m_pImpl->IsModuleInstalled( EModule::CALC );
894}
895
897{
898 // doesn't need mutex, never modified
899 return m_pImpl->IsModuleInstalled( EModule::DRAW );
900}
901
903{
904 std::unique_lock aGuard( impl_GetOwnStaticMutex() );
905 return m_pImpl->IsModuleInstalled( EModule::WRITER );
906}
907
909{
910 // doesn't need mutex, never modified
911 return m_pImpl->IsModuleInstalled( EModule::IMPRESS );
912}
913
915{
916 // doesn't need mutex, never modified
917 return m_pImpl->IsModuleInstalled( EModule::DATABASE );
918}
919
921{
922 switch( eModule )
923 {
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;
937 }
938
939 return OUString();
940}
941
943{
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 :-(
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;
964
966}
967
969{
973 return EFactory::WRITERWEB;
975 return EFactory::WRITER;
976 if (sName == FACTORYNAME_CALC)
977 return EFactory::CALC;
978 if (sName == FACTORYNAME_DRAW)
979 return EFactory::DRAW;
981 return EFactory::IMPRESS;
982 if (sName == FACTORYNAME_MATH)
983 return EFactory::MATH;
985 return EFactory::CHART;
987 return EFactory::DATABASE;
991 return EFactory::BASIC;
992
994}
995
997 const css::uno::Sequence< css::beans::PropertyValue >& lMediaDescriptor)
998{
999 css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1000
1001 css::uno::Reference< css::container::XNameAccess > xFilterCfg;
1002 css::uno::Reference< css::container::XNameAccess > xTypeCfg;
1003 try
1004 {
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);
1009 }
1010 catch(const css::uno::RuntimeException&)
1011 { throw; }
1012 catch(const css::uno::Exception&)
1013 { return EFactory::UNKNOWN_FACTORY; }
1014
1015 ::comphelper::SequenceAsHashMap stlDesc(lMediaDescriptor);
1016
1017 // is there already a filter inside the descriptor?
1018 OUString sFilterName = stlDesc.getUnpackedValueOrDefault("FilterName", OUString());
1019 if (!sFilterName.isEmpty())
1020 {
1021 try
1022 {
1023 ::comphelper::SequenceAsHashMap stlFilterProps (xFilterCfg->getByName(sFilterName));
1024 OUString sDocumentService = stlFilterProps.getUnpackedValueOrDefault("DocumentService", OUString());
1026
1027 if (eApp != EFactory::UNKNOWN_FACTORY)
1028 return eApp;
1029 }
1030 catch(const css::uno::RuntimeException&)
1031 { throw; }
1032 catch(const css::uno::Exception&)
1033 { /* do nothing here ... may the following code can help!*/ }
1034 }
1035
1036 // is there already a type inside the descriptor?
1037 OUString sTypeName = stlDesc.getUnpackedValueOrDefault("TypeName", OUString());
1038 if (sTypeName.isEmpty())
1039 {
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);
1044 }
1045
1046 if (sTypeName.isEmpty())
1048
1049 // yes - there is a type info
1050 // Try to find the preferred filter.
1051 try
1052 {
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());
1058
1059 if (eApp != EFactory::UNKNOWN_FACTORY)
1060 return eApp;
1061 }
1062 catch(const css::uno::RuntimeException&)
1063 { throw; }
1064 catch(const css::uno::Exception&)
1065 { /* do nothing here ... may the following code can help!*/ }
1066
1067 // no filter/no type/no detection result => no fun :-)
1069}
1070
1071SvtModuleOptions::EFactory SvtModuleOptions::ClassifyFactoryByModel(const css::uno::Reference< css::frame::XModel >& xModel)
1072{
1073 css::uno::Reference< css::lang::XServiceInfo > xInfo(xModel, css::uno::UNO_QUERY);
1074 if (!xInfo.is())
1076
1077 const css::uno::Sequence< OUString > lServices = xInfo->getSupportedServiceNames();
1078
1079 for (const OUString& rService : lServices)
1080 {
1082 if (eApp != EFactory::UNKNOWN_FACTORY)
1083 return eApp;
1084 }
1085
1087}
1088
1089css::uno::Sequence < OUString > SvtModuleOptions::GetAllServiceNames()
1090{
1091 std::unique_lock aGuard( impl_GetOwnStaticMutex() );
1092 return m_pImpl->GetAllServiceNames();
1093}
1094
1096{
1097 OUString aModule;
1098 if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::WRITER))
1100 else if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::CALC))
1102 else if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::IMPRESS))
1104 else if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::DATABASE))
1106 else if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::DRAW))
1108 else if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::WEB))
1110 else if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::GLOBAL))
1112 else if (m_pImpl->IsModuleInstalled(SvtModuleOptions::EModule::MATH))
1114 return aModule;
1115}
1116
1117/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr OUStringLiteral sDocumentService
static void holdConfigItem(EItem eItem)
Definition: itemholder1.cxx:68
o3tl::enumarray< SvtModuleOptions::EFactory, FactoryInfo > m_lFactories
virtual void Notify(const css::uno::Sequence< OUString > &lPropertyNames) override
is called from the ConfigManager before application ends of from the PropertyChangeListener if the su...
void SetFactoryDefaultFilter(SvtModuleOptions::EFactory eFactory, const OUString &sFilter)
OUString const & GetFactoryDefaultFilter(SvtModuleOptions::EFactory eFactory) const
static OUString GetFactoryEmptyDocumentURL(SvtModuleOptions::EFactory eFactory)
bool IsDefaultFilterReadonly(SvtModuleOptions::EFactory eFactory) const
void impl_Read(const css::uno::Sequence< OUString > &lSetNames)
sal_Int32 GetFactoryIcon(SvtModuleOptions::EFactory eFactory) const
virtual void ImplCommit() override
writes the changed values into the sub tree.
css::uno::Sequence< OUString > GetAllServiceNames()
void SetFactoryStandardTemplate(SvtModuleOptions::EFactory eFactory, const OUString &sTemplate)
OUString const & GetFactoryName(SvtModuleOptions::EFactory eFactory) const
static bool ClassifyFactoryByName(std::u16string_view sName, SvtModuleOptions::EFactory &eFactory)
static css::uno::Sequence< OUString > impl_ExpandSetNames(const css::uno::Sequence< OUString > &lSetNames)
virtual ~SvtModuleOptions_Impl() override
bool IsModuleInstalled(SvtModuleOptions::EModule eModule) const
OUString const & GetFactoryStandardTemplate(SvtModuleOptions::EFactory eFactory) const
bool IsModuleInstalled(EModule eModule) const
OUString GetDefaultModuleName() const
bool IsImpress() const
virtual ~SvtModuleOptions() override
OUString GetModuleName(EModule eModule) const
bool IsDefaultFilterReadonly(EFactory eFactory) const
bool IsMath() const
static EFactory ClassifyFactoryByURL(const OUString &sURL, const css::uno::Sequence< css::beans::PropertyValue > &lMediaDescriptor)
return the corresponding application ID for the given properties.
bool IsDraw() const
bool IsWriter() const
OUString GetFactoryEmptyDocumentURL(EFactory eFactory) const
bool IsCalc() const
OUString GetFactoryStandardTemplate(EFactory eFactory) const
bool IsChart() const
const OUString & GetFactoryName(EFactory eFactory) const
css::uno::Sequence< OUString > GetAllServiceNames()
static OUString GetFactoryShortName(EFactory eFactory)
void SetFactoryStandardTemplate(EFactory eFactory, const OUString &sTemplate)
bool IsDataBase() const
static EFactory ClassifyFactoryByShortName(std::u16string_view sName)
return the corresponding application ID for the given short name.
void SetFactoryDefaultFilter(EFactory eFactory, const OUString &sFilter)
sal_Int32 GetFactoryIcon(EFactory eFactory) const
static EFactory ClassifyFactoryByModel(const css::uno::Reference< css::frame::XModel > &xModel)
return the corresponding application ID for the given properties.
static bool ClassifyFactoryByName(std::u16string_view sName, EFactory &eFactory)
OUString GetFactoryDefaultFilter(EFactory eFactory) const
std::shared_ptr< SvtModuleOptions_Impl > m_pImpl
static EFactory ClassifyFactoryByServiceName(std::u16string_view sName)
return the corresponding application ID for the given document service name.
TValueType getUnpackedValueOrDefault(const OUString &sKey, const TValueType &aDefault) const
css::uno::Sequence< css::uno::Any > GetProperties(const css::uno::Sequence< OUString > &rNames)
bool SetSetProperties(const OUString &rNode, const css::uno::Sequence< css::beans::PropertyValue > &rValues)
css::uno::Sequence< OUString > GetNodeNames(const OUString &rNode)
Definition: configitem.cxx:685
bool EnableNotification(const css::uno::Sequence< OUString > &rNames, bool bEnableInternalNotification=false)
enables notifications about changes on selected sub nodes/values
Definition: configitem.cxx:604
bool IsModified() const
Definition: configitem.hxx:177
css::uno::Sequence< sal_Bool > GetReadOnlyStates(const css::uno::Sequence< OUString > &rNames)
Definition: configitem.cxx:316
int nCount
float u
OUString sName
@ ModuleOptions
constexpr OUStringLiteral FACTORYNAME_WRITERWEB
#define PROPERTYCOUNT
constexpr OUStringLiteral FACTORYNAME_STARTMODULE
#define PROPERTYHANDLE_SHORTNAME
#define PROPERTYNAME_DEFAULTFILTER
#define PROPERTYNAME_SHORTNAME
#define PROPERTYHANDLE_TEMPLATEFILE
constexpr OUStringLiteral FACTORYNAME_CHART
constexpr OUStringLiteral FACTORYNAME_WRITER
constexpr OUStringLiteral FACTORYNAME_IMPRESS
constexpr OUStringLiteral FACTORYNAME_DRAW
#define PATHSEPARATOR
#define FACTORYCOUNT
constexpr OUStringLiteral ROOTNODE_FACTORIES
constexpr OUStringLiteral FACTORYNAME_WRITERGLOBAL
#define PROPERTYHANDLE_DEFAULTFILTER
#define PROPERTYHANDLE_EMPTYDOCUMENTURL
constexpr OUStringLiteral FACTORYNAME_BASIC
#define PROPERTYHANDLE_WINDOWATTRIBUTES
constexpr OUStringLiteral FACTORYNAME_MATH
constexpr OUStringLiteral FACTORYNAME_CALC
#define PROPERTYNAME_EMPTYDOCUMENTURL
#define PROPERTYNAME_ICON
constexpr OUStringLiteral FACTORYNAME_DATABASE
#define PROPERTYHANDLE_ICON
#define PROPERTYNAME_TEMPLATEFILE
#define PROPERTYNAME_WINDOWATTRIBUTES
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
int i
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
Reference< XModel > xModel
std::mutex mutex
Definition: textsearch.cxx:94
signed char sal_Int8