summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzymon Kłos <eszkadev@gmail.com>2019-05-14 23:14:34 +0200
committerAndras Timar <andras.timar@collabora.com>2019-05-19 21:19:30 +0200
commit8e13c14a1221430cdbd79be5b5c27a1c781ffb1d (patch)
tree0961f5319c5c92f2213f25820f7cabeb707f83d7
parent2b9392b7969b59425ff81cd4a8837dd3b1f8f284 (diff)
tdf#117480 fix crash in mailmerge
Catch exceptions and hide progress dialog. b2d85f9207bc9bf7489d0a1fd9b35f062502639d Reviewed-on: https://gerrit.libreoffice.org/65815 Reviewed-by: Szymon Kłos <szymon.klos@collabora.com> Tested-by: Szymon Kłos <szymon.klos@collabora.com> Change-Id: Ie63c8d7e001c90f40cf7504fd8248a6742e9d244 Reviewed-on: https://gerrit.libreoffice.org/72398 Reviewed-by: Andras Timar <andras.timar@collabora.com> Tested-by: Andras Timar <andras.timar@collabora.com>
-rw-r--r--sw/source/uibase/dbui/dbmgr.cxx723
1 files changed, 365 insertions, 358 deletions
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 55e82e50e8f0..21e104e20be7 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1240,442 +1240,449 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
vcl::Window *pSourceWindow = nullptr;
VclPtr<CancelableDialog> pProgressDlg;
- if( !bIsMergeSilent )
- {
- // construct the process dialog
- pSourceWindow = &pSourceShell->GetView().GetEditWin();
- vcl::Window* pParent = pSourceWindow;
- if( !bMT_PRINTER )
- pProgressDlg = VclPtr<CreateMonitor>::Create(
- pParent, pParent != pSourceWindow );
- else {
- pProgressDlg = VclPtr<PrintMonitor>::Create(
- pParent, pParent != pSourceWindow,
- PrintMonitor::MONITOR_TYPE_PRINT );
- static_cast<PrintMonitor*>( pProgressDlg.get() )->SetText(
- pSourceDocSh->GetTitle(22) );
- }
- pProgressDlg->SetCancelHdl( LINK(this, SwDBManager, PrtCancelHdl) );
- pProgressDlg->Show();
-
- 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 );
- if (nMaxDumpDocs)
- lcl_SaveDebugDoc( xTargetDocShell.get(), "MergeDoc" );
- }
- else if( pTargetView )
+ try
{
- pTargetShell = pTargetView->GetWrtShellPtr();
- pTargetDoc = pTargetShell->GetDoc();
- xTargetDocShell = pTargetView->GetDocShell();
- }
+ if( !bIsMergeSilent )
+ {
+ // construct the process dialog
+ pSourceWindow = &pSourceShell->GetView().GetEditWin();
+ vcl::Window* pParent = pSourceWindow;
+ if( !bMT_PRINTER )
+ pProgressDlg = VclPtr<CreateMonitor>::Create(
+ pParent, pParent != pSourceWindow );
+ else {
+ pProgressDlg = VclPtr<PrintMonitor>::Create(
+ pParent, pParent != pSourceWindow,
+ PrintMonitor::MONITOR_TYPE_PRINT );
+ static_cast<PrintMonitor*>( pProgressDlg.get() )->SetText(
+ pSourceDocSh->GetTitle(22) );
+ }
+ pProgressDlg->SetCancelHdl( LINK(this, SwDBManager, PrtCancelHdl) );
+ pProgressDlg->Show();
- if( bCreateSingleFile )
- {
- // determine the page style and number used at the start of the source document
- pSourceShell->SttEndDoc(true);
- nStartingPageNo = pSourceShell->GetVirtPageNum();
- }
+ Application::Reschedule( true );
+ }
- // Progress, to prohibit KeyInputs
- SfxProgress aProgress(pSourceDocSh, ::aEmptyOUStr, 1);
+ 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 (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*>( pProgressDlg.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*>( pProgressDlg.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*>( pProgressDlg.get() )->SetCurrentPosition( nDocNo );
- else {
- PrintMonitor *pPrintMonDlg = static_cast<PrintMonitor*>( pProgressDlg.get() );
- pPrintMonDlg->m_pPrinter->SetText( bNeedsTempFiles
- ? aTempFileURL->GetBase() : pSourceDocSh->GetTitle( 22 ) );
- OUString sStat( SwResId(STR_STATSTR_LETTER) );
- sStat += " " + OUString::number( nDocNo );
- pPrintMonDlg->m_pPrintInfo->SetText( 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 = "_";
}
- pProgressDlg->Update();
- }
-
- 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*>( pProgressDlg.get() )->SetCurrentPosition( nDocNo );
+ else {
+ PrintMonitor *pPrintMonDlg = static_cast<PrintMonitor*>( pProgressDlg.get() );
+ pPrintMonDlg->m_pPrinter->SetText( bNeedsTempFiles
+ ? aTempFileURL->GetBase() : pSourceDocSh->GetTitle( 22 ) );
+ OUString sStat( SwResId(STR_STATSTR_LETTER) );
+ sStat += " " + OUString::number( nDocNo );
+ pPrintMonDlg->m_pPrintInfo->SetText( sStat );
+ }
+ pProgressDlg->Update();
+ }
- // 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);
- 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();
+ pWorkShell->ConvertFieldsToText();
+ pWorkShell->SetNumberingRestart();
+ if( bSynchronizedDoc )
+ {
+ lcl_RemoveSectionLinks( *pWorkShell );
+ }
- if( !SwMailMergeHelper::CheckMailAddress( sColumnData ) )
+ 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 ( (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 ) )
+ {
+ m_aMergeStatus = MergeStatus::ERROR;
+ }
+
+ // back to the MM DB manager
+ pWorkDoc->SetDBManager( this );
+
+ if( bMT_EMAIL && !IsMergeError() )
{
- uno::Reference< mail::XMailMessage > xMessage = lcl_CreateMailFromDoc(
- rMergeDescriptor, sFileURL, sColumnData, sMailBodyMimeType,
- sMailEncoding, pStoreToFilter->GetMimeType() );
- if( xMessage.is() )
+ // 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 )
- {
- // print the target document
- uno::Sequence< beans::PropertyValue > aOptions( rMergeDescriptor.aPrintOptions );
- lcl_PreparePrinterOptions( rMergeDescriptor.aPrintOptions, aOptions );
- pTargetView->ExecPrint( aOptions, bIsMergeSilent, false/*bPrintAsync*/ );
- }
- }
- // 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();
+ // 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 );
+ Application::Reschedule( true );
- pProgressDlg.disposeAndClear();
+ pProgressDlg.disposeAndClear();
- // unlock all dispatchers
- pViewFrame = SfxViewFrame::GetFirst(pSourceDocSh);
- while (pViewFrame)
- {
- pViewFrame->GetDispatcher()->Lock(false);
- pViewFrame = SfxViewFrame::GetNext(*pViewFrame, pSourceDocSh);
- }
+ // unlock all dispatchers
+ pViewFrame = SfxViewFrame::GetFirst(pSourceDocSh);
+ while (pViewFrame)
+ {
+ pViewFrame->GetDispatcher()->Lock(false);
+ pViewFrame = SfxViewFrame::GetNext(*pViewFrame, pSourceDocSh);
+ }
- SW_MOD()->SetView(&pSourceShell->GetView());
+ SW_MOD()->SetView(&pSourceShell->GetView());
- if( xMailDispatcher.is() )
- {
- if( IsMergeOk() )
+ if( xMailDispatcher.is() )
{
- // 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();
+ 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();
}
- 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 );
+ // 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 );
+ }
+ catch(const uno::Exception&)
+ {
+ m_aMergeStatus = MergeStatus::ERROR;
+ }
return !IsMergeError();
}