Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <cstdarg>
21 :
22 : #include <stdio.h>
23 : #include <unotxdoc.hxx>
24 : #include <com/sun/star/text/NotePrintMode.hpp>
25 : #include <sfx2/app.hxx>
26 : #include <com/sun/star/sdb/CommandType.hpp>
27 : #include <com/sun/star/sdb/XDocumentDataSource.hpp>
28 : #include <com/sun/star/frame/XComponentLoader.hpp>
29 : #include <com/sun/star/lang/DisposedException.hpp>
30 : #include <com/sun/star/lang/XEventListener.hpp>
31 : #include <com/sun/star/util/NumberFormatter.hpp>
32 : #include <com/sun/star/sdb/DatabaseContext.hpp>
33 : #include <com/sun/star/sdb/TextConnectionSettings.hpp>
34 : #include <com/sun/star/sdb/XCompletedConnection.hpp>
35 : #include <com/sun/star/sdb/XCompletedExecution.hpp>
36 : #include <com/sun/star/container/XChild.hpp>
37 : #include <com/sun/star/text/MailMergeEvent.hpp>
38 : #include <com/sun/star/frame/XStorable.hpp>
39 : #include <com/sun/star/task/InteractionHandler.hpp>
40 : #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
41 : #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
42 : #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
43 : #include <com/sun/star/uno/XNamingService.hpp>
44 : #include <com/sun/star/util/XCloseable.hpp>
45 : #include <com/sun/star/beans/XPropertySet.hpp>
46 : #include <sfx2/fcontnr.hxx>
47 : #include <sfx2/filedlghelper.hxx>
48 : #include <sfx2/viewfrm.hxx>
49 : #include <dbconfig.hxx>
50 : #include <swdbtoolsclient.hxx>
51 : #include <pagedesc.hxx>
52 : #include <vcl/lstbox.hxx>
53 : #include <unotools/tempfile.hxx>
54 : #include <unotools/pathoptions.hxx>
55 : #include <svl/urihelper.hxx>
56 : #include <svl/zforlist.hxx>
57 : #include <svl/zformat.hxx>
58 : #include <svl/stritem.hxx>
59 : #include <svl/eitem.hxx>
60 : #include <vcl/oldprintadaptor.hxx>
61 : #include <sfx2/docfile.hxx>
62 : #include <sfx2/progress.hxx>
63 : #include <sfx2/dispatch.hxx>
64 : #include <svl/mailenum.hxx>
65 : #include <cmdid.h>
66 : #include <swmodule.hxx>
67 : #include <view.hxx>
68 : #include <docsh.hxx>
69 : #include <edtwin.hxx>
70 : #include <wrtsh.hxx>
71 : #include <fldbas.hxx>
72 : #include <initui.hxx>
73 : #include <swundo.hxx>
74 : #include <flddat.hxx>
75 : #include <modcfg.hxx>
76 : #include <shellio.hxx>
77 : #include <dbui.hxx>
78 : #include <dbmgr.hxx>
79 : #include <doc.hxx>
80 : #include <IDocumentSettingAccess.hxx>
81 : #include <IDocumentLinksAdministration.hxx>
82 : #include <IDocumentContentOperations.hxx>
83 : #include <IDocumentFieldsAccess.hxx>
84 : #include <swwait.hxx>
85 : #include <swunohelper.hxx>
86 : #include <dbui.hrc>
87 : #include <globals.hrc>
88 : #include <statstr.hrc>
89 : #include <mmconfigitem.hxx>
90 : #include <sfx2/request.hxx>
91 : #include <hintids.hxx>
92 : #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
93 : #include <com/sun/star/sdbc/XRowSet.hpp>
94 : #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
95 : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
96 : #include <com/sun/star/sdb/XQueriesSupplier.hpp>
97 : #include <com/sun/star/sdb/XColumn.hpp>
98 : #include <com/sun/star/sdbc/DataType.hpp>
99 : #include <com/sun/star/sdbc/ResultSetType.hpp>
100 : #include <com/sun/star/mail/MailAttachment.hpp>
101 : #include <comphelper/processfactory.hxx>
102 : #include <comphelper/property.hxx>
103 : #include <comphelper/string.hxx>
104 : #include <comphelper/types.hxx>
105 : #include <mailmergehelper.hxx>
106 : #include <maildispatcher.hxx>
107 : #include <svtools/htmlcfg.hxx>
108 : #include <i18nlangtag/languagetag.hxx>
109 : #include <com/sun/star/util/XNumberFormatTypes.hpp>
110 : #include <editeng/langitem.hxx>
111 : #include <svl/numuno.hxx>
112 :
113 : #include <unomailmerge.hxx>
114 : #include <sfx2/event.hxx>
115 : #include <vcl/msgbox.hxx>
116 : #include <svx/dataaccessdescriptor.hxx>
117 : #include <osl/mutex.hxx>
118 : #include <rtl/textenc.h>
119 : #include <ndindex.hxx>
120 : #include <pam.hxx>
121 : #include <swcrsr.hxx>
122 : #include <swevent.hxx>
123 : #include <osl/file.hxx>
124 : #include <swabstdlg.hxx>
125 : #include <fmthdft.hxx>
126 : #include <envelp.hrc>
127 : #include <vector>
128 : #include <unomid.h>
129 : #include <section.hxx>
130 : #include <rootfrm.hxx>
131 : #include <fmtpdsc.hxx>
132 : #include <ndtxt.hxx>
133 : #include <calc.hxx>
134 : #include <dbfld.hxx>
135 :
136 : #include <boost/scoped_ptr.hpp>
137 :
138 : using namespace ::osl;
139 : using namespace ::svx;
140 : using namespace ::com::sun::star;
141 : using namespace ::com::sun::star::text;
142 : using namespace ::com::sun::star::uno;
143 : using namespace ::com::sun::star::container;
144 : using namespace ::com::sun::star::frame;
145 : using namespace ::com::sun::star::lang;
146 : using namespace ::com::sun::star::sdb;
147 : using namespace ::com::sun::star::sdbc;
148 : using namespace ::com::sun::star::sdbcx;
149 : using namespace ::com::sun::star::beans;
150 : using namespace ::com::sun::star::util;
151 : using namespace ::com::sun::star::task;
152 : using namespace ::com::sun::star::ui::dialogs;
153 :
154 : #define DB_SEP_SPACE 0
155 : #define DB_SEP_TAB 1
156 : #define DB_SEP_RETURN 2
157 : #define DB_SEP_NEWLINE 3
158 :
159 : const sal_Char cCursor[] = "Cursor";
160 : const sal_Char cCommand[] = "Command";
161 : const sal_Char cCommandType[] = "CommandType";
162 : const sal_Char cDataSourceName[] = "DataSourceName";
163 : const sal_Char cSelection[] = "Selection";
164 : const sal_Char cActiveConnection[] = "ActiveConnection";
165 :
166 : // Use nameless namespace to avoid to rubbish the global namespace
167 :
168 : namespace
169 : {
170 :
171 0 : bool lcl_getCountFromResultSet( sal_Int32& rCount, const uno::Reference<XResultSet>& xResultSet )
172 : {
173 0 : uno::Reference<XPropertySet> xPrSet(xResultSet, UNO_QUERY);
174 0 : if(xPrSet.is())
175 : {
176 : try
177 : {
178 0 : bool bFinal = false;
179 0 : Any aFinal = xPrSet->getPropertyValue("IsRowCountFinal");
180 0 : aFinal >>= bFinal;
181 0 : if(!bFinal)
182 : {
183 0 : xResultSet->last();
184 0 : xResultSet->first();
185 : }
186 0 : Any aCount = xPrSet->getPropertyValue("RowCount");
187 0 : if( aCount >>= rCount )
188 0 : return true;
189 : }
190 0 : catch(const Exception&)
191 : {
192 : }
193 : }
194 0 : return false;
195 : }
196 : }
197 :
198 : class SwConnectionDisposedListener_Impl : public cppu::WeakImplHelper1
199 : < lang::XEventListener >
200 : {
201 : SwDBManager& rDBManager;
202 :
203 : virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
204 : public:
205 : SwConnectionDisposedListener_Impl(SwDBManager& rMgr);
206 : virtual ~SwConnectionDisposedListener_Impl();
207 :
208 : };
209 :
210 5045 : struct SwDBManager_Impl
211 : {
212 : SwDSParam* pMergeData;
213 : AbstractMailMergeDlg* pMergeDialog;
214 : uno::Reference<lang::XEventListener> xDisposeListener;
215 :
216 5052 : SwDBManager_Impl(SwDBManager& rDBManager)
217 : :pMergeData(0)
218 : ,pMergeDialog(0)
219 5052 : ,xDisposeListener(new SwConnectionDisposedListener_Impl(rDBManager))
220 5052 : {}
221 : };
222 :
223 4 : static void lcl_InitNumberFormatter(SwDSParam& rParam, uno::Reference<XDataSource> xSource)
224 : {
225 4 : uno::Reference<XComponentContext> xContext = ::comphelper::getProcessComponentContext();
226 4 : rParam.xFormatter = uno::Reference<util::XNumberFormatter>(util::NumberFormatter::create(xContext), UNO_QUERY);
227 4 : if(!xSource.is())
228 0 : xSource = SwDBManager::getDataSourceAsParent(rParam.xConnection, rParam.sDataSource);
229 :
230 8 : uno::Reference<XPropertySet> xSourceProps(xSource, UNO_QUERY);
231 4 : if(xSourceProps.is())
232 : {
233 4 : Any aFormats = xSourceProps->getPropertyValue("NumberFormatsSupplier");
234 4 : if(aFormats.hasValue())
235 : {
236 4 : uno::Reference<XNumberFormatsSupplier> xSuppl;
237 4 : aFormats >>= xSuppl;
238 4 : if(xSuppl.is())
239 : {
240 4 : uno::Reference< XPropertySet > xSettings = xSuppl->getNumberFormatSettings();
241 8 : Any aNull = xSettings->getPropertyValue("NullDate");
242 4 : aNull >>= rParam.aNullDate;
243 4 : if(rParam.xFormatter.is())
244 8 : rParam.xFormatter->attachNumberFormatsSupplier(xSuppl);
245 4 : }
246 4 : }
247 4 : }
248 4 : }
249 :
250 0 : static bool lcl_MoveAbsolute(SwDSParam* pParam, long nAbsPos)
251 : {
252 0 : bool bRet = false;
253 : try
254 : {
255 0 : if(pParam->bScrollable)
256 : {
257 0 : bRet = pParam->xResultSet->absolute( nAbsPos );
258 : }
259 : else
260 : {
261 : OSL_FAIL("no absolute positioning available");
262 : }
263 : }
264 0 : catch(const Exception&)
265 : {
266 : }
267 0 : return bRet;
268 : }
269 :
270 0 : static bool lcl_GetColumnCnt(SwDSParam* pParam,
271 : const OUString& rColumnName, long nLanguage, OUString& rResult, double* pNumber)
272 : {
273 0 : uno::Reference< XColumnsSupplier > xColsSupp( pParam->xResultSet, UNO_QUERY );
274 0 : uno::Reference<XNameAccess> xCols;
275 : try
276 : {
277 0 : xCols = xColsSupp->getColumns();
278 : }
279 0 : catch(const lang::DisposedException&)
280 : {
281 : }
282 0 : if(!xCols.is() || !xCols->hasByName(rColumnName))
283 0 : return false;
284 0 : Any aCol = xCols->getByName(rColumnName);
285 0 : uno::Reference< XPropertySet > xColumnProps;
286 0 : aCol >>= xColumnProps;
287 :
288 0 : SwDBFormatData aFormatData;
289 0 : if(!pParam->xFormatter.is())
290 : {
291 : uno::Reference<XDataSource> xSource = SwDBManager::getDataSourceAsParent(
292 0 : pParam->xConnection,pParam->sDataSource);
293 0 : lcl_InitNumberFormatter(*pParam, xSource );
294 : }
295 0 : aFormatData.aNullDate = pParam->aNullDate;
296 0 : aFormatData.xFormatter = pParam->xFormatter;
297 :
298 0 : aFormatData.aLocale = LanguageTag( (LanguageType)nLanguage ).getLocale();
299 :
300 0 : rResult = SwDBManager::GetDBField( xColumnProps, aFormatData, pNumber);
301 0 : return true;
302 : };
303 :
304 : // import data
305 4 : bool SwDBManager::MergeNew( const SwMergeDescriptor& rMergeDesc )
306 : {
307 : OSL_ENSURE(!bInMerge && !pImpl->pMergeData, "merge already activated!");
308 :
309 4 : SwDBData aData;
310 4 : aData.nCommandType = CommandType::TABLE;
311 8 : uno::Reference<XResultSet> xResSet;
312 8 : Sequence<Any> aSelection;
313 8 : uno::Reference< XConnection> xConnection;
314 :
315 4 : aData.sDataSource = rMergeDesc.rDescriptor.getDataSource();
316 4 : rMergeDesc.rDescriptor[daCommand] >>= aData.sCommand;
317 4 : rMergeDesc.rDescriptor[daCommandType] >>= aData.nCommandType;
318 :
319 4 : if ( rMergeDesc.rDescriptor.has(daCursor) )
320 4 : rMergeDesc.rDescriptor[daCursor] >>= xResSet;
321 4 : if ( rMergeDesc.rDescriptor.has(daSelection) )
322 4 : rMergeDesc.rDescriptor[daSelection] >>= aSelection;
323 4 : if ( rMergeDesc.rDescriptor.has(daConnection) )
324 4 : rMergeDesc.rDescriptor[daConnection] >>= xConnection;
325 :
326 4 : if(aData.sDataSource.isEmpty() || aData.sCommand.isEmpty() || !xResSet.is())
327 : {
328 0 : return false;
329 : }
330 :
331 4 : pImpl->pMergeData = new SwDSParam(aData, xResSet, aSelection);
332 4 : SwDSParam* pTemp = FindDSData(aData, false);
333 4 : if(pTemp)
334 4 : *pTemp = *pImpl->pMergeData;
335 : else
336 : {
337 : // calls from the calculator may have added a connection with an invalid commandtype
338 : //"real" data base connections added here have to re-use the already available
339 : //DSData and set the correct CommandType
340 0 : SwDBData aTempData(aData);
341 0 : aData.nCommandType = -1;
342 0 : pTemp = FindDSData(aData, false);
343 0 : if(pTemp)
344 0 : *pTemp = *pImpl->pMergeData;
345 : else
346 : {
347 0 : SwDSParam* pInsert = new SwDSParam(*pImpl->pMergeData);
348 0 : aDataSourceParams.push_back(pInsert);
349 : try
350 : {
351 0 : uno::Reference<XComponent> xComponent(pInsert->xConnection, UNO_QUERY);
352 0 : if(xComponent.is())
353 0 : xComponent->addEventListener(pImpl->xDisposeListener);
354 : }
355 0 : catch(const Exception&)
356 : {
357 : }
358 0 : }
359 : }
360 4 : if(!pImpl->pMergeData->xConnection.is())
361 4 : pImpl->pMergeData->xConnection = xConnection;
362 : // add an XEventListener
363 :
364 : try{
365 : //set to start position
366 4 : if(pImpl->pMergeData->aSelection.getLength())
367 : {
368 0 : sal_Int32 nPos = 0;
369 0 : pImpl->pMergeData->aSelection.getConstArray()[ pImpl->pMergeData->nSelectionIndex++ ] >>= nPos;
370 0 : pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->absolute( nPos );
371 0 : pImpl->pMergeData->CheckEndOfDB();
372 0 : if(pImpl->pMergeData->nSelectionIndex >= pImpl->pMergeData->aSelection.getLength())
373 0 : pImpl->pMergeData->bEndOfDB = true;
374 : }
375 : else
376 : {
377 4 : pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->first();
378 4 : pImpl->pMergeData->CheckEndOfDB();
379 : }
380 : }
381 0 : catch(const Exception&)
382 : {
383 0 : pImpl->pMergeData->bEndOfDB = true;
384 0 : pImpl->pMergeData->CheckEndOfDB();
385 : OSL_FAIL("exception in MergeNew()");
386 : }
387 :
388 8 : uno::Reference<XDataSource> xSource = SwDBManager::getDataSourceAsParent(xConnection,aData.sDataSource);
389 :
390 4 : lcl_InitNumberFormatter(*pImpl->pMergeData, xSource);
391 :
392 4 : rMergeDesc.rSh.ChgDBData(aData);
393 4 : bInMerge = true;
394 :
395 4 : if (IsInitDBFields())
396 : {
397 : // with database fields without DB-Name, use DB-Name from Doc
398 0 : std::vector<OUString> aDBNames;
399 0 : aDBNames.push_back(OUString());
400 0 : SwDBData aInsertData = rMergeDesc.rSh.GetDBData();
401 0 : OUString sDBName = aInsertData.sDataSource;
402 0 : sDBName += OUString(DB_DELIM);
403 0 : sDBName += aInsertData.sCommand;
404 0 : sDBName += OUString(DB_DELIM);
405 0 : sDBName += OUString::number(aInsertData.nCommandType);
406 0 : rMergeDesc.rSh.ChangeDBFields( aDBNames, sDBName);
407 0 : SetInitDBFields(false);
408 : }
409 :
410 4 : bool bRet = true;
411 4 : switch(rMergeDesc.nMergeType)
412 : {
413 : case DBMGR_MERGE:
414 0 : bRet = Merge(&rMergeDesc.rSh);
415 0 : break;
416 :
417 : case DBMGR_MERGE_PRINTER:
418 : case DBMGR_MERGE_EMAIL:
419 : case DBMGR_MERGE_FILE:
420 : case DBMGR_MERGE_SHELL:
421 : // save files and send them as e-Mail if required
422 : bRet = MergeMailFiles(&rMergeDesc.rSh,
423 4 : rMergeDesc);
424 4 : break;
425 :
426 : default:
427 : // insert selected entries
428 : // (was: InsertRecord)
429 0 : ImportFromConnection(&rMergeDesc.rSh);
430 0 : break;
431 : }
432 :
433 4 : DELETEZ( pImpl->pMergeData );
434 :
435 : // Recalculate original section visibility states, as field changes aren't
436 : // tracked (not undo-able). Has to be done, after pImpl->pMergeData is
437 : // gone, otherwise merge data is used for calculation!
438 4 : rMergeDesc.rSh.SwViewShell::UpdateFlds();
439 :
440 4 : bInMerge = false;
441 :
442 8 : return bRet;
443 : }
444 :
445 : // import data
446 0 : bool SwDBManager::Merge(SwWrtShell* pSh)
447 : {
448 0 : pSh->StartAllAction();
449 :
450 0 : pSh->SwViewShell::UpdateFlds(true);
451 0 : pSh->SetModified();
452 :
453 0 : pSh->EndAllAction();
454 :
455 0 : return true;
456 : }
457 :
458 0 : void SwDBManager::ImportFromConnection( SwWrtShell* pSh )
459 : {
460 0 : if(pImpl->pMergeData && !pImpl->pMergeData->bEndOfDB)
461 : {
462 : {
463 0 : pSh->StartAllAction();
464 0 : pSh->StartUndo(UNDO_EMPTY);
465 0 : bool bGroupUndo(pSh->DoesGroupUndo());
466 0 : pSh->DoGroupUndo(false);
467 :
468 0 : if( pSh->HasSelection() )
469 0 : pSh->DelRight();
470 :
471 0 : boost::scoped_ptr<SwWait> pWait;
472 :
473 : {
474 0 : sal_uLong i = 0;
475 0 : do {
476 :
477 0 : ImportDBEntry(pSh);
478 0 : if( 10 == ++i )
479 0 : pWait.reset(new SwWait( *pSh->GetView().GetDocShell(), true));
480 :
481 : } while(ToNextMergeRecord());
482 : }
483 :
484 0 : pSh->DoGroupUndo(bGroupUndo);
485 0 : pSh->EndUndo(UNDO_EMPTY);
486 0 : pSh->EndAllAction();
487 : }
488 : }
489 0 : }
490 :
491 0 : static OUString lcl_FindColumn(const OUString& sFormatStr,sal_uInt16 &nUsedPos, sal_uInt8 &nSeparator)
492 : {
493 0 : OUString sReturn;
494 0 : sal_uInt16 nLen = sFormatStr.getLength();
495 0 : nSeparator = 0xff;
496 0 : while(nUsedPos < nLen && nSeparator == 0xff)
497 : {
498 0 : sal_Unicode cAkt = sFormatStr[nUsedPos];
499 0 : switch(cAkt)
500 : {
501 : case ',':
502 0 : nSeparator = DB_SEP_SPACE;
503 0 : break;
504 : case ';':
505 0 : nSeparator = DB_SEP_RETURN;
506 0 : break;
507 : case ':':
508 0 : nSeparator = DB_SEP_TAB;
509 0 : break;
510 : case '#':
511 0 : nSeparator = DB_SEP_NEWLINE;
512 0 : break;
513 : default:
514 0 : sReturn += OUString(cAkt);
515 : }
516 0 : nUsedPos++;
517 :
518 : }
519 0 : return sReturn;
520 : }
521 :
522 0 : void SwDBManager::ImportDBEntry(SwWrtShell* pSh)
523 : {
524 0 : if(pImpl->pMergeData && !pImpl->pMergeData->bEndOfDB)
525 : {
526 0 : uno::Reference< XColumnsSupplier > xColsSupp( pImpl->pMergeData->xResultSet, UNO_QUERY );
527 0 : uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
528 0 : OUString sFormatStr;
529 0 : sal_uInt16 nFmtLen = sFormatStr.getLength();
530 0 : if( nFmtLen )
531 : {
532 0 : const char cSpace = ' ';
533 0 : const char cTab = '\t';
534 0 : sal_uInt16 nUsedPos = 0;
535 : sal_uInt8 nSeparator;
536 0 : OUString sColumn = lcl_FindColumn(sFormatStr, nUsedPos, nSeparator);
537 0 : while( !sColumn.isEmpty() )
538 : {
539 0 : if(!xCols->hasByName(sColumn))
540 0 : return;
541 0 : Any aCol = xCols->getByName(sColumn);
542 0 : uno::Reference< XPropertySet > xColumnProp;
543 0 : aCol >>= xColumnProp;
544 0 : if(xColumnProp.is())
545 : {
546 0 : SwDBFormatData aDBFormat;
547 0 : OUString sInsert = GetDBField( xColumnProp, aDBFormat);
548 0 : if( DB_SEP_SPACE == nSeparator )
549 0 : sInsert += OUString(cSpace);
550 0 : else if( DB_SEP_TAB == nSeparator)
551 0 : sInsert += OUString(cTab);
552 0 : pSh->Insert(sInsert);
553 0 : if( DB_SEP_RETURN == nSeparator)
554 0 : pSh->SplitNode();
555 0 : else if(DB_SEP_NEWLINE == nSeparator)
556 0 : pSh->InsertLineBreak();
557 : }
558 : else
559 : {
560 : // column not found -> show error
561 0 : OUStringBuffer sInsert;
562 0 : sInsert.append('?').append(sColumn).append('?');
563 0 : pSh->Insert(sInsert.makeStringAndClear());
564 : }
565 0 : sColumn = lcl_FindColumn(sFormatStr, nUsedPos, nSeparator);
566 0 : }
567 0 : pSh->SplitNode();
568 : }
569 : else
570 : {
571 0 : OUString sStr;
572 0 : Sequence<OUString> aColNames = xCols->getElementNames();
573 0 : const OUString* pColNames = aColNames.getConstArray();
574 0 : long nLength = aColNames.getLength();
575 0 : for(long i = 0; i < nLength; i++)
576 : {
577 0 : Any aCol = xCols->getByName(pColNames[i]);
578 0 : uno::Reference< XPropertySet > xColumnProp;
579 0 : aCol >>= xColumnProp;
580 0 : SwDBFormatData aDBFormat;
581 0 : sStr += GetDBField( xColumnProp, aDBFormat);
582 0 : if (i < nLength - 1)
583 0 : sStr += "\t";
584 0 : }
585 0 : pSh->SwEditShell::Insert2(sStr);
586 0 : pSh->SwFEShell::SplitNode(); // line feed
587 0 : }
588 : }
589 : }
590 :
591 : // fill Listbox with tablelist
592 0 : bool SwDBManager::GetTableNames(ListBox* pListBox, const OUString& rDBName)
593 : {
594 0 : bool bRet = false;
595 0 : OUString sOldTableName(pListBox->GetSelectEntry());
596 0 : pListBox->Clear();
597 0 : SwDSParam* pParam = FindDSConnection(rDBName, false);
598 0 : uno::Reference< XConnection> xConnection;
599 0 : if(pParam && pParam->xConnection.is())
600 0 : xConnection = pParam->xConnection;
601 : else
602 : {
603 0 : OUString sDBName(rDBName);
604 0 : if ( !sDBName.isEmpty() )
605 0 : xConnection = RegisterConnection( sDBName );
606 : }
607 0 : if(xConnection.is())
608 : {
609 0 : uno::Reference<XTablesSupplier> xTSupplier = uno::Reference<XTablesSupplier>(xConnection, UNO_QUERY);
610 0 : if(xTSupplier.is())
611 : {
612 0 : uno::Reference<XNameAccess> xTbls = xTSupplier->getTables();
613 0 : Sequence<OUString> aTbls = xTbls->getElementNames();
614 0 : const OUString* pTbls = aTbls.getConstArray();
615 0 : for(long i = 0; i < aTbls.getLength(); i++)
616 : {
617 0 : sal_uInt16 nEntry = pListBox->InsertEntry(pTbls[i]);
618 0 : pListBox->SetEntryData(nEntry, (void*)0);
619 0 : }
620 : }
621 0 : uno::Reference<XQueriesSupplier> xQSupplier = uno::Reference<XQueriesSupplier>(xConnection, UNO_QUERY);
622 0 : if(xQSupplier.is())
623 : {
624 0 : uno::Reference<XNameAccess> xQueries = xQSupplier->getQueries();
625 0 : Sequence<OUString> aQueries = xQueries->getElementNames();
626 0 : const OUString* pQueries = aQueries.getConstArray();
627 0 : for(long i = 0; i < aQueries.getLength(); i++)
628 : {
629 0 : sal_uInt16 nEntry = pListBox->InsertEntry(pQueries[i]);
630 0 : pListBox->SetEntryData(nEntry, (void*)1);
631 0 : }
632 : }
633 0 : if (!sOldTableName.isEmpty())
634 0 : pListBox->SelectEntry(sOldTableName);
635 0 : bRet = true;
636 : }
637 0 : return bRet;
638 : }
639 :
640 : // fill Listbox with column names of a database
641 0 : void SwDBManager::GetColumnNames(ListBox* pListBox,
642 : const OUString& rDBName, const OUString& rTableName, bool bAppend)
643 : {
644 0 : if (!bAppend)
645 0 : pListBox->Clear();
646 0 : SwDBData aData;
647 0 : aData.sDataSource = rDBName;
648 0 : aData.sCommand = rTableName;
649 0 : aData.nCommandType = -1;
650 0 : SwDSParam* pParam = FindDSData(aData, false);
651 0 : uno::Reference< XConnection> xConnection;
652 0 : if(pParam && pParam->xConnection.is())
653 0 : xConnection = pParam->xConnection;
654 : else
655 : {
656 0 : OUString sDBName(rDBName);
657 0 : xConnection = RegisterConnection( sDBName );
658 : }
659 0 : uno::Reference< XColumnsSupplier> xColsSupp = SwDBManager::GetColumnSupplier(xConnection, rTableName);
660 0 : if(xColsSupp.is())
661 : {
662 0 : uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
663 0 : const Sequence<OUString> aColNames = xCols->getElementNames();
664 0 : const OUString* pColNames = aColNames.getConstArray();
665 0 : for(int nCol = 0; nCol < aColNames.getLength(); nCol++)
666 : {
667 0 : pListBox->InsertEntry(pColNames[nCol]);
668 : }
669 0 : ::comphelper::disposeComponent( xColsSupp );
670 0 : }
671 0 : }
672 :
673 0 : void SwDBManager::GetColumnNames(ListBox* pListBox,
674 : uno::Reference< XConnection> xConnection,
675 : const OUString& rTableName, bool bAppend)
676 : {
677 0 : if (!bAppend)
678 0 : pListBox->Clear();
679 0 : uno::Reference< XColumnsSupplier> xColsSupp = SwDBManager::GetColumnSupplier(xConnection, rTableName);
680 0 : if(xColsSupp.is())
681 : {
682 0 : uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
683 0 : const Sequence<OUString> aColNames = xCols->getElementNames();
684 0 : const OUString* pColNames = aColNames.getConstArray();
685 0 : for(int nCol = 0; nCol < aColNames.getLength(); nCol++)
686 : {
687 0 : pListBox->InsertEntry(pColNames[nCol]);
688 : }
689 0 : ::comphelper::disposeComponent( xColsSupp );
690 0 : }
691 0 : }
692 :
693 5052 : SwDBManager::SwDBManager()
694 : : bCancel(false)
695 : , bInitDBFields(false)
696 : , bSingleJobs(false)
697 : , bInMerge(false)
698 : , bMergeSilent(false)
699 : , bMergeLock(false)
700 5052 : , pImpl(new SwDBManager_Impl(*this))
701 10104 : , pMergeEvtSrc(NULL)
702 : {
703 5052 : }
704 :
705 10090 : SwDBManager::~SwDBManager()
706 : {
707 5045 : for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.size(); nPos++)
708 : {
709 0 : SwDSParam* pParam = &aDataSourceParams[nPos];
710 0 : if(pParam->xConnection.is())
711 : {
712 : try
713 : {
714 0 : uno::Reference<XComponent> xComp(pParam->xConnection, UNO_QUERY);
715 0 : if(xComp.is())
716 0 : xComp->dispose();
717 : }
718 0 : catch(const RuntimeException&)
719 : {
720 : //may be disposed already since multiple entries may have used the same connection
721 : }
722 : }
723 : }
724 5045 : delete pImpl;
725 5045 : }
726 :
727 : // save bulk letters as single documents
728 2 : static OUString lcl_FindUniqueName(SwWrtShell* pTargetShell, const OUString& rStartingPageDesc, sal_uLong nDocNo )
729 : {
730 : do
731 : {
732 2 : OUString sTest = rStartingPageDesc;
733 2 : sTest += OUString::number( nDocNo );
734 2 : if( !pTargetShell->FindPageDescByName( sTest ) )
735 4 : return sTest;
736 0 : ++nDocNo;
737 0 : }while(true);
738 : }
739 :
740 2 : static void lcl_CopyFollowPageDesc(
741 : SwWrtShell& rTargetShell,
742 : const SwPageDesc& rSourcePageDesc,
743 : const SwPageDesc& rTargetPageDesc,
744 : const sal_uLong nDocNo )
745 : {
746 : //now copy the follow page desc, too
747 2 : const SwPageDesc* pFollowPageDesc = rSourcePageDesc.GetFollow();
748 2 : OUString sFollowPageDesc = pFollowPageDesc->GetName();
749 2 : if( sFollowPageDesc != rSourcePageDesc.GetName() )
750 : {
751 0 : SwDoc* pTargetDoc = rTargetShell.GetDoc();
752 0 : OUString sNewFollowPageDesc = lcl_FindUniqueName(&rTargetShell, sFollowPageDesc, nDocNo );
753 0 : SwPageDesc* pTargetFollowPageDesc = pTargetDoc->MakePageDesc(sNewFollowPageDesc);
754 :
755 0 : pTargetDoc->CopyPageDesc(*pFollowPageDesc, *pTargetFollowPageDesc, false);
756 0 : SwPageDesc aDesc(rTargetPageDesc);
757 0 : aDesc.SetFollow(pTargetFollowPageDesc);
758 0 : pTargetDoc->ChgPageDesc(rTargetPageDesc.GetName(), aDesc);
759 2 : }
760 2 : }
761 :
762 0 : static void lcl_RemoveSectionLinks( SwWrtShell& rWorkShell )
763 : {
764 : //reset all links of the sections of synchronized labels
765 0 : sal_uInt16 nSections = rWorkShell.GetSectionFmtCount();
766 0 : for( sal_uInt16 nSection = 0; nSection < nSections; ++nSection )
767 : {
768 0 : SwSectionData aSectionData( *rWorkShell.GetSectionFmt( nSection ).GetSection() );
769 0 : if( aSectionData.GetType() == FILE_LINK_SECTION )
770 : {
771 0 : aSectionData.SetType( CONTENT_SECTION );
772 0 : aSectionData.SetLinkFileName( OUString() );
773 0 : rWorkShell.UpdateSection( nSection, aSectionData );
774 : }
775 0 : }
776 0 : rWorkShell.SetLabelDoc( false );
777 0 : }
778 :
779 0 : static void lcl_SaveDoc( SfxObjectShell *xTargetDocShell,
780 : const char *name, int no = 0 )
781 : {
782 0 : OUString sExt( ".odt" );
783 0 : OUString basename = OUString::createFromAscii( name );
784 0 : if (no > 0)
785 0 : basename += OUString::number(no) + "-";
786 : // aTempFile is not deleted, but that seems to be intentional
787 0 : utl::TempFile aTempFile(basename, true, &sExt);
788 0 : INetURLObject aTempFileURL( aTempFile.GetURL() );
789 : SfxMedium* pDstMed = new SfxMedium(
790 : aTempFileURL.GetMainURL( INetURLObject::NO_DECODE ),
791 0 : STREAM_STD_READWRITE );
792 0 : if( !xTargetDocShell->DoSaveAs( *pDstMed ) )
793 : SAL_WARN( "sw.mailmerge", "Error saving: " << aTempFile.GetURL() );
794 : else
795 : SAL_INFO( "sw.mailmerge", "Saved doc as: " << aTempFile.GetURL() );
796 0 : delete pDstMed;
797 0 : }
798 :
799 4 : bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
800 : const SwMergeDescriptor& rMergeDescriptor)
801 : {
802 : //check if the doc is synchronized and contains at least one linked section
803 4 : bool bSynchronizedDoc = pSourceShell->IsLabelDoc() && pSourceShell->GetSectionFmtCount() > 1;
804 4 : bool bNoError = true;
805 4 : const bool bEMail = rMergeDescriptor.nMergeType == DBMGR_MERGE_EMAIL;
806 4 : const bool bMergeShell = rMergeDescriptor.nMergeType == DBMGR_MERGE_SHELL;
807 :
808 4 : ::rtl::Reference< MailDispatcher > xMailDispatcher;
809 8 : OUString sBodyMimeType;
810 4 : rtl_TextEncoding eEncoding = ::osl_getThreadTextEncoding();
811 :
812 : static const char *sMaxDumpDocs = 0;
813 : static sal_Int32 nMaxDumpDocs = 0;
814 4 : if (!sMaxDumpDocs)
815 : {
816 2 : sMaxDumpDocs = getenv("SW_DEBUG_MAILMERGE_DOCS");
817 2 : if (!sMaxDumpDocs)
818 2 : sMaxDumpDocs = "";
819 : else
820 0 : nMaxDumpDocs = rtl_ustr_toInt32(reinterpret_cast<const sal_Unicode*>( sMaxDumpDocs ), 10);
821 : }
822 :
823 4 : if(bEMail)
824 : {
825 0 : xMailDispatcher.set( new MailDispatcher(rMergeDescriptor.xSmtpServer));
826 0 : if(!rMergeDescriptor.bSendAsAttachment && rMergeDescriptor.bSendAsHTML)
827 : {
828 0 : sBodyMimeType = "text/html; charset=";
829 0 : sBodyMimeType += OUString::createFromAscii(
830 0 : rtl_getBestMimeCharsetFromTextEncoding( eEncoding ));
831 0 : SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get();
832 0 : eEncoding = rHtmlOptions.GetTextEncoding();
833 : }
834 : else
835 0 : sBodyMimeType =
836 0 : OUString("text/plain; charset=UTF-8; format=flowed");
837 : }
838 :
839 8 : uno::Reference< XPropertySet > xColumnProp;
840 : {
841 4 : bool bColumnName = !sEMailAddrFld.isEmpty();
842 :
843 4 : if (bColumnName)
844 : {
845 0 : uno::Reference< XColumnsSupplier > xColsSupp( pImpl->pMergeData->xResultSet, UNO_QUERY );
846 0 : uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
847 0 : if(!xCols->hasByName(sEMailAddrFld))
848 0 : return false;
849 0 : Any aCol = xCols->getByName(sEMailAddrFld);
850 0 : aCol >>= xColumnProp;
851 : }
852 :
853 : // Try saving the source document
854 4 : SfxDispatcher* pSfxDispatcher = pSourceShell->GetView().GetViewFrame()->GetDispatcher();
855 4 : SwDocShell* pSourceDocSh = pSourceShell->GetView().GetDocShell();
856 :
857 4 : uno::Reference<document::XDocumentProperties> xSourceDocProps;
858 : {
859 : uno::Reference<document::XDocumentPropertiesSupplier>
860 4 : xDPS(pSourceDocSh->GetModel(), uno::UNO_QUERY);
861 4 : xSourceDocProps.set(xDPS->getDocumentProperties());
862 4 : OSL_ENSURE(xSourceDocProps.is(), "DocumentProperties is null");
863 : }
864 :
865 4 : if( !bMergeShell && pSourceDocSh->IsModified() )
866 0 : pSfxDispatcher->Execute( pSourceDocSh->HasName() ? SID_SAVEDOC : SID_SAVEASDOC, SfxCallMode::SYNCHRON|SfxCallMode::RECORD);
867 4 : if( bMergeShell || !pSourceDocSh->IsModified() )
868 : {
869 : const SfxFilter* pStoreToFilter = SwIoSystem::GetFileFilter(
870 4 : pSourceDocSh->GetMedium()->GetURLObject().GetMainURL(INetURLObject::NO_DECODE));
871 4 : SfxFilterContainer* pFilterContainer = SwDocShell::Factory().GetFilterContainer();
872 4 : const OUString* pStoreToFilterOptions = 0;
873 :
874 : // if a save_to filter is set then use it - otherwise use the default
875 4 : if( bEMail && !rMergeDescriptor.bSendAsAttachment )
876 : {
877 0 : OUString sExtension = rMergeDescriptor.bSendAsHTML ? OUString("html") : OUString("txt");
878 0 : pStoreToFilter = pFilterContainer->GetFilter4Extension(sExtension, SFX_FILTER_EXPORT);
879 : }
880 4 : else if( !rMergeDescriptor.sSaveToFilter.isEmpty())
881 : {
882 : const SfxFilter* pFilter =
883 0 : pFilterContainer->GetFilter4FilterName( rMergeDescriptor.sSaveToFilter );
884 0 : if(pFilter)
885 : {
886 0 : pStoreToFilter = pFilter;
887 0 : if(!rMergeDescriptor.sSaveToFilterOptions.isEmpty())
888 0 : pStoreToFilterOptions = &rMergeDescriptor.sSaveToFilterOptions;
889 : }
890 : }
891 4 : bCancel = false;
892 :
893 : // in case of creating a single resulting file this has to be created here
894 4 : SwWrtShell* pTargetShell = 0;
895 4 : SwDoc* pTargetDoc = 0;
896 :
897 4 : SfxObjectShellRef xTargetDocShell;
898 :
899 4 : SwView* pTargetView = 0;
900 8 : boost::scoped_ptr< utl::TempFile > aTempFile;
901 8 : OUString sModifiedStartingPageDesc;
902 8 : OUString sStartingPageDesc;
903 4 : sal_uInt16 nStartingPageNo = 0;
904 4 : bool bPageStylesWithHeaderFooter = false;
905 :
906 4 : vcl::Window *pSourceWindow = 0;
907 4 : CancelableModelessDialog *pProgressDlg = 0;
908 :
909 4 : if (!IsMergeSilent()) {
910 0 : pSourceWindow = &pSourceShell->GetView().GetEditWin();
911 0 : if( bMergeShell )
912 0 : pProgressDlg = new CreateMonitor( pSourceWindow );
913 : else {
914 0 : pProgressDlg = new PrintMonitor( pSourceWindow, PrintMonitor::MONITOR_TYPE_PRINT );
915 0 : static_cast<PrintMonitor*>( pProgressDlg )->SetText(pSourceShell->GetView().GetDocShell()->GetTitle(22));
916 : }
917 0 : pProgressDlg->SetCancelHdl( LINK(this, SwDBManager, PrtCancelHdl) );
918 0 : pProgressDlg->Show();
919 :
920 0 : for( sal_uInt16 i = 0; i < 25; i++)
921 0 : Application::Reschedule();
922 : }
923 :
924 4 : if(rMergeDescriptor.bCreateSingleFile)
925 : {
926 : // create a target docshell to put the merged document into
927 4 : xTargetDocShell = new SwDocShell( SFX_CREATE_MODE_STANDARD );
928 4 : xTargetDocShell->DoInitNew( 0 );
929 4 : if (nMaxDumpDocs)
930 0 : lcl_SaveDoc( xTargetDocShell, "MergeDoc" );
931 4 : SfxViewFrame* pTargetFrame = SfxViewFrame::LoadHiddenDocument( *xTargetDocShell, 0 );
932 4 : if (bMergeShell && pSourceWindow) {
933 : //the created window has to be located at the same position as the source window
934 0 : vcl::Window& rTargetWindow = pTargetFrame->GetFrame().GetWindow();
935 0 : rTargetWindow.SetPosPixel(pSourceWindow->GetPosPixel());
936 : }
937 :
938 4 : pTargetView = static_cast<SwView*>( pTargetFrame->GetViewShell() );
939 :
940 : //initiate SelectShell() to create sub shells
941 4 : pTargetView->AttrChangedNotify( &pTargetView->GetWrtShell() );
942 4 : pTargetShell = pTargetView->GetWrtShellPtr();
943 4 : pTargetDoc = pTargetShell->GetDoc();
944 4 : pTargetDoc->SetInMailMerge(true);
945 :
946 : //copy the styles from the source to the target document
947 4 : pTargetView->GetDocShell()->_LoadStyles( *pSourceDocSh, true );
948 :
949 : //determine the page style and number used at the start of the source document
950 4 : pSourceShell->SttEndDoc(true);
951 4 : nStartingPageNo = pSourceShell->GetVirtPageNum();
952 8 : sStartingPageDesc = sModifiedStartingPageDesc = pSourceShell->GetPageDesc(
953 8 : pSourceShell->GetCurPageDesc()).GetName();
954 :
955 : // #i72517#
956 4 : const SwPageDesc* pSourcePageDesc = pSourceShell->FindPageDescByName( sStartingPageDesc );
957 4 : const SwFrmFmt& rMaster = pSourcePageDesc->GetMaster();
958 6 : bPageStylesWithHeaderFooter = rMaster.GetHeader().IsActive() ||
959 6 : rMaster.GetFooter().IsActive();
960 :
961 : // copy compatibility options
962 4 : pTargetShell->GetDoc()->ReplaceCompatibilityOptions( *pSourceShell->GetDoc());
963 : // #72821# copy dynamic defaults
964 4 : pTargetShell->GetDoc()->ReplaceDefaults( *pSourceShell->GetDoc());
965 :
966 4 : pTargetShell->GetDoc()->ReplaceDocumentProperties( *pSourceShell->GetDoc());
967 : }
968 :
969 : // Progress, to prohibit KeyInputs
970 8 : SfxProgress aProgress(pSourceDocSh, ::aEmptyOUStr, 1);
971 :
972 : // lock all dispatchers
973 4 : SfxViewFrame* pViewFrm = SfxViewFrame::GetFirst(pSourceDocSh);
974 8 : while (pViewFrm)
975 : {
976 0 : pViewFrm->GetDispatcher()->Lock(true);
977 0 : pViewFrm = SfxViewFrame::GetNext(*pViewFrm, pSourceDocSh);
978 : }
979 :
980 4 : sal_Int32 nDocNo = 1;
981 4 : sal_Int32 nDocCount = 0;
982 4 : if( !IsMergeSilent() && bMergeShell &&
983 0 : lcl_getCountFromResultSet( nDocCount, pImpl->pMergeData->xResultSet ) )
984 0 : static_cast<CreateMonitor*>( pProgressDlg )->SetTotalCount( nDocCount );
985 :
986 : long nStartRow, nEndRow;
987 4 : bool bFreezedLayouts = false;
988 : // collect temporary files
989 8 : ::std::vector< OUString> aFilesToRemove;
990 10 : do
991 : {
992 10 : nStartRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
993 : {
994 10 : OUString sPath(sSubject);
995 :
996 20 : OUString sAddress;
997 10 : if( !bEMail && bColumnName )
998 : {
999 0 : SwDBFormatData aDBFormat;
1000 0 : aDBFormat.xFormatter = pImpl->pMergeData->xFormatter;
1001 0 : aDBFormat.aNullDate = pImpl->pMergeData->aNullDate;
1002 0 : sAddress = GetDBField( xColumnProp, aDBFormat);
1003 0 : if (sAddress.isEmpty())
1004 0 : sAddress = "_";
1005 0 : sPath += sAddress;
1006 : }
1007 :
1008 : // create a new temporary file name - only done once in case of bCreateSingleFile
1009 10 : if( 1 == nDocNo || !rMergeDescriptor.bCreateSingleFile )
1010 : {
1011 4 : INetURLObject aEntry(sPath);
1012 8 : OUString sLeading;
1013 : //#i97667# if the name is from a database field then it will be used _as is_
1014 4 : if( !sAddress.isEmpty() )
1015 0 : sLeading = sAddress;
1016 : else
1017 4 : sLeading = aEntry.GetBase();
1018 4 : aEntry.removeSegment();
1019 4 : sPath = aEntry.GetMainURL( INetURLObject::NO_DECODE );
1020 8 : OUString sExt(comphelper::string::stripStart(pStoreToFilter->GetDefaultExtension(), '*'));
1021 : aTempFile.reset(
1022 4 : new utl::TempFile(sLeading, true, &sExt, &sPath));
1023 4 : if( rMergeDescriptor.bSubjectIsFilename )
1024 4 : aTempFile->EnableKillingFile();
1025 : }
1026 :
1027 10 : if( !aTempFile->IsValid() )
1028 : {
1029 0 : ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED );
1030 0 : bNoError = false;
1031 0 : bCancel = true;
1032 : }
1033 : else
1034 : {
1035 10 : INetURLObject aTempFileURL(aTempFile->GetURL());
1036 10 : if (!IsMergeSilent()) {
1037 0 : if( bMergeShell )
1038 0 : static_cast<CreateMonitor*>( pProgressDlg )->SetCurrentPosition( nDocNo );
1039 : else {
1040 0 : PrintMonitor *pPrintMonDlg = static_cast<PrintMonitor*>( pProgressDlg );
1041 0 : pPrintMonDlg->m_pPrinter->SetText( aTempFileURL.GetBase() );
1042 0 : OUString sStat(SW_RES(STR_STATSTR_LETTER)); // Brief
1043 0 : sStat += " ";
1044 0 : sStat += OUString::number( nDocNo );
1045 0 : pPrintMonDlg->m_pPrintInfo->SetText( sStat );
1046 : }
1047 0 : pProgressDlg->Update();
1048 : }
1049 :
1050 : // Computation time for the GUI
1051 260 : for( sal_uInt16 i = 0; i < 25; i++ )
1052 250 : Application::Reschedule();
1053 :
1054 : // The SfxObjectShell will be closed explicitly later but it is more safe to use SfxObjectShellLock here
1055 : // copy the source document
1056 20 : SfxObjectShellLock xWorkDocSh = pSourceDocSh->GetDoc()->CreateCopy( true );
1057 :
1058 : //create a view frame for the document
1059 10 : SwView* pWorkView = static_cast< SwView* >( SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 )->GetViewShell() );
1060 : //request the layout calculation
1061 10 : SwWrtShell& rWorkShell = pWorkView->GetWrtShell();
1062 10 : pWorkView->AttrChangedNotify( &rWorkShell );// in order for SelectShell to be called
1063 :
1064 10 : SwDoc* pWorkDoc = rWorkShell.GetDoc();
1065 10 : pWorkDoc->ReplaceDocumentProperties( *pSourceDocSh->GetDoc());
1066 10 : if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
1067 0 : lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo );
1068 10 : SwDBManager* pOldDBManager = pWorkDoc->GetDBManager();
1069 10 : pWorkDoc->SetDBManager( this );
1070 10 : pWorkDoc->getIDocumentLinksAdministration().EmbedAllLinks();
1071 :
1072 : // #i69458# lock fields to prevent access to the result set while calculating layout
1073 10 : rWorkShell.LockExpFlds();
1074 10 : rWorkShell.CalcLayout();
1075 10 : rWorkShell.UnlockExpFlds();
1076 :
1077 10 : SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE), xWorkDocSh));
1078 10 : rWorkShell.SwViewShell::UpdateFlds();
1079 10 : SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), xWorkDocSh));
1080 :
1081 10 : pWorkDoc->RemoveInvisibleContent();
1082 :
1083 : // launch MailMergeEvent if required
1084 10 : const SwXMailMerge *pEvtSrc = GetMailMergeEvtSrc();
1085 10 : if(pEvtSrc)
1086 : {
1087 10 : uno::Reference< XInterface > xRef( (XMailMergeBroadcaster *) pEvtSrc );
1088 20 : text::MailMergeEvent aEvt( xRef, xWorkDocSh->GetModel() );
1089 20 : pEvtSrc->LaunchMailMergeEvent( aEvt );
1090 : }
1091 :
1092 10 : if(rMergeDescriptor.bCreateSingleFile)
1093 : {
1094 : OSL_ENSURE( pTargetShell, "no target shell available!" );
1095 : // copy created file into the target document
1096 10 : rWorkShell.ConvertFieldsToText();
1097 10 : rWorkShell.SetNumberingRestart();
1098 10 : if( bSynchronizedDoc )
1099 : {
1100 0 : lcl_RemoveSectionLinks( rWorkShell );
1101 : }
1102 :
1103 : // insert the document into the target document
1104 :
1105 : //#i72517# put the styles to the target document
1106 : //if the source uses headers or footers each new copy need to copy a new page styles
1107 : SwPageDesc* pTargetPageDesc;
1108 10 : if(bPageStylesWithHeaderFooter)
1109 : {
1110 : //create a new pagestyle
1111 : //copy the pagedesc from the current document to the new document and change the name of the to-be-applied style
1112 2 : OUString sNewPageDescName = lcl_FindUniqueName(pTargetShell, sStartingPageDesc, nDocNo );
1113 2 : pTargetPageDesc = pTargetDoc->MakePageDesc( sNewPageDescName );
1114 2 : const SwPageDesc* pWorkPageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc );
1115 :
1116 2 : if(pWorkPageDesc && pTargetPageDesc)
1117 : {
1118 2 : pTargetDoc->CopyPageDesc( *pWorkPageDesc, *pTargetPageDesc, false );
1119 2 : sModifiedStartingPageDesc = sNewPageDescName;
1120 2 : lcl_CopyFollowPageDesc( *pTargetShell, *pWorkPageDesc, *pTargetPageDesc, nDocNo );
1121 2 : }
1122 : }
1123 : else
1124 8 : pTargetPageDesc = pTargetShell->FindPageDescByName( sModifiedStartingPageDesc );
1125 :
1126 10 : sal_uInt16 nStartPage = pTargetShell->GetPageCnt();
1127 10 : if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
1128 0 : lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo );
1129 10 : pTargetDoc->AppendDoc(*rWorkShell.GetDoc(),
1130 20 : nStartingPageNo, pTargetPageDesc, nDocNo == 1);
1131 :
1132 : // #i72820# calculate layout to be able to find the correct page index
1133 10 : pTargetShell->CalcLayout();
1134 10 : if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
1135 0 : lcl_SaveDoc( xTargetDocShell, "MergeDoc" );
1136 10 : if (bMergeShell)
1137 : {
1138 : SwDocMergeInfo aMergeInfo;
1139 10 : aMergeInfo.nStartPageInTarget = nStartPage;
1140 : aMergeInfo.nEndPageInTarget =
1141 10 : nStartPage + pSourceShell->GetPageCnt() - 1;
1142 10 : aMergeInfo.nDBRow = nStartRow;
1143 10 : rMergeDescriptor.pMailMergeConfigItem->AddMergedDocument( aMergeInfo );
1144 : }
1145 : }
1146 : else
1147 : {
1148 0 : OUString sFileURL = aTempFileURL.GetMainURL( INetURLObject::NO_DECODE );
1149 : SfxMedium* pDstMed = new SfxMedium(
1150 : sFileURL,
1151 0 : STREAM_STD_READWRITE );
1152 0 : pDstMed->SetFilter( pStoreToFilter );
1153 0 : if(pDstMed->GetItemSet())
1154 : {
1155 0 : if(pStoreToFilterOptions )
1156 0 : pDstMed->GetItemSet()->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, *pStoreToFilterOptions));
1157 0 : if(rMergeDescriptor.aSaveToFilterData.getLength())
1158 0 : pDstMed->GetItemSet()->Put(SfxUsrAnyItem(SID_FILTER_DATA, makeAny(rMergeDescriptor.aSaveToFilterData)));
1159 : }
1160 :
1161 : //convert fields to text if we are exporting to PDF
1162 : //this prevents a second merge while updating the fields in SwXTextDocument::getRendererCount()
1163 0 : if( pStoreToFilter && pStoreToFilter->GetFilterName().equalsAscii("writer_pdf_Export"))
1164 0 : rWorkShell.ConvertFieldsToText();
1165 0 : xWorkDocSh->DoSaveAs(*pDstMed);
1166 0 : xWorkDocSh->DoSaveCompleted(pDstMed);
1167 0 : if( xWorkDocSh->GetError() )
1168 : {
1169 : // error message ??
1170 0 : ErrorHandler::HandleError( xWorkDocSh->GetError() );
1171 0 : bCancel = true;
1172 0 : bNoError = false;
1173 : }
1174 0 : if( bEMail )
1175 : {
1176 0 : SwDBFormatData aDBFormat;
1177 0 : aDBFormat.xFormatter = pImpl->pMergeData->xFormatter;
1178 0 : aDBFormat.aNullDate = pImpl->pMergeData->aNullDate;
1179 0 : OUString sMailAddress = GetDBField( xColumnProp, aDBFormat);
1180 0 : if(!SwMailMergeHelper::CheckMailAddress( sMailAddress ))
1181 : {
1182 : OSL_FAIL("invalid e-Mail address in database column");
1183 : }
1184 : else
1185 : {
1186 0 : SwMailMessage* pMessage = new SwMailMessage;
1187 0 : uno::Reference< mail::XMailMessage > xMessage = pMessage;
1188 0 : if(rMergeDescriptor.pMailMergeConfigItem->IsMailReplyTo())
1189 0 : pMessage->setReplyToAddress(rMergeDescriptor.pMailMergeConfigItem->GetMailReplyTo());
1190 0 : pMessage->addRecipient( sMailAddress );
1191 0 : pMessage->SetSenderAddress( rMergeDescriptor.pMailMergeConfigItem->GetMailAddress() );
1192 0 : OUString sBody;
1193 0 : if(rMergeDescriptor.bSendAsAttachment)
1194 : {
1195 0 : sBody = rMergeDescriptor.sMailBody;
1196 0 : mail::MailAttachment aAttach;
1197 0 : aAttach.Data = new SwMailTransferable(
1198 : sFileURL,
1199 : rMergeDescriptor.sAttachmentName,
1200 0 : pStoreToFilter->GetMimeType());
1201 0 : aAttach.ReadableName = rMergeDescriptor.sAttachmentName;
1202 0 : pMessage->addAttachment( aAttach );
1203 : }
1204 : else
1205 : {
1206 : {
1207 : //read in the temporary file and use it as mail body
1208 0 : SfxMedium aMedium( sFileURL, STREAM_READ);
1209 0 : SvStream* pInStream = aMedium.GetInStream();
1210 : OSL_ENSURE(pInStream, "no output file created?");
1211 0 : if(pInStream)
1212 : {
1213 0 : pInStream->SetStreamCharSet( eEncoding );
1214 0 : OString sLine;
1215 0 : bool bDone = pInStream->ReadLine( sLine );
1216 0 : while ( bDone )
1217 : {
1218 0 : sBody += OStringToOUString(sLine, eEncoding);
1219 0 : sBody += "\n";
1220 0 : bDone = pInStream->ReadLine( sLine );
1221 0 : }
1222 0 : }
1223 : }
1224 : }
1225 0 : pMessage->setSubject( rMergeDescriptor.sSubject );
1226 : uno::Reference< datatransfer::XTransferable> xBody =
1227 : new SwMailTransferable(
1228 : sBody,
1229 0 : sBodyMimeType);
1230 0 : pMessage->setBody( xBody );
1231 :
1232 0 : if(rMergeDescriptor.aCopiesTo.getLength())
1233 : {
1234 0 : const OUString* pCopies = rMergeDescriptor.aCopiesTo.getConstArray();
1235 0 : for( sal_Int32 nToken = 0; nToken < rMergeDescriptor.aCopiesTo.getLength(); ++nToken)
1236 0 : pMessage->addCcRecipient( pCopies[nToken] );
1237 : }
1238 0 : if(rMergeDescriptor.aBlindCopiesTo.getLength())
1239 : {
1240 0 : const OUString* pCopies = rMergeDescriptor.aBlindCopiesTo.getConstArray();
1241 0 : for( sal_Int32 nToken = 0; nToken < rMergeDescriptor.aBlindCopiesTo.getLength(); ++nToken)
1242 0 : pMessage->addBccRecipient( pCopies[nToken] );
1243 : }
1244 0 : xMailDispatcher->enqueueMailMessage( xMessage );
1245 0 : if(!xMailDispatcher->isStarted())
1246 0 : xMailDispatcher->start();
1247 : //schedule for removal
1248 0 : aFilesToRemove.push_back(sFileURL);
1249 0 : }
1250 0 : }
1251 : }
1252 10 : pWorkDoc->SetDBManager( pOldDBManager );
1253 :
1254 20 : xWorkDocSh->DoClose();
1255 10 : }
1256 : }
1257 10 : nDocNo++;
1258 10 : nEndRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
1259 :
1260 : // Freeze the layouts of the target document after the first inserted
1261 : // sub-document, to get the correct PageDesc.
1262 10 : if(!bFreezedLayouts && (rMergeDescriptor.bCreateSingleFile))
1263 : {
1264 4 : std::set<SwRootFrm*> aAllLayouts = pTargetShell->GetDoc()->GetAllLayouts();
1265 : std::for_each( aAllLayouts.begin(), aAllLayouts.end(),
1266 4 : ::std::bind2nd(::std::mem_fun(&SwRootFrm::FreezeLayout), true));
1267 4 : bFreezedLayouts = true;
1268 : }
1269 20 : } while( !bCancel &&
1270 10 : (bSynchronizedDoc && (nStartRow != nEndRow)? ExistsNextRecord() : ToNextMergeRecord()));
1271 4 : if (rMergeDescriptor.bCreateSingleFile)
1272 : {
1273 : // sw::DocumentLayoutManager::CopyLayoutFmt() did not generate
1274 : // unique fly names, do it here once.
1275 4 : pTargetDoc->SetInMailMerge(false);
1276 4 : pTargetDoc->SetAllUniqueFlyNames();
1277 : }
1278 :
1279 104 : for( sal_uInt16 i = 0; i < 25; i++)
1280 100 : Application::Reschedule();
1281 :
1282 : // Unfreeze target document layouts and correct all PageDescs.
1283 4 : if(rMergeDescriptor.bCreateSingleFile)
1284 : {
1285 4 : std::set<SwRootFrm*> aAllLayouts = pTargetShell->GetDoc()->GetAllLayouts();
1286 : std::for_each( aAllLayouts.begin(), aAllLayouts.end(),
1287 4 : ::std::bind2nd(::std::mem_fun(&SwRootFrm::FreezeLayout), false));
1288 4 : std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllCheckPageDescs));
1289 : }
1290 :
1291 4 : DELETEZ( pProgressDlg );
1292 :
1293 : // save the single output document
1294 4 : if (bMergeShell)
1295 : {
1296 4 : rMergeDescriptor.pMailMergeConfigItem->SetTargetView( pTargetView );
1297 : }
1298 0 : else if(rMergeDescriptor.bCreateSingleFile)
1299 : {
1300 0 : if( rMergeDescriptor.nMergeType != DBMGR_MERGE_PRINTER )
1301 : {
1302 : OSL_ENSURE( aTempFile.get(), "Temporary file not available" );
1303 0 : INetURLObject aTempFileURL( rMergeDescriptor.bSubjectIsFilename ? sSubject : aTempFile->GetURL());
1304 : SfxMedium* pDstMed = new SfxMedium(
1305 : aTempFileURL.GetMainURL( INetURLObject::NO_DECODE ),
1306 0 : STREAM_STD_READWRITE );
1307 0 : pDstMed->SetFilter( pStoreToFilter );
1308 0 : if(pDstMed->GetItemSet())
1309 : {
1310 0 : if(pStoreToFilterOptions )
1311 0 : pDstMed->GetItemSet()->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, *pStoreToFilterOptions));
1312 0 : if(rMergeDescriptor.aSaveToFilterData.getLength())
1313 0 : pDstMed->GetItemSet()->Put(SfxUsrAnyItem(SID_FILTER_DATA, makeAny(rMergeDescriptor.aSaveToFilterData)));
1314 : }
1315 :
1316 0 : xTargetDocShell->DoSaveAs(*pDstMed);
1317 0 : xTargetDocShell->DoSaveCompleted(pDstMed);
1318 0 : if( xTargetDocShell->GetError() )
1319 : {
1320 : // error message ??
1321 0 : ErrorHandler::HandleError( xTargetDocShell->GetError() );
1322 0 : bNoError = false;
1323 0 : }
1324 : }
1325 0 : else if( pTargetView ) // must be available!
1326 : {
1327 : //print the target document
1328 : #if OSL_DEBUG_LEVEL > 1
1329 : bool _bVal;
1330 : sal_Int16 _nVal;
1331 : OUString _sVal;
1332 : const beans::PropertyValue* pDbgPrintOptions = rMergeDescriptor.aPrintOptions.getConstArray();
1333 : for( sal_Int32 nOption = 0; nOption < rMergeDescriptor.aPrintOptions.getLength(); ++nOption)
1334 : {
1335 : OUString aName( pDbgPrintOptions[nOption].Name );
1336 : uno::Any aVal( pDbgPrintOptions[nOption].Value );
1337 : aVal >>= _bVal;
1338 : aVal >>= _nVal;
1339 : aVal >>= _sVal;
1340 : }
1341 : #endif
1342 : // printing should be done synchronously otherwise the document
1343 : // might already become invalid during the process
1344 0 : uno::Sequence< beans::PropertyValue > aOptions( rMergeDescriptor.aPrintOptions );
1345 :
1346 0 : aOptions.realloc( 1 );
1347 0 : aOptions[ 0 ].Name = "Wait";
1348 0 : aOptions[ 0 ].Value <<= sal_True ;
1349 : // move print options
1350 0 : const beans::PropertyValue* pPrintOptions = rMergeDescriptor.aPrintOptions.getConstArray();
1351 0 : for( sal_Int32 nOption = 0, nIndex = 1 ; nOption < rMergeDescriptor.aPrintOptions.getLength(); ++nOption)
1352 : {
1353 0 : if( pPrintOptions[nOption].Name == "CopyCount" || pPrintOptions[nOption].Name == "FileName"
1354 0 : || pPrintOptions[nOption].Name == "Collate" || pPrintOptions[nOption].Name == "Pages"
1355 0 : || pPrintOptions[nOption].Name == "Wait" || pPrintOptions[nOption].Name == "PrinterName" )
1356 : {
1357 : // add an option
1358 0 : aOptions.realloc( nIndex + 1 );
1359 0 : aOptions[ nIndex ].Name = pPrintOptions[nOption].Name;
1360 0 : aOptions[ nIndex++ ].Value = pPrintOptions[nOption].Value ;
1361 : }
1362 : }
1363 :
1364 0 : pTargetView->ExecPrint( aOptions, IsMergeSilent(), rMergeDescriptor.bPrintAsync );
1365 : }
1366 :
1367 : // Leave docshell available for caller (e.g. MM wizard)
1368 0 : if (!bMergeShell)
1369 0 : xTargetDocShell->DoClose();
1370 : }
1371 :
1372 : //remove the temporary files
1373 4 : ::std::vector<OUString>::iterator aFileIter;
1374 12 : for(aFileIter = aFilesToRemove.begin();
1375 8 : aFileIter != aFilesToRemove.end(); ++aFileIter)
1376 0 : SWUnoHelper::UCB_DeleteFile( *aFileIter );
1377 :
1378 : // unlock all dispatchers
1379 4 : pViewFrm = SfxViewFrame::GetFirst(pSourceDocSh);
1380 8 : while (pViewFrm)
1381 : {
1382 0 : pViewFrm->GetDispatcher()->Lock(false);
1383 0 : pViewFrm = SfxViewFrame::GetNext(*pViewFrm, pSourceDocSh);
1384 : }
1385 :
1386 8 : SW_MOD()->SetView(&pSourceShell->GetView());
1387 4 : }
1388 : }
1389 :
1390 4 : if(bEMail)
1391 : {
1392 0 : xMailDispatcher->stop();
1393 0 : xMailDispatcher->shutdown();
1394 : }
1395 :
1396 8 : return bNoError;
1397 : }
1398 :
1399 0 : void SwDBManager::MergeCancel()
1400 : {
1401 0 : bCancel = true;
1402 0 : }
1403 :
1404 0 : IMPL_LINK_INLINE_START( SwDBManager, PrtCancelHdl, Button *, pButton )
1405 : {
1406 0 : pButton->GetParent()->Hide();
1407 0 : MergeCancel();
1408 0 : return 0;
1409 : }
1410 0 : IMPL_LINK_INLINE_END( SwDBManager, PrtCancelHdl, Button *, pButton )
1411 :
1412 : // determine the column's Numberformat and transfer to the forwarded Formatter,
1413 : // if applicable.
1414 0 : sal_uLong SwDBManager::GetColumnFmt( const OUString& rDBName,
1415 : const OUString& rTableName,
1416 : const OUString& rColNm,
1417 : SvNumberFormatter* pNFmtr,
1418 : long nLanguage )
1419 : {
1420 0 : sal_uLong nRet = 0;
1421 0 : if(pNFmtr)
1422 : {
1423 0 : uno::Reference< XDataSource> xSource;
1424 0 : uno::Reference< XConnection> xConnection;
1425 0 : bool bUseMergeData = false;
1426 0 : uno::Reference< XColumnsSupplier> xColsSupp;
1427 0 : bool bDisposeConnection = false;
1428 0 : if(pImpl->pMergeData &&
1429 0 : pImpl->pMergeData->sDataSource.equals(rDBName) && pImpl->pMergeData->sCommand.equals(rTableName))
1430 : {
1431 0 : xConnection = pImpl->pMergeData->xConnection;
1432 0 : xSource = SwDBManager::getDataSourceAsParent(xConnection,rDBName);
1433 0 : bUseMergeData = true;
1434 0 : xColsSupp.set(pImpl->pMergeData->xResultSet, css::uno::UNO_QUERY);
1435 : }
1436 0 : if(!xConnection.is())
1437 : {
1438 0 : SwDBData aData;
1439 0 : aData.sDataSource = rDBName;
1440 0 : aData.sCommand = rTableName;
1441 0 : aData.nCommandType = -1;
1442 0 : SwDSParam* pParam = FindDSData(aData, false);
1443 0 : if(pParam && pParam->xConnection.is())
1444 : {
1445 0 : xConnection = pParam->xConnection;
1446 0 : xColsSupp.set(pParam->xResultSet, css::uno::UNO_QUERY);
1447 : }
1448 : else
1449 : {
1450 0 : OUString sDBName(rDBName);
1451 0 : xConnection = RegisterConnection( sDBName );
1452 0 : bDisposeConnection = true;
1453 : }
1454 0 : if(bUseMergeData)
1455 0 : pImpl->pMergeData->xConnection = xConnection;
1456 : }
1457 0 : bool bDispose = !xColsSupp.is();
1458 0 : if(bDispose)
1459 : {
1460 0 : xColsSupp = SwDBManager::GetColumnSupplier(xConnection, rTableName);
1461 : }
1462 0 : if(xColsSupp.is())
1463 : {
1464 0 : uno::Reference<XNameAccess> xCols;
1465 : try
1466 : {
1467 0 : xCols = xColsSupp->getColumns();
1468 : }
1469 0 : catch(const Exception&)
1470 : {
1471 : OSL_FAIL("Exception in getColumns()");
1472 : }
1473 0 : if(!xCols.is() || !xCols->hasByName(rColNm))
1474 0 : return nRet;
1475 0 : Any aCol = xCols->getByName(rColNm);
1476 0 : uno::Reference< XPropertySet > xColumn;
1477 0 : aCol >>= xColumn;
1478 0 : nRet = GetColumnFmt(xSource, xConnection, xColumn, pNFmtr, nLanguage);
1479 0 : if(bDispose)
1480 : {
1481 0 : ::comphelper::disposeComponent( xColsSupp );
1482 : }
1483 0 : if(bDisposeConnection)
1484 : {
1485 0 : ::comphelper::disposeComponent( xConnection );
1486 0 : }
1487 : }
1488 : else
1489 0 : nRet = pNFmtr->GetFormatIndex( NF_NUMBER_STANDARD, LANGUAGE_SYSTEM );
1490 : }
1491 0 : return nRet;
1492 : }
1493 :
1494 0 : sal_uLong SwDBManager::GetColumnFmt( uno::Reference< XDataSource> xSource,
1495 : uno::Reference< XConnection> xConnection,
1496 : uno::Reference< XPropertySet> xColumn,
1497 : SvNumberFormatter* pNFmtr,
1498 : long nLanguage )
1499 : {
1500 : // set the NumberFormat in the doc if applicable
1501 0 : sal_uLong nRet = 0;
1502 :
1503 0 : if(!xSource.is())
1504 : {
1505 0 : uno::Reference<XChild> xChild(xConnection, UNO_QUERY);
1506 0 : if ( xChild.is() )
1507 0 : xSource = uno::Reference<XDataSource>(xChild->getParent(), UNO_QUERY);
1508 : }
1509 0 : if(xSource.is() && xConnection.is() && xColumn.is() && pNFmtr)
1510 : {
1511 0 : SvNumberFormatsSupplierObj* pNumFmt = new SvNumberFormatsSupplierObj( pNFmtr );
1512 0 : uno::Reference< util::XNumberFormatsSupplier > xDocNumFmtsSupplier = pNumFmt;
1513 0 : uno::Reference< XNumberFormats > xDocNumberFormats = xDocNumFmtsSupplier->getNumberFormats();
1514 0 : uno::Reference< XNumberFormatTypes > xDocNumberFormatTypes(xDocNumberFormats, UNO_QUERY);
1515 :
1516 0 : com::sun::star::lang::Locale aLocale( LanguageTag( (LanguageType)nLanguage ).getLocale());
1517 :
1518 : //get the number formatter of the data source
1519 0 : uno::Reference<XPropertySet> xSourceProps(xSource, UNO_QUERY);
1520 0 : uno::Reference< XNumberFormats > xNumberFormats;
1521 0 : if(xSourceProps.is())
1522 : {
1523 0 : Any aFormats = xSourceProps->getPropertyValue("NumberFormatsSupplier");
1524 0 : if(aFormats.hasValue())
1525 : {
1526 0 : uno::Reference<XNumberFormatsSupplier> xSuppl;
1527 0 : aFormats >>= xSuppl;
1528 0 : if(xSuppl.is())
1529 : {
1530 0 : xNumberFormats = xSuppl->getNumberFormats();
1531 0 : }
1532 0 : }
1533 : }
1534 0 : bool bUseDefault = true;
1535 : try
1536 : {
1537 0 : Any aFormatKey = xColumn->getPropertyValue("FormatKey");
1538 0 : if(aFormatKey.hasValue())
1539 : {
1540 0 : sal_Int32 nFmt = 0;
1541 0 : aFormatKey >>= nFmt;
1542 0 : if(xNumberFormats.is())
1543 : {
1544 : try
1545 : {
1546 0 : uno::Reference<XPropertySet> xNumProps = xNumberFormats->getByKey( nFmt );
1547 0 : Any aFormatString = xNumProps->getPropertyValue("FormatString");
1548 0 : Any aLocaleVal = xNumProps->getPropertyValue("Locale");
1549 0 : OUString sFormat;
1550 0 : aFormatString >>= sFormat;
1551 0 : lang::Locale aLoc;
1552 0 : aLocaleVal >>= aLoc;
1553 0 : nFmt = xDocNumberFormats->queryKey( sFormat, aLoc, sal_False );
1554 0 : if(NUMBERFORMAT_ENTRY_NOT_FOUND == sal::static_int_cast< sal_uInt32, sal_Int32>(nFmt))
1555 0 : nFmt = xDocNumberFormats->addNew( sFormat, aLoc );
1556 0 : nRet = nFmt;
1557 0 : bUseDefault = false;
1558 : }
1559 0 : catch(const Exception&)
1560 : {
1561 : OSL_FAIL("illegal number format key");
1562 : }
1563 : }
1564 0 : }
1565 : }
1566 0 : catch(const Exception&)
1567 : {
1568 : OSL_FAIL("no FormatKey property found");
1569 : }
1570 0 : if(bUseDefault)
1571 0 : nRet = SwDBManager::GetDbtoolsClient().getDefaultNumberFormat(xColumn, xDocNumberFormatTypes, aLocale);
1572 : }
1573 0 : return nRet;
1574 : }
1575 :
1576 0 : sal_Int32 SwDBManager::GetColumnType( const OUString& rDBName,
1577 : const OUString& rTableName,
1578 : const OUString& rColNm )
1579 : {
1580 0 : sal_Int32 nRet = DataType::SQLNULL;
1581 0 : SwDBData aData;
1582 0 : aData.sDataSource = rDBName;
1583 0 : aData.sCommand = rTableName;
1584 0 : aData.nCommandType = -1;
1585 0 : SwDSParam* pParam = FindDSData(aData, false);
1586 0 : uno::Reference< XConnection> xConnection;
1587 0 : uno::Reference< XColumnsSupplier > xColsSupp;
1588 0 : bool bDispose = false;
1589 0 : if(pParam && pParam->xConnection.is())
1590 : {
1591 0 : xConnection = pParam->xConnection;
1592 0 : xColsSupp = uno::Reference< XColumnsSupplier >( pParam->xResultSet, UNO_QUERY );
1593 : }
1594 : else
1595 : {
1596 0 : OUString sDBName(rDBName);
1597 0 : xConnection = RegisterConnection( sDBName );
1598 : }
1599 0 : if( !xColsSupp.is() )
1600 : {
1601 0 : xColsSupp = SwDBManager::GetColumnSupplier(xConnection, rTableName);
1602 0 : bDispose = true;
1603 : }
1604 0 : if(xColsSupp.is())
1605 : {
1606 0 : uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
1607 0 : if(xCols->hasByName(rColNm))
1608 : {
1609 0 : Any aCol = xCols->getByName(rColNm);
1610 0 : uno::Reference<XPropertySet> xCol;
1611 0 : aCol >>= xCol;
1612 0 : Any aType = xCol->getPropertyValue("Type");
1613 0 : aType >>= nRet;
1614 : }
1615 0 : if(bDispose)
1616 0 : ::comphelper::disposeComponent( xColsSupp );
1617 : }
1618 0 : return nRet;
1619 : }
1620 :
1621 0 : uno::Reference< sdbc::XConnection> SwDBManager::GetConnection(const OUString& rDataSource,
1622 : uno::Reference<XDataSource>& rxSource)
1623 : {
1624 0 : Reference< sdbc::XConnection> xConnection;
1625 0 : Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
1626 : try
1627 : {
1628 0 : Reference<XCompletedConnection> xComplConnection(SwDBManager::GetDbtoolsClient().getDataSource(rDataSource, xContext),UNO_QUERY);
1629 0 : if ( xComplConnection.is() )
1630 : {
1631 0 : rxSource.set(xComplConnection,UNO_QUERY);
1632 0 : Reference< XInteractionHandler > xHandler( InteractionHandler::createWithParent(xContext, 0), UNO_QUERY_THROW );
1633 0 : xConnection = xComplConnection->connectWithCompletion( xHandler );
1634 0 : }
1635 : }
1636 0 : catch(const Exception&)
1637 : {
1638 : }
1639 :
1640 0 : return xConnection;
1641 : }
1642 :
1643 0 : uno::Reference< sdbcx::XColumnsSupplier> SwDBManager::GetColumnSupplier(uno::Reference<sdbc::XConnection> xConnection,
1644 : const OUString& rTableOrQuery,
1645 : sal_uInt8 eTableOrQuery)
1646 : {
1647 0 : Reference< sdbcx::XColumnsSupplier> xRet;
1648 : try
1649 : {
1650 0 : if(eTableOrQuery == SW_DB_SELECT_UNKNOWN)
1651 : {
1652 : //search for a table with the given command name
1653 0 : Reference<XTablesSupplier> xTSupplier = Reference<XTablesSupplier>(xConnection, UNO_QUERY);
1654 0 : if(xTSupplier.is())
1655 : {
1656 0 : Reference<XNameAccess> xTbls = xTSupplier->getTables();
1657 0 : eTableOrQuery = xTbls->hasByName(rTableOrQuery) ?
1658 0 : SW_DB_SELECT_TABLE : SW_DB_SELECT_QUERY;
1659 0 : }
1660 : }
1661 : sal_Int32 nCommandType = SW_DB_SELECT_TABLE == eTableOrQuery ?
1662 0 : CommandType::TABLE : CommandType::QUERY;
1663 0 : Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
1664 0 : Reference<XRowSet> xRowSet(xMgr->createInstance("com.sun.star.sdb.RowSet"), UNO_QUERY);
1665 :
1666 0 : OUString sDataSource;
1667 0 : Reference<XDataSource> xSource = SwDBManager::getDataSourceAsParent(xConnection, sDataSource);
1668 0 : Reference<XPropertySet> xSourceProperties(xSource, UNO_QUERY);
1669 0 : if(xSourceProperties.is())
1670 : {
1671 0 : xSourceProperties->getPropertyValue("Name") >>= sDataSource;
1672 : }
1673 :
1674 0 : Reference<XPropertySet> xRowProperties(xRowSet, UNO_QUERY);
1675 0 : xRowProperties->setPropertyValue("DataSourceName", makeAny(sDataSource));
1676 0 : xRowProperties->setPropertyValue("Command", makeAny(OUString(rTableOrQuery)));
1677 0 : xRowProperties->setPropertyValue("CommandType", makeAny(nCommandType));
1678 0 : xRowProperties->setPropertyValue("FetchSize", makeAny((sal_Int32)10));
1679 0 : xRowProperties->setPropertyValue("ActiveConnection", makeAny(xConnection));
1680 0 : xRowSet->execute();
1681 0 : xRet = Reference<XColumnsSupplier>( xRowSet, UNO_QUERY );
1682 : }
1683 0 : catch(const uno::Exception&)
1684 : {
1685 : OSL_FAIL("Exception in SwDBManager::GetColumnSupplier");
1686 : }
1687 :
1688 0 : return xRet;
1689 : }
1690 :
1691 0 : OUString SwDBManager::GetDBField(uno::Reference<XPropertySet> xColumnProps,
1692 : const SwDBFormatData& rDBFormatData,
1693 : double* pNumber)
1694 : {
1695 0 : uno::Reference< XColumn > xColumn(xColumnProps, UNO_QUERY);
1696 0 : OUString sRet;
1697 : OSL_ENSURE(xColumn.is(), "SwDBManager::::ImportDBField: illegal arguments");
1698 0 : if(!xColumn.is())
1699 0 : return sRet;
1700 :
1701 0 : Any aType = xColumnProps->getPropertyValue("Type");
1702 0 : sal_Int32 eDataType = DataType::SQLNULL;
1703 0 : aType >>= eDataType;
1704 0 : switch(eDataType)
1705 : {
1706 : case DataType::CHAR:
1707 : case DataType::VARCHAR:
1708 : case DataType::LONGVARCHAR:
1709 : try
1710 : {
1711 0 : sRet = xColumn->getString();
1712 0 : sRet = sRet.replace( '\xb', '\n' ); // MSWord uses \xb as a newline
1713 : }
1714 0 : catch(const SQLException&)
1715 : {
1716 : }
1717 0 : break;
1718 : case DataType::BIT:
1719 : case DataType::BOOLEAN:
1720 : case DataType::TINYINT:
1721 : case DataType::SMALLINT:
1722 : case DataType::INTEGER:
1723 : case DataType::BIGINT:
1724 : case DataType::FLOAT:
1725 : case DataType::REAL:
1726 : case DataType::DOUBLE:
1727 : case DataType::NUMERIC:
1728 : case DataType::DECIMAL:
1729 : case DataType::DATE:
1730 : case DataType::TIME:
1731 : case DataType::TIMESTAMP:
1732 : {
1733 :
1734 : try
1735 : {
1736 0 : SwDbtoolsClient& aClient = SwDBManager::GetDbtoolsClient();
1737 0 : sRet = aClient.getFormattedValue(
1738 : xColumnProps,
1739 : rDBFormatData.xFormatter,
1740 : rDBFormatData.aLocale,
1741 0 : rDBFormatData.aNullDate);
1742 0 : if (pNumber)
1743 : {
1744 0 : double fVal = xColumn->getDouble();
1745 0 : if(!xColumn->wasNull())
1746 : {
1747 0 : *pNumber = fVal;
1748 : }
1749 : }
1750 : }
1751 0 : catch(const Exception&)
1752 : {
1753 : OSL_FAIL("exception caught");
1754 : }
1755 :
1756 : }
1757 0 : break;
1758 : }
1759 :
1760 0 : return sRet;
1761 : }
1762 :
1763 : // checks if a desired data source table or query is open
1764 100 : bool SwDBManager::IsDataSourceOpen(const OUString& rDataSource,
1765 : const OUString& rTableOrQuery, bool bMergeShell)
1766 : {
1767 100 : if(pImpl->pMergeData)
1768 : {
1769 64 : return !bMergeLock &&
1770 32 : ((rDataSource == pImpl->pMergeData->sDataSource &&
1771 0 : rTableOrQuery == pImpl->pMergeData->sCommand)
1772 32 : ||(rDataSource.isEmpty() && rTableOrQuery.isEmpty()))
1773 32 : &&
1774 32 : pImpl->pMergeData->xResultSet.is();
1775 : }
1776 68 : else if(!bMergeShell)
1777 : {
1778 34 : SwDBData aData;
1779 34 : aData.sDataSource = rDataSource;
1780 34 : aData.sCommand = rTableOrQuery;
1781 34 : aData.nCommandType = -1;
1782 34 : SwDSParam* pFound = FindDSData(aData, false);
1783 34 : return (pFound && pFound->xResultSet.is());
1784 : }
1785 34 : return false;
1786 : }
1787 :
1788 : // read column data at a specified position
1789 0 : bool SwDBManager::GetColumnCnt(const OUString& rSourceName, const OUString& rTableName,
1790 : const OUString& rColumnName, sal_uInt32 nAbsRecordId,
1791 : long nLanguage,
1792 : OUString& rResult, double* pNumber)
1793 : {
1794 0 : bool bRet = false;
1795 0 : SwDSParam* pFound = 0;
1796 : //check if it's the merge data source
1797 0 : if(pImpl->pMergeData &&
1798 0 : rSourceName == pImpl->pMergeData->sDataSource &&
1799 0 : rTableName == pImpl->pMergeData->sCommand)
1800 : {
1801 0 : pFound = pImpl->pMergeData;
1802 : }
1803 : else
1804 : {
1805 0 : SwDBData aData;
1806 0 : aData.sDataSource = rSourceName;
1807 0 : aData.sCommand = rTableName;
1808 0 : aData.nCommandType = -1;
1809 0 : pFound = FindDSData(aData, false);
1810 : }
1811 0 : if (!pFound)
1812 0 : return false;
1813 : //check validity of supplied record Id
1814 0 : if(pFound->aSelection.getLength())
1815 : {
1816 : //the destination has to be an element of the selection
1817 0 : const Any* pSelection = pFound->aSelection.getConstArray();
1818 0 : bool bFound = false;
1819 0 : for(sal_Int32 nPos = 0; !bFound && nPos < pFound->aSelection.getLength(); nPos++)
1820 : {
1821 0 : sal_Int32 nSelection = 0;
1822 0 : pSelection[nPos] >>= nSelection;
1823 0 : if(nSelection == static_cast<sal_Int32>(nAbsRecordId))
1824 0 : bFound = true;
1825 : }
1826 0 : if(!bFound)
1827 0 : return false;
1828 : }
1829 0 : if(pFound->xResultSet.is() && !pFound->bAfterSelection)
1830 : {
1831 0 : sal_Int32 nOldRow = 0;
1832 : try
1833 : {
1834 0 : nOldRow = pFound->xResultSet->getRow();
1835 : }
1836 0 : catch(const Exception&)
1837 : {
1838 0 : return false;
1839 : }
1840 : //position to the desired index
1841 0 : bool bMove = true;
1842 0 : if ( nOldRow != static_cast<sal_Int32>(nAbsRecordId) )
1843 0 : bMove = lcl_MoveAbsolute(pFound, nAbsRecordId);
1844 0 : if(bMove)
1845 : {
1846 0 : bRet = lcl_GetColumnCnt(pFound, rColumnName, nLanguage, rResult, pNumber);
1847 : }
1848 0 : if ( nOldRow != static_cast<sal_Int32>(nAbsRecordId) )
1849 0 : bMove = lcl_MoveAbsolute(pFound, nOldRow);
1850 : }
1851 0 : return bRet;
1852 : }
1853 :
1854 : // reads the column data at the current position
1855 0 : bool SwDBManager::GetMergeColumnCnt(const OUString& rColumnName, sal_uInt16 nLanguage,
1856 : OUString &rResult, double *pNumber, sal_uInt32 * /*pFormat*/)
1857 : {
1858 0 : if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is() || pImpl->pMergeData->bAfterSelection )
1859 : {
1860 0 : rResult = "";
1861 0 : return false;
1862 : }
1863 :
1864 0 : bool bRet = lcl_GetColumnCnt(pImpl->pMergeData, rColumnName, nLanguage, rResult, pNumber);
1865 0 : return bRet;
1866 : }
1867 :
1868 10 : bool SwDBManager::ToNextMergeRecord()
1869 : {
1870 : OSL_ENSURE(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is(), "no data source in merge");
1871 10 : return ToNextRecord(pImpl->pMergeData);
1872 : }
1873 :
1874 22 : bool SwDBManager::FillCalcWithMergeData( SvNumberFormatter *pDocFormatter,
1875 : sal_uInt16 nLanguage, bool asString, SwCalc &rCalc )
1876 : {
1877 22 : if (!(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is()))
1878 20 : return false;
1879 :
1880 2 : uno::Reference< XColumnsSupplier > xColsSupp( pImpl->pMergeData->xResultSet, UNO_QUERY );
1881 2 : if(xColsSupp.is())
1882 : {
1883 2 : uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
1884 4 : const Sequence<OUString> aColNames = xCols->getElementNames();
1885 2 : const OUString* pColNames = aColNames.getConstArray();
1886 4 : OUString aString;
1887 :
1888 2 : const bool bExistsNextRecord = ExistsNextRecord();
1889 :
1890 30 : for( int nCol = 0; nCol < aColNames.getLength(); nCol++ )
1891 : {
1892 28 : const OUString &rColName = pColNames[nCol];
1893 :
1894 : // empty variables, if no more records;
1895 28 : if( !bExistsNextRecord )
1896 : {
1897 28 : rCalc.VarChange( rColName, 0 );
1898 56 : continue;
1899 : }
1900 :
1901 0 : double aNumber = DBL_MAX;
1902 0 : if( lcl_GetColumnCnt(pImpl->pMergeData, rColName, nLanguage, aString, &aNumber) )
1903 : {
1904 : // get the column type
1905 0 : sal_Int32 nColumnType = DataType::SQLNULL;
1906 0 : Any aCol = xCols->getByName( pColNames[nCol] );
1907 0 : uno::Reference<XPropertySet> xCol;
1908 0 : aCol >>= xCol;
1909 0 : Any aType = xCol->getPropertyValue( "Type" );
1910 0 : aType >>= nColumnType;
1911 :
1912 : sal_uInt32 nFmt;
1913 0 : if( !GetMergeColumnCnt(pColNames[nCol], nLanguage, aString, &aNumber, &nFmt) )
1914 0 : continue;
1915 :
1916 : // aNumber is overwritten by SwDBField::FormatValue, so store initial status
1917 0 : bool colIsNumber = aNumber != DBL_MAX;
1918 : bool bValidValue = SwDBField::FormatValue( pDocFormatter, aString, nFmt,
1919 0 : aNumber, nColumnType, NULL );
1920 0 : if( colIsNumber )
1921 : {
1922 0 : if( bValidValue )
1923 : {
1924 0 : SwSbxValue aValue;
1925 0 : if( !asString )
1926 0 : aValue.PutDouble( aNumber );
1927 : else
1928 0 : aValue.PutString( aString );
1929 : SAL_INFO( "sw.dbmgr", "'" << pColNames[nCol] << "': " << aNumber << " / " << aString );
1930 0 : rCalc.VarChange( pColNames[nCol], aValue );
1931 : }
1932 : }
1933 : else
1934 : {
1935 0 : SwSbxValue aValue;
1936 0 : aValue.PutString( aString );
1937 : SAL_INFO( "sw.dbmgr", "'" << pColNames[nCol] << "': " << aString );
1938 0 : rCalc.VarChange( pColNames[nCol], aValue );
1939 0 : }
1940 : }
1941 : }
1942 4 : return bExistsNextRecord;
1943 : }
1944 0 : return false;
1945 : }
1946 :
1947 0 : bool SwDBManager::ToNextRecord(
1948 : const OUString& rDataSource, const OUString& rCommand, sal_Int32 /*nCommandType*/)
1949 : {
1950 0 : SwDSParam* pFound = 0;
1951 0 : if(pImpl->pMergeData &&
1952 0 : rDataSource == pImpl->pMergeData->sDataSource &&
1953 0 : rCommand == pImpl->pMergeData->sCommand)
1954 0 : pFound = pImpl->pMergeData;
1955 : else
1956 : {
1957 0 : SwDBData aData;
1958 0 : aData.sDataSource = rDataSource;
1959 0 : aData.sCommand = rCommand;
1960 0 : aData.nCommandType = -1;
1961 0 : pFound = FindDSData(aData, false);
1962 : }
1963 0 : return ToNextRecord(pFound);
1964 : }
1965 :
1966 10 : bool SwDBManager::ToNextRecord(SwDSParam* pParam)
1967 : {
1968 10 : bool bRet = true;
1969 20 : if(!pParam || !pParam->xResultSet.is() || pParam->bEndOfDB ||
1970 8 : (pParam->aSelection.getLength() && pParam->aSelection.getLength() <= pParam->nSelectionIndex))
1971 : {
1972 2 : if(pParam)
1973 2 : pParam->CheckEndOfDB();
1974 2 : return false;
1975 : }
1976 : try
1977 : {
1978 8 : if(pParam->aSelection.getLength())
1979 : {
1980 0 : sal_Int32 nPos = 0;
1981 0 : pParam->aSelection.getConstArray()[ pParam->nSelectionIndex++ ] >>= nPos;
1982 0 : pParam->bEndOfDB = !pParam->xResultSet->absolute( nPos );
1983 0 : pParam->CheckEndOfDB();
1984 0 : bRet = !pParam->bEndOfDB;
1985 0 : if(pParam->nSelectionIndex >= pParam->aSelection.getLength())
1986 0 : pParam->bEndOfDB = true;
1987 : }
1988 : else
1989 : {
1990 8 : sal_Int32 nBefore = pParam->xResultSet->getRow();
1991 8 : pParam->bEndOfDB = !pParam->xResultSet->next();
1992 8 : if( !pParam->bEndOfDB && nBefore == pParam->xResultSet->getRow())
1993 : {
1994 : //next returned true but it didn't move
1995 0 : pParam->bEndOfDB = true;
1996 : }
1997 :
1998 8 : pParam->CheckEndOfDB();
1999 8 : bRet = !pParam->bEndOfDB;
2000 8 : ++pParam->nSelectionIndex;
2001 : }
2002 : }
2003 0 : catch(const Exception&)
2004 : {
2005 : }
2006 8 : return bRet;
2007 : }
2008 :
2009 : // synchronized labels contain a next record field at their end
2010 : // to assure that the next page can be created in mail merge
2011 : // the cursor position must be validated
2012 2 : bool SwDBManager::ExistsNextRecord() const
2013 : {
2014 2 : return pImpl->pMergeData && !pImpl->pMergeData->bEndOfDB;
2015 : }
2016 :
2017 0 : sal_uInt32 SwDBManager::GetSelectedRecordId()
2018 : {
2019 0 : sal_uInt32 nRet = 0;
2020 : OSL_ENSURE(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is(), "no data source in merge");
2021 0 : if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is())
2022 0 : return sal_False;
2023 : try
2024 : {
2025 0 : nRet = pImpl->pMergeData->xResultSet->getRow();
2026 : }
2027 0 : catch(const Exception&)
2028 : {
2029 : }
2030 0 : return nRet;
2031 : }
2032 :
2033 0 : bool SwDBManager::ToRecordId(sal_Int32 nSet)
2034 : {
2035 : OSL_ENSURE(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is(), "no data source in merge");
2036 0 : if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is()|| nSet < 0)
2037 0 : return false;
2038 0 : bool bRet = false;
2039 0 : sal_Int32 nAbsPos = nSet;
2040 :
2041 0 : if(nAbsPos >= 0)
2042 : {
2043 0 : bRet = lcl_MoveAbsolute(pImpl->pMergeData, nAbsPos);
2044 0 : pImpl->pMergeData->bEndOfDB = !bRet;
2045 0 : pImpl->pMergeData->CheckEndOfDB();
2046 : }
2047 0 : return bRet;
2048 : }
2049 :
2050 0 : bool SwDBManager::OpenDataSource(const OUString& rDataSource, const OUString& rTableOrQuery,
2051 : sal_Int32 nCommandType, bool bCreate)
2052 : {
2053 0 : SwDBData aData;
2054 0 : aData.sDataSource = rDataSource;
2055 0 : aData.sCommand = rTableOrQuery;
2056 0 : aData.nCommandType = nCommandType;
2057 :
2058 0 : SwDSParam* pFound = FindDSData(aData, true);
2059 0 : uno::Reference< XDataSource> xSource;
2060 0 : if(pFound->xResultSet.is())
2061 0 : return true;
2062 0 : SwDSParam* pParam = FindDSConnection(rDataSource, false);
2063 0 : uno::Reference< XConnection> xConnection;
2064 0 : if(pParam && pParam->xConnection.is())
2065 0 : pFound->xConnection = pParam->xConnection;
2066 0 : else if(bCreate)
2067 : {
2068 0 : OUString sDataSource(rDataSource);
2069 0 : pFound->xConnection = RegisterConnection( sDataSource );
2070 : }
2071 0 : if(pFound->xConnection.is())
2072 : {
2073 : try
2074 : {
2075 0 : uno::Reference< sdbc::XDatabaseMetaData > xMetaData = pFound->xConnection->getMetaData();
2076 : try
2077 : {
2078 : pFound->bScrollable = xMetaData
2079 0 : ->supportsResultSetType((sal_Int32)ResultSetType::SCROLL_INSENSITIVE);
2080 : }
2081 0 : catch(const Exception&)
2082 : {
2083 : // DB driver may not be ODBC 3.0 compliant
2084 0 : pFound->bScrollable = true;
2085 : }
2086 0 : pFound->xStatement = pFound->xConnection->createStatement();
2087 0 : OUString aQuoteChar = xMetaData->getIdentifierQuoteString();
2088 0 : OUString sStatement("SELECT * FROM ");
2089 0 : sStatement = "SELECT * FROM ";
2090 0 : sStatement += aQuoteChar;
2091 0 : sStatement += rTableOrQuery;
2092 0 : sStatement += aQuoteChar;
2093 0 : pFound->xResultSet = pFound->xStatement->executeQuery( sStatement );
2094 :
2095 : //after executeQuery the cursor must be positioned
2096 0 : pFound->bEndOfDB = !pFound->xResultSet->next();
2097 0 : pFound->bAfterSelection = false;
2098 0 : pFound->CheckEndOfDB();
2099 0 : ++pFound->nSelectionIndex;
2100 : }
2101 0 : catch (const Exception&)
2102 : {
2103 0 : pFound->xResultSet = 0;
2104 0 : pFound->xStatement = 0;
2105 0 : pFound->xConnection = 0;
2106 : }
2107 : }
2108 0 : return pFound->xResultSet.is();
2109 : }
2110 :
2111 0 : uno::Reference< XConnection> SwDBManager::RegisterConnection(OUString& rDataSource)
2112 : {
2113 0 : SwDSParam* pFound = SwDBManager::FindDSConnection(rDataSource, true);
2114 0 : uno::Reference< XDataSource> xSource;
2115 0 : if(!pFound->xConnection.is())
2116 : {
2117 0 : pFound->xConnection = SwDBManager::GetConnection(rDataSource, xSource );
2118 : try
2119 : {
2120 0 : uno::Reference<XComponent> xComponent(pFound->xConnection, UNO_QUERY);
2121 0 : if(xComponent.is())
2122 0 : xComponent->addEventListener(pImpl->xDisposeListener);
2123 : }
2124 0 : catch(const Exception&)
2125 : {
2126 : }
2127 : }
2128 0 : return pFound->xConnection;
2129 : }
2130 :
2131 0 : sal_uInt32 SwDBManager::GetSelectedRecordId(
2132 : const OUString& rDataSource, const OUString& rTableOrQuery, sal_Int32 nCommandType)
2133 : {
2134 0 : sal_uInt32 nRet = 0xffffffff;
2135 : //check for merge data source first
2136 0 : if(pImpl->pMergeData && rDataSource == pImpl->pMergeData->sDataSource &&
2137 0 : rTableOrQuery == pImpl->pMergeData->sCommand &&
2138 0 : (nCommandType == -1 || nCommandType == pImpl->pMergeData->nCommandType) &&
2139 0 : pImpl->pMergeData->xResultSet.is())
2140 0 : nRet = GetSelectedRecordId();
2141 : else
2142 : {
2143 0 : SwDBData aData;
2144 0 : aData.sDataSource = rDataSource;
2145 0 : aData.sCommand = rTableOrQuery;
2146 0 : aData.nCommandType = nCommandType;
2147 0 : SwDSParam* pFound = FindDSData(aData, false);
2148 0 : if(pFound && pFound->xResultSet.is())
2149 : {
2150 : try
2151 : { //if a selection array is set the current row at the result set may not be set yet
2152 0 : if(pFound->aSelection.getLength())
2153 : {
2154 0 : sal_Int32 nSelIndex = pFound->nSelectionIndex;
2155 0 : if(nSelIndex >= pFound->aSelection.getLength())
2156 0 : nSelIndex = pFound->aSelection.getLength() -1;
2157 0 : pFound->aSelection.getConstArray()[nSelIndex] >>= nRet;
2158 :
2159 : }
2160 : else
2161 0 : nRet = pFound->xResultSet->getRow();
2162 : }
2163 0 : catch(const Exception&)
2164 : {
2165 : }
2166 0 : }
2167 : }
2168 0 : return nRet;
2169 : }
2170 :
2171 : // close all data sources - after fields were updated
2172 76 : void SwDBManager::CloseAll(bool bIncludingMerge)
2173 : {
2174 : //the only thing done here is to reset the selection index
2175 : //all connections stay open
2176 76 : for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.size(); nPos++)
2177 : {
2178 0 : SwDSParam* pParam = &aDataSourceParams[nPos];
2179 0 : if(bIncludingMerge || pParam != pImpl->pMergeData)
2180 : {
2181 0 : pParam->nSelectionIndex = 0;
2182 0 : pParam->bAfterSelection = false;
2183 0 : pParam->bEndOfDB = false;
2184 : try
2185 : {
2186 0 : if(!bInMerge && pParam->xResultSet.is())
2187 0 : pParam->xResultSet->first();
2188 : }
2189 0 : catch(const Exception&)
2190 : {}
2191 : }
2192 : }
2193 76 : }
2194 :
2195 38 : SwDSParam* SwDBManager::FindDSData(const SwDBData& rData, bool bCreate)
2196 : {
2197 : //prefer merge data if available
2198 46 : if(pImpl->pMergeData && rData.sDataSource == pImpl->pMergeData->sDataSource &&
2199 50 : rData.sCommand == pImpl->pMergeData->sCommand &&
2200 8 : (rData.nCommandType == -1 || rData.nCommandType == pImpl->pMergeData->nCommandType ||
2201 0 : (bCreate && pImpl->pMergeData->nCommandType == -1)))
2202 : {
2203 4 : return pImpl->pMergeData;
2204 : }
2205 :
2206 34 : SwDSParam* pFound = 0;
2207 34 : for(sal_uInt16 nPos = aDataSourceParams.size(); nPos; nPos--)
2208 : {
2209 0 : SwDSParam* pParam = &aDataSourceParams[nPos - 1];
2210 0 : if(rData.sDataSource == pParam->sDataSource &&
2211 0 : rData.sCommand == pParam->sCommand &&
2212 0 : (rData.nCommandType == -1 || rData.nCommandType == pParam->nCommandType ||
2213 0 : (bCreate && pParam->nCommandType == -1)))
2214 : {
2215 : // calls from the calculator may add a connection with an invalid commandtype
2216 : //later added "real" data base connections have to re-use the already available
2217 : //DSData and set the correct CommandType
2218 0 : if(bCreate && pParam->nCommandType == -1)
2219 0 : pParam->nCommandType = rData.nCommandType;
2220 0 : pFound = pParam;
2221 0 : break;
2222 : }
2223 : }
2224 34 : if(bCreate)
2225 : {
2226 0 : if(!pFound)
2227 : {
2228 0 : pFound = new SwDSParam(rData);
2229 0 : aDataSourceParams.push_back(pFound);
2230 : try
2231 : {
2232 0 : uno::Reference<XComponent> xComponent(pFound->xConnection, UNO_QUERY);
2233 0 : if(xComponent.is())
2234 0 : xComponent->addEventListener(pImpl->xDisposeListener);
2235 : }
2236 0 : catch(const Exception&)
2237 : {
2238 : }
2239 : }
2240 : }
2241 34 : return pFound;
2242 : }
2243 :
2244 0 : SwDSParam* SwDBManager::FindDSConnection(const OUString& rDataSource, bool bCreate)
2245 : {
2246 : //prefer merge data if available
2247 0 : if(pImpl->pMergeData && rDataSource == pImpl->pMergeData->sDataSource )
2248 : {
2249 0 : return pImpl->pMergeData;
2250 : }
2251 0 : SwDSParam* pFound = 0;
2252 0 : for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.size(); nPos++)
2253 : {
2254 0 : SwDSParam* pParam = &aDataSourceParams[nPos];
2255 0 : if(rDataSource == pParam->sDataSource)
2256 : {
2257 0 : pFound = pParam;
2258 0 : break;
2259 : }
2260 : }
2261 0 : if(bCreate && !pFound)
2262 : {
2263 0 : SwDBData aData;
2264 0 : aData.sDataSource = rDataSource;
2265 0 : pFound = new SwDSParam(aData);
2266 0 : aDataSourceParams.push_back(pFound);
2267 : try
2268 : {
2269 0 : uno::Reference<XComponent> xComponent(pFound->xConnection, UNO_QUERY);
2270 0 : if(xComponent.is())
2271 0 : xComponent->addEventListener(pImpl->xDisposeListener);
2272 : }
2273 0 : catch(const Exception&)
2274 : {
2275 0 : }
2276 : }
2277 0 : return pFound;
2278 : }
2279 :
2280 1004 : const SwDBData& SwDBManager::GetAddressDBName()
2281 : {
2282 1004 : return SW_MOD()->GetDBConfig()->GetAddressSource();
2283 : }
2284 :
2285 0 : Sequence<OUString> SwDBManager::GetExistingDatabaseNames()
2286 : {
2287 0 : Reference<XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
2288 0 : Reference<XDatabaseContext> xDBContext = DatabaseContext::create(xContext);
2289 0 : return xDBContext->getElementNames();
2290 : }
2291 :
2292 0 : OUString SwDBManager::LoadAndRegisterDataSource()
2293 : {
2294 0 : sfx2::FileDialogHelper aDlgHelper( TemplateDescription::FILEOPEN_SIMPLE, 0 );
2295 0 : Reference < XFilePicker > xFP = aDlgHelper.GetFilePicker();
2296 :
2297 0 : OUString sHomePath(SvtPathOptions().GetWorkPath());
2298 0 : aDlgHelper.SetDisplayDirectory( sHomePath );
2299 :
2300 0 : Reference<XFilterManager> xFltMgr(xFP, UNO_QUERY);
2301 :
2302 0 : OUString sFilterAll(SW_RES(STR_FILTER_ALL));
2303 0 : OUString sFilterAllData(SW_RES(STR_FILTER_ALL_DATA));
2304 0 : OUString sFilterSXB(SW_RES(STR_FILTER_SXB));
2305 0 : OUString sFilterSXC(SW_RES(STR_FILTER_SXC));
2306 0 : OUString sFilterDBF(SW_RES(STR_FILTER_DBF));
2307 0 : OUString sFilterXLS(SW_RES(STR_FILTER_XLS));
2308 0 : OUString sFilterTXT(SW_RES(STR_FILTER_TXT));
2309 0 : OUString sFilterCSV(SW_RES(STR_FILTER_CSV));
2310 : #ifdef WNT
2311 : OUString sFilterMDB(SW_RES(STR_FILTER_MDB));
2312 : OUString sFilterACCDB(SW_RES(STR_FILTER_ACCDB));
2313 : #endif
2314 0 : xFltMgr->appendFilter( sFilterAll, "*" );
2315 0 : xFltMgr->appendFilter( sFilterAllData, "*.ods;*.sxc;*.dbf;*.xls;*.txt;*.csv");
2316 :
2317 0 : xFltMgr->appendFilter( sFilterSXB, "*.odb" );
2318 0 : xFltMgr->appendFilter( sFilterSXC, "*.ods;*.sxc" );
2319 0 : xFltMgr->appendFilter( sFilterDBF, "*.dbf" );
2320 0 : xFltMgr->appendFilter( sFilterXLS, "*.xls" );
2321 0 : xFltMgr->appendFilter( sFilterTXT, "*.txt" );
2322 0 : xFltMgr->appendFilter( sFilterCSV, "*.csv" );
2323 : #ifdef WNT
2324 : xFltMgr->appendFilter( sFilterMDB, "*.mdb" );
2325 : xFltMgr->appendFilter( sFilterACCDB, "*.accdb" );
2326 : #endif
2327 :
2328 0 : xFltMgr->setCurrentFilter( sFilterAll ) ;
2329 0 : OUString sFind;
2330 0 : if( ERRCODE_NONE == aDlgHelper.Execute() )
2331 : {
2332 0 : Any aURLAny;
2333 0 : uno::Reference< beans::XPropertySet > aSettings;
2334 0 : const OUString aURI( xFP->getFiles().getConstArray()[0] );
2335 0 : const DBConnURITypes type = GetDBunoURI( aURI, aURLAny );
2336 :
2337 0 : if( DBCONN_FLAT == type )
2338 : {
2339 0 : Reference<XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
2340 0 : uno::Reference < sdb::XTextConnectionSettings > xSettingsDlg = sdb::TextConnectionSettings::create(xContext);
2341 0 : if( xSettingsDlg->execute() )
2342 0 : aSettings.set( uno::Reference < beans::XPropertySet >( xSettingsDlg, uno::UNO_QUERY_THROW ) );
2343 : }
2344 0 : sFind = LoadAndRegisterDataSource( type, aURLAny, DBCONN_FLAT == type ? &aSettings : 0, aURI );
2345 : }
2346 0 : return sFind;
2347 : }
2348 :
2349 4 : SwDBManager::DBConnURITypes SwDBManager::GetDBunoURI(const OUString &rURI, Any &aURLAny)
2350 : {
2351 4 : INetURLObject aURL( rURI );
2352 8 : OUString sExt( aURL.GetExtension() );
2353 4 : DBConnURITypes type = DBCONN_UNKNOWN;
2354 :
2355 4 : if(sExt == "odb")
2356 : {
2357 0 : type = DBCONN_ODB;
2358 : }
2359 8 : else if(sExt.equalsIgnoreAsciiCase("sxc")
2360 4 : || sExt.equalsIgnoreAsciiCase("ods")
2361 4 : || sExt.equalsIgnoreAsciiCase("xls"))
2362 : {
2363 4 : OUString sDBURL("sdbc:calc:");
2364 4 : sDBURL += aURL.GetMainURL(INetURLObject::NO_DECODE);
2365 4 : aURLAny <<= sDBURL;
2366 4 : type = DBCONN_CALC;
2367 : }
2368 0 : else if(sExt.equalsIgnoreAsciiCase("dbf"))
2369 : {
2370 0 : aURL.removeSegment();
2371 0 : aURL.removeFinalSlash();
2372 0 : OUString sDBURL("sdbc:dbase:");
2373 0 : sDBURL += aURL.GetMainURL(INetURLObject::NO_DECODE);
2374 0 : aURLAny <<= sDBURL;
2375 0 : type = DBCONN_DBASE;
2376 : }
2377 0 : else if(sExt.equalsIgnoreAsciiCase("csv") || sExt.equalsIgnoreAsciiCase("txt"))
2378 : {
2379 0 : aURL.removeSegment();
2380 0 : aURL.removeFinalSlash();
2381 0 : OUString sDBURL("sdbc:flat:");
2382 : //only the 'path' has to be added
2383 0 : sDBURL += aURL.GetMainURL(INetURLObject::NO_DECODE);
2384 0 : aURLAny <<= sDBURL;
2385 0 : type = DBCONN_FLAT;
2386 : }
2387 : #ifdef WNT
2388 : else if(sExt.equalsIgnoreAsciiCase("mdb"))
2389 : {
2390 : OUString sDBURL("sdbc:ado:access:PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=");
2391 : sDBURL += aURL.PathToFileName();
2392 : aURLAny <<= sDBURL;
2393 : type = DBCONN_MSJET;
2394 : }
2395 : else if(sExt.equalsIgnoreAsciiCase("accdb"))
2396 : {
2397 : OUString sDBURL("sdbc:ado:PROVIDER=Microsoft.ACE.OLEDB.12.0;DATA SOURCE=");
2398 : sDBURL += aURL.PathToFileName();
2399 : aURLAny <<= sDBURL;
2400 : type = DBCONN_MSACE;
2401 : }
2402 : #endif
2403 8 : return type;
2404 : }
2405 :
2406 4 : OUString SwDBManager::LoadAndRegisterDataSource(const DBConnURITypes type, const Any &aURLAny, const uno::Reference< beans::XPropertySet > *pSettings,
2407 : const OUString &rURI, const OUString *pPrefix, const OUString *pDestDir)
2408 : {
2409 4 : INetURLObject aURL( rURI );
2410 8 : OUString sExt( aURL.GetExtension() );
2411 8 : Any aTableFilterAny;
2412 8 : Any aSuppressVersionsAny;
2413 8 : Any aInfoAny;
2414 4 : bool bStore = true;
2415 4 : OUString sFind;
2416 8 : Sequence<OUString> aFilters(1);
2417 :
2418 4 : switch (type) {
2419 : case DBCONN_UNKNOWN:
2420 : case DBCONN_CALC:
2421 4 : break;
2422 : case DBCONN_ODB:
2423 0 : bStore = false;
2424 0 : break;
2425 : case DBCONN_FLAT:
2426 : case DBCONN_DBASE:
2427 : //set the filter to the file name without extension
2428 0 : aFilters[0] = aURL.getBase();
2429 0 : aTableFilterAny <<= aFilters;
2430 0 : break;
2431 : case DBCONN_MSJET:
2432 : case DBCONN_MSACE:
2433 0 : aSuppressVersionsAny <<= makeAny(true);
2434 0 : break;
2435 : }
2436 :
2437 : try
2438 : {
2439 4 : Reference<XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
2440 8 : Reference<XDatabaseContext> xDBContext = DatabaseContext::create(xContext);
2441 :
2442 : OUString sNewName = INetURLObject::decode( aURL.getName(),
2443 : '%',
2444 : INetURLObject::DECODE_UNAMBIGUOUS,
2445 8 : RTL_TEXTENCODING_UTF8 );
2446 4 : sal_Int32 nExtLen = aURL.GetExtension().getLength();
2447 4 : sNewName = sNewName.replaceAt( sNewName.getLength() - nExtLen - 1, nExtLen + 1, "" );
2448 4 : if (pPrefix)
2449 4 : sNewName = *pPrefix + sNewName;
2450 :
2451 : //find a unique name if sNewName already exists
2452 4 : sFind = sNewName;
2453 4 : sal_Int32 nIndex = 0;
2454 8 : while(xDBContext->hasByName(sFind))
2455 : {
2456 0 : sFind = sNewName;
2457 0 : sFind += OUString::number(++nIndex);
2458 : }
2459 :
2460 8 : Reference<XInterface> xNewInstance;
2461 4 : if(!bStore)
2462 : {
2463 : //odb-file
2464 0 : Any aDataSource = xDBContext->getByName(aURL.GetMainURL(INetURLObject::NO_DECODE));
2465 0 : aDataSource >>= xNewInstance;
2466 : }
2467 : else
2468 : {
2469 4 : xNewInstance = xDBContext->createInstance();
2470 4 : Reference<XPropertySet> xDataProperties(xNewInstance, UNO_QUERY);
2471 :
2472 4 : if(aURLAny.hasValue())
2473 4 : xDataProperties->setPropertyValue("URL", aURLAny);
2474 4 : if(aTableFilterAny.hasValue())
2475 0 : xDataProperties->setPropertyValue("TableFilter", aTableFilterAny);
2476 4 : if(aSuppressVersionsAny.hasValue())
2477 0 : xDataProperties->setPropertyValue("SuppressVersionColumns", aSuppressVersionsAny);
2478 4 : if(aInfoAny.hasValue())
2479 0 : xDataProperties->setPropertyValue("Info", aInfoAny);
2480 :
2481 4 : if( DBCONN_FLAT == type && pSettings )
2482 : {
2483 0 : uno::Any aSettings = xDataProperties->getPropertyValue( "Settings" );
2484 0 : uno::Reference < beans::XPropertySet > xDSSettings;
2485 0 : aSettings >>= xDSSettings;
2486 0 : ::comphelper::copyProperties( *pSettings, xDSSettings );
2487 0 : xDSSettings->setPropertyValue( "Extension", uno::makeAny( sExt ));
2488 : }
2489 :
2490 8 : Reference<XDocumentDataSource> xDS(xNewInstance, UNO_QUERY_THROW);
2491 8 : Reference<XStorable> xStore(xDS->getDatabaseDocument(), UNO_QUERY_THROW);
2492 8 : OUString sOutputExt = ".odb";
2493 8 : OUString sTmpName;
2494 : {
2495 4 : OUString sHomePath(SvtPathOptions().GetWorkPath());
2496 8 : utl::TempFile aTempFile(sNewName, true, &sOutputExt, pDestDir ? pDestDir : &sHomePath);
2497 4 : aTempFile.EnableKillingFile(true);
2498 8 : sTmpName = aTempFile.GetURL();
2499 : }
2500 8 : xStore->storeAsURL(sTmpName, Sequence< PropertyValue >());
2501 : }
2502 8 : xDBContext->registerObject( sFind, xNewInstance );
2503 : }
2504 0 : catch(const Exception&)
2505 : {
2506 0 : sFind = "";
2507 : }
2508 8 : return sFind;
2509 : }
2510 :
2511 4 : OUString SwDBManager::LoadAndRegisterDataSource(const OUString &rURI, const OUString *pPrefix, const OUString *pDestDir,
2512 : const uno::Reference< beans::XPropertySet > *pSettings)
2513 : {
2514 4 : Any aURLAny;
2515 4 : DBConnURITypes type = GetDBunoURI( rURI, aURLAny );
2516 4 : return LoadAndRegisterDataSource( type, aURLAny, pSettings, rURI, pPrefix, pDestDir );
2517 : }
2518 :
2519 0 : void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh,
2520 : const Sequence<PropertyValue>& rProperties,
2521 : bool bWithDataSourceBrowser)
2522 : {
2523 : //prevent second call
2524 0 : if(pImpl->pMergeDialog)
2525 0 : return ;
2526 0 : OUString sDataSource, sDataTableOrQuery;
2527 0 : Sequence<Any> aSelection;
2528 :
2529 0 : sal_Int32 nCmdType = CommandType::TABLE;
2530 0 : uno::Reference< XConnection> xConnection;
2531 :
2532 0 : ODataAccessDescriptor aDescriptor(rProperties);
2533 0 : sDataSource = aDescriptor.getDataSource();
2534 0 : OSL_VERIFY(aDescriptor[daCommand] >>= sDataTableOrQuery);
2535 0 : OSL_VERIFY(aDescriptor[daCommandType] >>= nCmdType);
2536 :
2537 0 : if ( aDescriptor.has(daSelection) )
2538 0 : aDescriptor[daSelection] >>= aSelection;
2539 0 : if ( aDescriptor.has(daConnection) )
2540 0 : aDescriptor[daConnection] >>= xConnection;
2541 :
2542 0 : if(sDataSource.isEmpty() || sDataTableOrQuery.isEmpty())
2543 : {
2544 : OSL_FAIL("PropertyValues missing or unset");
2545 0 : return;
2546 : }
2547 :
2548 : //always create a connection for the dialog and dispose it after the dialog has been closed
2549 0 : SwDSParam* pFound = 0;
2550 0 : if(!xConnection.is())
2551 : {
2552 0 : xConnection = SwDBManager::RegisterConnection(sDataSource);
2553 0 : pFound = FindDSConnection(sDataSource, true);
2554 : }
2555 0 : SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
2556 : OSL_ENSURE(pFact, "Dialog creation failed!");
2557 : pImpl->pMergeDialog = pFact->CreateMailMergeDlg( DLG_MAILMERGE,
2558 0 : &rSh.GetView().GetViewFrame()->GetWindow(), rSh,
2559 : sDataSource,
2560 : sDataTableOrQuery,
2561 : nCmdType,
2562 : xConnection,
2563 0 : bWithDataSourceBrowser ? 0 : &aSelection);
2564 : OSL_ENSURE(pImpl->pMergeDialog, "Dialog creation failed!");
2565 0 : if(pImpl->pMergeDialog->Execute() == RET_OK)
2566 : {
2567 0 : aDescriptor[daSelection] <<= pImpl->pMergeDialog->GetSelection();
2568 :
2569 0 : uno::Reference<XResultSet> xResSet = pImpl->pMergeDialog->GetResultSet();
2570 0 : if(xResSet.is())
2571 0 : aDescriptor[daCursor] <<= xResSet;
2572 :
2573 : // SfxObjectShellRef is ok, since there should be no control over the document lifetime here
2574 0 : SfxObjectShellRef xDocShell = rSh.GetView().GetViewFrame()->GetObjectShell();
2575 0 : SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE), xDocShell));
2576 : {
2577 : //copy rSh to aTempFile
2578 0 : OUString sTempURL;
2579 : const SfxFilter *pSfxFlt = SwIoSystem::GetFilterOfFormat(
2580 : OUString(FILTER_XML),
2581 0 : SwDocShell::Factory().GetFilterContainer() );
2582 : try
2583 : {
2584 :
2585 0 : uno::Sequence< beans::PropertyValue > aValues(1);
2586 0 : beans::PropertyValue* pValues = aValues.getArray();
2587 0 : pValues[0].Name = "FilterName";
2588 0 : pValues[0].Value <<= OUString(pSfxFlt->GetFilterName());
2589 0 : uno::Reference< XStorable > xStore( xDocShell->GetModel(), uno::UNO_QUERY);
2590 0 : sTempURL = URIHelper::SmartRel2Abs( INetURLObject(), utl::TempFile::CreateTempName() );
2591 0 : xStore->storeToURL( sTempURL, aValues );
2592 : }
2593 0 : catch(const uno::Exception&)
2594 : {
2595 : }
2596 0 : if( xDocShell->GetError() )
2597 : {
2598 : // error message ??
2599 0 : ErrorHandler::HandleError( xDocShell->GetError() );
2600 : }
2601 : else
2602 : {
2603 : // the shell will be explicitly closed, but it is more safe to use SfxObjectShellLock here
2604 : // especially for the case that the loading has failed
2605 0 : SfxObjectShellLock xWorkDocSh( new SwDocShell( SFX_CREATE_MODE_INTERNAL ));
2606 0 : SfxMedium* pWorkMed = new SfxMedium( sTempURL, STREAM_STD_READ );
2607 0 : pWorkMed->SetFilter( pSfxFlt );
2608 0 : if( xWorkDocSh->DoLoad(pWorkMed) )
2609 : {
2610 0 : SfxViewFrame *pFrame = SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 );
2611 0 : SwView *pView = (SwView*) pFrame->GetViewShell();
2612 0 : pView->AttrChangedNotify( &pView->GetWrtShell() );// in order for SelectShell to be called
2613 : //set the current DBManager
2614 0 : SwDoc* pWorkDoc = pView->GetWrtShell().GetDoc();
2615 0 : SwDBManager* pWorkDBManager = pWorkDoc->GetDBManager();
2616 0 : pWorkDoc->SetDBManager( this );
2617 :
2618 0 : SwMergeDescriptor aMergeDesc( pImpl->pMergeDialog->GetMergeType(), pView->GetWrtShell(), aDescriptor );
2619 0 : aMergeDesc.sSaveToFilter = pImpl->pMergeDialog->GetSaveFilter();
2620 0 : aMergeDesc.bCreateSingleFile = pImpl->pMergeDialog->IsSaveSingleDoc();
2621 0 : aMergeDesc.bSubjectIsFilename = aMergeDesc.bCreateSingleFile;
2622 0 : if( !aMergeDesc.bCreateSingleFile && pImpl->pMergeDialog->IsGenerateFromDataBase() )
2623 : {
2624 0 : aMergeDesc.sAddressFromColumn = pImpl->pMergeDialog->GetColumnName();
2625 0 : aMergeDesc.sSubject = pImpl->pMergeDialog->GetPath();
2626 : }
2627 :
2628 0 : MergeNew(aMergeDesc);
2629 :
2630 0 : pWorkDoc->SetDBManager( pWorkDBManager );
2631 : //close the temporary file
2632 0 : uno::Reference< util::XCloseable > xClose( xWorkDocSh->GetModel(), uno::UNO_QUERY );
2633 0 : if (xClose.is())
2634 : {
2635 : try
2636 : {
2637 : //! 'sal_True' -> transfer ownership to vetoing object if vetoed!
2638 : //! I.e. now that object is responsible for closing the model and doc shell.
2639 0 : xClose->close( sal_True );
2640 : }
2641 0 : catch (const uno::Exception&)
2642 : {
2643 : }
2644 0 : }
2645 0 : }
2646 : }
2647 : //remove the temporary file
2648 0 : SWUnoHelper::UCB_DeleteFile( sTempURL );
2649 : }
2650 0 : SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE_END, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE_END), rSh.GetView().GetViewFrame()->GetObjectShell()));
2651 :
2652 : // reset the cursor inside
2653 0 : xResSet = NULL;
2654 0 : aDescriptor[daCursor] <<= xResSet;
2655 : }
2656 0 : if(pFound)
2657 : {
2658 0 : for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.size(); nPos++)
2659 : {
2660 0 : SwDSParam* pParam = &aDataSourceParams[nPos];
2661 0 : if(pParam == pFound)
2662 : {
2663 : try
2664 : {
2665 0 : uno::Reference<XComponent> xComp(pParam->xConnection, UNO_QUERY);
2666 0 : if(xComp.is())
2667 0 : xComp->dispose();
2668 : }
2669 0 : catch(const RuntimeException&)
2670 : {
2671 : //may be disposed already since multiple entries may have used the same connection
2672 : }
2673 0 : break;
2674 : }
2675 : //pFound doesn't need to be removed/deleted -
2676 : //this has been done by the SwConnectionDisposedListener_Impl already
2677 : }
2678 : }
2679 0 : DELETEZ(pImpl->pMergeDialog);
2680 : }
2681 :
2682 0 : void SwDBManager::InsertText(SwWrtShell& rSh,
2683 : const Sequence< PropertyValue>& rProperties)
2684 : {
2685 0 : OUString sDataSource, sDataTableOrQuery;
2686 0 : uno::Reference<XResultSet> xResSet;
2687 0 : Sequence<Any> aSelection;
2688 0 : sal_Int16 nCmdType = CommandType::TABLE;
2689 0 : const PropertyValue* pValues = rProperties.getConstArray();
2690 0 : uno::Reference< XConnection> xConnection;
2691 0 : for(sal_Int32 nPos = 0; nPos < rProperties.getLength(); nPos++)
2692 : {
2693 0 : if ( pValues[nPos].Name == cDataSourceName )
2694 0 : pValues[nPos].Value >>= sDataSource;
2695 0 : else if ( pValues[nPos].Name == cCommand )
2696 0 : pValues[nPos].Value >>= sDataTableOrQuery;
2697 0 : else if ( pValues[nPos].Name == cCursor )
2698 0 : pValues[nPos].Value >>= xResSet;
2699 0 : else if ( pValues[nPos].Name == cSelection )
2700 0 : pValues[nPos].Value >>= aSelection;
2701 0 : else if ( pValues[nPos].Name == cCommandType )
2702 0 : pValues[nPos].Value >>= nCmdType;
2703 0 : else if ( pValues[nPos].Name == cActiveConnection )
2704 0 : pValues[nPos].Value >>= xConnection;
2705 : }
2706 0 : if(sDataSource.isEmpty() || sDataTableOrQuery.isEmpty() || !xResSet.is())
2707 : {
2708 : OSL_FAIL("PropertyValues missing or unset");
2709 0 : return;
2710 : }
2711 0 : Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
2712 0 : uno::Reference<XDataSource> xSource;
2713 0 : uno::Reference<XChild> xChild(xConnection, UNO_QUERY);
2714 0 : if(xChild.is())
2715 0 : xSource = uno::Reference<XDataSource>(xChild->getParent(), UNO_QUERY);
2716 0 : if(!xSource.is())
2717 0 : xSource = SwDBManager::GetDbtoolsClient().getDataSource(sDataSource, xContext);
2718 0 : uno::Reference< XColumnsSupplier > xColSupp( xResSet, UNO_QUERY );
2719 0 : SwDBData aDBData;
2720 0 : aDBData.sDataSource = sDataSource;
2721 0 : aDBData.sCommand = sDataTableOrQuery;
2722 0 : aDBData.nCommandType = nCmdType;
2723 :
2724 0 : SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
2725 : OSL_ENSURE(pFact, "SwAbstractDialogFactory fail!");
2726 :
2727 0 : boost::scoped_ptr<AbstractSwInsertDBColAutoPilot> pDlg(pFact->CreateSwInsertDBColAutoPilot( rSh.GetView(),
2728 : xSource,
2729 : xColSupp,
2730 0 : aDBData ));
2731 : OSL_ENSURE(pDlg, "Dialog creation failed!");
2732 0 : if( RET_OK == pDlg->Execute() )
2733 : {
2734 0 : OUString sDummy;
2735 0 : if(!xConnection.is())
2736 0 : xConnection = xSource->getConnection(sDummy, sDummy);
2737 : try
2738 : {
2739 0 : pDlg->DataToDoc( aSelection , xSource, xConnection, xResSet);
2740 : }
2741 0 : catch(const Exception&)
2742 : {
2743 : OSL_FAIL("exception caught");
2744 0 : }
2745 0 : }
2746 : }
2747 :
2748 : SwDbtoolsClient* SwDBManager::pDbtoolsClient = NULL;
2749 :
2750 0 : SwDbtoolsClient& SwDBManager::GetDbtoolsClient()
2751 : {
2752 0 : if ( !pDbtoolsClient )
2753 0 : pDbtoolsClient = new SwDbtoolsClient;
2754 0 : return *pDbtoolsClient;
2755 : }
2756 :
2757 90 : void SwDBManager::RemoveDbtoolsClient()
2758 : {
2759 90 : delete pDbtoolsClient;
2760 90 : pDbtoolsClient = 0;
2761 90 : }
2762 :
2763 4 : uno::Reference<XDataSource> SwDBManager::getDataSourceAsParent(const uno::Reference< XConnection>& _xConnection,const OUString& _sDataSourceName)
2764 : {
2765 4 : uno::Reference<XDataSource> xSource;
2766 : try
2767 : {
2768 4 : uno::Reference<XChild> xChild(_xConnection, UNO_QUERY);
2769 4 : if ( xChild.is() )
2770 4 : xSource = uno::Reference<XDataSource>(xChild->getParent(), UNO_QUERY);
2771 4 : if ( !xSource.is() )
2772 0 : xSource = SwDBManager::GetDbtoolsClient().getDataSource(_sDataSourceName, ::comphelper::getProcessComponentContext());
2773 : }
2774 0 : catch(const Exception&)
2775 : {
2776 : OSL_FAIL("exception in getDataSourceAsParent caught");
2777 : }
2778 4 : return xSource;
2779 : }
2780 :
2781 0 : uno::Reference<XResultSet> SwDBManager::createCursor(const OUString& _sDataSourceName,
2782 : const OUString& _sCommand,
2783 : sal_Int32 _nCommandType,
2784 : const uno::Reference<XConnection>& _xConnection
2785 : )
2786 : {
2787 0 : uno::Reference<XResultSet> xResultSet;
2788 : try
2789 : {
2790 0 : uno::Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
2791 0 : if( xMgr.is() )
2792 : {
2793 0 : uno::Reference<XInterface> xInstance = xMgr->createInstance("com.sun.star.sdb.RowSet");
2794 0 : uno::Reference<XPropertySet> xRowSetPropSet(xInstance, UNO_QUERY);
2795 0 : if(xRowSetPropSet.is())
2796 : {
2797 0 : xRowSetPropSet->setPropertyValue("DataSourceName", makeAny(_sDataSourceName));
2798 0 : xRowSetPropSet->setPropertyValue("ActiveConnection", makeAny(_xConnection));
2799 0 : xRowSetPropSet->setPropertyValue("Command", makeAny(_sCommand));
2800 0 : xRowSetPropSet->setPropertyValue("CommandType", makeAny(_nCommandType));
2801 :
2802 0 : uno::Reference< XCompletedExecution > xRowSet(xInstance, UNO_QUERY);
2803 :
2804 0 : if ( xRowSet.is() )
2805 : {
2806 0 : uno::Reference< XInteractionHandler > xHandler( InteractionHandler::createWithParent(comphelper::getComponentContext(xMgr), 0), UNO_QUERY_THROW );
2807 0 : xRowSet->executeWithCompletion(xHandler);
2808 : }
2809 0 : xResultSet = uno::Reference<XResultSet>(xRowSet, UNO_QUERY);
2810 0 : }
2811 0 : }
2812 : }
2813 0 : catch(const Exception&)
2814 : {
2815 : OSL_FAIL("Caught exception while creating a new RowSet!");
2816 : }
2817 0 : return xResultSet;
2818 : }
2819 :
2820 5052 : SwConnectionDisposedListener_Impl::SwConnectionDisposedListener_Impl(SwDBManager& rMgr) :
2821 5052 : rDBManager(rMgr)
2822 : {
2823 5052 : };
2824 :
2825 10090 : SwConnectionDisposedListener_Impl::~SwConnectionDisposedListener_Impl()
2826 : {
2827 10090 : };
2828 :
2829 0 : void SwConnectionDisposedListener_Impl::disposing( const EventObject& rSource )
2830 : throw (RuntimeException, std::exception)
2831 : {
2832 0 : ::SolarMutexGuard aGuard;
2833 0 : uno::Reference<XConnection> xSource(rSource.Source, UNO_QUERY);
2834 0 : for(sal_uInt16 nPos = rDBManager.aDataSourceParams.size(); nPos; nPos--)
2835 : {
2836 0 : SwDSParam* pParam = &rDBManager.aDataSourceParams[nPos - 1];
2837 0 : if(pParam->xConnection.is() &&
2838 0 : (xSource == pParam->xConnection))
2839 : {
2840 0 : rDBManager.aDataSourceParams.erase(rDBManager.aDataSourceParams.begin() + nPos - 1);
2841 : }
2842 0 : }
2843 270 : }
2844 :
2845 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|