From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- framework/source/fwi/classes/converter.cxx | 116 ++++++++ .../source/fwi/classes/protocolhandlercache.cxx | 257 +++++++++++++++++ framework/source/fwi/helper/mischelper.cxx | 154 ++++++++++ framework/source/fwi/helper/shareablemutex.cxx | 49 ++++ framework/source/fwi/jobs/configaccess.cxx | 184 ++++++++++++ .../source/fwi/threadhelp/transactionmanager.cxx | 219 ++++++++++++++ .../source/fwi/uielement/constitemcontainer.cxx | 288 +++++++++++++++++++ framework/source/fwi/uielement/itemcontainer.cxx | 212 ++++++++++++++ .../source/fwi/uielement/rootitemcontainer.cxx | 313 +++++++++++++++++++++ 9 files changed, 1792 insertions(+) create mode 100644 framework/source/fwi/classes/converter.cxx create mode 100644 framework/source/fwi/classes/protocolhandlercache.cxx create mode 100644 framework/source/fwi/helper/mischelper.cxx create mode 100644 framework/source/fwi/helper/shareablemutex.cxx create mode 100644 framework/source/fwi/jobs/configaccess.cxx create mode 100644 framework/source/fwi/threadhelp/transactionmanager.cxx create mode 100644 framework/source/fwi/uielement/constitemcontainer.cxx create mode 100644 framework/source/fwi/uielement/itemcontainer.cxx create mode 100644 framework/source/fwi/uielement/rootitemcontainer.cxx (limited to 'framework/source/fwi') diff --git a/framework/source/fwi/classes/converter.cxx b/framework/source/fwi/classes/converter.cxx new file mode 100644 index 000000000..a29c5b127 --- /dev/null +++ b/framework/source/fwi/classes/converter.cxx @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +namespace framework{ + +/** + * converts a sequence of PropertyValue to a sequence of NamedValue. + */ +css::uno::Sequence< css::beans::NamedValue > Converter::convert_seqPropVal2seqNamedVal( const css::uno::Sequence< css::beans::PropertyValue >& lSource ) +{ + sal_Int32 nCount = lSource.getLength(); + css::uno::Sequence< css::beans::NamedValue > lDestination(nCount); + auto lDestinationRange = asNonConstRange(lDestination); + for (sal_Int32 nItem=0; nItem Converter::convert_seqOUString2OUStringList( const css::uno::Sequence< OUString >& lSource ) +{ + std::vector lDestination; + sal_Int32 nCount = lSource.getLength(); + + lDestination.reserve(nCount); + for (sal_Int32 nItem = 0; nItem < nCount; ++nItem) + { + lDestination.push_back(lSource[nItem]); + } + + return lDestination; +} + +OUString Converter::convert_DateTime2ISO8601( const DateTime& aSource ) +{ + OUStringBuffer sBuffer(25); + + sal_Int32 nYear = aSource.GetYear(); + sal_Int32 nMonth = aSource.GetMonth(); + sal_Int32 nDay = aSource.GetDay(); + + sal_Int32 nHour = aSource.GetHour(); + sal_Int32 nMin = aSource.GetMin(); + sal_Int32 nSec = aSource.GetSec(); + + // write year formatted as "YYYY" + if (nYear<10) + sBuffer.append("000"); + else if (nYear<100) + sBuffer.append("00"); + else if (nYear<1000) + sBuffer.append("0"); + sBuffer.append( nYear ); + + sBuffer.append("-"); + // write month formatted as "MM" + if (nMonth<10) + sBuffer.append("0"); + sBuffer.append( nMonth ); + + sBuffer.append("-"); + // write day formatted as "DD" + if (nDay<10) + sBuffer.append("0"); + sBuffer.append( nDay ); + + sBuffer.append("T"); + // write hours formatted as "hh" + if (nHour<10) + sBuffer.append("0"); + sBuffer.append( nHour ); + + sBuffer.append(":"); + // write min formatted as "mm" + if (nMin<10) + sBuffer.append("0"); + sBuffer.append( nMin ); + + sBuffer.append(":"); + // write sec formatted as "ss" + if (nSec<10) + sBuffer.append("0"); + sBuffer.append( nSec ); + + sBuffer.append("Z"); + + return sBuffer.makeStringAndClear(); +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/fwi/classes/protocolhandlercache.cxx b/framework/source/fwi/classes/protocolhandlercache.cxx new file mode 100644 index 000000000..7619d4323 --- /dev/null +++ b/framework/source/fwi/classes/protocolhandlercache.cxx @@ -0,0 +1,257 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +/*TODO + - change "singleton" behaviour by using new helper ::comhelper::SingletonRef + - rename method exist() to existHandlerForURL() or similar one + - may it's a good idea to replace struct ProtocolHandler by css::beans::NamedValue type?! +*/ + +#include +#include + +#include +#include +#include +#include + +constexpr OUStringLiteral SETNAME_HANDLER = u"HandlerSet"; // name of configuration set inside package + +namespace framework{ + +/** + @short overloaded index operator of hash map to support pattern key search + @descr All keys inside this hash map are URL pattern which points to a uno + implementation name of a protocol handler service which is registered + for this pattern. This operator makes it easy to find such registered + handler by using a full qualified URL and compare it with all pattern + keys. + + @param sURL + the full qualified URL which should match to a registered pattern + + @return An iterator which points to the found item inside the hash or PatternHash::end() + if no pattern match this given sURL. + */ +namespace { + +PatternHash::const_iterator findPatternKey(PatternHash const * hash, const OUString& sURL) +{ + return std::find_if(hash->begin(), hash->end(), + [&sURL](const PatternHash::value_type& rEntry) { + WildCard aPattern(rEntry.first); + return aPattern.Matches(sURL); + }); +} + +} + +/** + @short initialize static member of class HandlerCache + @descr We use a singleton pattern to implement this handler cache. + That means it use two static member list to hold all necessary information + and a ref count mechanism to create/destroy it on demand. + */ +std::optional HandlerCache::s_pHandler; +std::optional HandlerCache::s_pPattern; +sal_Int32 HandlerCache::m_nRefCount = 0; +HandlerCFGAccess* HandlerCache::s_pConfig = nullptr; + +/** + @short ctor of the cache of all registered protocol handler + @descr It tries to open the right configuration package automatically + and fill the internal structures. After that the cache can be + used for read access on this data and perform some search + operations on it. + */ +HandlerCache::HandlerCache() +{ + SolarMutexGuard aGuard; + + if (m_nRefCount==0) + { + s_pHandler.emplace(); + s_pPattern.emplace(); + s_pConfig = new HandlerCFGAccess(PACKAGENAME_PROTOCOLHANDLER); + s_pConfig->read(*s_pHandler, *s_pPattern); + s_pConfig->setCache(this); + } + + ++m_nRefCount; +} + +/** + @short dtor of the cache + @descr It frees all used memory. In further implementations (may if we support write access too) + it's a good place to flush changes back to the configuration - but not needed yet. + */ +HandlerCache::~HandlerCache() +{ + SolarMutexGuard aGuard; + + if( m_nRefCount==1) + { + s_pConfig->setCache(nullptr); + + delete s_pConfig; + s_pConfig = nullptr; + s_pHandler.reset(); + s_pPattern.reset(); + } + + --m_nRefCount; +} + +/** + @short dtor of the cache + @descr It frees all used memory. In further implementations (may if we support write access too) + it's a good place to flush changes back to the configuration - but not needed yet. + */ +bool HandlerCache::search( const OUString& sURL, ProtocolHandler* pReturn ) const +{ + bool bFound = false; + + SolarMutexGuard aGuard; + + PatternHash::const_iterator pItem = findPatternKey(s_pPattern ? &*s_pPattern : nullptr, sURL); + if (pItem != s_pPattern->end()) + { + *pReturn = (*s_pHandler)[pItem->second]; + bFound = true; + } + + return bFound; +} + +/** + @short search for a registered handler by using a URL struct + @descr We combine necessary parts of this struct to a valid URL string + and call our other search method ... + It's a helper for outside code. + */ +bool HandlerCache::search( const css::util::URL& aURL, ProtocolHandler* pReturn ) const +{ + return search( aURL.Complete, pReturn ); +} + +void HandlerCache::takeOver(HandlerHash aHandler, PatternHash aPattern) +{ + SolarMutexGuard aGuard; + + s_pHandler = std::move(aHandler); + s_pPattern = std::move(aPattern); +} + +/** + @short dtor of the config access class + @descr It opens the configuration package automatically by using base class mechanism. + After that "read()" method of this class should be called to use it. + + @param sPackage + specifies the package name of the configuration data which should be used + */ +HandlerCFGAccess::HandlerCFGAccess( const OUString& sPackage ) + : ConfigItem(sPackage) + , m_pCache(nullptr) +{ + css::uno::Sequence< OUString > lListenPaths { SETNAME_HANDLER }; + EnableNotification(lListenPaths); +} + +/** + @short use base class mechanism to fill given structures + @descr User use us as a wrapper between configuration api and his internal structures. + He give us some pointer to his member and we fill it. + + @param rHandlerHash + list of protocol handler infos + + @param rPatternHash + reverse map of handler pattern to her uno names + */ +void HandlerCFGAccess::read( HandlerHash& rHandlerHash, PatternHash& rPatternHash ) +{ + // list of all uno implementation names without encoding + css::uno::Sequence< OUString > lNames = GetNodeNames( SETNAME_HANDLER, ::utl::ConfigNameFormat::LocalPath ); + sal_Int32 nSourceCount = lNames.getLength(); + sal_Int32 nTargetCount = nSourceCount; + // list of all full qualified path names of configuration entries + css::uno::Sequence< OUString > lFullNames ( nTargetCount ); + auto lFullNamesRange = asNonConstRange(lFullNames); + // expand names to full path names + sal_Int32 nSource=0; + sal_Int32 nTarget=0; + for( nSource=0; nSource lValues = GetProperties( lFullNames ); + SAL_WARN_IF( lFullNames.getLength()!=lValues.getLength(), "fwk", "HandlerCFGAccess::read(): Miss some configuration values of handler set!" ); + + // fill structures + nSource = 0; + for( nTarget=0; nTarget lTemp; + lValues[nTarget] >>= lTemp; + aHandler.m_lProtocols = Converter::convert_seqOUString2OUStringList(lTemp); + + // register his pattern into the performance search hash + for (auto const& item : aHandler.m_lProtocols) + { + rPatternHash[item] = lNames[nSource]; + } + + // insert the handler info into the normal handler cache + rHandlerHash[lNames[nSource]] = aHandler; + ++nSource; + } +} + +void HandlerCFGAccess::Notify(const css::uno::Sequence< OUString >& /*lPropertyNames*/) +{ + HandlerHash aHandler; + PatternHash aPattern; + + read(aHandler, aPattern); + if (m_pCache) + m_pCache->takeOver(std::move(aHandler), std::move(aPattern)); +} + +void HandlerCFGAccess::ImplCommit() +{ +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/fwi/helper/mischelper.cxx b/framework/source/fwi/helper/mischelper.cxx new file mode 100644 index 000000000..e9c664d47 --- /dev/null +++ b/framework/source/fwi/helper/mischelper.cxx @@ -0,0 +1,154 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + +namespace framework +{ + +uno::Reference< linguistic2::XLanguageGuessing > const & LanguageGuessingHelper::GetGuesser() const +{ + if (!m_xLanguageGuesser.is()) + { + try + { + m_xLanguageGuesser = linguistic2::LanguageGuessing::create( m_xContext ); + } + catch (const uno::Exception &) + { + SAL_WARN( "fwk", "failed to get language guessing component" ); + } + } + return m_xLanguageGuesser; +} + +void FillLangItems( std::set< OUString > &rLangItems, + const uno::Reference< frame::XFrame > & rxFrame, + const LanguageGuessingHelper & rLangGuessHelper, + SvtScriptType nScriptType, + const OUString & rCurLang, + const OUString & rKeyboardLang, + const OUString & rGuessedTextLang ) +{ + rLangItems.clear(); + + //1--add current language + if( !rCurLang.isEmpty() && + LANGUAGE_DONTKNOW != SvtLanguageTable::GetLanguageType( rCurLang )) + rLangItems.insert( rCurLang ); + + //2--System + const AllSettings& rAllSettings = Application::GetSettings(); + LanguageType rSystemLanguage = rAllSettings.GetLanguageTag().getLanguageType(); + if( rSystemLanguage != LANGUAGE_DONTKNOW ) + { + if ( IsScriptTypeMatchingToLanguage( nScriptType, rSystemLanguage )) + rLangItems.insert( SvtLanguageTable::GetLanguageString( rSystemLanguage ) ); + } + + //3--UI + LanguageType rUILanguage = rAllSettings.GetUILanguageTag().getLanguageType(); + if( rUILanguage != LANGUAGE_DONTKNOW ) + { + if ( IsScriptTypeMatchingToLanguage( nScriptType, rUILanguage )) + rLangItems.insert( SvtLanguageTable::GetLanguageString( rUILanguage ) ); + } + + //4--guessed language + const uno::Reference< linguistic2::XLanguageGuessing >& xLangGuesser( rLangGuessHelper.GetGuesser() ); + if ( xLangGuesser.is() && !rGuessedTextLang.isEmpty()) + { + css::lang::Locale aLocale(xLangGuesser->guessPrimaryLanguage( rGuessedTextLang, 0, rGuessedTextLang.getLength()) ); + LanguageType nLang = LanguageTag( aLocale ).makeFallback().getLanguageType(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_NONE && nLang != LANGUAGE_SYSTEM + && IsScriptTypeMatchingToLanguage( nScriptType, nLang )) + rLangItems.insert( SvtLanguageTable::GetLanguageString( nLang )); + } + + //5--keyboard language + if( !rKeyboardLang.isEmpty() ) + { + if ( IsScriptTypeMatchingToLanguage( nScriptType, SvtLanguageTable::GetLanguageType( rKeyboardLang ))) + rLangItems.insert( rKeyboardLang ); + } + + //6--all languages used in current document + Reference< css::frame::XModel > xModel; + if ( rxFrame.is() ) + { + Reference< css::frame::XController > xController = rxFrame->getController(); + if ( xController.is() ) + xModel = xController->getModel(); + } + Reference< document::XDocumentLanguages > xDocumentLanguages( xModel, UNO_QUERY ); + /*the description of nScriptType + LATIN : 0x001 + ASIAN : 0x002 + COMPLEX: 0x004 + */ + const sal_Int16 nMaxCount = 7; + if ( !xDocumentLanguages.is() ) + return; + + const Sequence< Locale > rLocales( xDocumentLanguages->getDocumentLanguages( static_cast(nScriptType), nMaxCount )); + for ( const Locale& rLocale : rLocales ) + { + if ( rLangItems.size() == static_cast< size_t >(nMaxCount) ) + break; + if( IsScriptTypeMatchingToLanguage( nScriptType, SvtLanguageTable::GetLanguageType( rLocale.Language ))) + rLangItems.insert( rLocale.Language ); + } +} + +auto (*g_pGetMultiplexerListener)( + css::uno::Reference const & xComponentContext, + uno::Reference const&, + std::function const&)> const&) + -> uno::Reference = nullptr; + +uno::Reference +GetFirstListenerWith_Impl( + css::uno::Reference const & xComponentContext, + uno::Reference const& xEventFocus, + std::function const&)> const& rPredicate) +{ + assert(g_pGetMultiplexerListener != nullptr); // should not be called too early, nor too late + return g_pGetMultiplexerListener(xComponentContext, xEventFocus, rPredicate); +} + + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/fwi/helper/shareablemutex.cxx b/framework/source/fwi/helper/shareablemutex.cxx new file mode 100644 index 000000000..cd3b6bd18 --- /dev/null +++ b/framework/source/fwi/helper/shareablemutex.cxx @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +namespace framework +{ +ShareableMutex::ShareableMutex() +{ + m_pMutexRef = new MutexRef; + m_pMutexRef->acquire(); +} + +ShareableMutex::ShareableMutex(const ShareableMutex& rShareableMutex) +{ + m_pMutexRef = rShareableMutex.m_pMutexRef; + m_pMutexRef->acquire(); +} + +ShareableMutex& ShareableMutex::operator=(const ShareableMutex& rShareableMutex) +{ + rShareableMutex.m_pMutexRef->acquire(); + m_pMutexRef->release(); + m_pMutexRef = rShareableMutex.m_pMutexRef; + return *this; +} + +void ShareableMutex::acquire() { m_pMutexRef->m_oslMutex.acquire(); } + +void ShareableMutex::release() { m_pMutexRef->m_oslMutex.release(); } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/fwi/jobs/configaccess.cxx b/framework/source/fwi/jobs/configaccess.cxx new file mode 100644 index 000000000..fde891293 --- /dev/null +++ b/framework/source/fwi/jobs/configaccess.cxx @@ -0,0 +1,184 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include +#include + +#include + +namespace framework{ + +/** + @short open the configuration of this job + @descr We open the configuration of this job only. Not the whole package or the whole + job set. We are interested on our own properties only. + We set the opened configuration access as our member. So any following method, + which needs cfg access, can use it. That prevent us against multiple open/close requests. + But you can use this method to upgrade an already opened configuration too. + + @param eMode + force opening of the configuration access in readonly or in read/write mode + */ +ConfigAccess::ConfigAccess( /*IN*/ css::uno::Reference< css::uno::XComponentContext > xContext, + /*IN*/ OUString sRoot ) + : m_xContext (std::move( xContext)) + , m_sRoot (std::move( sRoot )) + , m_eMode ( E_CLOSED ) +{ +} + +/** + @short last chance to close an open configuration access point + @descr In case our user forgot to close this configuration point + in the right way, normally he will run into some trouble - + e.g. losing data. + */ +ConfigAccess::~ConfigAccess() +{ + close(); +} + +/** + @short return the internal mode of this instance + @descr May be the outside user need any information about successfully opened + or closed config access point objects. He can control the internal mode to do so. + + @return The internal open state of this object. + */ +ConfigAccess::EOpenMode ConfigAccess::getMode() const +{ + std::unique_lock g(m_mutex); + return m_eMode; +} + +/** + @short open the configuration access in the specified mode + @descr We set the opened configuration access as our member. So any following method, + which needs cfg access, can use it. That prevent us against multiple open/close requests. + But you can use this method to upgrade an already opened configuration too. + It's possible to open a config access in READONLY mode first and "open" it at a second + time within the mode READWRITE. Then we will upgrade it. Downgrade will be possible too. + + But note: closing will be done explicitly by calling method close() ... not by + downgrading with mode CLOSED! + + @param eMode + force (re)opening of the configuration access in readonly or in read/write mode + */ +void ConfigAccess::open( /*IN*/ EOpenMode eMode ) +{ + std::unique_lock g(m_mutex); + + // check if configuration is already open in the right mode. + // By the way: Don't allow closing by using this method! + if ( eMode == E_CLOSED || m_eMode == eMode ) + return; + + // We have to close the old access point without any question here. + // It will be open again using the new mode. + // can be called without checks! It does the checks by itself ... + // e.g. for already closed or not opened configuration. + // Flushing of all made changes will be done here too. + closeImpl(); + + // create the configuration provider, which provides sub access points + css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider = css::configuration::theDefaultProvider::get(m_xContext); + css::beans::PropertyValue aParam; + aParam.Name = "nodepath"; + aParam.Value <<= m_sRoot; + + css::uno::Sequence< css::uno::Any > lParams{ css::uno::Any(aParam) }; + + // open it + try + { + if (eMode==E_READONLY) + m_xConfig = xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGREADACCESS , lParams); + else + if (eMode==E_READWRITE) + m_xConfig = xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGUPDATEACCESS, lParams); + } + catch(const css::uno::Exception&) + { + TOOLS_INFO_EXCEPTION("fwk", "open config"); + } + + m_eMode = E_CLOSED; + if (m_xConfig.is()) + m_eMode = eMode; +} + +/** + @short close the internal opened configuration access and flush all changes + @descr It checks, if the given access is valid and react in the right way. + It flushes all changes ... so nobody else must know this state. + */ +void ConfigAccess::close() +{ + std::unique_lock g(m_mutex); + closeImpl(); +} + +void ConfigAccess::closeImpl() +{ + // check already closed configuration + if (m_xConfig.is()) + { + css::uno::Reference< css::util::XChangesBatch > xFlush(m_xConfig, css::uno::UNO_QUERY); + if (xFlush.is()) + xFlush->commitChanges(); + m_xConfig.clear(); + m_eMode = E_CLOSED; + } +} + +/** + @short provides an access to the internal wrapped configuration access + @descr It's not allowed to safe this c++ (!) reference outside. You have + to use it directly. Further you must use our public lock member m_aLock + to synchronize your code with our internal structures and our interface + methods. Acquire it before you call cfg() and release it afterwards immediately. + + E.g.: ConfigAccess aAccess(...); + Guard aReadLock(aAccess.m_aLock); + Reference< XPropertySet > xSet(aAccess.cfg(), UNO_QUERY); + Any aProp = xSet->getPropertyValue("..."); + aReadLock.unlock(); + + @attention During this time it's not allowed to call the methods open() or close()! + Otherwise you will change your own referenced config access. Anything will + be possible then. + + @return A c++(!) reference to the uno instance of the configuration access point. + */ +const css::uno::Reference< css::uno::XInterface >& ConfigAccess::cfg() +{ + // must be synchronized from outside! + // => no lock here ... + return m_xConfig; +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/fwi/threadhelp/transactionmanager.cxx b/framework/source/fwi/threadhelp/transactionmanager.cxx new file mode 100644 index 000000000..86d5b354a --- /dev/null +++ b/framework/source/fwi/threadhelp/transactionmanager.cxx @@ -0,0 +1,219 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include + +#include + +namespace framework{ + +/*-************************************************************************************************************ + @short standard ctor + @descr Initialize instance with right start values for correct working. +*//*-*************************************************************************************************************/ +TransactionManager::TransactionManager() + : m_eWorkingMode ( E_INIT ) + , m_nTransactionCount ( 0 ) +{ + m_aBarrier.open(); +} + +/*-************************************************************************************************************ + @short standard dtor +*//*-*************************************************************************************************************/ +TransactionManager::~TransactionManager() +{ +} + +/*-**************************************************************************************************** + @short set new working mode + @descr These implementation knows for states of working: E_INIT, E_WORK, E_BEFORECLOSE, E_CLOSE + You can step during this ones only from the left to the right side and start at left side again! + (This is necessary e.g. for refcounted objects!) + This call will block till all current existing transactions was finished. + Following results can occur: + E_INIT : All requests on this implementation are refused. + It's your decision to react in a right way. + + E_WORK : The object can work now. The full functionality is available. + + E_BEFORECLOSE : The object start the closing mechanism ... but sometimes + e.g. the dispose() method need to call some private methods. + These some special methods should use E_SOFTEXCEPTIONS + to detect this special case! + + E_CLOSE : Object is already dead! All further requests will be refused. + It's your decision to react in a right way. + @param "eMode", is the new mode - but we don't accept setting mode in wrong order! + @onerror We do nothing. +*//*-*****************************************************************************************************/ +void TransactionManager::setWorkingMode( EWorkingMode eMode ) +{ + // Safe member access. + bool bWaitFor = false; + { + std::unique_lock aAccessGuard(m_aAccessLock); + // Change working mode first! + if ( + (m_eWorkingMode == E_INIT && eMode == E_WORK) || + ((m_eWorkingMode == E_WORK || m_eWorkingMode == E_INIT) && eMode == E_BEFORECLOSE) || + (m_eWorkingMode == E_BEFORECLOSE && eMode == E_CLOSE) || + (m_eWorkingMode == E_CLOSE && eMode == E_INIT) + ) + { + m_eWorkingMode = eMode; + if (m_eWorkingMode == E_BEFORECLOSE || m_eWorkingMode == E_CLOSE) + { + bWaitFor = true; + } + } + } + // Wait for current existing transactions then! + // (Only necessary for changing to E_BEFORECLOSE or E_CLOSE!... + // otherwise; if you wait at setting E_WORK another thread could finish an acquire-call during our unlock() and wait() call + // ... and we will wait forever here!!!) + // Don't forget to release access mutex before. + if( bWaitFor ) + { + m_aBarrier.wait(); + } +} + +/*-**************************************************************************************************** + @short get current working mode + @descr If you stand in your close() or init() method ... but don't know + if you called more than ones(!) ... you can use this function to get + right information. + e.g: You have a method init() which is used to change working mode from + E_INIT to E_WORK and should be used to initialize some member too ... + What should you do: + + void init( sal_Int32 nValue ) + { + // Reject this call if our transaction manager say: "Object already initialized!" + // Otherwise initialize your member. + if( m_aTransactionManager.getWorkingMode() == E_INIT ) + { + // Object is uninitialized ... + // Make member access threadsafe! + Guard aGuard( m_aMutex ); + + // Check working mode again .. because another instance could be faster. + // (It's possible to set this guard at first of this method too!) + if( m_aTransactionManager.getWorkingMode() == E_INIT ) + { + m_aMember = nValue; + + // Object is initialized now ... set working mode to E_WORK! + m_aTransactionManager.setWorkingMode( E_WORK ); + } + } + } + + @seealso method setWorkingMode() + @return Current set mode. + + @onerror No error should occur. +*//*-*****************************************************************************************************/ +EWorkingMode TransactionManager::getWorkingMode() const +{ + // Synchronize access to internal member! + std::unique_lock aAccessLock( m_aAccessLock ); + return m_eWorkingMode; +} + +/*-**************************************************************************************************** + @short start new transaction + @descr A guard should use this method to start a new transaction. He should look for rejected + calls to by using parameter eMode and eReason. + If call was not rejected your transaction will be non breakable during releasing your transaction + guard! BUT ... your code isn't threadsafe then! It's a transaction manager only... + + @seealso method unregisterTransaction() + + @param "eMode" ,used to enable/disable throwing exceptions automatically for rejected calls +*//*-*****************************************************************************************************/ +void TransactionManager::registerTransaction( EExceptionMode eMode ) +{ + std::unique_lock aAccessGuard( m_aAccessLock ); + switch( m_eWorkingMode ) + { + case E_INIT: + if( eMode == E_HARDEXCEPTIONS ) + { + // Help programmer to find out, why this exception is thrown! + SAL_WARN( "fwk", "TransactionManager...: Owner instance not correctly initialized yet. Call was rejected! Normally it's an algorithm error ... wrong use of class!" ); + //ATTENTION: temp. disabled - till all bad code positions are detected and changed! */ + // throw css::uno::RuntimeException( "TransactionManager.: Owner instance not right initialized yet. Call was rejected! Normally it's an algorithm error... wrong using of class!\n", css::uno::Reference< css::uno::XInterface >() ); + } + break; + case E_WORK: + break; + case E_BEFORECLOSE: + if( eMode == E_HARDEXCEPTIONS ) + { + // Help programmer to find out, why this exception is thrown! + SAL_WARN( "fwk", "TransactionManager...: Owner instance stand in close method. Call was rejected!" ); + throw css::lang::DisposedException( "TransactionManager: Owner instance stand in close method. Call was rejected!" ); + } + break; + case E_CLOSE: + // Help programmer to find out, why this exception is thrown! + SAL_WARN( "fwk", "TransactionManager...: Owner instance already closed. Call was rejected!" ); + throw css::lang::DisposedException( "TransactionManager: Owner instance already closed. Call was rejected!" ); + } + + // Register this new transaction. + // If it is the first one .. close gate to disable changing of working mode. + ++m_nTransactionCount; + if( m_nTransactionCount == 1 ) + { + m_aBarrier.close(); + } +} + +/*-**************************************************************************************************** + @short finish transaction + @descr A guard should call this method to release current transaction. + + @seealso method registerTransaction() +*//*-*****************************************************************************************************/ +void TransactionManager::unregisterTransaction() +{ + // This call could not rejected! + // Safe access to internal member. + std::unique_lock aAccessGuard( m_aAccessLock ); + + // Deregister this transaction. + // If it was the last one ... open gate to enable changing of working mode! + // (see setWorkingMode()) + + --m_nTransactionCount; + if( m_nTransactionCount == 0 ) + { + m_aBarrier.open(); + } +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/fwi/uielement/constitemcontainer.cxx b/framework/source/fwi/uielement/constitemcontainer.cxx new file mode 100644 index 000000000..7e43a5009 --- /dev/null +++ b/framework/source/fwi/uielement/constitemcontainer.cxx @@ -0,0 +1,288 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include + +#include +#include +#include + +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; + +const int PROPHANDLE_UINAME = 1; +constexpr OUStringLiteral PROPNAME_UINAME = u"UIName"; + +namespace framework +{ + +ConstItemContainer::ConstItemContainer() +{ +} + +ConstItemContainer::ConstItemContainer( const ItemContainer& rItemContainer ) +{ + ShareGuard aLock( rItemContainer.m_aShareMutex ); + copyItemContainer( rItemContainer.m_aItemVector ); +} + +ConstItemContainer::ConstItemContainer( const Reference< XIndexAccess >& rSourceContainer, bool bFastCopy ) +{ + // We also have to copy the UIName property + try + { + Reference< XPropertySet > xPropSet( rSourceContainer, UNO_QUERY ); + if ( xPropSet.is() ) + { + xPropSet->getPropertyValue("UIName") >>= m_aUIName; + } + } + catch ( const Exception& ) + { + } + + if ( !rSourceContainer.is() ) + return; + + try + { + sal_Int32 nCount = rSourceContainer->getCount(); + m_aItemVector.reserve(nCount); + if ( bFastCopy ) + { + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + Sequence< PropertyValue > aPropSeq; + if ( rSourceContainer->getByIndex( i ) >>= aPropSeq ) + m_aItemVector.push_back( aPropSeq ); + } + } + else + { + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + Sequence< PropertyValue > aPropSeq; + if ( rSourceContainer->getByIndex( i ) >>= aPropSeq ) + { + sal_Int32 nContainerIndex = -1; + Reference< XIndexAccess > xIndexAccess; + for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ ) + { + if ( aPropSeq[j].Name == "ItemDescriptorContainer" ) + { + aPropSeq[j].Value >>= xIndexAccess; + nContainerIndex = j; + break; + } + } + + if ( xIndexAccess.is() && nContainerIndex >= 0 ) + aPropSeq.getArray()[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess ); + + m_aItemVector.push_back( aPropSeq ); + } + } + } + } + catch ( const IndexOutOfBoundsException& ) + { + } +} + +ConstItemContainer::~ConstItemContainer() +{ +} + +// private +void ConstItemContainer::copyItemContainer( const std::vector< Sequence< PropertyValue > >& rSourceVector ) +{ + const sal_uInt32 nCount = rSourceVector.size(); + for ( sal_uInt32 i = 0; i < nCount; i++ ) + { + sal_Int32 nContainerIndex = -1; + Sequence< PropertyValue > aPropSeq( rSourceVector[i] ); + Reference< XIndexAccess > xIndexAccess; + for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ ) + { + if ( aPropSeq[j].Name == "ItemDescriptorContainer" ) + { + aPropSeq[j].Value >>= xIndexAccess; + nContainerIndex = j; + break; + } + } + + if ( xIndexAccess.is() && nContainerIndex >= 0 ) + aPropSeq.getArray()[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess ); + + m_aItemVector.push_back( aPropSeq ); + } +} + +Reference< XIndexAccess > ConstItemContainer::deepCopyContainer( const Reference< XIndexAccess >& rSubContainer ) +{ + Reference< XIndexAccess > xReturn; + if ( rSubContainer.is() ) + { + ItemContainer* pSource = comphelper::getFromUnoTunnel( rSubContainer ); + rtl::Reference pSubContainer; + if ( pSource ) + pSubContainer = new ConstItemContainer( *pSource ); + else + pSubContainer = new ConstItemContainer( rSubContainer ); + xReturn = pSubContainer; + } + + return xReturn; +} + +// XUnoTunnel +sal_Int64 ConstItemContainer::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier ) +{ + return comphelper::getSomethingImpl(rIdentifier, this); +} + +const Sequence< sal_Int8 >& ConstItemContainer::getUnoTunnelId() noexcept +{ + static const comphelper::UnoIdInit theConstItemContainerUnoTunnelId; + return theConstItemContainerUnoTunnelId.getSeq(); +} + +// XElementAccess +sal_Bool SAL_CALL ConstItemContainer::hasElements() +{ + return ( !m_aItemVector.empty() ); +} + +// XIndexAccess +sal_Int32 SAL_CALL ConstItemContainer::getCount() +{ + return m_aItemVector.size(); +} + +Any SAL_CALL ConstItemContainer::getByIndex( sal_Int32 Index ) +{ + if ( sal_Int32( m_aItemVector.size()) <= Index ) + throw IndexOutOfBoundsException( OUString(), static_cast(this) ); + return Any( m_aItemVector[Index] ); +} + +namespace +{ + std::vector makePropertyMap(const css::uno::Sequence& rProps) + { + std::vector aEntries; + for (auto const& it : rProps) + aEntries.emplace_back(it.Name, it.Handle, it.Type, it.Attributes, 0); + return aEntries; + } +} + +// XPropertySet +Reference< XPropertySetInfo > SAL_CALL ConstItemContainer::getPropertySetInfo() +{ + // Create structure of propertysetinfo for baseclass "OPropertySetHelper". + // (Use method "getInfoHelper()".) + static std::vector aPropertyInfos(makePropertyMap(getInfoHelper().getProperties())); + static Reference< XPropertySetInfo > xInfo(new comphelper::PropertySetInfo(aPropertyInfos)); + + return xInfo; +} + +void SAL_CALL ConstItemContainer::setPropertyValue( const OUString&, const Any& ) +{ +} + +Any SAL_CALL ConstItemContainer::getPropertyValue( const OUString& PropertyName ) +{ + if ( PropertyName == PROPNAME_UINAME ) + return Any( m_aUIName ); + + throw UnknownPropertyException(PropertyName); +} + +void SAL_CALL ConstItemContainer::addPropertyChangeListener( const OUString&, const css::uno::Reference< css::beans::XPropertyChangeListener >& ) +{ +} + +void SAL_CALL ConstItemContainer::removePropertyChangeListener( const OUString&, const css::uno::Reference< css::beans::XPropertyChangeListener >& ) +{ + // Only read-only properties - do nothing +} + +void SAL_CALL ConstItemContainer::addVetoableChangeListener( const OUString&, const css::uno::Reference< css::beans::XVetoableChangeListener >& ) +{ + // Only read-only properties - do nothing +} + +void SAL_CALL ConstItemContainer::removeVetoableChangeListener( const OUString&, const css::uno::Reference< css::beans::XVetoableChangeListener >& ) +{ + // Only read-only properties - do nothing +} + +// XFastPropertySet +void SAL_CALL ConstItemContainer::setFastPropertyValue( sal_Int32, const css::uno::Any& ) +{ +} + +Any SAL_CALL ConstItemContainer::getFastPropertyValue( sal_Int32 nHandle ) +{ + if ( nHandle == PROPHANDLE_UINAME ) + return Any( m_aUIName ); + + throw UnknownPropertyException(OUString::number(nHandle)); +} + +::cppu::IPropertyArrayHelper& ConstItemContainer::getInfoHelper() +{ + // Define static member to give structure of properties to baseclass "OPropertySetHelper". + // "impl_getStaticPropertyDescriptor" is a non exported and static function, who will define a static propertytable. + // "true" say: Table is sorted by name. + static ::cppu::OPropertyArrayHelper ourInfoHelper( impl_getStaticPropertyDescriptor(), true ); + + return ourInfoHelper; +} + +css::uno::Sequence< css::beans::Property > ConstItemContainer::impl_getStaticPropertyDescriptor() +{ + // Create a property array to initialize sequence! + // Table of all predefined properties of this class. It's used from OPropertySetHelper-class! + // Don't forget to change the defines (see begin of this file), if you add, change or delete a property in this list!!! + // It's necessary for methods of OPropertySetHelper. + // ATTENTION: + // YOU MUST SORT FOLLOW TABLE BY NAME ALPHABETICAL !!! + + return + { + css::beans::Property( PROPNAME_UINAME, PROPHANDLE_UINAME , + cppu::UnoType::get(), + css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ) + }; +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/fwi/uielement/itemcontainer.cxx b/framework/source/fwi/uielement/itemcontainer.cxx new file mode 100644 index 000000000..389bbaeaa --- /dev/null +++ b/framework/source/fwi/uielement/itemcontainer.cxx @@ -0,0 +1,212 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include + +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; + +constexpr OUStringLiteral WRONG_TYPE_EXCEPTION + = u"Type must be css::uno::Sequence< css::beans::PropertyValue >"; + +namespace framework +{ + +// XInterface, XTypeProvider + +ItemContainer::ItemContainer( const ShareableMutex& rMutex ) : + m_aShareMutex( rMutex ) +{ +} + +ItemContainer::ItemContainer( const ConstItemContainer& rConstItemContainer, const ShareableMutex& rMutex ) : m_aShareMutex( rMutex ) +{ + copyItemContainer( rConstItemContainer.m_aItemVector, rMutex ); +} + +ItemContainer::ItemContainer( const Reference< XIndexAccess >& rSourceContainer, const ShareableMutex& rMutex ) : + m_aShareMutex( rMutex ) +{ + if ( !rSourceContainer.is() ) + return; + + sal_Int32 nCount = rSourceContainer->getCount(); + try + { + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + Sequence< PropertyValue > aPropSeq; + if ( rSourceContainer->getByIndex( i ) >>= aPropSeq ) + { + sal_Int32 nContainerIndex = -1; + Reference< XIndexAccess > xIndexAccess; + for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ ) + { + if ( aPropSeq[j].Name == "ItemDescriptorContainer" ) + { + aPropSeq[j].Value >>= xIndexAccess; + nContainerIndex = j; + break; + } + } + + if ( xIndexAccess.is() && nContainerIndex >= 0 ) + aPropSeq.getArray()[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess, rMutex ); + + m_aItemVector.push_back( aPropSeq ); + } + } + } + catch ( const IndexOutOfBoundsException& ) + { + } +} + +ItemContainer::~ItemContainer() +{ +} + +// private +void ItemContainer::copyItemContainer( const std::vector< Sequence< PropertyValue > >& rSourceVector, const ShareableMutex& rMutex ) +{ + const sal_uInt32 nCount = rSourceVector.size(); + for ( sal_uInt32 i = 0; i < nCount; ++i ) + { + sal_Int32 nContainerIndex = -1; + Sequence< PropertyValue > aPropSeq( rSourceVector[i] ); + Reference< XIndexAccess > xIndexAccess; + for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ ) + { + if ( aPropSeq[j].Name == "ItemDescriptorContainer" ) + { + aPropSeq[j].Value >>= xIndexAccess; + nContainerIndex = j; + break; + } + } + + if ( xIndexAccess.is() && nContainerIndex >= 0 ) + aPropSeq.getArray()[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess, rMutex ); + + m_aItemVector.push_back( aPropSeq ); + } +} + +Reference< XIndexAccess > ItemContainer::deepCopyContainer( const Reference< XIndexAccess >& rSubContainer, const ShareableMutex& rMutex ) +{ + Reference< XIndexAccess > xReturn; + if ( rSubContainer.is() ) + { + ConstItemContainer* pSource = comphelper::getFromUnoTunnel( rSubContainer ); + rtl::Reference pSubContainer; + if ( pSource ) + pSubContainer = new ItemContainer( *pSource, rMutex ); + else + pSubContainer = new ItemContainer( rSubContainer, rMutex ); + xReturn = pSubContainer; + } + + return xReturn; +} + +const Sequence< sal_Int8 >& ItemContainer::getUnoTunnelId() noexcept +{ + static const comphelper::UnoIdInit theItemContainerUnoTunnelId; + return theItemContainerUnoTunnelId.getSeq(); +} + +// XElementAccess +sal_Bool SAL_CALL ItemContainer::hasElements() +{ + ShareGuard aLock( m_aShareMutex ); + return ( !m_aItemVector.empty() ); +} + +// XIndexAccess +sal_Int32 SAL_CALL ItemContainer::getCount() +{ + ShareGuard aLock( m_aShareMutex ); + return m_aItemVector.size(); +} + +Any SAL_CALL ItemContainer::getByIndex( sal_Int32 Index ) +{ + ShareGuard aLock( m_aShareMutex ); + if ( sal_Int32( m_aItemVector.size()) <= Index ) + throw IndexOutOfBoundsException( OUString(), static_cast(this) ); + + return Any( m_aItemVector[Index] ); +} + +// XIndexContainer +void SAL_CALL ItemContainer::insertByIndex( sal_Int32 Index, const Any& aItem ) +{ + Sequence< PropertyValue > aSeq; + if ( !(aItem >>= aSeq) ) + throw IllegalArgumentException( WRONG_TYPE_EXCEPTION, + static_cast(this), 2 ); + + ShareGuard aLock( m_aShareMutex ); + if ( sal_Int32( m_aItemVector.size()) == Index ) + m_aItemVector.push_back( aSeq ); + else if ( sal_Int32( m_aItemVector.size()) >Index ) + { + std::vector< Sequence< PropertyValue > >::iterator aIter = m_aItemVector.begin(); + aIter += Index; + m_aItemVector.insert( aIter, aSeq ); + } + else + throw IndexOutOfBoundsException( OUString(), static_cast(this) ); +} + +void SAL_CALL ItemContainer::removeByIndex( sal_Int32 nIndex ) +{ + ShareGuard aLock( m_aShareMutex ); + if ( static_cast(m_aItemVector.size()) <= nIndex ) + throw IndexOutOfBoundsException( OUString(), static_cast(this) ); + + m_aItemVector.erase(m_aItemVector.begin() + nIndex); +} + +void SAL_CALL ItemContainer::replaceByIndex( sal_Int32 Index, const Any& aItem ) +{ + Sequence< PropertyValue > aSeq; + if ( !(aItem >>= aSeq) ) + throw IllegalArgumentException( WRONG_TYPE_EXCEPTION, + static_cast(this), 2 ); + + ShareGuard aLock( m_aShareMutex ); + if ( sal_Int32( m_aItemVector.size()) <= Index ) + throw IndexOutOfBoundsException( OUString(), static_cast(this) ); + + m_aItemVector[Index] = aSeq; +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/fwi/uielement/rootitemcontainer.cxx b/framework/source/fwi/uielement/rootitemcontainer.cxx new file mode 100644 index 000000000..50ecd0d53 --- /dev/null +++ b/framework/source/fwi/uielement/rootitemcontainer.cxx @@ -0,0 +1,313 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; + +constexpr OUStringLiteral WRONG_TYPE_EXCEPTION + = u"Type must be css::uno::Sequence< css::beans::PropertyValue >"; + +const int PROPHANDLE_UINAME = 1; +constexpr OUStringLiteral PROPNAME_UINAME = u"UIName"; + +namespace framework +{ + +RootItemContainer::RootItemContainer() + : ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >( m_aMutex ) + , ::cppu::OPropertySetHelper ( *static_cast< ::cppu::OBroadcastHelper* >(this) ) +{ +} + +RootItemContainer::RootItemContainer( const Reference< XIndexAccess >& rSourceContainer ) + : ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >( m_aMutex ) + , ::cppu::OPropertySetHelper ( *static_cast< ::cppu::OBroadcastHelper* >(this) ) +{ + // We also have to copy the UIName property + try + { + Reference< XPropertySet > xPropSet( rSourceContainer, UNO_QUERY ); + if ( xPropSet.is() ) + { + xPropSet->getPropertyValue("UIName") >>= m_aUIName; + } + } + catch ( const Exception& ) + { + } + + if ( !rSourceContainer.is() ) + return; + + sal_Int32 nCount = rSourceContainer->getCount(); + try + { + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + Sequence< PropertyValue > aPropSeq; + if ( rSourceContainer->getByIndex( i ) >>= aPropSeq ) + { + sal_Int32 nContainerIndex = -1; + Reference< XIndexAccess > xIndexAccess; + for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ ) + { + if ( aPropSeq[j].Name == "ItemDescriptorContainer" ) + { + aPropSeq[j].Value >>= xIndexAccess; + nContainerIndex = j; + break; + } + } + + if ( xIndexAccess.is() && nContainerIndex >= 0 ) + aPropSeq.getArray()[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess ); + + m_aItemVector.push_back( aPropSeq ); + } + } + } + catch ( const IndexOutOfBoundsException& ) + { + } +} + +RootItemContainer::~RootItemContainer() +{ +} + +Any SAL_CALL RootItemContainer::queryInterface( const Type& _rType ) +{ + Any aRet = RootItemContainer_BASE::queryInterface( _rType ); + if ( !aRet.hasValue() ) + aRet = OPropertySetHelper::queryInterface( _rType ); + return aRet; +} + +Sequence< Type > SAL_CALL RootItemContainer::getTypes( ) +{ + return comphelper::concatSequences( + RootItemContainer_BASE::getTypes(), + ::cppu::OPropertySetHelper::getTypes() + ); +} + +Reference< XIndexAccess > RootItemContainer::deepCopyContainer( const Reference< XIndexAccess >& rSubContainer ) +{ + Reference< XIndexAccess > xReturn; + if ( rSubContainer.is() ) + { + ConstItemContainer* pSource = comphelper::getFromUnoTunnel( rSubContainer ); + rtl::Reference pSubContainer; + if ( pSource ) + pSubContainer = new ItemContainer( *pSource, m_aShareMutex ); + else + pSubContainer = new ItemContainer( rSubContainer, m_aShareMutex ); + xReturn = pSubContainer; + } + + return xReturn; +} + +// XUnoTunnel +sal_Int64 RootItemContainer::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier ) +{ + return comphelper::getSomethingImpl(rIdentifier, this); +} + +const Sequence< sal_Int8 >& RootItemContainer::getUnoTunnelId() noexcept +{ + static const comphelper::UnoIdInit theRootItemContainerUnoTunnelId; + return theRootItemContainerUnoTunnelId.getSeq(); +} + +// XElementAccess +sal_Bool SAL_CALL RootItemContainer::hasElements() +{ + ShareGuard aLock( m_aShareMutex ); + return ( !m_aItemVector.empty() ); +} + +// XIndexAccess +sal_Int32 SAL_CALL RootItemContainer::getCount() +{ + ShareGuard aLock( m_aShareMutex ); + return m_aItemVector.size(); +} + +Any SAL_CALL RootItemContainer::getByIndex( sal_Int32 Index ) +{ + ShareGuard aLock( m_aShareMutex ); + if ( sal_Int32( m_aItemVector.size()) <= Index ) + throw IndexOutOfBoundsException( OUString(), static_cast(this) ); + + return Any( m_aItemVector[Index] ); +} + +// XIndexContainer +void SAL_CALL RootItemContainer::insertByIndex( sal_Int32 Index, const Any& aItem ) +{ + Sequence< PropertyValue > aSeq; + if ( !(aItem >>= aSeq) ) + throw IllegalArgumentException( WRONG_TYPE_EXCEPTION, static_cast(this), 2 ); + + ShareGuard aLock( m_aShareMutex ); + if ( sal_Int32( m_aItemVector.size()) == Index ) + m_aItemVector.push_back( aSeq ); + else if ( sal_Int32( m_aItemVector.size()) >Index ) + { + std::vector< Sequence< PropertyValue > >::iterator aIter = m_aItemVector.begin(); + aIter += Index; + m_aItemVector.insert( aIter, aSeq ); + } + else + throw IndexOutOfBoundsException( OUString(), static_cast(this) ); +} + +void SAL_CALL RootItemContainer::removeByIndex( sal_Int32 nIndex ) +{ + ShareGuard aLock( m_aShareMutex ); + if ( static_cast(m_aItemVector.size()) <= nIndex ) + throw IndexOutOfBoundsException( OUString(), static_cast(this) ); + + m_aItemVector.erase(m_aItemVector.begin() + nIndex); +} + +void SAL_CALL RootItemContainer::replaceByIndex( sal_Int32 Index, const Any& aItem ) +{ + Sequence< PropertyValue > aSeq; + if ( !(aItem >>= aSeq) ) + throw IllegalArgumentException( WRONG_TYPE_EXCEPTION, static_cast(this), 2 ); + + ShareGuard aLock( m_aShareMutex ); + if ( sal_Int32( m_aItemVector.size()) <= Index ) + throw IndexOutOfBoundsException( OUString(), static_cast(this) ); + + m_aItemVector[Index] = aSeq; +} + +Reference< XInterface > SAL_CALL RootItemContainer::createInstanceWithContext( const Reference< XComponentContext >& ) +{ + return static_cast(new ItemContainer( m_aShareMutex )); +} + +Reference< XInterface > SAL_CALL RootItemContainer::createInstanceWithArgumentsAndContext( const Sequence< Any >&, const Reference< XComponentContext >& ) +{ + return static_cast(new ItemContainer( m_aShareMutex )); +} + +// XPropertySet helper +sal_Bool SAL_CALL RootItemContainer::convertFastPropertyValue( Any& aConvertedValue , + Any& aOldValue , + sal_Int32 nHandle , + const Any& aValue ) +{ + // Initialize state with sal_False !!! + // (Handle can be invalid) + bool bReturn = false; + + switch( nHandle ) + { + case PROPHANDLE_UINAME: + bReturn = PropHelper::willPropertyBeChanged( + css::uno::Any(m_aUIName), + aValue, + aOldValue, + aConvertedValue); + break; + } + + // Return state of operation. + return bReturn; +} + +void SAL_CALL RootItemContainer::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle , + const css::uno::Any& aValue ) +{ + switch( nHandle ) + { + case PROPHANDLE_UINAME: + aValue >>= m_aUIName; + break; + } +} + +void SAL_CALL RootItemContainer::getFastPropertyValue( css::uno::Any& aValue , + sal_Int32 nHandle ) const +{ + switch( nHandle ) + { + case PROPHANDLE_UINAME: + aValue <<= m_aUIName; + break; + } +} + +::cppu::IPropertyArrayHelper& SAL_CALL RootItemContainer::getInfoHelper() +{ + // Define static member to give structure of properties to baseclass "OPropertySetHelper". + // "impl_getStaticPropertyDescriptor" is a non exported and static function, who will define a static propertytable. + // "true" say: Table is sorted by name. + static ::cppu::OPropertyArrayHelper ourInfoHelper( impl_getStaticPropertyDescriptor(), true ); + + return ourInfoHelper; +} + +css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL RootItemContainer::getPropertySetInfo() +{ + // Create structure of propertysetinfo for baseclass "OPropertySetHelper". + // (Use method "getInfoHelper()".) + static css::uno::Reference< css::beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); + + return xInfo; +} + +css::uno::Sequence< css::beans::Property > RootItemContainer::impl_getStaticPropertyDescriptor() +{ + // Create a property array to initialize sequence! + // Table of all predefined properties of this class. It's used from OPropertySetHelper-class! + // Don't forget to change the defines (see begin of this file), if you add, change or delete a property in this list!!! + // It's necessary for methods of OPropertySetHelper. + // ATTENTION: + // YOU MUST SORT FOLLOW TABLE BY NAME ALPHABETICAL !!! + + return + { + css::beans::Property( PROPNAME_UINAME, PROPHANDLE_UINAME , + cppu::UnoType::get(), + css::beans::PropertyAttribute::TRANSIENT ) + }; +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3