[Libreoffice-commits] core.git: Branch 'distro/cib/libreoffice-6-1' - 2 commits - sw/source
Szymon Kłos (via logerrit)
logerrit at kemper.freedesktop.org
Fri Oct 11 07:43:03 UTC 2019
sw/source/uibase/dbui/dbmgr.cxx | 746 ++++++++++++++++++++--------------------
1 file changed, 380 insertions(+), 366 deletions(-)
New commits:
commit 30496b80fd061afe10f6842fe257babb2b2b4bf5
Author: Szymon Kłos <szymon.klos at collabora.com>
AuthorDate: Wed Jan 2 19:03:25 2019 +0100
Commit: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
CommitDate: Fri Oct 11 09:42:22 2019 +0200
tdf#117480 fix crash in mailmerge
Catch exceptions and hide progress dialog.
Reviewed-on: https://gerrit.libreoffice.org/65815
Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>
Tested-by: Szymon Kłos <szymon.klos at collabora.com>
Reviewed-on: https://gerrit.libreoffice.org/72280
Reviewed-by: Michael Stahl <Michael.Stahl at cib.de>
Tested-by: Jenkins
(cherry picked from commit 4bba6c122c3bb3468bccd69d53d70d00fd00bdcc)
Change-Id: Ie63c8d7e001c90f40cf7504fd8248a6742e9d244
Reviewed-on: https://gerrit.libreoffice.org/80553
Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
Tested-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index de0a9ad8869d..a4c618462f5f 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1319,453 +1319,464 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
vcl::Window *pSourceWindow = nullptr;
std::shared_ptr<weld::GenericDialogController> xProgressDlg;
- if( !bIsMergeSilent )
+ try
{
- // construct the process dialog
- pSourceWindow = &pSourceShell->GetView().GetEditWin();
- if (!bMT_PRINTER)
- xProgressDlg.reset(new CreateMonitor(pSourceWindow->GetFrameWeld()));
- else
+ if( !bIsMergeSilent )
{
- xProgressDlg.reset(new PrintMonitor(pSourceWindow->GetFrameWeld()));
- static_cast<PrintMonitor*>(xProgressDlg.get())->set_title(
- pSourceDocSh->GetTitle(22));
- }
- weld::DialogController::runAsync(xProgressDlg, [this, &xProgressDlg](sal_Int32 nResult){
- if (nResult == RET_CANCEL)
- MergeCancel();
- xProgressDlg.reset();
- });
-
- Application::Reschedule( true );
- }
-
- if( bCreateSingleFile && !pTargetView )
- {
- // create a target docshell to put the merged document into
- xTargetDocShell = lcl_CreateWorkingDocument( WorkingDocType::TARGET,
- *pSourceShell, bMT_SHELL ? pSourceWindow : nullptr,
- nullptr, &pTargetView, &pTargetShell, &pTargetDoc );
+ // construct the process dialog
+ pSourceWindow = &pSourceShell->GetView().GetEditWin();
+ if (!bMT_PRINTER)
+ xProgressDlg.reset(new CreateMonitor(pSourceWindow->GetFrameWeld()));
+ else
+ {
+ xProgressDlg.reset(new PrintMonitor(pSourceWindow->GetFrameWeld()));
+ static_cast<PrintMonitor*>(xProgressDlg.get())->set_title(
+ pSourceDocSh->GetTitle(22));
+ }
+ weld::DialogController::runAsync(xProgressDlg, [this, &xProgressDlg](sal_Int32 nResult){
+ if (nResult == RET_CANCEL)
+ MergeCancel();
+ xProgressDlg.reset();
+ });
- // import current print settings
- const SwPrintData &rPrintData = pSourceShell->getIDocumentDeviceAccess().getPrintData();
- pTargetDoc->getIDocumentDeviceAccess().setPrintData(rPrintData);
+ Application::Reschedule( true );
+ }
- if (nMaxDumpDocs)
- lcl_SaveDebugDoc( xTargetDocShell.get(), "MergeDoc" );
- }
- else if( pTargetView )
- {
- pTargetShell = pTargetView->GetWrtShellPtr();
- pTargetDoc = pTargetShell->GetDoc();
- xTargetDocShell = pTargetView->GetDocShell();
- }
+ if( bCreateSingleFile && !pTargetView )
+ {
+ // create a target docshell to put the merged document into
+ xTargetDocShell = lcl_CreateWorkingDocument( WorkingDocType::TARGET,
+ *pSourceShell, bMT_SHELL ? pSourceWindow : nullptr,
+ nullptr, &pTargetView, &pTargetShell, &pTargetDoc );
- if( bCreateSingleFile )
- {
- // determine the page style and number used at the start of the source document
- pSourceShell->SttEndDoc(true);
- nStartingPageNo = pSourceShell->GetVirtPageNum();
- }
+ // import current print settings
+ const SwPrintData &rPrintData = pSourceShell->getIDocumentDeviceAccess().getPrintData();
+ pTargetDoc->getIDocumentDeviceAccess().setPrintData(rPrintData);
- // Progress, to prohibit KeyInputs
- SfxProgress aProgress(pSourceDocSh, ::aEmptyOUStr, 1);
+ if (nMaxDumpDocs)
+ lcl_SaveDebugDoc( xTargetDocShell.get(), "MergeDoc" );
+ }
+ else if( pTargetView )
+ {
+ pTargetShell = pTargetView->GetWrtShellPtr();
+ pTargetDoc = pTargetShell->GetDoc();
+ xTargetDocShell = pTargetView->GetDocShell();
+ }
- // lock all dispatchers
- SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst(pSourceDocSh);
- while (pViewFrame)
- {
- pViewFrame->GetDispatcher()->Lock(true);
- pViewFrame = SfxViewFrame::GetNext(*pViewFrame, pSourceDocSh);
- }
+ if( bCreateSingleFile )
+ {
+ // determine the page style and number used at the start of the source document
+ pSourceShell->SttEndDoc(true);
+ nStartingPageNo = pSourceShell->GetVirtPageNum();
+ }
- sal_Int32 nDocNo = 1;
+ // Progress, to prohibit KeyInputs
+ SfxProgress aProgress(pSourceDocSh, ::aEmptyOUStr, 1);
- // For single file mode, the number of pages in the target document so far, which is used
- // by AppendDoc() to adjust position of page-bound objects. Getting this information directly
- // from the target doc would require repeated layouts of the doc, which is expensive, but
- // it can be manually computed from the source documents (for which we do layouts, so the page
- // count is known, and there is a blank page between each of them in the target document).
- int targetDocPageCount = 0;
+ // lock all dispatchers
+ SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst(pSourceDocSh);
+ while (pViewFrame)
+ {
+ pViewFrame->GetDispatcher()->Lock(true);
+ pViewFrame = SfxViewFrame::GetNext(*pViewFrame, pSourceDocSh);
+ }
- if( !bIsMergeSilent && !bMT_PRINTER )
- {
- sal_Int32 nRecordCount = 1;
- lcl_getCountFromResultSet( nRecordCount, pImpl->pMergeData );
+ sal_Int32 nDocNo = 1;
- // Synchronized docs don't auto-advance the record set, but there is a
- // "security" check, which will always advance the record set, if there
- // is no "next record" field in a synchronized doc => nRecordPerDoc > 0
- sal_Int32 nRecordPerDoc = pSourceShell->GetDoc()
- ->getIDocumentFieldsAccess().GetRecordsPerDocument();
- if ( bSynchronizedDoc && (nRecordPerDoc > 1) )
- --nRecordPerDoc;
- assert( nRecordPerDoc > 0 );
+ // For single file mode, the number of pages in the target document so far, which is used
+ // by AppendDoc() to adjust position of page-bound objects. Getting this information directly
+ // from the target doc would require repeated layouts of the doc, which is expensive, but
+ // it can be manually computed from the source documents (for which we do layouts, so the page
+ // count is known, and there is a blank page between each of them in the target document).
+ int targetDocPageCount = 0;
- sal_Int32 nMaxDocs = nRecordCount / nRecordPerDoc;
- if ( 0 != nRecordCount % nRecordPerDoc )
- nMaxDocs += 1;
- static_cast<CreateMonitor*>(xProgressDlg.get())->SetTotalCount(nMaxDocs);
- }
+ if( !bIsMergeSilent && !bMT_PRINTER )
+ {
+ sal_Int32 nRecordCount = 1;
+ lcl_getCountFromResultSet( nRecordCount, pImpl->pMergeData );
- long nStartRow, nEndRow;
- bool bFreezedLayouts = false;
- // to collect temporary email files
- std::vector< OUString> aFilesToRemove;
+ // Synchronized docs don't auto-advance the record set, but there is a
+ // "security" check, which will always advance the record set, if there
+ // is no "next record" field in a synchronized doc => nRecordPerDoc > 0
+ sal_Int32 nRecordPerDoc = pSourceShell->GetDoc()
+ ->getIDocumentFieldsAccess().GetRecordsPerDocument();
+ if ( bSynchronizedDoc && (nRecordPerDoc > 1) )
+ --nRecordPerDoc;
+ assert( nRecordPerDoc > 0 );
- // The SfxObjectShell will be closed explicitly later but
- // it is more safe to use SfxObjectShellLock here
- SfxObjectShellLock xWorkDocSh;
- SwView* pWorkView = nullptr;
- SwDoc* pWorkDoc = nullptr;
- SwDBManager* pWorkDocOrigDBManager = nullptr;
- SwWrtShell* pWorkShell = nullptr;
- bool bWorkDocInitialized = false;
+ sal_Int32 nMaxDocs = nRecordCount / nRecordPerDoc;
+ if ( 0 != nRecordCount % nRecordPerDoc )
+ nMaxDocs += 1;
+ static_cast<CreateMonitor*>(xProgressDlg.get())->SetTotalCount(nMaxDocs);
+ }
- do
- {
- nStartRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
+ long nStartRow, nEndRow;
+ bool bFreezedLayouts = false;
+ // to collect temporary email files
+ std::vector< OUString> aFilesToRemove;
- OUString sColumnData;
+ // The SfxObjectShell will be closed explicitly later but
+ // it is more safe to use SfxObjectShellLock here
+ SfxObjectShellLock xWorkDocSh;
+ SwView* pWorkView = nullptr;
+ SwDoc* pWorkDoc = nullptr;
+ SwDBManager* pWorkDocOrigDBManager = nullptr;
+ SwWrtShell* pWorkShell = nullptr;
+ bool bWorkDocInitialized = false;
- // Read the indicated data column, which should contain a valid mail
- // address or an optional file name
- if( bMT_EMAIL || bColumnName )
+ do
{
- sColumnData = GetDBField( xColumnProp, aColumnDBFormat );
- }
+ nStartRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
- // create a new temporary file name - only done once in case of bCreateSingleFile
- if( bNeedsTempFiles && ( !bWorkDocInitialized || !bCreateSingleFile ))
- {
- OUString sPrefix = sDescriptorPrefix;
- OUString sLeading;
+ OUString sColumnData;
- //#i97667# if the name is from a database field then it will be used _as is_
- if( bColumnName && !bMT_EMAIL )
- {
- if (!sColumnData.isEmpty())
- sLeading = sColumnData;
- else
- sLeading = "_";
- }
- else
+ // Read the indicated data column, which should contain a valid mail
+ // address or an optional file name
+ if( bMT_EMAIL || bColumnName )
{
- INetURLObject aEntry( sPrefix );
- sLeading = aEntry.GetBase();
- aEntry.removeSegment();
- sPrefix = aEntry.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ sColumnData = GetDBField( xColumnProp, aColumnDBFormat );
}
- OUString sExt(comphelper::string::stripStart(pStoreToFilter->GetDefaultExtension(), '*'));
- aTempFile.reset( new utl::TempFile(sLeading, sColumnData.isEmpty(), &sExt, &sPrefix, true) );
- if( !aTempFile->IsValid() )
+ // create a new temporary file name - only done once in case of bCreateSingleFile
+ if( bNeedsTempFiles && ( !bWorkDocInitialized || !bCreateSingleFile ))
{
- ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED );
- m_aMergeStatus = MergeStatus::Error;
- }
- }
+ OUString sPrefix = sDescriptorPrefix;
+ OUString sLeading;
- if( IsMergeOk() )
- {
- std::unique_ptr< INetURLObject > aTempFileURL;
- if( bNeedsTempFiles )
- aTempFileURL.reset( new INetURLObject(aTempFile->GetURL()));
- if( !bIsMergeSilent ) {
- if( !bMT_PRINTER )
- static_cast<CreateMonitor*>(xProgressDlg.get())->SetCurrentPosition(nDocNo);
- else {
- PrintMonitor *pPrintMonDlg = static_cast<PrintMonitor*>(xProgressDlg.get());
- pPrintMonDlg->m_xPrinter->set_label(bNeedsTempFiles
- ? aTempFileURL->GetBase() : pSourceDocSh->GetTitle( 2));
- OUString sStat( SwResId(STR_STATSTR_LETTER) );
- sStat += " " + OUString::number( nDocNo );
- pPrintMonDlg->m_xPrintInfo->set_label(sStat);
+ //#i97667# if the name is from a database field then it will be used _as is_
+ if( bColumnName && !bMT_EMAIL )
+ {
+ if (!sColumnData.isEmpty())
+ sLeading = sColumnData;
+ else
+ sLeading = "_";
}
- //TODO xProgressDlg->queue_draw();
- }
-
- Application::Reschedule( true );
-
- // Create a copy of the source document and work with that one instead of the source.
- // If we're not in the single file mode (which requires modifying the document for the merging),
- // it is enough to do this just once. Currently PDF also has to be treated special.
- if( !bWorkDocInitialized || bCreateSingleFile || bIsPDFexport )
- {
- assert( !xWorkDocSh.Is());
- pWorkDocOrigDBManager = this;
- xWorkDocSh = lcl_CreateWorkingDocument( WorkingDocType::COPY,
- *pSourceShell, nullptr, &pWorkDocOrigDBManager,
- &pWorkView, &pWorkShell, &pWorkDoc );
- if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
- lcl_SaveDebugDoc( xWorkDocSh, "WorkDoc", nDocNo );
-
- // #i69458# lock fields to prevent access to the result set while calculating layout
- // tdf#92324: and do not unlock: keep document locked during printing to avoid
- // ExpFields update during printing, generation of preview, etc.
- pWorkShell->LockExpFields();
- pWorkShell->CalcLayout();
- // tdf#121168: Now force correct page descriptions applied to page frames. Without
- // this, e.g., page frames starting with sections could have page descriptions set
- // wrong. This would lead to wrong page styles applied in SwDoc::AppendDoc below.
- pWorkShell->GetViewOptions()->SetIdle(true);
- for (auto aLayout : pWorkShell->GetDoc()->GetAllLayouts())
+ else
{
- aLayout->FreezeLayout(false);
- aLayout->AllCheckPageDescs();
+ INetURLObject aEntry( sPrefix );
+ sLeading = aEntry.GetBase();
+ aEntry.removeSegment();
+ sPrefix = aEntry.GetMainURL( INetURLObject::DecodeMechanism::NONE );
}
- }
- lcl_emitEvent(SfxEventHintId::SwEventFieldMerge, STR_SW_EVENT_FIELD_MERGE, xWorkDocSh);
-
- // tdf#92324: Allow ExpFields update only by explicit instruction to avoid
- // database cursor movement on any other fields update, for example during
- // print preview and other operations
- if ( pWorkShell->IsExpFieldsLocked() )
- pWorkShell->UnlockExpFields();
- pWorkShell->SwViewShell::UpdateFields();
- pWorkShell->LockExpFields();
-
- lcl_emitEvent(SfxEventHintId::SwEventFieldMergeFinished, STR_SW_EVENT_FIELD_MERGE_FINISHED, xWorkDocSh);
-
- // also emit MailMergeEvent on XInterface if possible
- const SwXMailMerge *pEvtSrc = GetMailMergeEvtSrc();
- if(pEvtSrc)
- {
- uno::Reference< uno::XInterface > xRef(
- static_cast<text::XMailMergeBroadcaster*>(const_cast<SwXMailMerge*>(pEvtSrc)) );
- text::MailMergeEvent aEvt( xRef, xWorkDocSh->GetModel() );
- pEvtSrc->LaunchMailMergeEvent( aEvt );
+ OUString sExt(comphelper::string::stripStart(pStoreToFilter->GetDefaultExtension(), '*'));
+ aTempFile.reset( new utl::TempFile(sLeading, sColumnData.isEmpty(), &sExt, &sPrefix, true) );
+ if( !aTempFile->IsValid() )
+ {
+ ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED );
+ m_aMergeStatus = MergeStatus::Error;
+ }
}
- // working copy is merged - prepare final steps depending on merge options
-
- if( bCreateSingleFile )
+ if( IsMergeOk() )
{
- assert( pTargetShell && "no target shell available!" );
+ std::unique_ptr< INetURLObject > aTempFileURL;
+ if( bNeedsTempFiles )
+ aTempFileURL.reset( new INetURLObject(aTempFile->GetURL()));
+ if( !bIsMergeSilent ) {
+ if( !bMT_PRINTER )
+ static_cast<CreateMonitor*>(xProgressDlg.get())->SetCurrentPosition(nDocNo);
+ else {
+ PrintMonitor *pPrintMonDlg = static_cast<PrintMonitor*>(xProgressDlg.get());
+ pPrintMonDlg->m_xPrinter->set_label(bNeedsTempFiles
+ ? aTempFileURL->GetBase() : pSourceDocSh->GetTitle( 2));
+ OUString sStat( SwResId(STR_STATSTR_LETTER) );
+ sStat += " " + OUString::number( nDocNo );
+ pPrintMonDlg->m_xPrintInfo->set_label(sStat);
+ }
+ //TODO xProgressDlg->queue_draw();
+ }
- // prepare working copy and target to append
+ Application::Reschedule( true );
- pWorkDoc->RemoveInvisibleContent();
- pWorkShell->ConvertFieldsToText();
- pWorkShell->SetNumberingRestart();
- if( bSynchronizedDoc )
+ // Create a copy of the source document and work with that one instead of the source.
+ // If we're not in the single file mode (which requires modifying the document for the merging),
+ // it is enough to do this just once. Currently PDF also has to be treated special.
+ if( !bWorkDocInitialized || bCreateSingleFile || bIsPDFexport )
{
- lcl_RemoveSectionLinks( *pWorkShell );
+ assert( !xWorkDocSh.Is());
+ pWorkDocOrigDBManager = this;
+ xWorkDocSh = lcl_CreateWorkingDocument( WorkingDocType::COPY,
+ *pSourceShell, nullptr, &pWorkDocOrigDBManager,
+ &pWorkView, &pWorkShell, &pWorkDoc );
+ if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
+ lcl_SaveDebugDoc( xWorkDocSh, "WorkDoc", nDocNo );
+
+ // #i69458# lock fields to prevent access to the result set while calculating layout
+ // tdf#92324: and do not unlock: keep document locked during printing to avoid
+ // ExpFields update during printing, generation of preview, etc.
+ pWorkShell->LockExpFields();
+ pWorkShell->CalcLayout();
+ // tdf#121168: Now force correct page descriptions applied to page frames. Without
+ // this, e.g., page frames starting with sections could have page descriptions set
+ // wrong. This would lead to wrong page styles applied in SwDoc::AppendDoc below.
+ pWorkShell->GetViewOptions()->SetIdle(true);
+ for (auto aLayout : pWorkShell->GetDoc()->GetAllLayouts())
+ {
+ aLayout->FreezeLayout(false);
+ aLayout->AllCheckPageDescs();
+ }
}
- if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
- lcl_SaveDebugDoc( xWorkDocSh, "WorkDoc", nDocNo );
+ lcl_emitEvent(SfxEventHintId::SwEventFieldMerge, STR_SW_EVENT_FIELD_MERGE, xWorkDocSh);
- // append the working document to the target document
- if( targetDocPageCount % 2 == 1 )
- ++targetDocPageCount; // Docs always start on odd pages (so offset must be even).
- SwNodeIndex appendedDocStart = pTargetDoc->AppendDoc( *pWorkDoc,
- nStartingPageNo, !bWorkDocInitialized, targetDocPageCount, nDocNo);
- // ensure layout is up to date in order to get correct page count
- pWorkShell->CalcLayout();
- targetDocPageCount += pWorkShell->GetPageCnt();
+ // tdf#92324: Allow ExpFields update only by explicit instruction to avoid
+ // database cursor movement on any other fields update, for example during
+ // print preview and other operations
+ if ( pWorkShell->IsExpFieldsLocked() )
+ pWorkShell->UnlockExpFields();
+ pWorkShell->SwViewShell::UpdateFields();
+ pWorkShell->LockExpFields();
- if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
- lcl_SaveDebugDoc( xTargetDocShell.get(), "MergeDoc" );
+ lcl_emitEvent(SfxEventHintId::SwEventFieldMergeFinished, STR_SW_EVENT_FIELD_MERGE_FINISHED, xWorkDocSh);
- if (bMT_SHELL)
+ // also emit MailMergeEvent on XInterface if possible
+ const SwXMailMerge *pEvtSrc = GetMailMergeEvtSrc();
+ if(pEvtSrc)
{
- SwDocMergeInfo aMergeInfo;
- // Name of the mark is actually irrelevant, UNO bookmarks have internals names.
- aMergeInfo.startPageInTarget = pTargetDoc->getIDocumentMarkAccess()->makeMark(
- appendedDocStart, "", IDocumentMarkAccess::MarkType::UNO_BOOKMARK,
- ::sw::mark::InsertMode::New);
- aMergeInfo.nDBRow = nStartRow;
- rMergeDescriptor.pMailMergeConfigItem->AddMergedDocument( aMergeInfo );
+ uno::Reference< uno::XInterface > xRef(
+ static_cast<text::XMailMergeBroadcaster*>(const_cast<SwXMailMerge*>(pEvtSrc)) );
+ text::MailMergeEvent aEvt( xRef, xWorkDocSh->GetModel() );
+ pEvtSrc->LaunchMailMergeEvent( aEvt );
}
- }
- else
- {
- assert( bNeedsTempFiles );
- assert( pWorkShell->IsExpFieldsLocked() );
- // fields are locked, so it's fine to
- // restore the old / empty DB manager for save
- pWorkDoc->SetDBManager( pWorkDocOrigDBManager );
+ // working copy is merged - prepare final steps depending on merge options
- // save merged document
- OUString sFileURL;
- if( !lcl_SaveDoc( aTempFileURL.get(), pStoreToFilter, pStoreToFilterOptions,
- &rMergeDescriptor.aSaveToFilterData, bIsPDFexport,
- xWorkDocSh, *pWorkShell, &sFileURL ) )
+ if( bCreateSingleFile )
{
- m_aMergeStatus = MergeStatus::Error;
- }
+ assert( pTargetShell && "no target shell available!" );
- // back to the MM DB manager
- pWorkDoc->SetDBManager( this );
+ // prepare working copy and target to append
- if( bMT_EMAIL && !IsMergeError() )
- {
- // schedule file for later removal
- aFilesToRemove.push_back( sFileURL );
+ pWorkDoc->RemoveInvisibleContent();
+ // remove of invisible content has influence on page count and so on fields for page count,
+ // therefore layout has to be updated before fields are converted to text
+ pWorkShell->CalcLayout();
+ pWorkShell->ConvertFieldsToText();
+ pWorkShell->SetNumberingRestart();
+ if( bSynchronizedDoc )
+ {
+ lcl_RemoveSectionLinks( *pWorkShell );
+ }
+
+ if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
+ lcl_SaveDebugDoc( xWorkDocSh, "WorkDoc", nDocNo );
+
+ // append the working document to the target document
+ if( targetDocPageCount % 2 == 1 )
+ ++targetDocPageCount; // Docs always start on odd pages (so offset must be even).
+ SwNodeIndex appendedDocStart = pTargetDoc->AppendDoc( *pWorkDoc,
+ nStartingPageNo, !bWorkDocInitialized, targetDocPageCount, nDocNo);
+ targetDocPageCount += pWorkShell->GetPageCnt();
- if( !SwMailMergeHelper::CheckMailAddress( sColumnData ) )
+ if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
+ lcl_SaveDebugDoc( xTargetDocShell.get(), "MergeDoc" );
+
+ if (bMT_SHELL)
{
- OSL_FAIL("invalid e-Mail address in database column");
+ SwDocMergeInfo aMergeInfo;
+ // Name of the mark is actually irrelevant, UNO bookmarks have internals names.
+ aMergeInfo.startPageInTarget = pTargetDoc->getIDocumentMarkAccess()->makeMark(
+ appendedDocStart, "", IDocumentMarkAccess::MarkType::UNO_BOOKMARK,
+ ::sw::mark::InsertMode::New);
+ aMergeInfo.nDBRow = nStartRow;
+ rMergeDescriptor.pMailMergeConfigItem->AddMergedDocument( aMergeInfo );
}
- else
+ }
+ else
+ {
+ assert( bNeedsTempFiles );
+ assert( pWorkShell->IsExpFieldsLocked() );
+
+ // fields are locked, so it's fine to
+ // restore the old / empty DB manager for save
+ pWorkDoc->SetDBManager( pWorkDocOrigDBManager );
+
+ // save merged document
+ OUString sFileURL;
+ if( !lcl_SaveDoc( aTempFileURL.get(), pStoreToFilter, pStoreToFilterOptions,
+ &rMergeDescriptor.aSaveToFilterData, bIsPDFexport,
+ xWorkDocSh, *pWorkShell, &sFileURL ) )
{
- uno::Reference< mail::XMailMessage > xMessage = lcl_CreateMailFromDoc(
- rMergeDescriptor, sFileURL, sColumnData, sMailBodyMimeType,
- sMailEncoding, pStoreToFilter->GetMimeType() );
- if( xMessage.is() )
+ m_aMergeStatus = MergeStatus::Error;
+ }
+
+ // back to the MM DB manager
+ pWorkDoc->SetDBManager( this );
+
+ if( bMT_EMAIL && !IsMergeError() )
+ {
+ // schedule file for later removal
+ aFilesToRemove.push_back( sFileURL );
+
+ if( !SwMailMergeHelper::CheckMailAddress( sColumnData ) )
+ {
+ OSL_FAIL("invalid e-Mail address in database column");
+ }
+ else
{
- osl::MutexGuard aGuard( pImpl->m_aAllEmailSendMutex );
- pImpl->m_xLastMessage.set( xMessage );
- xMailDispatcher->enqueueMailMessage( xMessage );
- if( !xMailDispatcher->isStarted() )
- xMailDispatcher->start();
+ uno::Reference< mail::XMailMessage > xMessage = lcl_CreateMailFromDoc(
+ rMergeDescriptor, sFileURL, sColumnData, sMailBodyMimeType,
+ sMailEncoding, pStoreToFilter->GetMimeType() );
+ if( xMessage.is() )
+ {
+ osl::MutexGuard aGuard( pImpl->m_aAllEmailSendMutex );
+ pImpl->m_xLastMessage.set( xMessage );
+ xMailDispatcher->enqueueMailMessage( xMessage );
+ if( !xMailDispatcher->isStarted() )
+ xMailDispatcher->start();
+ }
}
}
}
+ if( bCreateSingleFile || bIsPDFexport )
+ {
+ pWorkDoc->SetDBManager( pWorkDocOrigDBManager );
+ xWorkDocSh->DoClose();
+ xWorkDocSh = nullptr;
+ }
}
- if( bCreateSingleFile || bIsPDFexport )
+
+ bWorkDocInitialized = true;
+ nDocNo++;
+ nEndRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
+
+ // Freeze the layouts of the target document after the first inserted
+ // sub-document, to get the correct PageDesc.
+ if(!bFreezedLayouts && bCreateSingleFile)
{
- pWorkDoc->SetDBManager( pWorkDocOrigDBManager );
- xWorkDocSh->DoClose();
- xWorkDocSh = nullptr;
+ for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() )
+ aLayout->FreezeLayout(true);
+ bFreezedLayouts = true;
}
- }
+ } while( IsMergeOk() &&
+ ((bSynchronizedDoc && (nStartRow != nEndRow)) ? IsValidMergeRecord() : ToNextMergeRecord()));
- bWorkDocInitialized = true;
- nDocNo++;
- nEndRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
-
- // Freeze the layouts of the target document after the first inserted
- // sub-document, to get the correct PageDesc.
- if(!bFreezedLayouts && bCreateSingleFile)
+ if ( xWorkDocSh.Is() && pWorkView->GetWrtShell().IsExpFieldsLocked() )
{
- for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() )
- aLayout->FreezeLayout(true);
- bFreezedLayouts = true;
+ // Unlock document fields after merge complete
+ pWorkView->GetWrtShell().UnlockExpFields();
}
- } while( IsMergeOk() &&
- ((bSynchronizedDoc && (nStartRow != nEndRow)) ? IsValidMergeRecord() : ToNextMergeRecord()));
- if ( xWorkDocSh.Is() && pWorkView->GetWrtShell().IsExpFieldsLocked() )
- {
- // Unlock document fields after merge complete
- pWorkView->GetWrtShell().UnlockExpFields();
- }
-
- if( !bCreateSingleFile )
- {
- if( bMT_PRINTER )
- Printer::FinishPrintJob( pWorkView->GetPrinterController());
- if( !bIsPDFexport )
+ if( !bCreateSingleFile )
{
- pWorkDoc->SetDBManager( pWorkDocOrigDBManager );
- xWorkDocSh->DoClose();
+ if( bMT_PRINTER )
+ Printer::FinishPrintJob( pWorkView->GetPrinterController());
+ if( !bIsPDFexport )
+ {
+ pWorkDoc->SetDBManager( pWorkDocOrigDBManager );
+ xWorkDocSh->DoClose();
+ }
}
- }
- else if( IsMergeOk() ) // && bCreateSingleFile
- {
- Application::Reschedule( true );
-
- // sw::DocumentLayoutManager::CopyLayoutFormat() did not generate
- // unique fly names, do it here once.
- pTargetDoc->SetInMailMerge(false);
- pTargetDoc->SetAllUniqueFlyNames();
-
- // Unfreeze target document layouts and correct all PageDescs.
- SAL_INFO( "sw.pageframe", "(MergeMailFiles pTargetShell->CalcLayout in" );
- pTargetShell->CalcLayout();
- SAL_INFO( "sw.pageframe", "MergeMailFiles pTargetShell->CalcLayout out)" );
- pTargetShell->GetViewOptions()->SetIdle( true );
- pTargetDoc->GetIDocumentUndoRedo().DoUndo( true );
- for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() )
+ else if( IsMergeOk() ) // && bCreateSingleFile
{
- aLayout->FreezeLayout(false);
- aLayout->AllCheckPageDescs();
- }
+ Application::Reschedule( true );
- Application::Reschedule( true );
+ // sw::DocumentLayoutManager::CopyLayoutFormat() did not generate
+ // unique fly names, do it here once.
+ pTargetDoc->SetInMailMerge(false);
+ pTargetDoc->SetAllUniqueFlyNames();
+
+ // Unfreeze target document layouts and correct all PageDescs.
+ SAL_INFO( "sw.pageframe", "(MergeMailFiles pTargetShell->CalcLayout in" );
+ pTargetShell->CalcLayout();
+ SAL_INFO( "sw.pageframe", "MergeMailFiles pTargetShell->CalcLayout out)" );
+ pTargetShell->GetViewOptions()->SetIdle( true );
+ pTargetDoc->GetIDocumentUndoRedo().DoUndo( true );
+ for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() )
+ {
+ aLayout->FreezeLayout(false);
+ aLayout->AllCheckPageDescs();
+ }
- if( IsMergeOk() && bMT_FILE )
- {
- // save merged document
- assert( aTempFile.get() );
- INetURLObject aTempFileURL;
- if (sDescriptorPrefix.isEmpty() || !rMergeDescriptor.bPrefixIsFilename)
- aTempFileURL.SetURL( aTempFile->GetURL() );
- else
+ Application::Reschedule( true );
+
+ if( IsMergeOk() && bMT_FILE )
{
- aTempFileURL.SetURL(sDescriptorPrefix);
- // remove the unneeded temporary file
- aTempFile->EnableKillingFile();
+ // save merged document
+ assert( aTempFile.get() );
+ INetURLObject aTempFileURL;
+ if (sDescriptorPrefix.isEmpty() || !rMergeDescriptor.bPrefixIsFilename)
+ aTempFileURL.SetURL( aTempFile->GetURL() );
+ else
+ {
+ aTempFileURL.SetURL(sDescriptorPrefix);
+ // remove the unneeded temporary file
+ aTempFile->EnableKillingFile();
+ }
+ if( !lcl_SaveDoc( &aTempFileURL, pStoreToFilter,
+ pStoreToFilterOptions, &rMergeDescriptor.aSaveToFilterData,
+ bIsPDFexport, xTargetDocShell.get(), *pTargetShell ) )
+ {
+ m_aMergeStatus = MergeStatus::Error;
+ }
}
- if( !lcl_SaveDoc( &aTempFileURL, pStoreToFilter,
- pStoreToFilterOptions, &rMergeDescriptor.aSaveToFilterData,
- bIsPDFexport, xTargetDocShell.get(), *pTargetShell ) )
+ else if( IsMergeOk() && bMT_PRINTER )
{
- m_aMergeStatus = MergeStatus::Error;
+ // print the target document
+ uno::Sequence< beans::PropertyValue > aOptions( rMergeDescriptor.aPrintOptions );
+ lcl_PreparePrinterOptions( rMergeDescriptor.aPrintOptions, aOptions );
+ pTargetView->ExecPrint( aOptions, bIsMergeSilent, false/*bPrintAsync*/ );
}
}
- else if( IsMergeOk() && bMT_PRINTER )
+
+ // we also show canceled documents, as long as there was no error
+ if( !IsMergeError() && bMT_SHELL )
+ // leave docshell available for caller (e.g. MM wizard)
+ rMergeDescriptor.pMailMergeConfigItem->SetTargetView( pTargetView );
+ else if( xTargetDocShell.is() )
+ xTargetDocShell->DoClose();
+
+ Application::Reschedule( true );
+
+ if (xProgressDlg)
{
- // print the target document
- uno::Sequence< beans::PropertyValue > aOptions( rMergeDescriptor.aPrintOptions );
- lcl_PreparePrinterOptions( rMergeDescriptor.aPrintOptions, aOptions );
- pTargetView->ExecPrint( aOptions, bIsMergeSilent, false/*bPrintAsync*/ );
+ xProgressDlg->response(RET_OK);
}
- }
- // we also show canceled documents, as long as there was no error
- if( !IsMergeError() && bMT_SHELL )
- // leave docshell available for caller (e.g. MM wizard)
- rMergeDescriptor.pMailMergeConfigItem->SetTargetView( pTargetView );
- else if( xTargetDocShell.is() )
- xTargetDocShell->DoClose();
+ // unlock all dispatchers
+ pViewFrame = SfxViewFrame::GetFirst(pSourceDocSh);
+ while (pViewFrame)
+ {
+ pViewFrame->GetDispatcher()->Lock(false);
+ pViewFrame = SfxViewFrame::GetNext(*pViewFrame, pSourceDocSh);
+ }
- Application::Reschedule( true );
+ SW_MOD()->SetView(&pSourceShell->GetView());
- if (xProgressDlg)
- {
- xProgressDlg->response(RET_OK);
- }
+ if( xMailDispatcher.is() )
+ {
+ if( IsMergeOk() )
+ {
+ // TODO: Instead of polling via an AutoTimer, post an Idle event,
+ // if the main loop has been made thread-safe.
+ AutoTimer aEmailDispatcherPollTimer;
+ aEmailDispatcherPollTimer.SetDebugName(
+ "sw::SwDBManager aEmailDispatcherPollTimer" );
+ aEmailDispatcherPollTimer.SetTimeout( 500 );
+ aEmailDispatcherPollTimer.Start();
+ while( IsMergeOk() && pImpl->m_xLastMessage.is() )
+ Application::Yield();
+ aEmailDispatcherPollTimer.Stop();
+ }
+ xMailDispatcher->stop();
+ xMailDispatcher->shutdown();
+ }
- // unlock all dispatchers
- pViewFrame = SfxViewFrame::GetFirst(pSourceDocSh);
- while (pViewFrame)
- {
- pViewFrame->GetDispatcher()->Lock(false);
- pViewFrame = SfxViewFrame::GetNext(*pViewFrame, pSourceDocSh);
+ // remove the temporary files
+ // has to be done after xMailDispatcher is finished, as mails may be
+ // delivered as message attachments!
+ for( const OUString &sFileURL : aFilesToRemove )
+ SWUnoHelper::UCB_DeleteFile( sFileURL );
}
-
- SW_MOD()->SetView(&pSourceShell->GetView());
-
- if( xMailDispatcher.is() )
+ catch (const uno::Exception&)
{
- if( IsMergeOk() )
+ if (xProgressDlg)
{
- // TODO: Instead of polling via an AutoTimer, post an Idle event,
- // if the main loop has been made thread-safe.
- AutoTimer aEmailDispatcherPollTimer;
- aEmailDispatcherPollTimer.SetDebugName(
- "sw::SwDBManager aEmailDispatcherPollTimer" );
- aEmailDispatcherPollTimer.SetTimeout( 500 );
- aEmailDispatcherPollTimer.Start();
- while( IsMergeOk() && pImpl->m_xLastMessage.is() )
- Application::Yield();
- aEmailDispatcherPollTimer.Stop();
+ xProgressDlg->response(RET_CANCEL);
}
- xMailDispatcher->stop();
- xMailDispatcher->shutdown();
}
- // remove the temporary files
- // has to be done after xMailDispatcher is finished, as mails may be
- // delivered as message attachments!
- for( const OUString &sFileURL : aFilesToRemove )
- SWUnoHelper::UCB_DeleteFile( sFileURL );
-
return !IsMergeError();
}
commit 68fde939500888a4feb094b9f31c3917e93f4d26
Author: Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Tue Jul 3 21:38:48 2018 +1000
Commit: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
CommitDate: Fri Oct 11 09:42:07 2019 +0200
Avoid failing assert in SwDBManager::MergeMailFiles
The failing assert reproducing scenario is the steps in
https://bugs.documentfoundation.org/show_bug.cgi?id=116543#c0
rMergeDescriptor.nMergeType == DBMGR_MERGE_PRINTER;
rMergeDescriptor.bPrefixIsFilename is true;
rMergeDescriptor.sPrefix is empty.
The failing assert is unrelated to the crash in tdf#116543.
It looks like the assertion was incorrect; assert on empty
prefix instead.
Change-Id: Ibeedb90a9fac810124283fc06aa756777fa04720
Reviewed-on: https://gerrit.libreoffice.org/56863
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
Reviewed-on: https://gerrit.libreoffice.org/80552
Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
Tested-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index bb3c5c97b7bb..de0a9ad8869d 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1200,19 +1200,22 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
const bool bIsMergeSilent = IsMergeSilent();
bool bCheckSingleFile_ = rMergeDescriptor.bCreateSingleFile;
+ OUString sPrefix_ = rMergeDescriptor.sPrefix;
if( bMT_EMAIL )
{
assert( !rMergeDescriptor.bPrefixIsFilename );
- assert( bMT_EMAIL && !bCheckSingleFile_ );
+ assert(!bCheckSingleFile_);
bCheckSingleFile_ = false;
}
else if( bMT_SHELL || bMT_PRINTER )
{
- assert( !rMergeDescriptor.bPrefixIsFilename );
- assert( (bMT_SHELL || bMT_PRINTER) && bCheckSingleFile_ );
+ assert(bCheckSingleFile_);
bCheckSingleFile_ = true;
+ assert(sPrefix_.isEmpty());
+ sPrefix_.clear();
}
const bool bCreateSingleFile = bCheckSingleFile_;
+ const OUString sDescriptorPrefix = sPrefix_;
// Setup for dumping debugging documents
static const char *sMaxDumpDocs = nullptr;
@@ -1435,7 +1438,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
// create a new temporary file name - only done once in case of bCreateSingleFile
if( bNeedsTempFiles && ( !bWorkDocInitialized || !bCreateSingleFile ))
{
- OUString sPrefix = rMergeDescriptor.sPrefix;
+ OUString sPrefix = sDescriptorPrefix;
OUString sLeading;
//#i97667# if the name is from a database field then it will be used _as is_
@@ -1690,11 +1693,11 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
// save merged document
assert( aTempFile.get() );
INetURLObject aTempFileURL;
- if( rMergeDescriptor.sPrefix.isEmpty() || !rMergeDescriptor.bPrefixIsFilename )
+ if (sDescriptorPrefix.isEmpty() || !rMergeDescriptor.bPrefixIsFilename)
aTempFileURL.SetURL( aTempFile->GetURL() );
else
{
- aTempFileURL.SetURL( rMergeDescriptor.sPrefix );
+ aTempFileURL.SetURL(sDescriptorPrefix);
// remove the unneeded temporary file
aTempFile->EnableKillingFile();
}
More information about the Libreoffice-commits
mailing list