framework/source/uiconfiguration/uiconfigurationmanager.cxx | 33 ++++++++++-- sw/qa/extras/odfexport/odfexport.cxx | 32 +++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-)
New commits: commit 5c74b979eac620dc1a435fcdf9e88488fd4217d9 Author: David Hashe <[email protected]> AuthorDate: Fri Apr 25 20:30:57 2025 -0400 Commit: Miklos Vajna <[email protected]> CommitDate: Wed May 21 09:20:33 2025 +0200 tdf#60700 stop creating empty UIConfiguration subdirs in ODFs This change stops the creation of various subdirectories of the Configurations2/ directory on new documents that do not have anything that needs to be stored in those subdirectories. Previously, LibreOffice would always create a bunch of empty subdirectories that were not necessary. Whenever an XStorage is opened readwrite on a path, it will immediately create that path. LibreOffice was opening all of these paths readwrite. So, the solution is to always open these paths as readonly, and then when we need to write data to them we close them and re-open them as readwrite. If we never need to write data to a path, then it won't be created. This patch specifically stops the creation of subdirectories that were being created directly by UIConfigurationManager. There are other paths that were being created by ImageManager and DocumentAcceleratorConfiguration, and those paths will be handled by other patches. Test coverage was added in aaed16eef8b2d32ac02c8cb3a42ca25246cb0d33 $ CPPUNIT_TEST_NAME="Test testTdf69500" make CppunitTest_sw_odfexport I also manually tested with the following procedure: 1. Open a new document in writer. 2. Tools > Customize > Toolbars. 3. Set scope to "Untitled 1". 4. Add a new toolbar "New Toolbar 1". 5. Add any command from Available Commands to the new toolbar. 6. OK. 7. Visually verify that the toolbar is present. 8. Save the document. 9. Verify that the toolbar is saved correctly inside the file. $ unzip -l Untitled\ 1.odt Archive: Untitled 1.odt Length Date Time Name --------- ---------- ----- ---- 39 2025-04-25 23:35 mimetype 353 2025-04-25 23:35 Configurations2/toolbar/custom_toolbar_2a773c3.xml 0 2025-04-25 23:35 Configurations2/accelerator/ 0 2025-04-25 23:35 Configurations2/images/Bitmaps/ 12645 2025-04-25 23:35 styles.xml 899 2025-04-25 23:35 manifest.rdf 3563 2025-04-25 23:35 content.xml 1012 2025-04-25 23:35 meta.xml 14748 2025-04-25 23:35 settings.xml 318 2025-04-25 23:35 Thumbnails/thumbnail.png 1180 2025-04-25 23:35 META-INF/manifest.xml --------- ------- 34757 11 files 10. Close and reopen the document. 11. Visually verify that the toolbar is present. Change-Id: If0a93675204576b3b6f7fe9113cada398e4da2ea Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184655 Tested-by: Jenkins Reviewed-by: Miklos Vajna <[email protected]> diff --git a/framework/source/uiconfiguration/uiconfigurationmanager.cxx b/framework/source/uiconfiguration/uiconfigurationmanager.cxx index 29be73cc0a72..7a2af67a45b0 100644 --- a/framework/source/uiconfiguration/uiconfigurationmanager.cxx +++ b/framework/source/uiconfiguration/uiconfigurationmanager.cxx @@ -163,10 +163,12 @@ private: { UIElementType() : bModified( false ), bLoaded( false ), + bShouldReloadRWOnStore( false ), nElementType( css::ui::UIElementType::UNKNOWN ) {} bool bModified; bool bLoaded; + bool bShouldReloadRWOnStore; sal_Int16 nElementType; UIElementDataHashMap aElementsHashMap; css::uno::Reference< css::embed::XStorage > xStorage; @@ -631,8 +633,6 @@ void UIConfigurationManager::impl_Initialize() // Initialize the top-level structures with the storage data if ( m_xDocConfigStorage.is() ) { - tools::Long nModes = m_bReadOnly ? ElementModes::READ : ElementModes::READWRITE; - // Try to access our module sub folder for ( sal_Int16 i = 1; i < css::ui::UIElementType::COUNT; i++ ) @@ -640,7 +640,7 @@ void UIConfigurationManager::impl_Initialize() Reference< XStorage > xElementTypeStorage; try { - xElementTypeStorage = m_xDocConfigStorage->openStorageElement( OUString(UIELEMENTTYPENAMES[i]), nModes ); + xElementTypeStorage = m_xDocConfigStorage->openStorageElement( OUString(UIELEMENTTYPENAMES[i]), ElementModes::READ ); } catch ( const css::container::NoSuchElementException& ) { @@ -660,6 +660,7 @@ void UIConfigurationManager::impl_Initialize() m_aUIElements[i].nElementType = i; m_aUIElements[i].bModified = false; + m_aUIElements[i].bShouldReloadRWOnStore = !m_bReadOnly; m_aUIElements[i].xStorage = std::move(xElementTypeStorage); } } @@ -1286,8 +1287,30 @@ void SAL_CALL UIConfigurationManager::store() { UIElementType& rElementType = m_aUIElements[i]; - if ( rElementType.bModified && rElementType.xStorage.is() ) - impl_storeElementTypeData( rElementType.xStorage, rElementType ); + if ( rElementType.bModified ) + { + if ( rElementType.bShouldReloadRWOnStore ) + { + rElementType.bShouldReloadRWOnStore = false; + rElementType.xStorage.clear(); + try + { + rElementType.xStorage = m_xDocConfigStorage->openStorageElement( OUString(UIELEMENTTYPENAMES[i]), + ElementModes::READWRITE ); + } + catch ( const Exception& ) + { + rElementType.xStorage = m_xDocConfigStorage->openStorageElement( OUString(UIELEMENTTYPENAMES[i]), + ElementModes::READ ); + throw; + } + } + if ( rElementType.xStorage.is() ) + { + impl_storeElementTypeData( rElementType.xStorage, rElementType ); + } + + } } catch ( const Exception& ) { diff --git a/sw/qa/extras/odfexport/odfexport.cxx b/sw/qa/extras/odfexport/odfexport.cxx index 058d8adac6ba..ca4efa7076be 100644 --- a/sw/qa/extras/odfexport/odfexport.cxx +++ b/sw/qa/extras/odfexport/odfexport.cxx @@ -1527,6 +1527,38 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf60700_accelerators) } } +CPPUNIT_TEST_FIXTURE(Test, testTdf60700_directories) +{ + createSwDoc(); + save(mpFilter); + + // There is no way to read the contents of Configurations2/ from a loaded document, + // because only UIConfigurationManager has a reference to it and there is no method + // to access that reference from outside the class. So, we inspect the zipfile + // directly. + + uno::Sequence<uno::Any> aArgs{ uno::Any(maTempFile.GetURL()) }; + uno::Reference<container::XNameAccess> xNameAccess( + m_xSFactory->createInstanceWithArguments(u"com.sun.star.packages.zip.ZipFileAccess"_ustr, + aArgs), + uno::UNO_QUERY); + const css::uno::Sequence<OUString> aNames(xNameAccess->getElementNames()); + + int nMatches = 0; + for (const OUString& sName : aNames) + { + OUString sRest; + if (sName.startsWith("Configurations2/", &sRest) && !sRest.isEmpty()) + { + ++nMatches; + } + } + + // There should be two elements ("accelerator", "images") within Configurations2/ on a fresh document. + CPPUNIT_ASSERT_EQUAL(2, nMatches); +} + + } // end of anonymous namespace CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
