connectivity/source/drivers/kab/KCatalog.cxx | 3 connectivity/source/drivers/kab/KCatalog.hxx | 1 connectivity/source/drivers/kab/KStatement.cxx | 3 connectivity/source/drivers/kab/KStatement.hxx | 2 sw/CppunitTest_sw_mailmerge.mk | 1 sw/inc/dbmgr.hxx | 19 +++++ sw/qa/extras/mailmerge/mailmerge.cxx | 90 +++++++++++++++++-------- sw/source/uibase/dbui/dbmgr.cxx | 17 ++-- sw/source/uibase/uno/unomailmerge.cxx | 4 - 9 files changed, 98 insertions(+), 42 deletions(-)
New commits: commit c3da6e3844b974d7f3c60f6dd3f66c3aac519a68 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Fri Nov 25 14:02:06 2016 +0100 KAB loplugin:datamembershadow Change-Id: I1962ab1d131cf714f8bd540b589e793c4389cfb2 diff --git a/connectivity/source/drivers/kab/KCatalog.cxx b/connectivity/source/drivers/kab/KCatalog.cxx index 63d0449..06cc13c 100644 --- a/connectivity/source/drivers/kab/KCatalog.cxx +++ b/connectivity/source/drivers/kab/KCatalog.cxx @@ -34,8 +34,7 @@ using namespace ::cppu; KabCatalog::KabCatalog(KabConnection* _pCon) : connectivity::sdbcx::OCatalog(_pCon), - m_pConnection(_pCon), - m_xMetaData(m_pConnection->getMetaData()) + m_pConnection(_pCon) { } diff --git a/connectivity/source/drivers/kab/KCatalog.hxx b/connectivity/source/drivers/kab/KCatalog.hxx index e524b57..c3c45fa 100644 --- a/connectivity/source/drivers/kab/KCatalog.hxx +++ b/connectivity/source/drivers/kab/KCatalog.hxx @@ -31,7 +31,6 @@ namespace connectivity class KabCatalog : public connectivity::sdbcx::OCatalog { KabConnection* m_pConnection; // used to get the metadata - css::uno::Reference< css::sdbc::XDatabaseMetaData > m_xMetaData; // just to make things easier public: explicit KabCatalog(KabConnection* _pCon); diff --git a/connectivity/source/drivers/kab/KStatement.cxx b/connectivity/source/drivers/kab/KStatement.cxx index a59070c..2b0a3cd 100644 --- a/connectivity/source/drivers/kab/KStatement.cxx +++ b/connectivity/source/drivers/kab/KStatement.cxx @@ -66,8 +66,7 @@ KabCommonStatement::KabCommonStatement(KabConnection* _pConnection ) m_aParser(_pConnection->getComponentContext()), m_aSQLIterator(_pConnection, _pConnection->createCatalog()->getTables(), m_aParser), m_pParseTree(nullptr), - m_pConnection(_pConnection), - rBHelper(KabCommonStatement_BASE::rBHelper) + m_pConnection(_pConnection) { m_pConnection->acquire(); } diff --git a/connectivity/source/drivers/kab/KStatement.hxx b/connectivity/source/drivers/kab/KStatement.hxx index d0fe69f..e76522c 100644 --- a/connectivity/source/drivers/kab/KStatement.hxx +++ b/connectivity/source/drivers/kab/KStatement.hxx @@ -91,7 +91,7 @@ namespace connectivity virtual ~KabCommonStatement() override; public: - ::cppu::OBroadcastHelper& rBHelper; + using KabCommonStatement_BASE::rBHelper; explicit KabCommonStatement(KabConnection *_pConnection); using KabCommonStatement_BASE::operator css::uno::Reference< css::uno::XInterface >; commit 0b0e43d26a669fb98633e73f483720ae8f06f0cb Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Thu Nov 24 13:52:23 2016 +0100 MM UNO always print single files to printer Fix a missing hunk from e0ad036eed6b151ea81311fcf9ba46f1726b103c, which causes assertion, if MM is used via UNO. Thanks to Alex Kempshall, finding the assertion when testing MM. Change-Id: Ia0cd6053838adc6f0a4ce93902f06423849bf851 diff --git a/sw/source/uibase/uno/unomailmerge.cxx b/sw/source/uibase/uno/unomailmerge.cxx index 0107496..32e2fd1 100644 --- a/sw/source/uibase/uno/unomailmerge.cxx +++ b/sw/source/uibase/uno/unomailmerge.cxx @@ -693,7 +693,7 @@ uno::Any SAL_CALL SwXMailMerge::execute( // #i25686# printing should not be done asynchronously to prevent dangling offices // when mail merge is called as command line macro aMergeDesc.aPrintOptions = m_aPrintSettings; - aMergeDesc.bCreateSingleFile = false; + aMergeDesc.bCreateSingleFile = true; } break; case MailMergeType::SHELL: commit bbf246e40c7814bfc4038d456d388d1f90048287 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Tue Oct 4 10:13:24 2016 +0000 tdf#102010 Never overwrite MM files via UNO Fixes the regression introduced by commit e637b6743a506ef74c93ccbe15ab6642f3baa34f This commit removed the crazy bSubjectIsFilename handling, where I didn't understood the case of bSubjectIsFilename and a user supplied prefix. Mail merge to files never overwrites an existing document, but there is the special case, when a user selects a target filename in the MM dialog for single file MM. Should be fixed by a successive commmit, reverting this and removing an existing file before starting the MM job. Change-Id: Idda487023e6984de9c1e701fc088a6b7f92e9847 diff --git a/sw/CppunitTest_sw_mailmerge.mk b/sw/CppunitTest_sw_mailmerge.mk index 693a5e2..8d2a3f8 100644 --- a/sw/CppunitTest_sw_mailmerge.mk +++ b/sw/CppunitTest_sw_mailmerge.mk @@ -21,6 +21,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_mailmerge, \ sfx \ sw \ test \ + tl \ unotest \ utl \ )) diff --git a/sw/inc/dbmgr.hxx b/sw/inc/dbmgr.hxx index 6078b27..b124106 100644 --- a/sw/inc/dbmgr.hxx +++ b/sw/inc/dbmgr.hxx @@ -162,7 +162,23 @@ struct SwMergeDescriptor * @defgroup file Mail merge as File settings * @addtogroup file * @{ */ - OUString sPath; + + /** + * Basename incl. the path for the generated files. + * + * The final filename will be created by concating a number to prevent + * overwriting an existing file and the extension based on the filter + * settings. + */ + OUString sPrefix; + /** + * Use the sPrefix as the target filename also overwriting an existing + * target file. + * + * Just used for the internal mail merge dialogs as mail merge never + * overwrites existing files (see SwDBManager::ExecuteFormLetter). + */ + bool bPrefixIsFilename; /** @} */ /** @@ -205,6 +221,7 @@ struct SwMergeDescriptor rSh(rShell), rDescriptor(rDesc), bCreateSingleFile( false ), + bPrefixIsFilename( false ), bSendAsHTML( true ), bSendAsAttachment( false ), pMailMergeConfigItem( nullptr ) diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx index 7d45b17..0c35652 100644 --- a/sw/qa/extras/mailmerge/mailmerge.cxx +++ b/sw/qa/extras/mailmerge/mailmerge.cxx @@ -25,6 +25,8 @@ #include <com/sun/star/sdbc/XRowSet.hpp> #include <com/sun/star/sdbcx/XRowLocate.hpp> +#include <tools/urlobj.hxx> + #include <wrtsh.hxx> #include <ndtxt.hxx> #include <swdtflvr.hxx> @@ -145,7 +147,8 @@ public: ( OUString( m_directories.getURLFromSrc(mpTestDocumentPath) + OUString::createFromAscii(filename)) ) ) ) ); mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_DATA_SOURCE_NAME ), uno::Any( aDBName ) ) ); mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_OUTPUT_URL ), uno::Any( aWorkDir ) ) ); - mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_FILE_NAME_PREFIX ), uno::Any( aPrefix )) ); + if (file) + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_FILE_NAME_PREFIX ), uno::Any( aPrefix )) ); if (bPrefixIsColumn) mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_FILE_NAME_FROM_COLUMN ), uno::Any( true ) ) ); @@ -173,7 +176,7 @@ public: } - void executeMailMerge() + void executeMailMerge( bool bDontLoadResult = false ) { uno::Sequence< beans::NamedValue > aSeqMailMergeArgs = comphelper::containerToSequence( mMMargs ); uno::Any res = mxJob->execute( aSeqMailMergeArgs ); @@ -196,6 +199,8 @@ public: bOk &= rValue >>= mnCurOutputType; else if (rName == UNO_NAME_FILE_NAME_FROM_COLUMN) bOk &= rValue >>= bMMFilenameFromColumn; + else if (rName == UNO_NAME_DOCUMENT_URL) + bOk &= rValue >>= msMailMergeDocumentURL; } CPPUNIT_ASSERT(bOk); @@ -214,7 +219,7 @@ public: else { CPPUNIT_ASSERT(res == true); - if( !bMMFilenameFromColumn ) + if( !bMMFilenameFromColumn && !bDontLoadResult ) loadMailMergeDocument( 0 ); } } @@ -252,7 +257,17 @@ public: */ void loadMailMergeDocument( int number ) { - OUString name = msMailMergeOutputPrefix + OUString::number( number ) + ".odt"; + OUString name; + if (!msMailMergeOutputPrefix.isEmpty()) + name = msMailMergeOutputPrefix; + else + { + INetURLObject aURLObj; + aURLObj.SetSmartProtocol( INetProtocol::File ); + aURLObj.SetSmartURL( msMailMergeDocumentURL ); + name = aURLObj.GetBase(); + } + name += OUString::number( number ) + ".odt"; loadMailMergeDocument( name ); } @@ -262,6 +277,7 @@ protected: uno::Reference< css::task::XJob > mxJob; std::vector< beans::NamedValue > mMMargs; + OUString msMailMergeDocumentURL; OUString msMailMergeOutputURL; OUString msMailMergeOutputPrefix; sal_Int16 mnCurOutputType; @@ -603,5 +619,27 @@ DECLARE_FILE_MAILMERGE_TEST_COLUMN(testDirMailMerge, "simple-mail-merge.odt", "1 } } +DECLARE_FILE_MAILMERGE_TEST(testTdf102010, "empty.odt", "10-testing-addresses.ods", "testing-addresses") +{ + // Create "correct" automatic filename for non-user-supplied-prefix + for (auto aNamedValueIter = mMMargs.begin(); aNamedValueIter != mMMargs.end();) + { + if ( aNamedValueIter->Name == UNO_NAME_FILE_NAME_PREFIX ) + aNamedValueIter = mMMargs.erase( aNamedValueIter ); + else + { + std::cout << aNamedValueIter->Name << ": " << aNamedValueIter->Value << std::endl; + ++aNamedValueIter; + } + } + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_SAVE_AS_SINGLE_FILE ), uno::Any( true ) ) ); + + // Generate correct mail merge result filename + executeMailMerge(); + // Don't overwrite previous result + executeMailMerge( true ); + loadMailMergeDocument( 1 ); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index 1a3e035..398486c 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -1098,11 +1098,13 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, bool bCheckSingleFile_ = rMergeDescriptor.bCreateSingleFile; if( bMT_EMAIL ) { + assert( !rMergeDescriptor.bPrefixIsFilename ); assert( bMT_EMAIL && !bCheckSingleFile_ ); bCheckSingleFile_ = false; } else if( bMT_SHELL || bMT_PRINTER ) { + assert( !rMergeDescriptor.bPrefixIsFilename ); assert( (bMT_SHELL || bMT_PRINTER) && bCheckSingleFile_ ); bCheckSingleFile_ = true; } @@ -1318,7 +1320,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, // create a new temporary file name - only done once in case of bCreateSingleFile if( bNeedsTempFiles && ( !bWorkDocInitialized || !bCreateSingleFile )) { - OUString sPath = rMergeDescriptor.sPath; + OUString sPrefix = rMergeDescriptor.sPrefix; OUString sLeading; //#i97667# if the name is from a database field then it will be used _as is_ @@ -1331,14 +1333,14 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, } else { - INetURLObject aEntry( sPath ); + INetURLObject aEntry( sPrefix ); sLeading = aEntry.GetBase(); aEntry.removeSegment(); - sPath = aEntry.GetMainURL( INetURLObject::NO_DECODE ); + sPrefix = aEntry.GetMainURL( INetURLObject::NO_DECODE ); } OUString sExt(comphelper::string::stripStart(pStoreToFilter->GetDefaultExtension(), '*')); - aTempFile.reset( new utl::TempFile(sLeading, sColumnData.isEmpty(), &sExt, &sPath, true) ); + aTempFile.reset( new utl::TempFile(sLeading, sColumnData.isEmpty(), &sExt, &sPrefix, true) ); if( !aTempFile->IsValid() ) { ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED ); @@ -1559,11 +1561,11 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, // save merged document assert( aTempFile.get() ); INetURLObject aTempFileURL; - if( rMergeDescriptor.sPath.isEmpty() ) + if( rMergeDescriptor.sPrefix.isEmpty() || !rMergeDescriptor.bPrefixIsFilename ) aTempFileURL.SetURL( aTempFile->GetURL() ); else { - aTempFileURL.SetURL( rMergeDescriptor.sPath ); + aTempFileURL.SetURL( rMergeDescriptor.sPrefix ); // remove the unneeded temporary file aTempFile->EnableKillingFile(); } @@ -2863,7 +2865,8 @@ void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh, SwMergeDescriptor aMergeDesc( pImpl->pMergeDialog->GetMergeType(), rSh, aDescriptor ); aMergeDesc.sSaveToFilter = pImpl->pMergeDialog->GetSaveFilter(); aMergeDesc.bCreateSingleFile = pImpl->pMergeDialog->IsSaveSingleDoc(); - aMergeDesc.sPath = pImpl->pMergeDialog->GetTargetURL(); + aMergeDesc.bPrefixIsFilename = aMergeDesc.bCreateSingleFile; + aMergeDesc.sPrefix = pImpl->pMergeDialog->GetTargetURL(); if( !aMergeDesc.bCreateSingleFile && pImpl->pMergeDialog->IsGenerateFromDataBase() ) { aMergeDesc.sDBcolumn = pImpl->pMergeDialog->GetColumnName(); diff --git a/sw/source/uibase/uno/unomailmerge.cxx b/sw/source/uibase/uno/unomailmerge.cxx index 49aaacc..0107496 100644 --- a/sw/source/uibase/uno/unomailmerge.cxx +++ b/sw/source/uibase/uno/unomailmerge.cxx @@ -738,7 +738,7 @@ uno::Any SAL_CALL SwXMailMerge::execute( aPath += aCurFileNamePrefix; } - aMergeDesc.sPath = aPath; + aMergeDesc.sPrefix = aPath; aMergeDesc.sSaveToFilter = m_sSaveFilter; aMergeDesc.sSaveToFilterOptions = m_sSaveFilterOptions; aMergeDesc.aSaveToFilterData = m_aSaveFilterData; commit 660159a68acd54a8f213920457c1aeed79cffea5 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Mon Oct 3 21:51:56 2016 +0200 MM allow easier manipulation of MM test arguments Keep the beans::NamedValue vector around and convert it to a uno::Sequence just before executing the mail merge job. Change-Id: Ib2b4863337af20fb4423cc1b4ea4223d66d63ae5 diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx index bb4ec55..7d45b17 100644 --- a/sw/qa/extras/mailmerge/mailmerge.cxx +++ b/sw/qa/extras/mailmerge/mailmerge.cxx @@ -138,29 +138,29 @@ public: uno::Reference< task::XJob > xJob( getMultiServiceFactory()->createInstance( "com.sun.star.text.MailMerge" ), uno::UNO_QUERY_THROW ); mxJob.set( xJob ); - std::vector< beans::NamedValue > args; + mMMargs.reserve( 15 ); - args.push_back( beans::NamedValue( OUString( UNO_NAME_OUTPUT_TYPE ), uno::Any( file ? text::MailMergeType::FILE : text::MailMergeType::SHELL ) ) ); - args.push_back( beans::NamedValue( OUString( UNO_NAME_DOCUMENT_URL ), uno::Any( + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_OUTPUT_TYPE ), uno::Any( file ? text::MailMergeType::FILE : text::MailMergeType::SHELL ) ) ); + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_DOCUMENT_URL ), uno::Any( ( OUString( m_directories.getURLFromSrc(mpTestDocumentPath) + OUString::createFromAscii(filename)) ) ) ) ); - args.push_back( beans::NamedValue( OUString( UNO_NAME_DATA_SOURCE_NAME ), uno::Any( aDBName ) ) ); - args.push_back( beans::NamedValue( OUString( UNO_NAME_OUTPUT_URL ), uno::Any( aWorkDir ) ) ); - args.push_back( beans::NamedValue( OUString( UNO_NAME_FILE_NAME_PREFIX ), uno::Any( aPrefix )) ); + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_DATA_SOURCE_NAME ), uno::Any( aDBName ) ) ); + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_OUTPUT_URL ), uno::Any( aWorkDir ) ) ); + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_FILE_NAME_PREFIX ), uno::Any( aPrefix )) ); if (bPrefixIsColumn) - args.push_back( beans::NamedValue( OUString( UNO_NAME_FILE_NAME_FROM_COLUMN ), uno::Any( true ) ) ); + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_FILE_NAME_FROM_COLUMN ), uno::Any( true ) ) ); if (tablename) { - args.push_back( beans::NamedValue( OUString( UNO_NAME_DAD_COMMAND_TYPE ), uno::Any( sdb::CommandType::TABLE ) ) ); - args.push_back( beans::NamedValue( OUString( UNO_NAME_DAD_COMMAND ), uno::Any( OUString::createFromAscii(tablename) ) ) ); + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_DAD_COMMAND_TYPE ), uno::Any( sdb::CommandType::TABLE ) ) ); + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_DAD_COMMAND ), uno::Any( OUString::createFromAscii(tablename) ) ) ); } if (nDataSets > 0) { uno::Reference< sdbc::XRowSet > xCurResultSet = getXResultFromDataset( tablename, aDBName ); uno::Reference< sdbcx::XRowLocate > xCurRowLocate( xCurResultSet, uno::UNO_QUERY ); - args.push_back( beans::NamedValue( OUString( UNO_NAME_RESULT_SET ), uno::Any( xCurResultSet ) ) ); + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_RESULT_SET ), uno::Any( xCurResultSet ) ) ); std::vector< uno::Any > vResult; vResult.reserve( nDataSets ); sal_Int32 i; @@ -168,20 +168,20 @@ public: { vResult.push_back( uno::Any( xCurRowLocate->getBookmark() ) ); } - args.push_back( beans::NamedValue( OUString( UNO_NAME_SELECTION ), uno::Any( comphelper::containerToSequence(vResult) ) ) ); + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_SELECTION ), uno::Any( comphelper::containerToSequence(vResult) ) ) ); } - mSeqMailMergeArgs = comphelper::containerToSequence( args ); } void executeMailMerge() { - uno::Any res = mxJob->execute( mSeqMailMergeArgs ); + uno::Sequence< beans::NamedValue > aSeqMailMergeArgs = comphelper::containerToSequence( mMMargs ); + uno::Any res = mxJob->execute( aSeqMailMergeArgs ); - const beans::NamedValue *pArguments = mSeqMailMergeArgs.getConstArray(); + const beans::NamedValue *pArguments = aSeqMailMergeArgs.getConstArray(); bool bOk = true; bool bMMFilenameFromColumn = false; - sal_Int32 nArgs = mSeqMailMergeArgs.getLength(); + sal_Int32 nArgs = aSeqMailMergeArgs.getLength(); for (sal_Int32 i = 0; i < nArgs; ++i) { const OUString &rName = pArguments[i].Name; @@ -189,9 +189,9 @@ public: // all error checking was already done by the MM job execution if (rName == UNO_NAME_OUTPUT_URL) - bOk &= rValue >>= mailMergeOutputURL; + bOk &= rValue >>= msMailMergeOutputURL; else if (rName == UNO_NAME_FILE_NAME_PREFIX) - bOk &= rValue >>= mailMergeOutputPrefix; + bOk &= rValue >>= msMailMergeOutputPrefix; else if (rName == UNO_NAME_OUTPUT_TYPE) bOk &= rValue >>= mnCurOutputType; else if (rName == UNO_NAME_FILE_NAME_FROM_COLUMN) @@ -227,8 +227,8 @@ public: if (mnCurOutputType != text::MailMergeType::FILE) return nullptr; - OUString name = mailMergeOutputPrefix + OUString::number( 0 ) + ".odt"; - return parseExportInternal( mailMergeOutputURL + "/" + name, rStreamName ); + OUString name = msMailMergeOutputPrefix + OUString::number( 0 ) + ".odt"; + return parseExportInternal( msMailMergeOutputURL + "/" + name, rStreamName ); } void loadMailMergeDocument( const OUString &filename ) @@ -239,7 +239,7 @@ public: // Output name early, so in the case of a hang, the name of the hanging input file is visible. std::cout << filename << ","; mnStartTime = osl_getGlobalTimer(); - mxComponent = loadFromDesktop(mailMergeOutputURL + "/" + filename, "com.sun.star.text.TextDocument"); + mxComponent = loadFromDesktop(msMailMergeOutputURL + "/" + filename, "com.sun.star.text.TextDocument"); CPPUNIT_ASSERT( mxComponent.is()); OString name2 = OUStringToOString( filename, RTL_TEXTENCODING_UTF8 ); discardDumpedLayout(); @@ -252,7 +252,7 @@ public: */ void loadMailMergeDocument( int number ) { - OUString name = mailMergeOutputPrefix + OUString::number( number ) + ".odt"; + OUString name = msMailMergeOutputPrefix + OUString::number( number ) + ".odt"; loadMailMergeDocument( name ); } @@ -261,9 +261,9 @@ protected: int documentStartPageNumber( int document ) const; uno::Reference< css::task::XJob > mxJob; - uno::Sequence< beans::NamedValue > mSeqMailMergeArgs; - OUString mailMergeOutputURL; - OUString mailMergeOutputPrefix; + std::vector< beans::NamedValue > mMMargs; + OUString msMailMergeOutputURL; + OUString msMailMergeOutputPrefix; sal_Int16 mnCurOutputType; uno::Reference< lang::XComponent > mxMMComponent; const char* maMMtestFilename; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits