summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/svl/IndexedStyleSheets.hxx180
-rw-r--r--include/svl/style.hxx39
-rw-r--r--sc/source/core/data/stlpool.cxx51
-rw-r--r--sd/source/core/drawdoc4.cxx1
-rw-r--r--sd/source/core/stlpool.cxx99
-rw-r--r--svl/CppunitTest_svl_items.mk42
-rw-r--r--svl/Library_svl.mk1
-rw-r--r--svl/Module_svl.mk1
-rw-r--r--svl/qa/unit/items/test_IndexedStyleSheets.cxx160
-rw-r--r--svl/source/items/IndexedStyleSheets.cxx210
-rw-r--r--svl/source/items/style.cxx268
11 files changed, 894 insertions, 158 deletions
diff --git a/include/svl/IndexedStyleSheets.hxx b/include/svl/IndexedStyleSheets.hxx
new file mode 100644
index 000000000000..6980a978bd1d
--- /dev/null
+++ b/include/svl/IndexedStyleSheets.hxx
@@ -0,0 +1,180 @@
+/* -*- 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/.
+ */
+
+#ifndef SVL_INDEXEDSTYLESHEETS_HXX_
+#define SVL_INDEXEDSTYLESHEETS_HXX_
+
+#include <sal/types.h>
+
+#include <rtl/ustring.hxx>
+#include <rtl/ref.hxx>
+
+#include <boost/unordered_map.hpp>
+#include <vector>
+
+class SfxStyleSheetBase;
+
+namespace svl {
+
+/** Function object to check whether a style sheet a fulfills specific criteria.
+ * Derive from this class and override the Check() method.
+ */
+struct StyleSheetPredicate {
+ virtual bool Check(const SfxStyleSheetBase& styleSheet) = 0;
+ virtual ~StyleSheetPredicate() {;}
+};
+
+/** Function object for cleanup-Strategy for IndexedSfxStyleSheets::Clear().
+ * Derive from it and do what is necessary to dispose of a style sheet in Dispose().
+ */
+struct StyleSheetDisposer {
+ virtual void Dispose(rtl::Reference<SfxStyleSheetBase> styleSheet) = 0;
+ virtual ~StyleSheetDisposer() {;}
+};
+
+/** Function object to apply a method on all style sheets.
+ * Derive from it and do whatever you want to with the style sheet in the DoIt() method.
+ */
+struct StyleSheetCallback {
+ virtual void DoIt(const SfxStyleSheetBase& styleSheet) = 0;
+ virtual ~StyleSheetCallback() {;}
+};
+
+/** This class holds SfxStyleSheets and allows for access via an id and a name.
+ *
+ * @warning
+ * The identification of style sheets happens by their name. If the name of a sheet changes,
+ * it will not be found again! Please call Reindex() after changing a style sheet's name.
+ *
+ * @internal
+ * This class was implemented to mitigate solve #fdo 30770.
+ * The issue describes an Excel file which takes several hours to open.
+ * An analysis revealed that the time is spent searching for style sheets with linear scans in an array.
+ * This class implements access to the style sheets via their name in (usually) constant time.
+ *
+ * The return type for most methods is a vector of unsigned integers which denote the position
+ * of the style sheets in the vector, and not of pointers to style sheets.
+ * You will need a non-const StyleSheetPool to obtain the actual style sheets.
+ *
+ *
+ * Index-based access is required in several code portions. Hence we have to store the style sheets
+ * in a vector as well as in a map.
+ */
+class SAL_DLLPUBLIC IndexedStyleSheets SAL_FINAL {
+public:
+ IndexedStyleSheets();
+
+ /** Destructor.
+ *
+ * @internal
+ * Is explicit because it has to know how to dispose of SfxStyleSheetBase objects.
+ */
+ ~IndexedStyleSheets();
+
+ /** Adds a style sheet.
+ *
+ * If the style sheet is already contained, this call has no effect.
+ */
+ void
+ AddStyleSheet(rtl::Reference< SfxStyleSheetBase > style);
+
+ /** Removes a style sheet. */
+ bool
+ RemoveStyleSheet(rtl::Reference< SfxStyleSheetBase > style);
+
+ /** Check whether a specified style sheet is stored. */
+ bool
+ HasStyleSheet(rtl::Reference< SfxStyleSheetBase > style) const;
+
+ /** Obtain the number of style sheets which are held */
+ unsigned
+ GetNumberOfStyleSheets() const;
+
+ /** Obtain the number of style sheets for which a certain condition holds */
+ unsigned
+ GetNumberOfStyleSheetsWithPredicate(StyleSheetPredicate& predicate) const;
+
+ /** Return the stylesheet by its position.
+ * You can obtain the position by, e.g., FindStyleSheetPosition()
+ * @internal
+ * Method is not const because the returned style sheet is not const
+ */
+ rtl::Reference< SfxStyleSheetBase >
+ GetStyleSheetByPosition(unsigned pos);
+
+ /** Find the position of a provided style.
+ *
+ * @throws std::runtime_error if the style has not been found.
+ */
+ unsigned
+ FindStyleSheetPosition(const SfxStyleSheetBase& style) const;
+
+ /** Obtain the positions of all styles which have a given name
+ */
+ std::vector<unsigned>
+ FindPositionsByName(const rtl::OUString& name) const;
+
+ /** Obtain the positions of all styles which have a certain name and fulfill a certain condition.
+ *
+ * This method is fast because it can use the name-based index
+ */
+ std::vector<unsigned>
+ FindPositionsByNameAndPredicate(const rtl::OUString& name, StyleSheetPredicate& predicate) const;
+
+ /** Obtain the positions of all styles which fulfill a certain condition.
+ *
+ * This method is slow because it cannot use the name-based index
+ */
+ std::vector<unsigned>
+ FindPositionsByPredicate(StyleSheetPredicate& predicate) const;
+
+ /** Execute a callback on all style sheets */
+ void
+ ApplyToAllStyleSheets(StyleSheetCallback& callback) const;
+
+ /** Clear the contents of the index.
+ * The StyleSheetDisposer::Dispose() method is called on each style sheet, e.g., if you want to broadcast
+ * changes.
+ */
+ void
+ Clear(StyleSheetDisposer& cleanup);
+
+ void
+ Reindex();
+
+ /** Warning: counting for n starts at 0, i.e., the 0th style sheet is the first that is found. */
+ rtl::Reference<SfxStyleSheetBase>
+ GetNthStyleSheetThatMatchesPredicate(unsigned n, StyleSheetPredicate& predicate,
+ unsigned startAt = 0);
+
+private:
+ /** Register the position of a styleName in the index */
+ void
+ Register(const rtl::OUString& styleName, unsigned pos);
+
+ typedef std::vector<rtl::Reference<SfxStyleSheetBase> > VectorType;
+ /** Vector with the stylesheets to allow for index-based access.
+ */
+ VectorType mStyleSheets;
+
+ /** The map type that is used to store the mapping from strings to ids in mStyleSheets
+ *
+ * @internal
+ * Must be an unordered map. A regular map is too slow for some files. */
+ typedef boost::unordered_multimap<rtl::OUString, unsigned, rtl::OUStringHash> MapType;
+
+ /** A map which stores the positions of style sheets by their name */
+ MapType mPositionsByName;
+};
+
+} /* namespace svl */
+
+#endif /* SVL_INDEXEDSTYLESHEETS_HXX_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/svl/style.hxx b/include/svl/style.hxx
index 7a558e4f94b9..da6931b63e37 100644
--- a/include/svl/style.hxx
+++ b/include/svl/style.hxx
@@ -43,6 +43,7 @@ class SfxItemPool;
class SfxStyleSheetBasePool;
class SvStream;
+namespace svl { class IndexedStyleSheets; }
/*
Everyone changing instances of SfxStyleSheetBasePool or SfxStyleSheetBase
must broadcast this using <SfxStyleSheetBasePool::GetBroadcaster()> broadcasts.
@@ -144,12 +145,6 @@ public:
virtual sal_uInt16 GetVersion() const;
};
-
-
-typedef std::vector< rtl::Reference< SfxStyleSheetBase > > SfxStyles;
-
-
-
class SVL_DLLPUBLIC SfxStyleSheetIterator
/* [Beschreibung]
@@ -174,18 +169,18 @@ public:
virtual SfxStyleSheetBase* Find(const OUString& rStr);
virtual ~SfxStyleSheetIterator();
+ bool SearchUsed() const { return bSearchUsed; }
+
protected:
SfxStyleSheetBasePool* pBasePool;
SfxStyleFamily nSearchFamily;
sal_uInt16 nMask;
- bool SearchUsed() const { return bSearchUsed; }
private:
sal_uInt16 GetPos() { return nAktPosition; }
SVL_DLLPRIVATE bool IsTrivialSearch();
- SVL_DLLPRIVATE bool DoesStyleMatch(SfxStyleSheetBase *pStyle);
SfxStyleSheetBase* pAktStyle;
sal_uInt16 nAktPosition;
@@ -211,17 +206,24 @@ protected:
OUString aAppName;
SfxItemPool& rPool;
- SfxStyles aStyles;
SfxStyleFamily nSearchFamily;
sal_uInt16 nMask;
- SfxStyleSheetBase& Add( SfxStyleSheetBase& );
void ChangeParent( const OUString&, const OUString&, bool bVirtual = true );
virtual SfxStyleSheetBase* Create( const OUString&, SfxStyleFamily, sal_uInt16 );
virtual SfxStyleSheetBase* Create( const SfxStyleSheetBase& );
virtual ~SfxStyleSheetBasePool();
+ void StoreStyleSheet(rtl::Reference< SfxStyleSheetBase >);
+
+ /** Obtain the indexed style sheets.
+ */
+ const svl::IndexedStyleSheets&
+ GetIndexedStyleSheets() const;
+ rtl::Reference<SfxStyleSheetBase>
+ GetStyleSheetByPositionInIndex(unsigned pos);
+
public:
SfxStyleSheetBasePool( SfxItemPool& );
SfxStyleSheetBasePool( const SfxStyleSheetBasePool& );
@@ -250,6 +252,8 @@ public:
SfxStyleSheetBasePool& operator=( const SfxStyleSheetBasePool& );
SfxStyleSheetBasePool& operator+=( const SfxStyleSheetBasePool& );
+ unsigned GetNumberOfStyles();
+
virtual SfxStyleSheetBase* First();
virtual SfxStyleSheetBase* Next();
virtual SfxStyleSheetBase* Find( const OUString&, SfxStyleFamily eFam, sal_uInt16 n=SFXSTYLEBIT_ALL );
@@ -264,6 +268,21 @@ public:
void SetSearchMask(SfxStyleFamily eFam, sal_uInt16 n=SFXSTYLEBIT_ALL );
sal_uInt16 GetSearchMask() const;
SfxStyleFamily GetSearchFamily() const { return nSearchFamily; }
+
+ void Reindex();
+ /** Add a style sheet.
+ * Not an actual public function. Do not call it from non-subclasses.
+ */
+ SfxStyleSheetBase& Add( const SfxStyleSheetBase& );
+
+private:
+ /** This member holds the indexed style sheets.
+ *
+ * @internal
+ * This member is private and not protected in order to have more control which style sheets are added
+ * where. Ideally, all calls which add/remove/change style sheets are done in the base class.
+ */
+ boost::shared_ptr<svl::IndexedStyleSheets> mIndexedStyleSheets;
};
diff --git a/sc/source/core/data/stlpool.cxx b/sc/source/core/data/stlpool.cxx
index 455c483365f5..67a28622388a 100644
--- a/sc/source/core/data/stlpool.cxx
+++ b/sc/source/core/data/stlpool.cxx
@@ -36,6 +36,7 @@
#include <editeng/justifyitem.hxx>
#include <svl/itemset.hxx>
#include <svl/zforlist.hxx>
+#include <svl/IndexedStyleSheets.hxx>
#include <unotools/charclass.hxx>
#include <unotools/fontcvt.hxx>
#include <vcl/outdev.hxx>
@@ -93,7 +94,7 @@ SfxStyleSheetBase& ScStyleSheetPool::Make( const OUString& rName,
if ( rName == STRING_STANDARD && Find( rName, eFam ) != NULL )
{
OSL_FAIL("renaming additional default style");
- sal_uInt32 nCount = aStyles.size();
+ sal_uInt32 nCount = GetIndexedStyleSheets().GetNumberOfStyleSheets();
for ( sal_uInt32 nAdd = 1; nAdd <= nCount; nAdd++ )
{
OUString aNewName = ScGlobal::GetRscString(STR_STYLENAME_STANDARD);
@@ -102,7 +103,6 @@ SfxStyleSheetBase& ScStyleSheetPool::Make( const OUString& rName,
return SfxStyleSheetPool::Make(aNewName, eFam, mask);
}
}
-
return SfxStyleSheetPool::Make(rName, eFam, mask);
}
@@ -480,25 +480,54 @@ void ScStyleSheetPool::CreateStandardStyles()
DELETEZ( pEdEngine );
}
+namespace {
+
+struct CaseInsensitiveNamePredicate : svl::StyleSheetPredicate
+{
+ CaseInsensitiveNamePredicate(const rtl::OUString& rName, SfxStyleFamily eFam)
+ : mFamily(eFam)
+ {
+ mUppercaseName = ScGlobal::pCharClass->uppercase(rName);
+ }
+
+ bool
+ Check(const SfxStyleSheetBase& rStyleSheet)
+ {
+ if (rStyleSheet.GetFamily() == mFamily)
+ {
+ rtl::OUString aUpName = ScGlobal::pCharClass->uppercase(rStyleSheet.GetName());
+ if (mUppercaseName == aUpName)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ rtl::OUString mUppercaseName;
+ SfxStyleFamily mFamily;
+};
+}
+// Functor object to find all style sheets of a family which match a given name caseinsensitively
ScStyleSheet* ScStyleSheetPool::FindCaseIns( const OUString& rName, SfxStyleFamily eFam )
{
- OUString aUpSearch = ScGlobal::pCharClass->uppercase(rName);
+ CaseInsensitiveNamePredicate aPredicate(rName, eFam);
+ std::vector<unsigned> aFoundPositions = GetIndexedStyleSheets().FindPositionsByPredicate(aPredicate);
+ std::vector<unsigned>::const_iterator it = aFoundPositions.begin();
- sal_uInt32 nCount = aStyles.size();
- for (sal_uInt32 n=0; n<nCount; n++)
+ for (/**/;it != aFoundPositions.end(); ++it)
{
- SfxStyleSheetBase* pStyle = aStyles[n].get();
- if ( pStyle->GetFamily() == eFam )
+ SfxStyleSheetBase *pFound = GetStyleSheetByPositionInIndex(*it).get();
+ ScStyleSheet* pSheet = NULL;
+ // we do not know what kind of sheets we have.
+ pSheet = dynamic_cast<ScStyleSheet*>(pFound);
+ if (pSheet != NULL)
{
- OUString aUpName = ScGlobal::pCharClass->uppercase(pStyle->GetName());
- if (aUpName == aUpSearch)
- return (ScStyleSheet*)pStyle;
+ return pSheet;
}
}
-
return NULL;
}
diff --git a/sd/source/core/drawdoc4.cxx b/sd/source/core/drawdoc4.cxx
index a6f939b7639d..8ebb9250a3b7 100644
--- a/sd/source/core/drawdoc4.cxx
+++ b/sd/source/core/drawdoc4.cxx
@@ -1103,6 +1103,7 @@ void SdDrawDocument::RenameLayoutTemplate(const OUString& rOldLayoutName, const
aReplList.push_back(aReplData);
pSheet->SetName(aSheetName);
+ mxStyleSheetPool.get()->Reindex();
}
pSheet = aIter.Next();
diff --git a/sd/source/core/stlpool.cxx b/sd/source/core/stlpool.cxx
index 457350afd8b8..6b88b0bc6e75 100644
--- a/sd/source/core/stlpool.cxx
+++ b/sd/source/core/stlpool.cxx
@@ -53,6 +53,7 @@
#include <editeng/adjustitem.hxx>
#include <editeng/numdef.hxx>
#include <svl/itempool.hxx>
+#include <svl/IndexedStyleSheets.hxx>
#include "stlpool.hxx"
#include "sdresid.hxx"
@@ -127,8 +128,6 @@ SdStyleSheetPool::SdStyleSheetPool(SfxItemPool const& _rPool, SdDrawDocument* pD
}
}
-
-
SdStyleSheetPool::~SdStyleSheetPool()
{
DBG_ASSERT( mpDoc == NULL, "sd::SdStyleSheetPool::~SdStyleSheetPool(), dispose me first!" );
@@ -624,41 +623,66 @@ void SdStyleSheetPool::CopySheets(SdStyleSheetPool& rSourcePool, SfxStyleFamily
CopySheets(rSourcePool, eFamily, rCreatedSheets, emptyName);
}
+namespace
+{
+
+struct HasFamilyPredicate : svl::StyleSheetPredicate
+{
+ HasFamilyPredicate(SfxStyleFamily eFamily)
+ : meFamily(eFamily) {;}
+
+ bool Check(const SfxStyleSheetBase& sheet)
+ {
+ return sheet.GetFamily() == meFamily;
+ }
+ SfxStyleFamily meFamily;
+};
+
+}
+
void SdStyleSheetPool::CopySheets(SdStyleSheetPool& rSourcePool, SfxStyleFamily eFamily, SdStyleSheetVector& rCreatedSheets, OUString& rRenameSuffix)
{
OUString aHelpFile;
- sal_uInt32 nCount = rSourcePool.aStyles.size();
-
std::vector< std::pair< rtl::Reference< SfxStyleSheetBase >, OUString > > aNewStyles;
std::vector< std::pair< OUString, OUString > > aRenamedList;
- for (sal_uInt32 n = 0; n < nCount; n++)
+ // find all style sheets of the source pool which have the same family
+ HasFamilyPredicate aHasFamilyPredicate(eFamily);
+ std::vector<unsigned> aSheetsWithFamily = rSourcePool.GetIndexedStyleSheets().FindPositionsByPredicate(aHasFamilyPredicate);
+
+ for (std::vector<unsigned>::const_iterator it = aSheetsWithFamily.begin();
+ it != aSheetsWithFamily.end(); ++it )
{
- rtl::Reference< SfxStyleSheetBase > xSheet( rSourcePool.aStyles[sal::static_int_cast<sal_uInt16>(n)] );
+ rtl::Reference< SfxStyleSheetBase > xSheet = GetStyleSheetByPositionInIndex( *it );
+ rtl::OUString aName( xSheet->GetName() );
- if( xSheet->GetFamily() == eFamily )
+ // now check whether we already have a sheet with the same name
+ std::vector<unsigned> aSheetsWithName = GetIndexedStyleSheets().FindPositionsByName(aName);
+ bool bAddToList = false;
+ if (!aSheetsWithName.empty() && !rRenameSuffix.isEmpty())
{
- bool bAddToList = false;
- OUString aName( xSheet->GetName() );
- SfxStyleSheetBase* pExistingSheet = Find(aName, eFamily);
- if( pExistingSheet && !rRenameSuffix.isEmpty() )
+ // if we have a rename suffix, try to find a new name
+ SfxStyleSheetBase* pExistingSheet = GetStyleSheetByPositionInIndex(aSheetsWithName.front()).get();
+ sal_Int32 nHash = xSheet->GetItemSet().getHash();
+ if( pExistingSheet->GetItemSet().getHash() != nHash )
{
- sal_Int32 nHash = xSheet->GetItemSet().getHash();
- if( pExistingSheet->GetItemSet().getHash() != nHash )
+ // we have found a sheet with the same name, but different contents. Try to find a new name.
+ // If we already have a sheet with the new name, and it is equal to the one in the source pool,
+ // do nothing.
+ OUString aTmpName = aName + rRenameSuffix;
+ sal_Int32 nSuffix = 1;
+ do
{
- OUString aTmpName = aName + rRenameSuffix;
- sal_Int32 nSuffix = 1;
- do
- {
- aTmpName = aName + rRenameSuffix + OUString::number(nSuffix);
- pExistingSheet = Find(aTmpName, eFamily);
- nSuffix++;
- } while( pExistingSheet && pExistingSheet->GetItemSet().getHash() != nHash );
- aName = aTmpName;
- bAddToList = true;
- }
+ aTmpName = aName + rRenameSuffix + OUString::number(nSuffix);
+ pExistingSheet = Find(aTmpName, eFamily);
+ nSuffix++;
+ } while( pExistingSheet && pExistingSheet->GetItemSet().getHash() != nHash );
+ aName = aTmpName;
+ bAddToList = true;
}
+
+ // we do not already have a sheet with the same name and contents. Create a new one.
if ( !pExistingSheet )
{
rtl::Reference< SfxStyleSheetBase > xNewSheet( &Make( aName, eFamily ) );
@@ -701,6 +725,8 @@ void SdStyleSheetPool::CopySheets(SdStyleSheetPool& rSourcePool, SfxStyleFamily
DBG_ASSERT( rSourcePool.Find( (*aIter).second, eFamily ), "StyleSheet has invalid parent: Family mismatch" );
(*aIter).first->SetParent( (*aIter).second );
}
+ // we have changed names of style sheets. Trigger reindexing.
+ Reindex();
}
@@ -902,15 +928,30 @@ void SdStyleSheetPool::CreatePseudosIfNecessary()
|*
\************************************************************************/
+namespace
+{
+struct StyleSheetIsUserDefinedPredicate : svl::StyleSheetPredicate
+{
+ StyleSheetIsUserDefinedPredicate()
+ {;}
+
+ bool Check(const SfxStyleSheetBase& sheet)
+ {
+ return sheet.IsUserDefined();
+ }
+};
+}
+
void SdStyleSheetPool::UpdateStdNames()
{
OUString aHelpFile;
- sal_uInt32 nCount = aStyles.size();
+ StyleSheetIsUserDefinedPredicate aPredicate;
std::vector<SfxStyleSheetBase*> aEraseList;
-
- for( sal_uInt32 n=0; n < nCount; n++ )
+ std::vector<unsigned> aUserDefinedStyles = GetIndexedStyleSheets().FindPositionsByPredicate(aPredicate);
+ for (std::vector<unsigned>::const_iterator it = aUserDefinedStyles.begin();
+ it != aUserDefinedStyles.end(); ++it)
{
- SfxStyleSheetBase* pStyle = aStyles[ n ].get();
+ SfxStyleSheetBase* pStyle = GetStyleSheetByPositionInIndex(*it).get();
if( !pStyle->IsUserDefined() )
{
@@ -991,6 +1032,7 @@ void SdStyleSheetPool::UpdateStdNames()
// Sheet does exist: old sheet has to be removed
aEraseList.push_back( pStyle );
}
+ Reindex();
}
}
}
@@ -999,6 +1041,7 @@ void SdStyleSheetPool::UpdateStdNames()
// styles that could not be renamed, must be removed
for ( size_t i = 0, n = aEraseList.size(); i < n; ++i )
Remove( aEraseList[ i ] );
+ Reindex();
}
// Set new SvxNumBulletItem for the respective style sheet
diff --git a/svl/CppunitTest_svl_items.mk b/svl/CppunitTest_svl_items.mk
new file mode 100644
index 000000000000..d51b8fc43af3
--- /dev/null
+++ b/svl/CppunitTest_svl_items.mk
@@ -0,0 +1,42 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,svl_items))
+
+$(eval $(call gb_CppunitTest_use_external,svl_items,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_api,svl_items, \
+ offapi \
+ udkapi \
+))
+
+
+#$(eval $(call gb_CppunitTest_use_components,svl_items, \
+# ucb/source/core/ucb1 \
+#))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,svl_items, \
+ svl/qa/unit/items/test_IndexedStyleSheets \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,svl_items, \
+ svl \
+ comphelper \
+ sal \
+ cppu \
+ cppuhelper \
+))
+
+#$(eval $(call gb_CppunitTest_use_ure,svl_items))
+
+#$(eval $(call gb_CppunitTest_use_components,svl_urihelper,\
+# i18npool/util/i18npool \
+#))
+
+# vim: set noet sw=4 ts=4:
diff --git a/svl/Library_svl.mk b/svl/Library_svl.mk
index ba4d9b9b6121..a53b22340b58 100644
--- a/svl/Library_svl.mk
+++ b/svl/Library_svl.mk
@@ -79,6 +79,7 @@ $(eval $(call gb_Library_add_exception_objects,svl,\
svl/source/items/itemiter \
svl/source/items/itempool \
svl/source/items/itemprop \
+ svl/source/items/IndexedStyleSheets \
svl/source/items/itemset \
svl/source/items/lckbitem \
svl/source/items/macitem \
diff --git a/svl/Module_svl.mk b/svl/Module_svl.mk
index 684642c188ea..2e5e6a06dae3 100644
--- a/svl/Module_svl.mk
+++ b/svl/Module_svl.mk
@@ -32,6 +32,7 @@ $(eval $(call gb_Module_add_l10n_targets,svl,\
$(eval $(call gb_Module_add_check_targets,svl,\
CppunitTest_svl_lngmisc \
CppunitTest_svl_qa_cppunit \
+ CppunitTest_svl_items \
))
#TODO: CppunitTest_svl_urihelper depends on ucb, can only be added once svl is
diff --git a/svl/qa/unit/items/test_IndexedStyleSheets.cxx b/svl/qa/unit/items/test_IndexedStyleSheets.cxx
new file mode 100644
index 000000000000..ec8d82dcd5fd
--- /dev/null
+++ b/svl/qa/unit/items/test_IndexedStyleSheets.cxx
@@ -0,0 +1,160 @@
+/* -*- 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/.
+ */
+
+#include <svl/IndexedStyleSheets.hxx>
+
+// for SfxStyleSheetBase
+#include <svl/style.hxx>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+using namespace svl;
+
+class MockedStyleSheet : public SfxStyleSheetBase
+{
+ public:
+ MockedStyleSheet(const rtl::OUString& name)
+ : SfxStyleSheetBase(name, NULL, SFX_STYLE_FAMILY_CHAR, 0)
+ {;}
+
+};
+
+class IndexedStyleSheetsTest : public CppUnit::TestFixture
+{
+ void InstantiationWorks();
+ void AddedStylesheetsCanBeFoundAndRetrievedByPosition();
+ void AddingSameStylesheetTwiceHasNoEffect();
+ void RemovedStyleSheetIsNotFound();
+ void RemovingStyleSheetWhichIsNotAvailableHasNoEffect();
+ void StyleSheetsCanBeRetrievedByTheirName();
+ void KnowsThatItStoresAStyleSheet();
+
+ // Adds code needed to register the test suite
+ CPPUNIT_TEST_SUITE(IndexedStyleSheetsTest);
+
+ CPPUNIT_TEST(InstantiationWorks);
+ CPPUNIT_TEST(AddedStylesheetsCanBeFoundAndRetrievedByPosition);
+ CPPUNIT_TEST(AddingSameStylesheetTwiceHasNoEffect);
+ CPPUNIT_TEST(RemovedStyleSheetIsNotFound);
+ CPPUNIT_TEST(RemovingStyleSheetWhichIsNotAvailableHasNoEffect);
+ CPPUNIT_TEST(StyleSheetsCanBeRetrievedByTheirName);
+ CPPUNIT_TEST(KnowsThatItStoresAStyleSheet);
+
+ // End of test suite definition
+ CPPUNIT_TEST_SUITE_END();
+
+};
+
+void IndexedStyleSheetsTest::InstantiationWorks()
+{
+ IndexedStyleSheets iss;
+}
+
+void IndexedStyleSheetsTest::AddedStylesheetsCanBeFoundAndRetrievedByPosition()
+{
+ rtl::OUString name1("name1");
+ rtl::OUString name2("name2");
+ rtl::Reference<SfxStyleSheetBase> sheet1(new MockedStyleSheet(name1));
+ rtl::Reference<SfxStyleSheetBase> sheet2(new MockedStyleSheet(name2));
+ IndexedStyleSheets iss;
+ iss.AddStyleSheet(sheet1);
+ iss.AddStyleSheet(sheet2);
+ unsigned pos = iss.FindStyleSheetPosition(*sheet2);
+ rtl::Reference<SfxStyleSheetBase> retrieved = iss.GetStyleSheetByPosition(pos);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("retrieved sheet is that which has been inserted.", sheet2.get(), retrieved.get());
+}
+
+void IndexedStyleSheetsTest::AddingSameStylesheetTwiceHasNoEffect()
+{
+ rtl::Reference<SfxStyleSheetBase> sheet1(new MockedStyleSheet(rtl::OUString("sheet1")));
+ IndexedStyleSheets iss;
+ iss.AddStyleSheet(sheet1);
+ CPPUNIT_ASSERT_EQUAL(1u, iss.GetNumberOfStyleSheets());
+ iss.AddStyleSheet(sheet1);
+ CPPUNIT_ASSERT_EQUAL(1u, iss.GetNumberOfStyleSheets());
+}
+
+void IndexedStyleSheetsTest::RemovedStyleSheetIsNotFound()
+{
+ rtl::OUString name1("name1");
+ rtl::OUString name2("name2");
+ rtl::Reference<SfxStyleSheetBase> sheet1(new MockedStyleSheet(name1));
+ rtl::Reference<SfxStyleSheetBase> sheet2(new MockedStyleSheet(name2));
+ IndexedStyleSheets iss;
+ iss.AddStyleSheet(sheet1);
+ iss.AddStyleSheet(sheet2);
+ iss.RemoveStyleSheet(sheet1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Removed style sheet is not found.",
+ false, iss.HasStyleSheet(sheet1));
+}
+
+void IndexedStyleSheetsTest::RemovingStyleSheetWhichIsNotAvailableHasNoEffect()
+{
+ rtl::Reference<SfxStyleSheetBase> sheet1(new MockedStyleSheet(rtl::OUString("sheet1")));
+ rtl::Reference<SfxStyleSheetBase> sheet2(new MockedStyleSheet(rtl::OUString("sheet2")));
+ IndexedStyleSheets iss;
+ iss.AddStyleSheet(sheet1);
+ CPPUNIT_ASSERT_EQUAL(1u, iss.GetNumberOfStyleSheets());
+ iss.RemoveStyleSheet(sheet2);
+ CPPUNIT_ASSERT_EQUAL(1u, iss.GetNumberOfStyleSheets());
+}
+
+void IndexedStyleSheetsTest::StyleSheetsCanBeRetrievedByTheirName()
+{
+ rtl::OUString name1("name1");
+ rtl::OUString name2("name2");
+ rtl::Reference<SfxStyleSheetBase> sheet1(new MockedStyleSheet(name1));
+ rtl::Reference<SfxStyleSheetBase> sheet2(new MockedStyleSheet(name2));
+ rtl::Reference<SfxStyleSheetBase> sheet3(new MockedStyleSheet(name1));
+ IndexedStyleSheets iss;
+ iss.AddStyleSheet(sheet1);
+ iss.AddStyleSheet(sheet2);
+ iss.AddStyleSheet(sheet3);
+
+ std::vector<unsigned> r = iss.FindPositionsByName(name1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Two style sheets are found by 'name1'",
+ 2u, static_cast<unsigned>(r.size()));
+ CPPUNIT_ASSERT_EQUAL(0u, r.at(0));
+ CPPUNIT_ASSERT_EQUAL(2u, r.at(1));
+
+ r = iss.FindPositionsByName(name2);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("One style sheets is found by 'name2'",
+ 1u, static_cast<unsigned>(r.size()));
+ CPPUNIT_ASSERT_EQUAL(1u, r.at(0));
+}
+
+void IndexedStyleSheetsTest::KnowsThatItStoresAStyleSheet()
+{
+ rtl::OUString name1("name1");
+ rtl::OUString name2("name2");
+ rtl::Reference<SfxStyleSheetBase> sheet1(new MockedStyleSheet(name1));
+ rtl::Reference<SfxStyleSheetBase> sheet2(new MockedStyleSheet(name1));
+ rtl::Reference<SfxStyleSheetBase> sheet3(new MockedStyleSheet(name2));
+ rtl::Reference<SfxStyleSheetBase> sheet4(new MockedStyleSheet(name1));
+ IndexedStyleSheets iss;
+ iss.AddStyleSheet(sheet1);
+ iss.AddStyleSheet(sheet2);
+ iss.AddStyleSheet(sheet3);
+ // do not add sheet 4
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Finds first stored style sheet even though two style sheets have the same name.",
+ true, iss.HasStyleSheet(sheet1));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Finds second stored style sheet even though two style sheets have the same name.",
+ true, iss.HasStyleSheet(sheet2));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Does not find style sheet which is not stored and has the same name as a stored.",
+ false, iss.HasStyleSheet(sheet4));
+
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(IndexedStyleSheetsTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/svl/source/items/IndexedStyleSheets.cxx b/svl/source/items/IndexedStyleSheets.cxx
new file mode 100644
index 000000000000..ca45b534ee92
--- /dev/null
+++ b/svl/source/items/IndexedStyleSheets.cxx
@@ -0,0 +1,210 @@
+/* -*- 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/.
+ */
+
+
+#include <svl/IndexedStyleSheets.hxx>
+#include <svl/style.hxx>
+
+#include <stdexcept>
+#include <utility>
+
+using rtl::OUString;
+
+namespace svl {
+
+IndexedStyleSheets::IndexedStyleSheets()
+{;}
+
+
+void
+IndexedStyleSheets::Register(const rtl::OUString& name, unsigned pos)
+{
+ mPositionsByName.insert(std::make_pair(name, pos));
+}
+
+void
+IndexedStyleSheets::Reindex()
+{
+ mPositionsByName.clear();
+ unsigned i = 0;
+ for (VectorType::const_iterator it = mStyleSheets.begin();
+ it != mStyleSheets.end(); ++it) {
+ SfxStyleSheetBase* p = it->get();
+ Register(p->GetName(), i);
+ ++i;
+ }
+}
+
+unsigned
+IndexedStyleSheets::GetNumberOfStyleSheets() const
+{
+ return mStyleSheets.size();
+}
+
+void
+IndexedStyleSheets::AddStyleSheet(rtl::Reference< SfxStyleSheetBase > style)
+{
+ if (!HasStyleSheet(style)) {
+ mStyleSheets.push_back(style);
+ // since we just added an element to the vector, we can safely do -1 as it will always be >= 1
+ Register(style->GetName(), mStyleSheets.size()-1);
+ }
+}
+
+bool
+IndexedStyleSheets::RemoveStyleSheet(rtl::Reference< SfxStyleSheetBase > style)
+{
+ rtl::OUString styleName = style->GetName();
+ std::vector<unsigned> positions = FindPositionsByName(styleName);
+ bool found = false;
+ unsigned stylePosition = 0;
+ for (std::vector<unsigned>::const_iterator it = positions.begin();
+ it != positions.end(); ++it) {
+ if (mStyleSheets.at(*it) == style) {
+ found = true;
+ stylePosition = *it;
+ break;
+ }
+ }
+
+ if (found) {
+ mStyleSheets.erase(mStyleSheets.begin() + stylePosition);
+ Reindex();
+ }
+ return found;
+}
+
+std::vector<unsigned>
+IndexedStyleSheets::FindPositionsByName(const rtl::OUString& name) const
+{
+ std::vector<unsigned> r;
+ std::pair<MapType::const_iterator, MapType::const_iterator> range = mPositionsByName.equal_range(name);
+ for (MapType::const_iterator it = range.first; it != range.second; ++it) {
+ r.push_back(it->second);
+ }
+ return r;
+}
+
+std::vector<unsigned>
+IndexedStyleSheets::FindPositionsByNameAndPredicate(const rtl::OUString& name,
+ StyleSheetPredicate& predicate) const
+{
+ std::vector<unsigned> r;
+ MapType::const_iterator it = mPositionsByName.find(name);
+ for (/**/; it != mPositionsByName.end(); ++it) {
+ unsigned pos = it->second;
+ SfxStyleSheetBase *ssheet = mStyleSheets.at(pos).get();
+ if (predicate.Check(*ssheet)) {
+ r.push_back(pos);
+ }
+ }
+ return r;
+}
+
+
+unsigned
+IndexedStyleSheets::GetNumberOfStyleSheetsWithPredicate(StyleSheetPredicate& predicate) const
+{
+ unsigned r = 0;
+ for (VectorType::const_iterator it = mStyleSheets.begin(); it != mStyleSheets.end(); ++it) {
+ const SfxStyleSheetBase *ssheet = it->get();
+ if (predicate.Check(*ssheet)) {
+ ++r;
+ }
+ }
+ return r;
+}
+
+rtl::Reference<SfxStyleSheetBase>
+IndexedStyleSheets::GetNthStyleSheetThatMatchesPredicate(
+ unsigned n,
+ StyleSheetPredicate& predicate,
+ unsigned startAt)
+{
+ rtl::Reference<SfxStyleSheetBase> retval;
+ unsigned matching = 0;
+ for (VectorType::iterator it = mStyleSheets.begin()+startAt; it != mStyleSheets.end(); ++it) {
+ SfxStyleSheetBase *ssheet = it->get();
+ if (predicate.Check(*ssheet)) {
+ if (matching == n) {
+ retval = *it;
+ break;
+ }
+ ++matching;
+ }
+ }
+ return retval;
+}
+
+unsigned
+IndexedStyleSheets::FindStyleSheetPosition(const SfxStyleSheetBase& style) const
+{
+ VectorType::const_iterator it = std::find(mStyleSheets.begin(), mStyleSheets.end(), &style);
+ if (it == mStyleSheets.end()) {
+ throw std::runtime_error("IndexedStyleSheets::FindStylePosition Looked for style not in index");
+ }
+ return std::distance(mStyleSheets.begin(), it);
+}
+
+void
+IndexedStyleSheets::Clear(StyleSheetDisposer& disposer)
+{
+ for (VectorType::iterator it = mStyleSheets.begin(); it != mStyleSheets.end(); ++it) {
+ disposer.Dispose(*it);
+ }
+ mStyleSheets.clear();
+ mPositionsByName.clear();
+}
+
+IndexedStyleSheets::~IndexedStyleSheets()
+{;}
+
+bool
+IndexedStyleSheets::HasStyleSheet(rtl::Reference< SfxStyleSheetBase > style) const
+{
+ rtl::OUString styleName = style->GetName();
+ std::vector<unsigned> positions = FindPositionsByName(styleName);
+ for (std::vector<unsigned>::const_iterator it = positions.begin();
+ it != positions.end(); ++it) {
+ if (mStyleSheets.at(*it) == style) {
+ return true;
+ }
+ }
+ return false;
+}
+
+rtl::Reference< SfxStyleSheetBase >
+IndexedStyleSheets::GetStyleSheetByPosition(unsigned pos)
+{
+ return mStyleSheets.at(pos);
+}
+
+void
+IndexedStyleSheets::ApplyToAllStyleSheets(StyleSheetCallback& callback) const
+{
+ for (VectorType::const_iterator it = mStyleSheets.begin(); it != mStyleSheets.end(); ++it) {
+ callback.DoIt(**it);
+ }
+}
+
+std::vector<unsigned>
+IndexedStyleSheets::FindPositionsByPredicate(StyleSheetPredicate& predicate) const
+{
+ std::vector<unsigned> r;
+ for (VectorType::const_iterator it = mStyleSheets.begin(); it != mStyleSheets.end(); ++it) {
+ if (predicate.Check(**it)) {
+ r.push_back(std::distance(mStyleSheets.begin(), it));
+ }
+ }
+ return r;
+}
+
+} /* namespace svl */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/items/style.cxx b/svl/source/items/style.cxx
index 126cd814b4cb..ab9800e29bb2 100644
--- a/svl/source/items/style.cxx
+++ b/svl/source/items/style.cxx
@@ -26,12 +26,16 @@
#include <svl/poolitem.hxx>
#include <svl/itemset.hxx>
#include <svl/itempool.hxx>
+#include <svl/IndexedStyleSheets.hxx>
#include <poolio.hxx>
#include <svl/itemiter.hxx>
#include <svl/style.hxx>
#include <unotools/syslocale.hxx>
#include <algorithm>
#include <comphelper/servicehelper.hxx>
+
+#include <boost/numeric/conversion/cast.hpp>
+
#include <string.h>
#ifdef DBG_UTIL
@@ -362,22 +366,35 @@ inline bool SfxStyleSheetIterator::IsTrivialSearch()
(GetSearchFamily() == SFX_STYLE_FAMILY_ALL);
}
-bool SfxStyleSheetIterator::DoesStyleMatch(SfxStyleSheetBase *pStyle)
+namespace {
+
+struct DoesStyleMatchStyleSheetPredicate SAL_FINAL : public svl::StyleSheetPredicate
{
- bool bMatchFamily = ((GetSearchFamily() == SFX_STYLE_FAMILY_ALL) ||
- ( pStyle->GetFamily() == GetSearchFamily() ));
+ DoesStyleMatchStyleSheetPredicate(SfxStyleSheetIterator *it)
+ : mIterator(it) {;}
- bool bUsed = bSearchUsed ? pStyle->IsUsed( ) : false;
+ bool
+ Check(const SfxStyleSheetBase& styleSheet)
+ {
+ bool bMatchFamily = ((mIterator->GetSearchFamily() == SFX_STYLE_FAMILY_ALL) ||
+ ( styleSheet.GetFamily() == mIterator->GetSearchFamily() ));
+
+ bool bUsed = mIterator->SearchUsed() ? styleSheet.IsUsed( ) : false;
- bool bSearchHidden = ( GetSearchMask() & SFXSTYLEBIT_HIDDEN );
- bool bMatchVisibility = !( !bSearchHidden && pStyle->IsHidden() && !bUsed );
- bool bOnlyHidden = GetSearchMask( ) == SFXSTYLEBIT_HIDDEN && pStyle->IsHidden( );
+ bool bSearchHidden = ( mIterator->GetSearchMask() & SFXSTYLEBIT_HIDDEN );
+ bool bMatchVisibility = !( !bSearchHidden && styleSheet.IsHidden() && !bUsed );
+ bool bOnlyHidden = mIterator->GetSearchMask( ) == SFXSTYLEBIT_HIDDEN && styleSheet.IsHidden( );
+
+ bool bMatches = bMatchFamily && bMatchVisibility
+ && (( styleSheet.GetMask() & ( mIterator->GetSearchMask() & ~SFXSTYLEBIT_USED )) ||
+ bUsed || bOnlyHidden ||
+ ( mIterator->GetSearchMask() & SFXSTYLEBIT_ALL_VISIBLE ) == SFXSTYLEBIT_ALL_VISIBLE );
+ return bMatches;
+ }
+
+ SfxStyleSheetIterator *mIterator;
+};
- bool bMatches = bMatchFamily && bMatchVisibility
- && (( pStyle->GetMask() & ( GetSearchMask() & ~SFXSTYLEBIT_USED )) ||
- bUsed || bOnlyHidden ||
- ( GetSearchMask() & SFXSTYLEBIT_ALL_VISIBLE ) == SFXSTYLEBIT_ALL_VISIBLE );
- return bMatches;
}
SfxStyleSheetIterator::SfxStyleSheetIterator(SfxStyleSheetBasePool *pBase,
@@ -403,111 +420,94 @@ sal_uInt16 SfxStyleSheetIterator::Count()
{
sal_uInt16 n = 0;
if( IsTrivialSearch())
- n = (sal_uInt16) pBasePool->aStyles.size();
+ {
+ n = (sal_uInt16) pBasePool->mIndexedStyleSheets->GetNumberOfStyleSheets();
+ }
else
- for(sal_uInt16 i=0; i<pBasePool->aStyles.size(); i++)
- {
- SfxStyleSheetBase* pStyle = pBasePool->aStyles[i].get();
- if(DoesStyleMatch(pStyle))
- n++;
- }
+ {
+ DoesStyleMatchStyleSheetPredicate predicate(this);
+ n = pBasePool->mIndexedStyleSheets->GetNumberOfStyleSheetsWithPredicate(predicate);
+ }
return n;
}
SfxStyleSheetBase* SfxStyleSheetIterator::operator[](sal_uInt16 nIdx)
{
+ SfxStyleSheetBase* retval = NULL;
if( IsTrivialSearch())
- return pBasePool->aStyles[nIdx].get();
-
- sal_uInt16 z = 0;
- for(sal_uInt16 n=0; n<pBasePool->aStyles.size(); n++)
{
- SfxStyleSheetBase* pStyle = pBasePool->aStyles[n].get();
- if( DoesStyleMatch(pStyle))
- {
- if(z == nIdx)
- {
- nAktPosition=n;
- return pAktStyle=pStyle;
- }
- ++z;
- }
+ retval = pBasePool->mIndexedStyleSheets->GetStyleSheetByPosition(nIdx).get();
}
- OSL_FAIL("Incorrect index");
- return 0;
-}
-
-SfxStyleSheetBase* SfxStyleSheetIterator::First()
-{
- sal_Int32 nIdx = -1;
-
- if ( IsTrivialSearch() && pBasePool->aStyles.size() )
- nIdx = 0;
else
- for( sal_uInt16 n = 0; n < pBasePool->aStyles.size(); n++ )
+ {
+ DoesStyleMatchStyleSheetPredicate predicate(this);
+ rtl::Reference< SfxStyleSheetBase > ref =
+ pBasePool->mIndexedStyleSheets->GetNthStyleSheetThatMatchesPredicate(nIdx, predicate);
+ if (ref.get() != NULL)
{
- SfxStyleSheetBase* pStyle = pBasePool->aStyles[n].get();
-
- if ( DoesStyleMatch( pStyle ) )
- {
- nIdx = n;
- break;
- }
+ nAktPosition = pBasePool->mIndexedStyleSheets->FindStyleSheetPosition(*ref);
+ retval = ref.get();
}
+ }
- if ( nIdx != -1 )
+ if (retval == NULL)
{
- nAktPosition = (sal_uInt16)nIdx;
- return pAktStyle = pBasePool->aStyles[nIdx].get();
+ OSL_FAIL("Incorrect index");
}
- return 0;
+
+ return retval;
+}
+
+SfxStyleSheetBase* SfxStyleSheetIterator::First()
+{
+ return operator[](0);
}
SfxStyleSheetBase* SfxStyleSheetIterator::Next()
{
- sal_Int32 nIdx = -1;
+ SfxStyleSheetBase* retval = NULL;
- if ( IsTrivialSearch() &&
- (sal_uInt16)pBasePool->aStyles.size() > nAktPosition + 1 )
- nIdx = nAktPosition + 1;
- else
- for( sal_uInt16 n = nAktPosition + 1; n < pBasePool->aStyles.size(); n++ )
+ if ( IsTrivialSearch() )
+ {
+ unsigned nStyleSheets = pBasePool->mIndexedStyleSheets->GetNumberOfStyleSheets();
+ unsigned newPosition = nAktPosition +1;
+ if (nStyleSheets > newPosition)
{
- SfxStyleSheetBase* pStyle = pBasePool->aStyles[n].get();
-
- if ( DoesStyleMatch( pStyle ) )
- {
- nIdx = n;
- break;
- }
+ nAktPosition = newPosition;
+ retval = pBasePool->mIndexedStyleSheets->GetStyleSheetByPosition(nAktPosition).get();
}
-
- if ( nIdx != -1 )
+ }
+ else
{
- nAktPosition = (sal_uInt16)nIdx;
- return pAktStyle = pBasePool->aStyles[nIdx].get();
+ DoesStyleMatchStyleSheetPredicate predicate(this);
+ rtl::Reference< SfxStyleSheetBase > ref =
+ pBasePool->mIndexedStyleSheets->GetNthStyleSheetThatMatchesPredicate(
+ 0, predicate, nAktPosition+1);
+ retval = ref.get();
+ if (retval != NULL) {
+ nAktPosition = pBasePool->mIndexedStyleSheets->FindStyleSheetPosition(*ref);
+ }
}
- return 0;
+ pAktStyle = retval;
+ return retval;
}
-
SfxStyleSheetBase* SfxStyleSheetIterator::Find(const OUString& rStr)
{
- for ( sal_uInt16 n = 0; n < pBasePool->aStyles.size(); ++n )
- {
- SfxStyleSheetBase* pStyle = pBasePool->aStyles[n].get();
+ DoesStyleMatchStyleSheetPredicate predicate(this);
- // #98454# performance: in case of bSearchUsed==sal_True it may be
- // significant to first compare the name and only if it matches to call
- // the style sheet IsUsed() method in DoesStyleMatch().
- if ( pStyle->GetName() == rStr && DoesStyleMatch( pStyle ) )
- {
- nAktPosition = n;
- return pAktStyle = pStyle;
- }
+ std::vector<unsigned> positions =
+ pBasePool->mIndexedStyleSheets->FindPositionsByNameAndPredicate(rStr, predicate);
+ if (positions.empty()) {
+ return NULL;
}
- return 0;
+
+ unsigned pos = positions.front();
+ SfxStyleSheetBase* pStyle = pBasePool->mIndexedStyleSheets->GetStyleSheetByPosition(pos).get();
+ nAktPosition = pos;
+ pAktStyle = pStyle;
+ return pAktStyle;
}
sal_uInt16 SfxStyleSheetIterator::GetSearchMask() const
@@ -545,6 +545,7 @@ SfxStyleSheetBasePool::SfxStyleSheetBasePool( SfxItemPool& r )
, rPool(r)
, nSearchFamily(SFX_STYLE_FAMILY_PARA)
, nMask(SFXSTYLEBIT_ALL)
+ , mIndexedStyleSheets(new svl::IndexedStyleSheets)
{
#ifdef DBG_UTIL
aDbgStyleSheetReferences.mnPools++;
@@ -560,6 +561,7 @@ SfxStyleSheetBasePool::SfxStyleSheetBasePool( const SfxStyleSheetBasePool& r )
, rPool(r.rPool)
, nSearchFamily(r.nSearchFamily)
, nMask( r.nMask )
+ , mIndexedStyleSheets(new svl::IndexedStyleSheets)
{
#ifdef DBG_UTIL
aDbgStyleSheetReferences.mnPools++;
@@ -637,7 +639,7 @@ SfxStyleSheetBase& SfxStyleSheetBasePool::Make( const OUString& rName, SfxStyleF
if( !xStyle.is() )
{
xStyle = Create( rName, eFam, mask );
- aStyles.push_back(xStyle);
+ StoreStyleSheet(xStyle);
Broadcast( SfxStyleSheetHint( SFX_STYLESHEET_CREATED, *xStyle.get() ) );
}
return *xStyle.get();
@@ -647,13 +649,15 @@ SfxStyleSheetBase& SfxStyleSheetBasePool::Make( const OUString& rName, SfxStyleF
// sie neu erzeugt. Alle Vorlagen, die diese Vorlage zum Parent haben,
// werden umgehaengt.
-SfxStyleSheetBase& SfxStyleSheetBasePool::Add( SfxStyleSheetBase& rSheet )
+SfxStyleSheetBase& SfxStyleSheetBasePool::Add( const SfxStyleSheetBase& rSheet )
{
SfxStyleSheetIterator aIter(this, rSheet.GetFamily(), nMask);
SfxStyleSheetBase* pOld = aIter.Find( rSheet.GetName() );
- Remove( pOld );
+ if (pOld) {
+ Remove( pOld );
+ }
rtl::Reference< SfxStyleSheetBase > xNew( Create( rSheet ) );
- aStyles.push_back( xNew );
+ mIndexedStyleSheets->AddStyleSheet(xNew);
Broadcast( SfxStyleSheetHint( SFX_STYLESHEET_CHANGED, *xNew.get() ) );
return *xNew.get();
}
@@ -668,15 +672,27 @@ SfxStyleSheetBasePool& SfxStyleSheetBasePool::operator=( const SfxStyleSheetBase
return *this;
}
+namespace {
+struct AddStyleSheetCallback : svl::StyleSheetCallback
+{
+ AddStyleSheetCallback(SfxStyleSheetBasePool *pool)
+ : mPool(pool) {;}
+
+ void DoIt(const SfxStyleSheetBase& ssheet)
+ {
+ mPool->Add(ssheet);
+ }
+
+ SfxStyleSheetBasePool *mPool;
+};
+}
+
SfxStyleSheetBasePool& SfxStyleSheetBasePool::operator+=( const SfxStyleSheetBasePool& r )
{
if( &r != this )
{
- SfxStyles::const_iterator aIter( r.aStyles.begin() );
- while( aIter != r.aStyles.end() )
- {
- Add(*(*aIter++).get());
- }
+ AddStyleSheetCallback callback(this);
+ mIndexedStyleSheets->ApplyToAllStyleSheets(callback);
}
return *this;
}
@@ -715,9 +731,8 @@ void SfxStyleSheetBasePool::Remove( SfxStyleSheetBase* p )
{
// Reference to keep p alive until after Broadcast call!
rtl::Reference<SfxStyleSheetBase> xP(p);
- SfxStyles::iterator const aIter(
- std::find(aStyles.begin(), aStyles.end(), xP));
- if( aIter != aStyles.end() )
+ bool bWasRemoved = mIndexedStyleSheets->RemoveStyleSheet(xP);
+ if( bWasRemoved )
{
// Alle Styles umsetzen, deren Parent dieser hier ist
ChangeParent( p->GetName(), p->GetParent() );
@@ -735,8 +750,6 @@ void SfxStyleSheetBasePool::Remove( SfxStyleSheetBase* p )
// catch( com::sun::star::uno::Exception& )
// {
// }
-
- aStyles.erase(aIter);
Broadcast( SfxStyleSheetHint( SFX_STYLESHEET_ERASED, *p ) );
}
}
@@ -756,19 +769,24 @@ void SfxStyleSheetBasePool::Insert( SfxStyleSheetBase* p )
OSL_ENSURE( pOld, "svl::SfxStyleSheetBasePool::Insert(), Parent not found!" );
}
#endif
- aStyles.push_back( rtl::Reference< SfxStyleSheetBase >( p ) );
+ StoreStyleSheet(rtl::Reference< SfxStyleSheetBase >( p ) );
Broadcast( SfxStyleSheetHint( SFX_STYLESHEET_CREATED, *p ) );
}
-void SfxStyleSheetBasePool::Clear()
+namespace
{
- SfxStyles aClearStyles;
- aClearStyles.swap( aStyles );
- SfxStyles::iterator aIter( aClearStyles.begin() );
- while( aIter != aClearStyles.end() )
+struct StyleSheetDisposerFunctor SAL_FINAL : public svl::StyleSheetDisposer
+{
+ StyleSheetDisposerFunctor(SfxStyleSheetBasePool* pool)
+ : mPool(pool) {;}
+
+ void
+ Dispose(rtl::Reference<SfxStyleSheetBase> styleSheet)
{
- com::sun::star::uno::Reference< com::sun::star::lang::XComponent > xComp( static_cast< ::cppu::OWeakObject* >((*aIter).get()), com::sun::star::uno::UNO_QUERY );
+ cppu::OWeakObject* weakObject = static_cast< ::cppu::OWeakObject* >(styleSheet.get());
+ com::sun::star::uno::Reference< com::sun::star::lang::XComponent >
+ xComp( weakObject, com::sun::star::uno::UNO_QUERY );
if( xComp.is() ) try
{
xComp->dispose();
@@ -776,9 +794,18 @@ void SfxStyleSheetBasePool::Clear()
catch( com::sun::star::uno::Exception& )
{
}
-
- Broadcast( SfxStyleSheetHint( SFX_STYLESHEET_ERASED, *(*aIter++).get() ) );
+ mPool->Broadcast( SfxStyleSheetHint( SFX_STYLESHEET_ERASED, *styleSheet.get() ) );
}
+
+ SfxStyleSheetBasePool* mPool;
+};
+
+}
+
+void SfxStyleSheetBasePool::Clear()
+{
+ StyleSheetDisposerFunctor cleanup(this);
+ mIndexedStyleSheets->Clear(cleanup);
}
void SfxStyleSheetBasePool::ChangeParent(const OUString& rOld,
@@ -928,6 +955,11 @@ SfxUnoStyleSheet* SfxUnoStyleSheet::getUnoStyleSheet( const ::com::sun::star::un
}
}
+void
+SfxStyleSheetBasePool::StoreStyleSheet(rtl::Reference< SfxStyleSheetBase > xStyle)
+{
+ mIndexedStyleSheets->AddStyleSheet(xStyle);
+}
namespace
{
@@ -939,4 +971,22 @@ const ::com::sun::star::uno::Sequence< ::sal_Int8 >& SfxUnoStyleSheet::getIdenti
return theSfxUnoStyleSheetIdentifier::get().getSeq();
}
+void
+SfxStyleSheetBasePool::Reindex()
+{
+ mIndexedStyleSheets->Reindex();
+}
+
+const svl::IndexedStyleSheets&
+SfxStyleSheetBasePool::GetIndexedStyleSheets() const
+{
+ return *mIndexedStyleSheets;
+}
+
+rtl::Reference<SfxStyleSheetBase>
+SfxStyleSheetBasePool::GetStyleSheetByPositionInIndex(unsigned pos)
+{
+ return mIndexedStyleSheets->GetStyleSheetByPosition(pos);
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */