config_host/config_cups.h.in | 6 configure.ac | 3 include/sfx2/viewsh.hxx | 5 include/vcl/jobdata.hxx | 6 include/vcl/print.hxx | 9 + include/vcl/printerinfomanager.hxx | 10 + sfx2/source/view/viewprn.cxx | 15 ++ sw/source/uibase/dbui/dbmgr.cxx | 160 ++++++++++++++++++++----- sw/source/uibase/inc/view.hxx | 11 - sw/source/uibase/uno/unomailmerge.cxx | 2 vcl/inc/cupsmgr.hxx | 24 +++ vcl/source/gdi/print3.cxx | 73 ++++++----- vcl/unx/generic/printer/cupsmgr.cxx | 101 +++++++++++++-- vcl/unx/generic/printer/jobdata.cxx | 18 ++ vcl/unx/generic/printer/printerinfomanager.cxx | 15 ++ 15 files changed, 373 insertions(+), 85 deletions(-)
New commits: commit d5c93cccaebf92b7f99e174552a7c84a5c652690 Author: Miklos Vajna <[email protected]> Date: Wed Mar 11 16:03:25 2015 +0100 SwDBManager::MergeMailFiles: merge two bCreateSingleFile blocks Change-Id: Ia4290a8bfafc88c8e8e7601d62781c0da250824e diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index b01e2b2..85f7fa8 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -1141,9 +1141,6 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, rWorkShell.SwViewShell::UpdateFlds(); SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), xWorkDocSh)); - if( bCreateSingleFile ) - pWorkDoc->RemoveInvisibleContent(); - // launch MailMergeEvent if required const SwXMailMerge *pEvtSrc = GetMailMergeEvtSrc(); if(pEvtSrc) @@ -1155,6 +1152,8 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, if(bCreateSingleFile) { + pWorkDoc->RemoveInvisibleContent(); + OSL_ENSURE( pTargetShell, "no target shell available!" ); // copy created file into the target document rWorkShell.ConvertFieldsToText(); commit 138d29aa09417eba4d15ade4c9f4dab2620b6326 Author: LuboÅ¡ LuÅák <[email protected]> Date: Thu Feb 26 15:56:24 2015 +0100 support fast MM printing in non-single-file mode only for CUPS As said in the comment, the non-single-file mode could create way too many print jobs, so enable this only for the CUPS backend, which has been modified to send them as a single batch. Conflicts: configure.ac include/vcl/printerinfomanager.hxx sw/source/uibase/dbui/dbmgr.cxx vcl/inc/cupsmgr.hxx vcl/unx/generic/printer/cupsmgr.cxx vcl/unx/generic/printer/printerinfomanager.cxx Change-Id: I4c02ca0e8b91323b1d02f004c7b4813433064a11 diff --git a/config_host/config_cups.h.in b/config_host/config_cups.h.in new file mode 100644 index 0000000..6794703 --- /dev/null +++ b/config_host/config_cups.h.in @@ -0,0 +1,6 @@ +#ifndef CONFIG_CUPS_H +#define CONFIG_CUPS_H + +#define ENABLE_CUPS 0 + +#endif diff --git a/configure.ac b/configure.ac index 9131d9b..e8d4fe8 100644 --- a/configure.ac +++ b/configure.ac @@ -4633,7 +4633,7 @@ if test "$test_cups" = "yes"; then if test "$ac_cv_lib_cups_cupsPrintFiles" != "yes" -o "$ac_cv_header_cups_cups_h" != "yes"; then AC_MSG_ERROR([Could not find CUPS. Install libcups2-dev or cups-devel.]) fi - + AC_DEFINE(ENABLE_CUPS) else AC_MSG_RESULT([no]) fi @@ -12900,6 +12900,7 @@ AC_CONFIG_FILES([config_host.mk AC_CONFIG_HEADERS([config_host/config_buildid.h]) AC_CONFIG_HEADERS([config_host/config_clang.h]) AC_CONFIG_HEADERS([config_host/config_eot.h]) +AC_CONFIG_HEADERS([config_host/config_cups.h]) AC_CONFIG_HEADERS([config_host/config_features.h]) AC_CONFIG_HEADERS([config_host/config_folders.h]) AC_CONFIG_HEADERS([config_host/config_gcc.h]) diff --git a/include/vcl/jobdata.hxx b/include/vcl/jobdata.hxx index 8cffdd1..c173863 100644 --- a/include/vcl/jobdata.hxx +++ b/include/vcl/jobdata.hxx @@ -79,6 +79,12 @@ struct VCL_DLLPUBLIC JobData static bool constructFromStreamBuffer( void* pData, int bytes, JobData& rJobData ); }; +bool operator==(const psp::JobData& rLeft, const psp::JobData& rRight); +inline bool operator!=(const psp::JobData& rLeft, const psp::JobData& rRight) +{ + return !( rLeft == rRight ); +} + } // namespace diff --git a/include/vcl/printerinfomanager.hxx b/include/vcl/printerinfomanager.hxx index 97e68d1..ec5c587 100644 --- a/include/vcl/printerinfomanager.hxx +++ b/include/vcl/printerinfomanager.hxx @@ -196,6 +196,16 @@ public: // check whether a printer's feature string contains a subfeature bool checkFeatureToken( const OUString& rPrinterName, const char* pToken ) const; + // Starts printing in a batch mode, in which all printing will be done together instead of separate jobs. + // If the implementation supports it, calls to endSpool() will only delay the printing until flushBatchPrint() + // is called to print all delayed jobs. + // Returns false if failed or not supported (in which case endSpool() will print normally). + virtual bool startBatchPrint(); + // Actually spools all delayed print jobs, if enabled, and disables batch mode. + virtual bool flushBatchPrint(); + // Returns true batch printing is supported at all. + virtual bool supportsBatchPrint() const; + virtual ~PrinterInfoManager(); }; diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index af65b33..b01e2b2 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -135,6 +135,9 @@ #include <dbfld.hxx> #include <boost/scoped_ptr.hpp> +#include <config_cups.h> +#include <vcl/printerinfomanager.hxx> + using namespace ::osl; using namespace ::svx; @@ -820,6 +823,27 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, bool bNoError = true; const bool bEMail = rMergeDescriptor.nMergeType == DBMGR_MERGE_EMAIL; const bool bMergeShell = rMergeDescriptor.nMergeType == DBMGR_MERGE_SHELL; + bool bCreateSingleFile = rMergeDescriptor.bCreateSingleFile; + + if( rMergeDescriptor.nMergeType == DBMGR_MERGE_PRINTER ) + { + // It is possible to do MM printing in both modes for the same result, but the singlefile mode + // is slower because of all the temporary document copies and merging them together + // into the single file, while the other mode simply updates fields and prints for every record. + // However, this would cause one print job for every record, and e.g. CUPS refuses new jobs + // if it has many jobs enqueued (500 by default), and with the current printing framework + // (which uses a pull model) it's rather complicated to create a single print job + // in steps. + // To handle this, CUPS backend has been changed to cache all the documents to print + // and send them to CUPS only as one job at the very end. Therefore, with CUPS, it's ok + // to use the faster mode. As I have no idea about other platforms, keep them using + // the slower singlefile mode (or feel free to check them, or rewrite the printing code). +#if ENABLE_CUPS + bCreateSingleFile = !psp::PrinterInfoManager::get().supportsBatchPrint(); +#else + bCreateSingleFile = true; +#endif + } ::rtl::Reference< MailDispatcher > xMailDispatcher; OUString sBodyMimeType; @@ -937,7 +961,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, Application::Reschedule(); } - if(rMergeDescriptor.bCreateSingleFile) + if(bCreateSingleFile) { // create a target docshell to put the merged document into xTargetDocShell = new SwDocShell( SFX_CREATE_MODE_STANDARD ); @@ -1036,7 +1060,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, } // create a new temporary file name - only done once in case of bCreateSingleFile - if( createTempFile && ( 1 == nDocNo || !rMergeDescriptor.bCreateSingleFile )) + if( createTempFile && ( 1 == nDocNo || !bCreateSingleFile )) { INetURLObject aEntry(sPath); OUString sLeading; @@ -1086,7 +1110,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, // 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. - if( 1 == nDocNo || rMergeDescriptor.bCreateSingleFile ) + if( 1 == nDocNo || bCreateSingleFile ) { assert( !xWorkDocSh.Is()); // copy the source document @@ -1117,7 +1141,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, rWorkShell.SwViewShell::UpdateFlds(); SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), xWorkDocSh)); - if( rMergeDescriptor.bCreateSingleFile ) + if( bCreateSingleFile ) pWorkDoc->RemoveInvisibleContent(); // launch MailMergeEvent if required @@ -1129,7 +1153,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, pEvtSrc->LaunchMailMergeEvent( aEvt ); } - if(rMergeDescriptor.bCreateSingleFile) + if(bCreateSingleFile) { OSL_ENSURE( pTargetShell, "no target shell available!" ); // copy created file into the target document @@ -1162,6 +1186,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, } else if( rMergeDescriptor.nMergeType == DBMGR_MERGE_PRINTER ) { + assert(!bCreateSingleFile); if( 1 == nDocNo ) // set up printing only once at the beginning { // printing should be done synchronously otherwise the document @@ -1191,6 +1216,9 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, SfxPrinter* pDocPrt = pWorkView->GetPrinter(false); JobSetup aJobSetup = pDocPrt ? pDocPrt->GetJobSetup() : pWorkView->GetJobSetup(); Printer::PreparePrintJob( pWorkView->GetPrinterController(), aJobSetup ); +#if ENABLE_CUPS + psp::PrinterInfoManager::get().startBatchPrint(); +#endif } if( !Printer::ExecutePrintJob( pWorkView->GetPrinterController())) bCancel = true; @@ -1324,7 +1352,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, } } } - if( rMergeDescriptor.bCreateSingleFile ) + if( bCreateSingleFile ) { pWorkDoc->SetDBManager( pOldDBManager ); xWorkDocSh->DoClose(); @@ -1337,7 +1365,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, // Freeze the layouts of the target document after the first inserted // sub-document, to get the correct PageDesc. - if(!bFreezedLayouts && (rMergeDescriptor.bCreateSingleFile)) + if(!bFreezedLayouts && bCreateSingleFile) { std::set<SwRootFrm*> aAllLayouts = pTargetShell->GetDoc()->GetAllLayouts(); std::for_each( aAllLayouts.begin(), aAllLayouts.end(), @@ -1347,15 +1375,20 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, } while( !bCancel && (bSynchronizedDoc && (nStartRow != nEndRow)? ExistsNextRecord() : ToNextMergeRecord())); - if( !rMergeDescriptor.bCreateSingleFile ) + if( !bCreateSingleFile ) { if( rMergeDescriptor.nMergeType == DBMGR_MERGE_PRINTER ) + { Printer::FinishPrintJob( pWorkView->GetPrinterController()); +#if ENABLE_CUPS + psp::PrinterInfoManager::get().flushBatchPrint(); +#endif + } pWorkDoc->SetDBManager( pOldDBManager ); xWorkDocSh->DoClose(); } - if (rMergeDescriptor.bCreateSingleFile) + if (bCreateSingleFile) { // sw::DocumentLayoutManager::CopyLayoutFmt() did not generate // unique fly names, do it here once. @@ -1367,7 +1400,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, Application::Reschedule(); // Unfreeze target document layouts and correct all PageDescs. - if(rMergeDescriptor.bCreateSingleFile) + if(bCreateSingleFile) { pTargetShell->CalcLayout(); std::set<SwRootFrm*> aAllLayouts = pTargetShell->GetDoc()->GetAllLayouts(); @@ -1383,7 +1416,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, { rMergeDescriptor.pMailMergeConfigItem->SetTargetView( pTargetView ); } - else if(rMergeDescriptor.bCreateSingleFile) + else if(bCreateSingleFile) { if( rMergeDescriptor.nMergeType != DBMGR_MERGE_PRINTER ) { diff --git a/vcl/inc/cupsmgr.hxx b/vcl/inc/cupsmgr.hxx index c7b9487..4db4c1d 100644 --- a/vcl/inc/cupsmgr.hxx +++ b/vcl/inc/cupsmgr.hxx @@ -58,6 +58,23 @@ class CUPSManager : public PrinterInfoManager osl::Mutex m_aGetPPDMutex; bool m_bPPDThreadRunning; + struct PendingJob + { + OUString printerName; + OUString jobTitle; + JobData jobData; + bool banner; + OUString faxNumber; + OString file; + PendingJob( const OUString& printerName_, const OUString& jobTitle_, const JobData& jobData_, + bool banner_, const OUString& faxNumber_, const OString& file_ ) + : printerName( printerName_ ), jobTitle( jobTitle_ ), jobData( jobData_ ), banner( banner_ ), faxNumber( faxNumber_ ), file( file_ ) + {} + PendingJob() : banner( false ) {} + }; + std::list< PendingJob > pendingJobs; + bool batchMode; + CUPSManager(); virtual ~CUPSManager(); @@ -66,6 +83,9 @@ class CUPSManager : public PrinterInfoManager void getOptionsFromDocumentSetup( const JobData& rJob, bool bBanner, int& rNumOptions, void** rOptions ) const; void runDests(); OString threadedCupsGetPPD(const char* pPrinter); + + bool processPendingJobs(); + bool printJobs( const PendingJob& job, const std::vector< OString >& files ); public: static void runDestThread(void* pMgr); @@ -80,6 +100,10 @@ public: virtual bool endSpool( const OUString& rPrinterName, const OUString& rJobTitle, FILE* pFile, const JobData& rDocumentJobData, bool bBanner, const OUString& rFaxNumber ) SAL_OVERRIDE; virtual void setupJobContextData( JobData& rData ) SAL_OVERRIDE; + virtual bool startBatchPrint() SAL_OVERRIDE; + virtual bool flushBatchPrint() SAL_OVERRIDE; + virtual bool supportsBatchPrint() const SAL_OVERRIDE; + /// changes the info about a named printer virtual void changePrinterInfo( const OUString& rPrinter, const PrinterInfo& rNewInfo ) SAL_OVERRIDE; diff --git a/vcl/unx/generic/printer/cupsmgr.cxx b/vcl/unx/generic/printer/cupsmgr.cxx index 2dc978a..3ea62b0 100644 --- a/vcl/unx/generic/printer/cupsmgr.cxx +++ b/vcl/unx/generic/printer/cupsmgr.cxx @@ -626,8 +626,6 @@ bool CUPSManager::endSpool( const OUString& rPrintername, const OUString& rJobTi rDocumentJobData.m_nCopies ); - int nJobID = 0; - osl::MutexGuard aGuard( m_aCUPSMutex ); std::unordered_map< OUString, int, OUStringHash >::iterator dest_it = @@ -639,32 +637,105 @@ bool CUPSManager::endSpool( const OUString& rPrintername, const OUString& rJobTi } std::unordered_map< FILE*, OString, FPtrHash >::const_iterator it = m_aSpoolFiles.find( pFile ); - if( it != m_aSpoolFiles.end() ) + if( it == m_aSpoolFiles.end() ) + return false; + fclose( pFile ); + PendingJob job( rPrintername, rJobTitle, rDocumentJobData, bBanner, rFaxNumber, it->second ); + m_aSpoolFiles.erase( pFile ); + pendingJobs.push_back( job ); + if( !batchMode ) // process immediately, otherwise will be handled by flushBatchPrint() + return processPendingJobs(); + return true; +} + +bool CUPSManager::startBatchPrint() +{ + batchMode = true; + return true; +} + +bool CUPSManager::supportsBatchPrint() const +{ + return true; +} + +bool CUPSManager::flushBatchPrint() +{ + osl::MutexGuard aGuard( m_aCUPSMutex ); + return processPendingJobs(); +} + +bool CUPSManager::processPendingJobs() +{ + // Print all jobs that have the same data using one CUPS call (i.e. merge all jobs that differ only in files to print). + PendingJob currentJobData; + bool first = true; + std::vector< OString > files; + bool ok = true; + while( !pendingJobs.empty()) + { + if( first ) + { + currentJobData = pendingJobs.front(); + first = false; + } + else if( currentJobData.printerName != pendingJobs.front().printerName + || currentJobData.jobTitle != pendingJobs.front().jobTitle + || currentJobData.jobData != pendingJobs.front().jobData + || currentJobData.banner != pendingJobs.front().banner ) + { + if( !printJobs( currentJobData, files )) + ok = false; + files.clear(); + currentJobData = pendingJobs.front(); + } + files.push_back( pendingJobs.front().file ); + pendingJobs.pop_front(); + } + if( !first ) { - fclose( pFile ); + if( !printJobs( currentJobData, files )) // print the last batch + ok = false; + } + return ok; +} + +bool CUPSManager::printJobs( const PendingJob& job, const std::vector< OString >& files ) +{ + std::unordered_map< OUString, int, OUStringHash >::iterator dest_it = + m_aCUPSDestMap.find( job.printerName ); + rtl_TextEncoding aEnc = osl_getThreadTextEncoding(); // setup cups options int nNumOptions = 0; cups_option_t* pOptions = NULL; - getOptionsFromDocumentSetup( rDocumentJobData, bBanner, nNumOptions, reinterpret_cast<void**>(&pOptions) ); + getOptionsFromDocumentSetup( job.jobData, job.banner, nNumOptions, reinterpret_cast<void**>(&pOptions) ); - OString sJobName(OUStringToOString(rJobTitle, aEnc)); + OString sJobName(OUStringToOString(job.jobTitle, aEnc)); //fax4CUPS, "the job name will be dialled for you" //so override the jobname with the desired number - if (!rFaxNumber.isEmpty()) + if (!job.faxNumber.isEmpty()) { - sJobName = OUStringToOString(rFaxNumber, aEnc); + sJobName = OUStringToOString(job.faxNumber, aEnc); } cups_dest_t* pDest = ((cups_dest_t*)m_pDests) + dest_it->second; - nJobID = cupsPrintFile(pDest->name, - it->second.getStr(), + + std::vector< const char* > fnames; + for( std::vector< OString >::const_iterator it = files.begin(); + it != files.end(); + ++it ) + fnames.push_back( it->getStr()); + + int nJobID = cupsPrintFiles(pDest->name, + fnames.size(), + fnames.data(), sJobName.getStr(), nNumOptions, pOptions); SAL_INFO("vcl.unx.print", "cupsPrintFile( " << pDest->name << ", " - << it->second << ", " << rJobTitle << ", " << nNumOptions + << ( fnames.size() == 1 ? files.front() : OString::number( fnames.size()) ).getStr() << ", " << sJobName << ", " << nNumOptions << ", " << pOptions << " ) returns " << nJobID); for( int n = 0; n < nNumOptions; n++ ) SAL_INFO("vcl.unx.print", @@ -676,11 +747,13 @@ bool CUPSManager::endSpool( const OUString& rPrintername, const OUString& rJobTi system( aCmd.getStr() ); #endif - unlink( it->second.getStr() ); - m_aSpoolFiles.erase( pFile ); + for( std::vector< OString >::const_iterator it = files.begin(); + it != files.end(); + ++it ) + unlink( it->getStr()); + if( pOptions ) cupsFreeOptions( nNumOptions, pOptions ); - } return nJobID != 0; } diff --git a/vcl/unx/generic/printer/jobdata.cxx b/vcl/unx/generic/printer/jobdata.cxx index ae76040..dacf2e2 100644 --- a/vcl/unx/generic/printer/jobdata.cxx +++ b/vcl/unx/generic/printer/jobdata.cxx @@ -53,6 +53,24 @@ JobData& JobData::operator=(const JobData& rRight) return *this; } +bool psp::operator==(const psp::JobData& rLeft, const psp::JobData& rRight) +{ + return rLeft.m_nCopies == rRight.m_nCopies +// && rLeft.m_bCollate == rRight.m_bCollate + && rLeft.m_nLeftMarginAdjust == rRight.m_nLeftMarginAdjust + && rLeft.m_nRightMarginAdjust == rRight.m_nRightMarginAdjust + && rLeft.m_nTopMarginAdjust == rRight.m_nTopMarginAdjust + && rLeft.m_nBottomMarginAdjust == rRight.m_nBottomMarginAdjust + && rLeft.m_nColorDepth == rRight.m_nColorDepth + && rLeft.m_eOrientation == rRight.m_eOrientation + && rLeft.m_aPrinterName == rRight.m_aPrinterName + && rLeft.m_pParser == rRight.m_pParser +// && rLeft.m_aContext == rRight.m_aContext + && rLeft.m_nPSLevel == rRight.m_nPSLevel + && rLeft.m_nPDFDevice == rRight.m_nPDFDevice + && rLeft.m_nColorDevice == rRight.m_nColorDevice; +} + void JobData::setCollate( bool bCollate ) { if (m_nPDFDevice > 0) diff --git a/vcl/unx/generic/printer/printerinfomanager.cxx b/vcl/unx/generic/printer/printerinfomanager.cxx index 2690c88..0c9ed63 100644 --- a/vcl/unx/generic/printer/printerinfomanager.cxx +++ b/vcl/unx/generic/printer/printerinfomanager.cxx @@ -933,6 +933,21 @@ void PrinterInfoManager::setDefaultPaper( PPDContext& rContext ) const } } +bool PrinterInfoManager::startBatchPrint() +{ + return false; // not implemented +} + +bool PrinterInfoManager::supportsBatchPrint() const +{ + return false; +} + +bool PrinterInfoManager::flushBatchPrint() +{ + return false; +} + SystemQueueInfo::SystemQueueInfo() : m_bChanged( false ) { commit e0ad036eed6b151ea81311fcf9ba46f1726b103c Author: LuboÅ¡ LuÅák <[email protected]> Date: Thu Feb 19 16:39:06 2015 +0100 mailmerge doesn't need to use the singlefile technique for printing It should be sufficient for every record to just update the fields and print the document. The printing code apparently rather expects to do the printing in one go, so split the functions up there. Conflicts: include/sfx2/viewsh.hxx include/vcl/print.hxx sfx2/source/view/viewprn.cxx sw/source/uibase/dbui/dbmgr.cxx sw/source/uibase/uno/unomailmerge.cxx vcl/source/gdi/print3.cxx Change-Id: I4d17c703b3220f47609fc4b054ce048b299a0c92 diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx index 31e2d68..42cea72 100644 --- a/include/sfx2/viewsh.hxx +++ b/include/sfx2/viewsh.hxx @@ -35,6 +35,7 @@ #include <tools/gen.hxx> #include <tools/errcode.hxx> #include <vcl/jobset.hxx> +#include <boost/shared_ptr.hpp> class SfxBaseController; class Size; @@ -59,6 +60,7 @@ class Dialog; class Menu; class NotifyEvent; class SfxInPlaceClient; +namespace vcl { class PrinterController; } #define SFX_PRINTER_PRINTER 1 // without JOB SETUP => Temporary #define SFX_PRINTER_JOBSETUP 2 @@ -266,6 +268,9 @@ public: bool TryContextMenuInterception( Menu& rIn, const OUString& rMenuIdentifier, Menu*& rpOut, ::com::sun::star::ui::ContextMenuExecuteEvent aEvent ); void ExecPrint( const com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue >&, bool, bool ); + // Like ExecPrint(), but only sets up for printing. Use Printer::ExecutePrintJob() and Printer::FinishPrintJob() afterwards. + void StartPrint( const com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue >&, bool, bool ); + std::shared_ptr< vcl::PrinterController > GetPrinterController() const; void AddRemoveClipboardListener( const com::sun::star::uno::Reference < com::sun::star::datatransfer::clipboard::XClipboardListener>&, bool ); ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardNotifier > GetClipboardNotifier(); diff --git a/include/vcl/print.hxx b/include/vcl/print.hxx index b0dd3f0..d749769 100644 --- a/include/vcl/print.hxx +++ b/include/vcl/print.hxx @@ -405,9 +405,16 @@ public: const Image&, sal_uInt16 ) SAL_OVERRIDE; + // These 3 together are more modular PrintJob(), allowing printing more documents as one print job + // by repeated calls to ExecutePrintJob(). Used by mailmerge. + static void PreparePrintJob( std::shared_ptr<vcl::PrinterController> i_pController, + const JobSetup& i_rInitSetup ); + static bool ExecutePrintJob( std::shared_ptr<vcl::PrinterController> i_pController ); + static void FinishPrintJob( std::shared_ptr<vcl::PrinterController> i_pController ); + // implementation detail of PrintJob being asynchronous // not exported, not usable outside vcl - static void SAL_DLLPRIVATE ImplPrintJob( const std::shared_ptr<vcl::PrinterController>& i_pController, + static void SAL_DLLPRIVATE ImplPrintJob( std::shared_ptr<vcl::PrinterController> i_pController, const JobSetup& i_rInitSetup ); }; diff --git a/sfx2/source/view/viewprn.cxx b/sfx2/source/view/viewprn.cxx index 0ed526d..2104532 100644 --- a/sfx2/source/view/viewprn.cxx +++ b/sfx2/source/view/viewprn.cxx @@ -567,8 +567,10 @@ SfxPrinter* SfxViewShell::SetPrinter_Impl( SfxPrinter *pNewPrinter ) return pDocPrinter; } -void SfxViewShell::ExecPrint( const uno::Sequence < beans::PropertyValue >& rProps, bool bIsAPI, bool bIsDirect ) +void SfxViewShell::StartPrint( const uno::Sequence < beans::PropertyValue >& rProps, bool bIsAPI, bool bIsDirect ) { + assert( pImp->m_xPrinterController.get() == NULL ); + // get the current selection; our controller should know it Reference< frame::XController > xController( GetController() ); Reference< view::XSelectionSupplier > xSupplier( xController, UNO_QUERY ); @@ -610,11 +612,20 @@ void SfxViewShell::ExecPrint( const uno::Sequence < beans::PropertyValue >& rPro SfxObjectShell *pObjShell = GetObjectShell(); xNewController->setValue( OUString( "JobName" ), makeAny( OUString( pObjShell->GetTitle(0) ) ) ); +} +void SfxViewShell::ExecPrint( const uno::Sequence < beans::PropertyValue >& rProps, bool bIsAPI, bool bIsDirect ) +{ + StartPrint( rProps, bIsAPI, bIsDirect ); // FIXME: job setup SfxPrinter* pDocPrt = GetPrinter(false); JobSetup aJobSetup = pDocPrt ? pDocPrt->GetJobSetup() : GetJobSetup(); - Printer::PrintJob( xNewController, aJobSetup ); + Printer::PrintJob( GetPrinterController(), aJobSetup ); +} + +std::shared_ptr< vcl::PrinterController > SfxViewShell::GetPrinterController() const +{ + return pImp->m_xPrinterController; } Printer* SfxViewShell::GetActivePrinter() const diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index d93e85c..af65b33 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -23,6 +23,7 @@ #include <unotxdoc.hxx> #include <com/sun/star/text/NotePrintMode.hpp> #include <sfx2/app.hxx> +#include <sfx2/printer.hxx> #include <com/sun/star/sdb/CommandType.hpp> #include <com/sun/star/sdb/XDocumentDataSource.hpp> #include <com/sun/star/frame/XComponentLoader.hpp> @@ -1159,6 +1160,41 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, lcl_CopyFollowPageDesc( *pTargetShell, *pWorkPageDesc, *pTargetPageDesc, nDocNo ); } } + else if( rMergeDescriptor.nMergeType == DBMGR_MERGE_PRINTER ) + { + if( 1 == nDocNo ) // set up printing only once at the beginning + { + // printing should be done synchronously otherwise the document + // might already become invalid during the process + uno::Sequence< beans::PropertyValue > aOptions( rMergeDescriptor.aPrintOptions ); + + aOptions.realloc( 2 ); + aOptions[ 0 ].Name = "Wait"; + aOptions[ 0 ].Value <<= sal_True; + aOptions[ 1 ].Name = "MonitorVisible"; + aOptions[ 1 ].Value <<= sal_False; + // move print options + const beans::PropertyValue* pPrintOptions = rMergeDescriptor.aPrintOptions.getConstArray(); + for( sal_Int32 nOption = 0, nIndex = 1 ; nOption < rMergeDescriptor.aPrintOptions.getLength(); ++nOption) + { + if( pPrintOptions[nOption].Name == "CopyCount" || pPrintOptions[nOption].Name == "FileName" + || pPrintOptions[nOption].Name == "Collate" || pPrintOptions[nOption].Name == "Pages" + || pPrintOptions[nOption].Name == "Wait" || pPrintOptions[nOption].Name == "PrinterName" ) + { + // add an option + aOptions.realloc( nIndex + 1 ); + aOptions[ nIndex ].Name = pPrintOptions[nOption].Name; + aOptions[ nIndex++ ].Value = pPrintOptions[nOption].Value ; + } + } + pWorkView->StartPrint( aOptions, IsMergeSilent(), rMergeDescriptor.bPrintAsync ); + SfxPrinter* pDocPrt = pWorkView->GetPrinter(false); + JobSetup aJobSetup = pDocPrt ? pDocPrt->GetJobSetup() : pWorkView->GetJobSetup(); + Printer::PreparePrintJob( pWorkView->GetPrinterController(), aJobSetup ); + } + if( !Printer::ExecutePrintJob( pWorkView->GetPrinterController())) + bCancel = true; + } else pTargetPageDesc = pTargetShell->FindPageDescByName( sModifiedStartingPageDesc ); @@ -1313,6 +1349,8 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, if( !rMergeDescriptor.bCreateSingleFile ) { + if( rMergeDescriptor.nMergeType == DBMGR_MERGE_PRINTER ) + Printer::FinishPrintJob( pWorkView->GetPrinterController()); pWorkDoc->SetDBManager( pOldDBManager ); xWorkDocSh->DoClose(); } @@ -2665,7 +2703,7 @@ void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh, SwMergeDescriptor aMergeDesc( pImpl->pMergeDialog->GetMergeType(), pView->GetWrtShell(), aDescriptor ); aMergeDesc.sSaveToFilter = pImpl->pMergeDialog->GetSaveFilter(); - aMergeDesc.bCreateSingleFile = pImpl->pMergeDialog->IsSaveSingleDoc(); + aMergeDesc.bCreateSingleFile = pImpl->pMergeDialog->IsSaveSingleDoc() && pImpl->pMergeDialog->GetMergeType() != DBMGR_MERGE_PRINTER; aMergeDesc.bSubjectIsFilename = aMergeDesc.bCreateSingleFile; if( !aMergeDesc.bCreateSingleFile && pImpl->pMergeDialog->IsGenerateFromDataBase() ) { diff --git a/sw/source/uibase/uno/unomailmerge.cxx b/sw/source/uibase/uno/unomailmerge.cxx index 30adba6..216a6c6 100644 --- a/sw/source/uibase/uno/unomailmerge.cxx +++ b/sw/source/uibase/uno/unomailmerge.cxx @@ -691,7 +691,7 @@ uno::Any SAL_CALL SwXMailMerge::execute( // when mail merge is called as command line macro aMergeDesc.bPrintAsync = false; aMergeDesc.aPrintOptions = aPrintSettings; - aMergeDesc.bCreateSingleFile = true; + aMergeDesc.bCreateSingleFile = false; } break; case MailMergeType::SHELL: diff --git a/vcl/source/gdi/print3.cxx b/vcl/source/gdi/print3.cxx index bfabad1..3bd9f05 100644 --- a/vcl/source/gdi/print3.cxx +++ b/vcl/source/gdi/print3.cxx @@ -297,11 +297,9 @@ void Printer::PrintJob(const std::shared_ptr<PrinterController>& i_xController, } } -void Printer::ImplPrintJob(const std::shared_ptr<PrinterController>& i_xController, +void Printer::PreparePrintJob(std::shared_ptr<PrinterController> xController, const JobSetup& i_rInitSetup) { - std::shared_ptr<PrinterController> xController(i_xController); - // check if there is a default printer; if not, show an error box (if appropriate) if( GetDefaultPrinterName().isEmpty() ) { @@ -328,7 +326,7 @@ void Printer::ImplPrintJob(const std::shared_ptr<PrinterController>& i_xControll } // reset last page property - i_xController->setLastPage(false); + xController->setLastPage(false); // update "PageRange" property inferring from other properties: // case 1: "Pages" set from UNO API -> @@ -340,12 +338,12 @@ void Printer::ImplPrintJob(const std::shared_ptr<PrinterController>& i_xControll // "Pages" attribute from API is now equivalent to "PageRange" // AND "PrintContent" = 1 except calc where it is "PrintRange" = 1 // Argh ! That sure needs cleaning up - PropertyValue* pContentVal = i_xController->getValue(OUString("PrintRange")); + PropertyValue* pContentVal = xController->getValue(OUString("PrintRange")); if( ! pContentVal ) - pContentVal = i_xController->getValue(OUString("PrintContent")); + pContentVal = xController->getValue(OUString("PrintContent")); // case 1: UNO API has set "Pages" - PropertyValue* pPagesVal = i_xController->getValue(OUString("Pages")); + PropertyValue* pPagesVal = xController->getValue(OUString("Pages")); if( pPagesVal ) { OUString aPagesVal; @@ -358,7 +356,7 @@ void Printer::ImplPrintJob(const std::shared_ptr<PrinterController>& i_xControll if( pContentVal ) { pContentVal->Value = makeAny( sal_Int32( 1 ) ); - i_xController->setValue(OUString("PageRange"), pPagesVal->Value); + xController->setValue(OUString("PageRange"), pPagesVal->Value); } } } @@ -371,13 +369,13 @@ void Printer::ImplPrintJob(const std::shared_ptr<PrinterController>& i_xControll if( nContent == 0 ) { // do not overwrite PageRange if it is already set - PropertyValue* pRangeVal = i_xController->getValue(OUString("PageRange")); + PropertyValue* pRangeVal = xController->getValue(OUString("PageRange")); OUString aRange; if( pRangeVal ) pRangeVal->Value >>= aRange; if( aRange.isEmpty() ) { - sal_Int32 nPages = i_xController->getPageCount(); + sal_Int32 nPages = xController->getPageCount(); if( nPages > 0 ) { OUStringBuffer aBuf( 32 ); @@ -387,14 +385,14 @@ void Printer::ImplPrintJob(const std::shared_ptr<PrinterController>& i_xControll aBuf.appendAscii( "-" ); aBuf.append( nPages ); } - i_xController->setValue(OUString("PageRange"), makeAny(aBuf.makeStringAndClear())); + xController->setValue(OUString("PageRange"), makeAny(aBuf.makeStringAndClear())); } } } } } - PropertyValue* pReverseVal = i_xController->getValue(OUString("PrintReverse")); + PropertyValue* pReverseVal = xController->getValue(OUString("PrintReverse")); if( pReverseVal ) { bool bReverse = false; @@ -402,7 +400,7 @@ void Printer::ImplPrintJob(const std::shared_ptr<PrinterController>& i_xControll xController->setReversePrint( bReverse ); } - PropertyValue* pPapersizeFromSetupVal = i_xController->getValue(OUString("PapersizeFromSetup")); + PropertyValue* pPapersizeFromSetupVal = xController->getValue(OUString("PapersizeFromSetup")); if( pPapersizeFromSetupVal ) { bool bPapersizeFromSetup = false; @@ -411,35 +409,35 @@ void Printer::ImplPrintJob(const std::shared_ptr<PrinterController>& i_xControll } // setup NUp printing from properties - sal_Int32 nRows = i_xController->getIntProperty(OUString("NUpRows"), 1); - sal_Int32 nCols = i_xController->getIntProperty(OUString("NUpColumns"), 1); + sal_Int32 nRows = xController->getIntProperty(OUString("NUpRows"), 1); + sal_Int32 nCols = xController->getIntProperty(OUString("NUpColumns"), 1); if( nRows > 1 || nCols > 1 ) { PrinterController::MultiPageSetup aMPS; aMPS.nRows = nRows > 1 ? nRows : 1; aMPS.nColumns = nCols > 1 ? nCols : 1; - sal_Int32 nValue = i_xController->getIntProperty(OUString("NUpPageMarginLeft"), aMPS.nLeftMargin); + sal_Int32 nValue = xController->getIntProperty(OUString("NUpPageMarginLeft"), aMPS.nLeftMargin); if( nValue >= 0 ) aMPS.nLeftMargin = nValue; - nValue = i_xController->getIntProperty(OUString("NUpPageMarginRight"), aMPS.nRightMargin); + nValue = xController->getIntProperty(OUString("NUpPageMarginRight"), aMPS.nRightMargin); if( nValue >= 0 ) aMPS.nRightMargin = nValue; - nValue = i_xController->getIntProperty( OUString( "NUpPageMarginTop" ), aMPS.nTopMargin ); + nValue = xController->getIntProperty( OUString( "NUpPageMarginTop" ), aMPS.nTopMargin ); if( nValue >= 0 ) aMPS.nTopMargin = nValue; - nValue = i_xController->getIntProperty( OUString( "NUpPageMarginBottom" ), aMPS.nBottomMargin ); + nValue = xController->getIntProperty( OUString( "NUpPageMarginBottom" ), aMPS.nBottomMargin ); if( nValue >= 0 ) aMPS.nBottomMargin = nValue; - nValue = i_xController->getIntProperty( OUString( "NUpHorizontalSpacing" ), aMPS.nHorizontalSpacing ); + nValue = xController->getIntProperty( OUString( "NUpHorizontalSpacing" ), aMPS.nHorizontalSpacing ); if( nValue >= 0 ) aMPS.nHorizontalSpacing = nValue; - nValue = i_xController->getIntProperty( OUString( "NUpVerticalSpacing" ), aMPS.nVerticalSpacing ); + nValue = xController->getIntProperty( OUString( "NUpVerticalSpacing" ), aMPS.nVerticalSpacing ); if( nValue >= 0 ) aMPS.nVerticalSpacing = nValue; - aMPS.bDrawBorder = i_xController->getBoolProperty( OUString( "NUpDrawBorder" ), aMPS.bDrawBorder ); - aMPS.nOrder = static_cast<PrinterController::NupOrderType>(i_xController->getIntProperty( OUString( "NUpSubPageOrder" ), aMPS.nOrder )); - aMPS.aPaperSize = i_xController->getPrinter()->PixelToLogic( i_xController->getPrinter()->GetPaperSizePixel(), MapMode( MAP_100TH_MM ) ); - PropertyValue* pPgSizeVal = i_xController->getValue( OUString( "NUpPaperSize" ) ); + aMPS.bDrawBorder = xController->getBoolProperty( OUString( "NUpDrawBorder" ), aMPS.bDrawBorder ); + aMPS.nOrder = static_cast<PrinterController::NupOrderType>(xController->getIntProperty( OUString( "NUpSubPageOrder" ), aMPS.nOrder )); + aMPS.aPaperSize = xController->getPrinter()->PixelToLogic( xController->getPrinter()->GetPaperSizePixel(), MapMode( MAP_100TH_MM ) ); + PropertyValue* pPgSizeVal = xController->getValue( OUString( "NUpPaperSize" ) ); awt::Size aSizeVal; if( pPgSizeVal && (pPgSizeVal->Value >>= aSizeVal) ) { @@ -447,7 +445,7 @@ void Printer::ImplPrintJob(const std::shared_ptr<PrinterController>& i_xControll aMPS.aPaperSize.Height() = aSizeVal.Height; } - i_xController->setMultipage( aMPS ); + xController->setMultipage( aMPS ); } // in direct print case check whether there is anything to print. @@ -472,10 +470,10 @@ void Printer::ImplPrintJob(const std::shared_ptr<PrinterController>& i_xControll { try { - PrintDialog aDlg( NULL, i_xController ); + PrintDialog aDlg( NULL, xController ); if( ! aDlg.Execute() ) { - i_xController->abortJob(); + xController->abortJob(); return; } if( aDlg.isPrintToFile() ) @@ -483,7 +481,7 @@ void Printer::ImplPrintJob(const std::shared_ptr<PrinterController>& i_xControll OUString aFile = queryFile( xController->getPrinter().get() ); if( aFile.isEmpty() ) { - i_xController->abortJob(); + xController->abortJob(); return; } xController->setValue( OUString( "LocalFileName" ), @@ -501,19 +499,32 @@ void Printer::ImplPrintJob(const std::shared_ptr<PrinterController>& i_xControll } xController->pushPropertiesToPrinter(); +} +bool Printer::ExecutePrintJob(std::shared_ptr<PrinterController> xController) +{ OUString aJobName; PropertyValue* pJobNameVal = xController->getValue( OUString( "JobName" ) ); if( pJobNameVal ) pJobNameVal->Value >>= aJobName; - xController->getPrinter()->StartJob( aJobName, xController ); + return xController->getPrinter()->StartJob( aJobName, xController ); +} +void Printer::FinishPrintJob(std::shared_ptr<PrinterController> xController) +{ xController->resetPaperToLastConfigured(); - xController->jobFinished( xController->getJobState() ); } +void Printer::ImplPrintJob(std::shared_ptr<PrinterController> xController, + const JobSetup& i_rInitSetup) +{ + PreparePrintJob( xController, i_rInitSetup ); + ExecutePrintJob( xController ); + FinishPrintJob( xController ); +} + bool Printer::StartJob( const OUString& i_rJobName, std::shared_ptr<vcl::PrinterController>& i_xController) { mnError = PRINTER_OK; commit 1ef9952e804da953706cc514564db92a4a4a07b5 Author: LuboÅ¡ LuÅák <[email protected]> Date: Tue Feb 17 21:31:21 2015 +0100 do not needlessly make overriden functions more private These are public in the base class. Conflicts: sw/source/uibase/inc/view.hxx Change-Id: I839ffe56a835f99c2812cffb60804b74aaa9c5ac diff --git a/sw/source/uibase/inc/view.hxx b/sw/source/uibase/inc/view.hxx index 4378449..b921216 100644 --- a/sw/source/uibase/inc/view.hxx +++ b/sw/source/uibase/inc/view.hxx @@ -332,11 +332,6 @@ class SW_DLLPUBLIC SwView: public SfxViewShell SAL_DLLPRIVATE void SpellKontext(bool bOn = true) { m_bCenterCrsr = bOn; m_bAlwaysShowSel = bOn; } - // methods for printing - SAL_DLLPRIVATE virtual SfxPrinter* GetPrinter( bool bCreate = false ) SAL_OVERRIDE; - SAL_DLLPRIVATE virtual bool HasPrintOptionsPage() const SAL_OVERRIDE; - SAL_DLLPRIVATE virtual SfxTabPage* CreatePrintOptionsPage( vcl::Window* pParent, - const SfxItemSet& rSet) SAL_OVERRIDE; // for readonly switching SAL_DLLPRIVATE virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) SAL_OVERRIDE; SAL_DLLPRIVATE void _CheckReadonlyState(); @@ -664,6 +659,12 @@ public: void UpdateDocStats(); /// Where is the real cursor: in the annotation or in the main document? void SetAnnotationMode(bool bMode); + + // methods for printing + SAL_DLLPRIVATE virtual SfxPrinter* GetPrinter( bool bCreate = false ) SAL_OVERRIDE; + SAL_DLLPRIVATE virtual bool HasPrintOptionsPage() const SAL_OVERRIDE; + SAL_DLLPRIVATE virtual SfxTabPage* CreatePrintOptionsPage( vcl::Window* pParent, + const SfxItemSet& rSet) SAL_OVERRIDE; }; inline long SwView::GetXScroll() const commit 356d93766e27337a5463e793ceeb9da757a3a37f Author: LuboÅ¡ LuÅák <[email protected]> Date: Sun Feb 15 22:53:57 2015 +0100 avoid creating temporary document copies in non-singlefile MM mode The singlefile mode needs a new copy for every record, because it modifies it (such as changing fields to text), but the non-singlefile mode does not need all that relatively expensive work, because it just updates the fields and nothing else. Conflicts: sw/source/uibase/dbui/dbmgr.cxx Change-Id: If02cf8aca1d0f050ffb63cd85d5a9455afc5a6ea diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index 145b8dd..d93e85c 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -1008,6 +1008,14 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, bool bFreezedLayouts = false; // collect temporary files ::std::vector< OUString> aFilesToRemove; + + // The SfxObjectShell will be closed explicitly later but it is more safe to use SfxObjectShellLock here + SfxObjectShellLock xWorkDocSh; + // a view frame for the document + SwView* pWorkView = NULL; + SwDoc* pWorkDoc = NULL; + SwDBManager* pOldDBManager = NULL; + do { nStartRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0; @@ -1074,21 +1082,26 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, for( sal_uInt16 i = 0; i < 25; i++ ) Application::Reschedule(); - // The SfxObjectShell will be closed explicitly later but it is more safe to use SfxObjectShellLock here - // copy the source document - SfxObjectShellLock xWorkDocSh = pSourceDocSh->GetDoc()->CreateCopy( 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. + if( 1 == nDocNo || rMergeDescriptor.bCreateSingleFile ) + { + assert( !xWorkDocSh.Is()); + // copy the source document + xWorkDocSh = pSourceDocSh->GetDoc()->CreateCopy( true ); //create a view frame for the document - SwView* pWorkView = static_cast< SwView* >( SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 )->GetViewShell() ); + pWorkView = static_cast< SwView* >( SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 )->GetViewShell() ); //request the layout calculation SwWrtShell& rWorkShell = pWorkView->GetWrtShell(); pWorkView->AttrChangedNotify( &rWorkShell );// in order for SelectShell to be called - SwDoc* pWorkDoc = rWorkShell.GetDoc(); + pWorkDoc = rWorkShell.GetDoc(); pWorkDoc->ReplaceDocumentProperties( *pSourceDocSh->GetDoc()); if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) ) lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo ); - SwDBManager* pOldDBManager = pWorkDoc->GetDBManager(); + pOldDBManager = pWorkDoc->GetDBManager(); pWorkDoc->SetDBManager( this ); pWorkDoc->getIDocumentLinksAdministration().EmbedAllLinks(); @@ -1096,12 +1109,15 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, rWorkShell.LockExpFlds(); rWorkShell.CalcLayout(); rWorkShell.UnlockExpFlds(); + } + SwWrtShell& rWorkShell = pWorkView->GetWrtShell(); SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE), xWorkDocSh)); rWorkShell.SwViewShell::UpdateFlds(); SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), xWorkDocSh)); - pWorkDoc->RemoveInvisibleContent(); + if( rMergeDescriptor.bCreateSingleFile ) + pWorkDoc->RemoveInvisibleContent(); // launch MailMergeEvent if required const SwXMailMerge *pEvtSrc = GetMailMergeEvtSrc(); @@ -1272,9 +1288,12 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, } } } - pWorkDoc->SetDBManager( pOldDBManager ); - - xWorkDocSh->DoClose(); + if( rMergeDescriptor.bCreateSingleFile ) + { + pWorkDoc->SetDBManager( pOldDBManager ); + xWorkDocSh->DoClose(); + xWorkDocSh = NULL; + } } } nDocNo++; @@ -1291,6 +1310,13 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, } } while( !bCancel && (bSynchronizedDoc && (nStartRow != nEndRow)? ExistsNextRecord() : ToNextMergeRecord())); + + if( !rMergeDescriptor.bCreateSingleFile ) + { + pWorkDoc->SetDBManager( pOldDBManager ); + xWorkDocSh->DoClose(); + } + if (rMergeDescriptor.bCreateSingleFile) { // sw::DocumentLayoutManager::CopyLayoutFmt() did not generate commit d753dde3a701eba0fdfadb393c6380389246f0eb Author: LuboÅ¡ LuÅák <[email protected]> Date: Sun Feb 15 17:07:31 2015 +0100 do not create temp file(s) during MM if not needed Conflicts: sw/source/uibase/dbui/dbmgr.cxx Change-Id: I1360e215bff42dd866ab1d94a18a8f2f9ddc7c66 diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index 94e5bca..145b8dd 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -912,6 +912,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, SwView* pTargetView = 0; boost::scoped_ptr< utl::TempFile > aTempFile; + bool createTempFile = ( rMergeDescriptor.nMergeType == DBMGR_MERGE_EMAIL || rMergeDescriptor.nMergeType == DBMGR_MERGE_FILE ); OUString sModifiedStartingPageDesc; OUString sStartingPageDesc; sal_uInt16 nStartingPageNo = 0; @@ -1026,7 +1027,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, } // create a new temporary file name - only done once in case of bCreateSingleFile - if( 1 == nDocNo || !rMergeDescriptor.bCreateSingleFile ) + if( createTempFile && ( 1 == nDocNo || !rMergeDescriptor.bCreateSingleFile )) { INetURLObject aEntry(sPath); OUString sLeading; @@ -1042,23 +1043,25 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, new utl::TempFile(sLeading, true, &sExt, &sPath)); if( rMergeDescriptor.bSubjectIsFilename ) aTempFile->EnableKillingFile(); + if( !aTempFile->IsValid() ) + { + ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED ); + bNoError = false; + bCancel = true; + } } - if( !aTempFile->IsValid() ) - { - ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED ); - bNoError = false; - bCancel = true; - } - else + if( !bCancel ) { - INetURLObject aTempFileURL(aTempFile->GetURL()); + boost::scoped_ptr< INetURLObject > aTempFileURL; + if( createTempFile ) + aTempFileURL.reset( new INetURLObject(aTempFile->GetURL())); if (!IsMergeSilent()) { if( bMergeShell ) static_cast<CreateMonitor*>( pProgressDlg )->SetCurrentPosition( nDocNo ); else { PrintMonitor *pPrintMonDlg = static_cast<PrintMonitor*>( pProgressDlg ); - pPrintMonDlg->m_pPrinter->SetText( aTempFileURL.GetBase() ); + pPrintMonDlg->m_pPrinter->SetText( createTempFile ? aTempFileURL->GetBase() : OUString( pSourceDocSh->GetTitle( 22 ))); OUString sStat(SW_RES(STR_STATSTR_LETTER)); // Brief sStat += " "; sStat += OUString::number( nDocNo ); @@ -1164,7 +1167,8 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, } else { - OUString sFileURL = aTempFileURL.GetMainURL( INetURLObject::NO_DECODE ); + assert( createTempFile ); + OUString sFileURL = aTempFileURL->GetMainURL( INetURLObject::NO_DECODE ); SfxMedium* pDstMed = new SfxMedium( sFileURL, STREAM_STD_READWRITE ); @@ -1319,7 +1323,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, { if( rMergeDescriptor.nMergeType != DBMGR_MERGE_PRINTER ) { - OSL_ENSURE( aTempFile.get(), "Temporary file not available" ); + assert( aTempFile.get()); INetURLObject aTempFileURL( rMergeDescriptor.bSubjectIsFilename ? sSubject : aTempFile->GetURL()); SfxMedium* pDstMed = new SfxMedium( aTempFileURL.GetMainURL( INetURLObject::NO_DECODE ),
_______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
