fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / framework / source / accelerators / presethandler.cxx
blobe5ec774c75af751c460b3d93d326aef54606c1c8
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 <accelerators/presethandler.hxx>
22 #include <classes/fwkresid.hxx>
24 #include "classes/resource.hrc"
25 #include <services.h>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/configuration/CorruptedUIConfigurationException.hpp>
29 #include <com/sun/star/container/NoSuchElementException.hpp>
30 #include <com/sun/star/container/XNameAccess.hpp>
31 #include <com/sun/star/embed/ElementModes.hpp>
32 #include <com/sun/star/embed/XTransactedObject.hpp>
33 #include <com/sun/star/embed/FileSystemStorageFactory.hpp>
34 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
35 #include <com/sun/star/util/thePathSettings.hpp>
37 #include <vcl/svapp.hxx>
38 #include <cppuhelper/exc_hlp.hxx>
39 #include <rtl/ustrbuf.hxx>
40 #include <i18nlangtag/languagetag.hxx>
42 static const ::sal_Int32 ID_CORRUPT_UICONFIG_SHARE = 1;
43 static const ::sal_Int32 ID_CORRUPT_UICONFIG_USER = 2;
44 static const ::sal_Int32 ID_CORRUPT_UICONFIG_GENERAL = 3;
46 namespace framework
49 PresetHandler::PresetHandler(const css::uno::Reference< css::uno::XComponentContext >& xContext)
50 : m_xContext(xContext)
51 , m_eConfigType(E_GLOBAL)
52 , m_aSharedStorages()
53 , m_lDocumentStorages()
54 , m_aLanguageTag(LANGUAGE_USER_PRIV_NOTRANSLATE)
58 PresetHandler::PresetHandler(const PresetHandler& rCopy)
59 : m_aLanguageTag( rCopy.m_aLanguageTag)
61 m_xContext = rCopy.m_xContext;
62 m_eConfigType = rCopy.m_eConfigType;
63 m_sResourceType = rCopy.m_sResourceType;
64 m_sModule = rCopy.m_sModule;
65 m_aSharedStorages = rCopy.m_aSharedStorages;
66 m_xWorkingStorageShare = rCopy.m_xWorkingStorageShare;
67 m_xWorkingStorageNoLang = rCopy.m_xWorkingStorageNoLang;
68 m_xWorkingStorageUser = rCopy.m_xWorkingStorageUser;
69 m_lPresets = rCopy.m_lPresets;
70 m_lTargets = rCopy.m_lTargets;
71 m_lDocumentStorages = rCopy.m_lDocumentStorages;
72 m_sRelPathShare = rCopy.m_sRelPathShare;
73 m_sRelPathNoLang = rCopy.m_sRelPathNoLang;
74 m_sRelPathUser = rCopy.m_sRelPathUser;
77 PresetHandler::~PresetHandler()
79 m_xWorkingStorageShare.clear();
80 m_xWorkingStorageNoLang.clear();
81 m_xWorkingStorageUser.clear();
83 /* #i46497#
84 Dont call forgetCachedStorages() here for shared storages.
85 Because we opened different sub storages by using openPath().
86 And every already open path was reused and referenced (means it's
87 ref count was increased!)
88 So now we have to release our ref counts to these shared storages
89 only ... and not to free all used storages.
90 Otherwise we will disconnect all other open configuration access
91 objects which base on these storages.
93 m_aSharedStorages->m_lStoragesShare.closePath(m_sRelPathShare);
94 m_aSharedStorages->m_lStoragesUser.closePath (m_sRelPathUser );
96 /* On the other side closePath() is not needed for our special handled
97 document storage. Because it's not shared with others ... so we can
98 free it.
100 m_lDocumentStorages.forgetCachedStorages();
103 void PresetHandler::forgetCachedStorages()
105 SolarMutexGuard g;
107 if (m_eConfigType == E_DOCUMENT)
109 m_xWorkingStorageShare.clear();
110 m_xWorkingStorageNoLang.clear();
111 m_xWorkingStorageUser.clear();
114 m_lDocumentStorages.forgetCachedStorages();
117 namespace {
119 OUString lcl_getLocalizedMessage(::sal_Int32 nID)
121 OUString sMessage("Unknown error.");
123 switch(nID)
125 case ID_CORRUPT_UICONFIG_SHARE :
126 sMessage = FWK_RESSTR(STR_CORRUPT_UICFG_SHARE);
128 break;
130 case ID_CORRUPT_UICONFIG_USER :
131 sMessage = FWK_RESSTR(STR_CORRUPT_UICFG_USER);
132 break;
134 case ID_CORRUPT_UICONFIG_GENERAL :
135 sMessage = FWK_RESSTR(STR_CORRUPT_UICFG_GENERAL);
136 break;
139 return sMessage;
142 void lcl_throwCorruptedUIConfigurationException(
143 css::uno::Any const & exception, sal_Int32 id)
145 css::uno::Exception e;
146 bool ok = (exception >>= e);
147 OSL_ASSERT(ok); (void) ok; // avoid warnings
148 throw css::configuration::CorruptedUIConfigurationException(
149 lcl_getLocalizedMessage(id),
150 css::uno::Reference< css::uno::XInterface >(),
151 exception.getValueTypeName() + ": \"" + e.Message + "\"");
156 css::uno::Reference< css::embed::XStorage > PresetHandler::getOrCreateRootStorageShare()
158 css::uno::Reference< css::embed::XStorage > xRoot = m_aSharedStorages->m_lStoragesShare.getRootStorage();
159 if (xRoot.is())
160 return xRoot;
162 css::uno::Reference< css::uno::XComponentContext > xContext;
164 SolarMutexGuard g;
165 xContext = m_xContext;
168 css::uno::Reference< css::util::XPathSettings > xPathSettings =
169 css::util::thePathSettings::get( xContext );
171 OUString sShareLayer = xPathSettings->getBasePathShareLayer();
173 // "UIConfig" is a "multi path" ... use first part only here!
174 sal_Int32 nPos = sShareLayer.indexOf(';');
175 if (nPos > 0)
176 sShareLayer = sShareLayer.copy(0, nPos);
178 // Note: May be an user uses URLs without a final slash! Check it ...
179 nPos = sShareLayer.lastIndexOf('/');
180 if (nPos != sShareLayer.getLength()-1)
181 sShareLayer += "/";
183 sShareLayer += "soffice.cfg";
185 // TODO remove me!
186 // Attention: This is temp. workaround ... We create a temp. storage file
187 // based of a system directory. This must be used so, till the storage implementation
188 // can work on directories too.
190 css::uno::Sequence< css::uno::Any > lArgs(2);
191 lArgs[0] <<= sShareLayer;
192 lArgs[1] <<= css::embed::ElementModes::READ | css::embed::ElementModes::NOCREATE;
194 css::uno::Reference< css::lang::XSingleServiceFactory > xStorageFactory = css::embed::FileSystemStorageFactory::create( xContext );
195 css::uno::Reference< css::embed::XStorage > xStorage;
199 xStorage = css::uno::Reference< css::embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), css::uno::UNO_QUERY_THROW);
201 catch(const css::uno::Exception&)
203 css::uno::Any ex(cppu::getCaughtException());
204 lcl_throwCorruptedUIConfigurationException(
205 ex, ID_CORRUPT_UICONFIG_SHARE);
208 m_aSharedStorages->m_lStoragesShare.setRootStorage(xStorage);
210 return xStorage;
213 css::uno::Reference< css::embed::XStorage > PresetHandler::getOrCreateRootStorageUser()
215 css::uno::Reference< css::embed::XStorage > xRoot = m_aSharedStorages->m_lStoragesUser.getRootStorage();
216 if (xRoot.is())
217 return xRoot;
219 css::uno::Reference< css::uno::XComponentContext > xContext;
221 SolarMutexGuard g;
222 xContext = m_xContext;
225 css::uno::Reference< css::util::XPathSettings > xPathSettings =
226 css::util::thePathSettings::get( xContext );
228 OUString sUserLayer = xPathSettings->getBasePathUserLayer();
230 // Note: May be an user uses URLs without a final slash! Check it ...
231 sal_Int32 nPos = sUserLayer.lastIndexOf('/');
232 if (nPos != sUserLayer.getLength()-1)
233 sUserLayer += "/";
235 sUserLayer += "soffice.cfg"; // storage file
237 css::uno::Sequence< css::uno::Any > lArgs(2);
238 lArgs[0] <<= sUserLayer;
239 lArgs[1] <<= css::embed::ElementModes::READWRITE;
241 css::uno::Reference< css::lang::XSingleServiceFactory > xStorageFactory = css::embed::FileSystemStorageFactory::create( xContext );
242 css::uno::Reference< css::embed::XStorage > xStorage;
246 xStorage = css::uno::Reference< css::embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), css::uno::UNO_QUERY_THROW);
248 catch(const css::uno::Exception&)
250 css::uno::Any ex(cppu::getCaughtException());
251 lcl_throwCorruptedUIConfigurationException(
252 ex, ID_CORRUPT_UICONFIG_USER);
255 m_aSharedStorages->m_lStoragesUser.setRootStorage(xStorage);
257 return xStorage;
260 css::uno::Reference< css::embed::XStorage > PresetHandler::getWorkingStorageShare()
262 SolarMutexGuard g;
263 return m_xWorkingStorageShare;
266 css::uno::Reference< css::embed::XStorage > PresetHandler::getWorkingStorageUser()
268 SolarMutexGuard g;
269 return m_xWorkingStorageUser;
272 css::uno::Reference< css::embed::XStorage > PresetHandler::getParentStorageShare(const css::uno::Reference< css::embed::XStorage >& /*xChild*/)
274 css::uno::Reference< css::embed::XStorage > xWorking;
276 SolarMutexGuard g;
277 xWorking = m_xWorkingStorageShare;
280 return m_aSharedStorages->m_lStoragesShare.getParentStorage(xWorking);
283 css::uno::Reference< css::embed::XStorage > PresetHandler::getParentStorageUser(const css::uno::Reference< css::embed::XStorage >& /*xChild*/)
285 css::uno::Reference< css::embed::XStorage > xWorking;
287 SolarMutexGuard g;
288 xWorking = m_xWorkingStorageUser;
291 return m_aSharedStorages->m_lStoragesUser.getParentStorage(xWorking);
294 void PresetHandler::connectToResource( PresetHandler::EConfigType eConfigType ,
295 const OUString& sResource ,
296 const OUString& sModule ,
297 const css::uno::Reference< css::embed::XStorage >& xDocumentRoot,
298 const LanguageTag& rLanguageTag )
300 // TODO free all current open storages!
303 SolarMutexGuard g;
304 m_eConfigType = eConfigType;
305 m_sResourceType = sResource;
306 m_sModule = sModule;
307 m_aLanguageTag = rLanguageTag;
310 css::uno::Reference< css::embed::XStorage > xShare;
311 css::uno::Reference< css::embed::XStorage > xNoLang;
312 css::uno::Reference< css::embed::XStorage > xUser;
314 // special case for documents
315 // use outside root storage, if we run in E_DOCUMENT mode!
316 if (eConfigType == E_DOCUMENT)
318 if (!xDocumentRoot.is())
319 throw css::uno::RuntimeException(
320 "There is valid root storage, where the UI configuration can work on.");
321 m_lDocumentStorages.setRootStorage(xDocumentRoot);
322 xShare = xDocumentRoot;
323 xUser = xDocumentRoot;
325 else
327 xShare = getOrCreateRootStorageShare();
328 xUser = getOrCreateRootStorageUser();
331 // #...#
335 // a) inside share layer we should not create any new structures ... We jave to use
336 // existing ones only!
337 // b) inside user layer we can (SOFT mode!) but sometimes we should not (HARD mode!)
338 // create new empty structures. We should preferr using of any existing structure.
339 sal_Int32 eShareMode = (css::embed::ElementModes::READ | css::embed::ElementModes::NOCREATE);
340 sal_Int32 eUserMode = (css::embed::ElementModes::READWRITE );
342 OUStringBuffer sRelPathBuf(1024);
343 OUString sRelPathShare;
344 OUString sRelPathNoLang;
345 OUString sRelPathUser;
346 switch(eConfigType)
348 case E_GLOBAL :
350 sRelPathBuf.append("global");
351 sRelPathBuf.append("/");
352 sRelPathBuf.append(sResource);
353 sRelPathShare = sRelPathBuf.makeStringAndClear();
354 sRelPathUser = sRelPathShare;
356 xShare = impl_openPathIgnoringErrors(sRelPathShare, eShareMode, true );
357 xUser = impl_openPathIgnoringErrors(sRelPathUser , eUserMode , false);
359 break;
361 case E_MODULES :
363 sRelPathBuf.append("modules");
364 sRelPathBuf.append("/");
365 sRelPathBuf.append(sModule);
366 sRelPathBuf.append("/");
367 sRelPathBuf.append(sResource);
368 sRelPathShare = sRelPathBuf.makeStringAndClear();
369 sRelPathUser = sRelPathShare;
371 xShare = impl_openPathIgnoringErrors(sRelPathShare, eShareMode, true );
372 xUser = impl_openPathIgnoringErrors(sRelPathUser , eUserMode , false);
374 break;
376 case E_DOCUMENT :
378 // A document does not have a share layer in real.
379 // It has one layer only, and this one should be opened READ_WRITE.
380 // So we open the user layer here only and set the share layer equals to it .-)
382 sRelPathBuf.append(sResource);
383 sRelPathUser = sRelPathBuf.makeStringAndClear();
384 sRelPathShare = sRelPathUser;
388 xUser = m_lDocumentStorages.openPath(sRelPathUser , eUserMode );
389 xShare = xUser;
391 catch(const css::uno::RuntimeException&)
392 { throw; }
393 catch(const css::uno::Exception&)
394 { xShare.clear(); xUser.clear(); }
396 break;
399 // Non-localized global share
400 xNoLang = xShare;
401 sRelPathNoLang = sRelPathShare;
403 if (
404 (rLanguageTag != LanguageTag(LANGUAGE_USER_PRIV_NOTRANSLATE)) && // localized level?
405 (eConfigType != E_DOCUMENT ) // no localization in document mode!
408 // First try to find the right localized set inside share layer.
409 // Fallbacks are allowed there.
410 OUString aShareLocale( rLanguageTag.getBcp47());
411 OUString sLocalizedSharePath(sRelPathShare);
412 bool bAllowFallbacks = true;
413 xShare = impl_openLocalizedPathIgnoringErrors(sLocalizedSharePath, eShareMode, true , aShareLocale, bAllowFallbacks);
415 // The try to locate the right sub dir inside user layer ... without using fallbacks!
416 // Normally the corresponding sub dir should be created matching the specified locale.
417 // Because we allow creation of storages inside user layer by default.
418 OUString aUserLocale( rLanguageTag.getBcp47());
419 OUString sLocalizedUserPath(sRelPathUser);
420 bAllowFallbacks = false;
421 xUser = impl_openLocalizedPathIgnoringErrors(sLocalizedUserPath, eUserMode, false, aUserLocale, bAllowFallbacks);
423 sRelPathShare = sLocalizedSharePath;
424 sRelPathUser = sLocalizedUserPath;
427 // read content of level 3 (presets, targets)
428 css::uno::Reference< css::container::XNameAccess > xAccess;
429 css::uno::Sequence< OUString > lNames;
430 const OUString* pNames;
431 sal_Int32 c;
432 sal_Int32 i;
433 OUStringList lPresets;
434 OUStringList lTargets;
436 // read preset names of share layer
437 xAccess = css::uno::Reference< css::container::XNameAccess >(xShare, css::uno::UNO_QUERY);
438 if (xAccess.is())
440 lNames = xAccess->getElementNames();
441 pNames = lNames.getConstArray();
442 c = lNames.getLength();
444 for (i=0; i<c; ++i)
446 OUString sTemp = pNames[i];
447 sal_Int32 nPos = sTemp.indexOf(".xml");
448 if (nPos > -1)
449 sTemp = sTemp.copy(0,nPos);
450 lPresets.push_back(sTemp);
454 // read preset names of user layer
455 xAccess = css::uno::Reference< css::container::XNameAccess >(xUser, css::uno::UNO_QUERY);
456 if (xAccess.is())
458 lNames = xAccess->getElementNames();
459 pNames = lNames.getConstArray();
460 c = lNames.getLength();
462 for (i=0; i<c; ++i)
464 OUString sTemp = pNames[i];
465 sal_Int32 nPos = sTemp.indexOf(".xml");
466 if (nPos > -1)
467 sTemp = sTemp.copy(0,nPos);
468 lTargets.push_back(sTemp);
473 SolarMutexGuard g;
474 m_xWorkingStorageShare = xShare;
475 m_xWorkingStorageNoLang= xNoLang;
476 m_xWorkingStorageUser = xUser;
477 m_lPresets = lPresets;
478 m_lTargets = lTargets;
479 m_sRelPathShare = sRelPathShare;
480 m_sRelPathNoLang = sRelPathNoLang;
481 m_sRelPathUser = sRelPathUser;
485 catch(const css::uno::Exception&)
487 css::uno::Any ex(cppu::getCaughtException());
488 lcl_throwCorruptedUIConfigurationException(
489 ex, ID_CORRUPT_UICONFIG_GENERAL);
493 void PresetHandler::copyPresetToTarget(const OUString& sPreset,
494 const OUString& sTarget)
496 // dont check our preset list, if element exists
497 // We try to open it and forward all errors to the user!
499 css::uno::Reference< css::embed::XStorage > xWorkingShare;
500 css::uno::Reference< css::embed::XStorage > xWorkingNoLang;
501 css::uno::Reference< css::embed::XStorage > xWorkingUser;
503 SolarMutexGuard g;
504 xWorkingShare = m_xWorkingStorageShare;
505 xWorkingNoLang= m_xWorkingStorageNoLang;
506 xWorkingUser = m_xWorkingStorageUser;
509 // e.g. module without any config data ?!
510 if (
511 (!xWorkingShare.is()) ||
512 (!xWorkingUser.is() )
515 return;
518 OUString sPresetFile(sPreset);
519 sPresetFile += ".xml";
521 OUString sTargetFile(sTarget);
522 sTargetFile += ".xml";
524 // remove existing elements before you try to copy the preset to that location ...
525 // Otherwise w will get an ElementExistException inside copyElementTo()!
526 css::uno::Reference< css::container::XNameAccess > xCheckingUser(xWorkingUser, css::uno::UNO_QUERY_THROW);
527 if (xCheckingUser->hasByName(sTargetFile))
528 xWorkingUser->removeElement(sTargetFile);
530 xWorkingShare->copyElementTo(sPresetFile, xWorkingUser, sTargetFile);
532 // If our storages work in transacted mode, we have
533 // to commit all changes from bottom to top!
534 commitUserChanges();
537 css::uno::Reference< css::io::XStream > PresetHandler::openPreset(const OUString& sPreset,
538 bool bUseNoLangGlobal)
540 css::uno::Reference< css::embed::XStorage > xFolder;
542 SolarMutexGuard g;
543 xFolder = bUseNoLangGlobal? m_xWorkingStorageNoLang: m_xWorkingStorageShare;
546 // e.g. module without any config data ?!
547 if (!xFolder.is())
548 return css::uno::Reference< css::io::XStream >();
550 OUString sFile(sPreset);
551 sFile += ".xml";
553 // inform user about errors (use original exceptions!)
554 css::uno::Reference< css::io::XStream > xStream = xFolder->openStreamElement(sFile, css::embed::ElementModes::READ);
555 return xStream;
558 css::uno::Reference< css::io::XStream > PresetHandler::openTarget(const OUString& sTarget ,
559 bool bCreateIfMissing)
561 css::uno::Reference< css::embed::XStorage > xFolder;
563 SolarMutexGuard g;
564 xFolder = m_xWorkingStorageUser;
567 // e.g. module without any config data ?!
568 if (!xFolder.is())
569 return css::uno::Reference< css::io::XStream >();
571 OUString sFile(sTarget);
572 sFile += ".xml";
574 sal_Int32 nOpenMode = css::embed::ElementModes::READWRITE;
575 if (!bCreateIfMissing)
576 nOpenMode |= css::embed::ElementModes::NOCREATE;
578 // try it in read/write mode first and ignore errors.
579 css::uno::Reference< css::io::XStream > xStream;
582 xStream = xFolder->openStreamElement(sFile, nOpenMode);
583 return xStream;
585 catch(const css::uno::RuntimeException&)
586 { throw; }
587 catch(const css::uno::Exception&)
588 { xStream.clear(); }
590 // try it readonly if it failed before.
591 // inform user about errors (use original exceptions!)
592 nOpenMode &= ~css::embed::ElementModes::WRITE;
593 xStream = xFolder->openStreamElement(sFile, nOpenMode);
595 return xStream;
598 void PresetHandler::commitUserChanges()
600 css::uno::Reference< css::embed::XStorage > xWorking;
601 EConfigType eCfgType;
603 SolarMutexGuard g;
604 xWorking = m_xWorkingStorageUser;
605 eCfgType = m_eConfigType;
608 // e.g. module without any config data ?!
609 if (!xWorking.is())
610 return;
612 OUString sPath;
614 switch(eCfgType)
616 case E_GLOBAL :
617 case E_MODULES :
619 sPath = m_aSharedStorages->m_lStoragesUser.getPathOfStorage(xWorking);
620 m_aSharedStorages->m_lStoragesUser.commitPath(sPath);
621 m_aSharedStorages->m_lStoragesUser.notifyPath(sPath);
623 break;
625 case E_DOCUMENT :
627 sPath = m_lDocumentStorages.getPathOfStorage(xWorking);
628 m_lDocumentStorages.commitPath(sPath);
629 m_lDocumentStorages.notifyPath(sPath);
631 break;
635 void PresetHandler::addStorageListener(IStorageListener* pListener)
637 OUString sRelPath;
638 EConfigType eCfgType;
640 SolarMutexGuard g;
641 sRelPath = m_sRelPathUser; // use user path ... because we dont work directly on the share layer!
642 eCfgType = m_eConfigType;
645 if (sRelPath.isEmpty())
646 return;
648 switch(eCfgType)
650 case E_GLOBAL :
651 case E_MODULES :
653 m_aSharedStorages->m_lStoragesUser.addStorageListener(pListener, sRelPath);
655 break;
657 case E_DOCUMENT :
659 m_lDocumentStorages.addStorageListener(pListener, sRelPath);
661 break;
665 void PresetHandler::removeStorageListener(IStorageListener* pListener)
667 OUString sRelPath;
668 EConfigType eCfgType;
670 SolarMutexGuard g;
671 sRelPath = m_sRelPathUser; // use user path ... because we dont work directly on the share layer!
672 eCfgType = m_eConfigType;
675 if (sRelPath.isEmpty())
676 return;
678 switch(eCfgType)
680 case E_GLOBAL :
681 case E_MODULES :
683 m_aSharedStorages->m_lStoragesUser.removeStorageListener(pListener, sRelPath);
685 break;
687 case E_DOCUMENT :
689 m_lDocumentStorages.removeStorageListener(pListener, sRelPath);
691 break;
695 css::uno::Reference< css::embed::XStorage > PresetHandler::impl_openPathIgnoringErrors(const OUString& sPath ,
696 sal_Int32 eMode ,
697 bool bShare)
699 css::uno::Reference< css::embed::XStorage > xPath;
702 if (bShare)
703 xPath = m_aSharedStorages->m_lStoragesShare.openPath(sPath, eMode);
704 else
705 xPath = m_aSharedStorages->m_lStoragesUser.openPath(sPath, eMode);
707 catch(const css::uno::RuntimeException&)
708 { throw; }
709 catch(const css::uno::Exception&)
710 { xPath.clear(); }
711 return xPath;
714 ::std::vector< OUString >::const_iterator PresetHandler::impl_findMatchingLocalizedValue(
715 const ::std::vector< OUString >& lLocalizedValues,
716 OUString& rLanguageTag,
717 bool bAllowFallbacks )
719 ::std::vector< OUString >::const_iterator pFound = lLocalizedValues.end();
720 if (bAllowFallbacks)
722 pFound = LanguageTag::getFallback(lLocalizedValues, rLanguageTag);
723 // if we found a valid locale ... take it over to our in/out parameter
724 // rLanguageTag
725 if (pFound != lLocalizedValues.end())
727 rLanguageTag = *pFound;
730 else
732 for ( pFound = lLocalizedValues.begin();
733 pFound != lLocalizedValues.end();
734 ++pFound )
736 if (*pFound == rLanguageTag)
737 break;
741 return pFound;
744 css::uno::Reference< css::embed::XStorage > PresetHandler::impl_openLocalizedPathIgnoringErrors(
745 OUString& sPath ,
746 sal_Int32 eMode ,
747 bool bShare ,
748 OUString& rLanguageTag ,
749 bool bAllowFallback)
751 css::uno::Reference< css::embed::XStorage > xPath = impl_openPathIgnoringErrors(sPath, eMode, bShare);
752 ::std::vector< OUString > lSubFolders = impl_getSubFolderNames(xPath);
753 ::std::vector< OUString >::const_iterator pLocaleFolder = impl_findMatchingLocalizedValue(lSubFolders, rLanguageTag, bAllowFallback);
755 // no fallback ... creation not allowed => no storage
756 if (
757 (pLocaleFolder == lSubFolders.end() ) &&
758 ((eMode & css::embed::ElementModes::NOCREATE) == css::embed::ElementModes::NOCREATE)
760 return css::uno::Reference< css::embed::XStorage >();
762 // it doesn't matter, if there is a locale fallback or not
763 // If creation of storages is allowed, we do it anyway.
764 // Otherwhise we have no acc config at all, which can make other trouble.
765 OUString sLocalizedPath;
766 sLocalizedPath = sPath;
767 sLocalizedPath += "/";
768 if (pLocaleFolder != lSubFolders.end())
769 sLocalizedPath += *pLocaleFolder;
770 else
771 sLocalizedPath += rLanguageTag;
773 css::uno::Reference< css::embed::XStorage > xLocalePath = impl_openPathIgnoringErrors(sLocalizedPath, eMode, bShare);
775 if (xLocalePath.is())
776 sPath = sLocalizedPath;
777 else
778 sPath.clear();
780 return xLocalePath;
783 ::std::vector< OUString > PresetHandler::impl_getSubFolderNames(const css::uno::Reference< css::embed::XStorage >& xFolder)
785 css::uno::Reference< css::container::XNameAccess > xAccess(xFolder, css::uno::UNO_QUERY);
786 if (!xAccess.is())
787 return ::std::vector< OUString >();
789 ::std::vector< OUString > lSubFolders;
790 const css::uno::Sequence< OUString > lNames = xAccess->getElementNames();
791 const OUString* pNames = lNames.getConstArray();
792 sal_Int32 c = lNames.getLength();
793 sal_Int32 i = 0;
795 for (i=0; i<c; ++i)
799 if (xFolder->isStorageElement(pNames[i]))
800 lSubFolders.push_back(pNames[i]);
802 catch(const css::uno::RuntimeException&)
803 { throw; }
804 catch(const css::uno::Exception&)
808 return lSubFolders;
811 } // namespace framework
813 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */