File: | home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx |
Warning: | line 950, column 5 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 <sal/config.h> | ||||
21 | |||||
22 | #include <cassert> | ||||
23 | |||||
24 | #include <unotxdoc.hxx> | ||||
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/lang/DisposedException.hpp> | ||||
29 | #include <com/sun/star/lang/XEventListener.hpp> | ||||
30 | #include <com/sun/star/uri/UriReferenceFactory.hpp> | ||||
31 | #include <com/sun/star/uri/VndSunStarPkgUrlReferenceFactory.hpp> | ||||
32 | #include <com/sun/star/util/NumberFormatter.hpp> | ||||
33 | #include <com/sun/star/sdb/DatabaseContext.hpp> | ||||
34 | #include <com/sun/star/sdb/TextConnectionSettings.hpp> | ||||
35 | #include <com/sun/star/sdb/XCompletedConnection.hpp> | ||||
36 | #include <com/sun/star/sdb/XCompletedExecution.hpp> | ||||
37 | #include <com/sun/star/container/XChild.hpp> | ||||
38 | #include <com/sun/star/text/MailMergeEvent.hpp> | ||||
39 | #include <com/sun/star/frame/XStorable.hpp> | ||||
40 | #include <com/sun/star/task/InteractionHandler.hpp> | ||||
41 | #include <com/sun/star/ui/dialogs/TemplateDescription.hpp> | ||||
42 | #include <com/sun/star/ui/dialogs/XFilePicker3.hpp> | ||||
43 | #include <com/sun/star/beans/XPropertySet.hpp> | ||||
44 | #include <vcl/errinf.hxx> | ||||
45 | #include <vcl/print.hxx> | ||||
46 | #include <vcl/scheduler.hxx> | ||||
47 | #include <sfx2/fcontnr.hxx> | ||||
48 | #include <sfx2/filedlghelper.hxx> | ||||
49 | #include <sfx2/viewfrm.hxx> | ||||
50 | #include <dbconfig.hxx> | ||||
51 | #include <unotools/tempfile.hxx> | ||||
52 | #include <unotools/pathoptions.hxx> | ||||
53 | #include <svl/zforlist.hxx> | ||||
54 | #include <svl/stritem.hxx> | ||||
55 | #include <sfx2/docfile.hxx> | ||||
56 | #include <sfx2/docfilt.hxx> | ||||
57 | #include <sfx2/progress.hxx> | ||||
58 | #include <sfx2/dispatch.hxx> | ||||
59 | #include <cmdid.h> | ||||
60 | #include <swmodule.hxx> | ||||
61 | #include <view.hxx> | ||||
62 | #include <docsh.hxx> | ||||
63 | #include <edtwin.hxx> | ||||
64 | #include <wrtsh.hxx> | ||||
65 | #include <fldbas.hxx> | ||||
66 | #include <dbui.hxx> | ||||
67 | #include <dbmgr.hxx> | ||||
68 | #include <doc.hxx> | ||||
69 | #include <IDocumentLinksAdministration.hxx> | ||||
70 | #include <IDocumentFieldsAccess.hxx> | ||||
71 | #include <IDocumentUndoRedo.hxx> | ||||
72 | #include <swwait.hxx> | ||||
73 | #include <swunohelper.hxx> | ||||
74 | #include <strings.hrc> | ||||
75 | #include <mmconfigitem.hxx> | ||||
76 | #include <com/sun/star/sdbc/XRowSet.hpp> | ||||
77 | #include <com/sun/star/sdbcx/XTablesSupplier.hpp> | ||||
78 | #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> | ||||
79 | #include <com/sun/star/sdb/XQueriesSupplier.hpp> | ||||
80 | #include <com/sun/star/sdb/XColumn.hpp> | ||||
81 | #include <com/sun/star/sdbc/DataType.hpp> | ||||
82 | #include <com/sun/star/sdbc/ResultSetType.hpp> | ||||
83 | #include <com/sun/star/sdbc/SQLException.hpp> | ||||
84 | #include <com/sun/star/mail/MailAttachment.hpp> | ||||
85 | #include <comphelper/processfactory.hxx> | ||||
86 | #include <comphelper/property.hxx> | ||||
87 | #include <comphelper/storagehelper.hxx> | ||||
88 | #include <comphelper/string.hxx> | ||||
89 | #include <comphelper/types.hxx> | ||||
90 | #include <mailmergehelper.hxx> | ||||
91 | #include <maildispatcher.hxx> | ||||
92 | #include <svtools/htmlcfg.hxx> | ||||
93 | #include <i18nlangtag/languagetag.hxx> | ||||
94 | #include <com/sun/star/util/XNumberFormatTypes.hpp> | ||||
95 | #include <svl/numuno.hxx> | ||||
96 | #include <connectivity/dbtools.hxx> | ||||
97 | #include <connectivity/dbconversion.hxx> | ||||
98 | #include <unotools/charclass.hxx> | ||||
99 | #include <tools/diagnose_ex.h> | ||||
100 | |||||
101 | #include <unomailmerge.hxx> | ||||
102 | #include <sfx2/event.hxx> | ||||
103 | #include <svx/dataaccessdescriptor.hxx> | ||||
104 | #include <osl/mutex.hxx> | ||||
105 | #include <rtl/textenc.h> | ||||
106 | #include <rtl/tencinfo.h> | ||||
107 | #include <cppuhelper/implbase.hxx> | ||||
108 | #include <ndindex.hxx> | ||||
109 | #include <swevent.hxx> | ||||
110 | #include <sal/log.hxx> | ||||
111 | #include <swabstdlg.hxx> | ||||
112 | #include <vector> | ||||
113 | #include <section.hxx> | ||||
114 | #include <rootfrm.hxx> | ||||
115 | #include <calc.hxx> | ||||
116 | #include <dbfld.hxx> | ||||
117 | #include <IDocumentState.hxx> | ||||
118 | #include <imaildsplistener.hxx> | ||||
119 | #include <iodetect.hxx> | ||||
120 | #include <IDocumentDeviceAccess.hxx> | ||||
121 | |||||
122 | #include <memory> | ||||
123 | #include <comphelper/propertysequence.hxx> | ||||
124 | |||||
125 | using namespace ::com::sun::star; | ||||
126 | using namespace sw; | ||||
127 | |||||
128 | namespace { | ||||
129 | |||||
130 | void lcl_emitEvent(SfxEventHintId nEventId, sal_Int32 nStrId, SfxObjectShell* pDocShell) | ||||
131 | { | ||||
132 | SfxGetpApp()->NotifyEvent(SfxEventHint(nEventId, | ||||
133 | SwDocShell::GetEventName(nStrId), | ||||
134 | pDocShell)); | ||||
135 | } | ||||
136 | |||||
137 | } | ||||
138 | |||||
139 | std::vector<std::pair<SwDocShell*, OUString>> SwDBManager::m_aUncommittedRegistrations; | ||||
140 | |||||
141 | namespace { | ||||
142 | |||||
143 | enum class SwDBNextRecord { NEXT, FIRST }; | ||||
144 | |||||
145 | } | ||||
146 | |||||
147 | static bool lcl_ToNextRecord( SwDSParam* pParam, const SwDBNextRecord action = SwDBNextRecord::NEXT ); | ||||
148 | |||||
149 | namespace { | ||||
150 | |||||
151 | enum class WorkingDocType { SOURCE, TARGET, COPY }; | ||||
152 | |||||
153 | } | ||||
154 | |||||
155 | static SfxObjectShell* lcl_CreateWorkingDocument( | ||||
156 | const WorkingDocType aType, const SwWrtShell &rSourceWrtShell, | ||||
157 | const vcl::Window *pSourceWindow, | ||||
158 | SwDBManager** const ppDBManager, | ||||
159 | SwView** const pView, SwWrtShell** const pWrtShell, SwDoc** const pDoc ); | ||||
160 | |||||
161 | static bool lcl_getCountFromResultSet( sal_Int32& rCount, const SwDSParam* pParam ) | ||||
162 | { | ||||
163 | rCount = pParam->aSelection.getLength(); | ||||
164 | if ( rCount > 0 ) | ||||
165 | return true; | ||||
166 | |||||
167 | uno::Reference<beans::XPropertySet> xPrSet(pParam->xResultSet, uno::UNO_QUERY); | ||||
168 | if ( xPrSet.is() ) | ||||
169 | { | ||||
170 | try | ||||
171 | { | ||||
172 | bool bFinal = false; | ||||
173 | uno::Any aFinal = xPrSet->getPropertyValue("IsRowCountFinal"); | ||||
174 | aFinal >>= bFinal; | ||||
175 | if(!bFinal) | ||||
176 | { | ||||
177 | pParam->xResultSet->last(); | ||||
178 | pParam->xResultSet->first(); | ||||
179 | } | ||||
180 | uno::Any aCount = xPrSet->getPropertyValue("RowCount"); | ||||
181 | if( aCount >>= rCount ) | ||||
182 | return true; | ||||
183 | } | ||||
184 | catch(const uno::Exception&) | ||||
185 | { | ||||
186 | } | ||||
187 | } | ||||
188 | return false; | ||||
189 | } | ||||
190 | |||||
191 | class SwDBManager::ConnectionDisposedListener_Impl | ||||
192 | : public cppu::WeakImplHelper< lang::XEventListener > | ||||
193 | { | ||||
194 | private: | ||||
195 | SwDBManager * m_pDBManager; | ||||
196 | |||||
197 | virtual void SAL_CALL disposing( const lang::EventObject& Source ) override; | ||||
198 | |||||
199 | public: | ||||
200 | explicit ConnectionDisposedListener_Impl(SwDBManager& rMgr); | ||||
201 | |||||
202 | void Dispose() { m_pDBManager = nullptr; } | ||||
203 | |||||
204 | }; | ||||
205 | |||||
206 | namespace { | ||||
207 | |||||
208 | /// Listens to removed data sources, and if it's one that's embedded into this document, triggers embedding removal. | ||||
209 | class SwDataSourceRemovedListener : public cppu::WeakImplHelper<sdb::XDatabaseRegistrationsListener> | ||||
210 | { | ||||
211 | uno::Reference<sdb::XDatabaseContext> m_xDatabaseContext; | ||||
212 | SwDBManager* m_pDBManager; | ||||
213 | |||||
214 | public: | ||||
215 | explicit SwDataSourceRemovedListener(SwDBManager& rDBManager); | ||||
216 | virtual ~SwDataSourceRemovedListener() override; | ||||
217 | virtual void SAL_CALL registeredDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) override; | ||||
218 | virtual void SAL_CALL revokedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) override; | ||||
219 | virtual void SAL_CALL changedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) override; | ||||
220 | virtual void SAL_CALL disposing(const lang::EventObject& rObject) override; | ||||
221 | void Dispose(); | ||||
222 | }; | ||||
223 | |||||
224 | } | ||||
225 | |||||
226 | SwDataSourceRemovedListener::SwDataSourceRemovedListener(SwDBManager& rDBManager) | ||||
227 | : m_pDBManager(&rDBManager) | ||||
228 | { | ||||
229 | uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); | ||||
230 | m_xDatabaseContext = sdb::DatabaseContext::create(xComponentContext); | ||||
231 | m_xDatabaseContext->addDatabaseRegistrationsListener(this); | ||||
232 | } | ||||
233 | |||||
234 | SwDataSourceRemovedListener::~SwDataSourceRemovedListener() | ||||
235 | { | ||||
236 | if (m_xDatabaseContext.is()) | ||||
237 | m_xDatabaseContext->removeDatabaseRegistrationsListener(this); | ||||
238 | } | ||||
239 | |||||
240 | void SAL_CALL SwDataSourceRemovedListener::registeredDatabaseLocation(const sdb::DatabaseRegistrationEvent& /*rEvent*/) | ||||
241 | { | ||||
242 | } | ||||
243 | |||||
244 | void SAL_CALL SwDataSourceRemovedListener::revokedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) | ||||
245 | { | ||||
246 | if (!m_pDBManager || m_pDBManager->getEmbeddedName().isEmpty()) | ||||
247 | return; | ||||
248 | |||||
249 | SwDoc* pDoc = m_pDBManager->getDoc(); | ||||
250 | if (!pDoc) | ||||
251 | return; | ||||
252 | |||||
253 | SwDocShell* pDocShell = pDoc->GetDocShell(); | ||||
254 | if (!pDocShell) | ||||
255 | return; | ||||
256 | |||||
257 | OUString aOwnURL = pDocShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::WithCharset); | ||||
258 | OUString sTmpName = "vnd.sun.star.pkg://" + | ||||
259 | INetURLObject::encode(aOwnURL, INetURLObject::PART_AUTHORITY, INetURLObject::EncodeMechanism::All); | ||||
260 | sTmpName += "/" + m_pDBManager->getEmbeddedName(); | ||||
261 | |||||
262 | if (sTmpName != rEvent.OldLocation) | ||||
263 | return; | ||||
264 | |||||
265 | // The revoked database location is inside this document, then remove the | ||||
266 | // embedding, as otherwise it would be back on the next reload of the | ||||
267 | // document. | ||||
268 | pDocShell->GetStorage()->removeElement(m_pDBManager->getEmbeddedName()); | ||||
269 | m_pDBManager->setEmbeddedName(OUString(), *pDocShell); | ||||
270 | } | ||||
271 | |||||
272 | void SAL_CALL SwDataSourceRemovedListener::changedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) | ||||
273 | { | ||||
274 | if (rEvent.OldLocation != rEvent.NewLocation) | ||||
275 | revokedDatabaseLocation(rEvent); | ||||
276 | } | ||||
277 | |||||
278 | void SwDataSourceRemovedListener::disposing(const lang::EventObject& /*rObject*/) | ||||
279 | { | ||||
280 | m_xDatabaseContext.clear(); | ||||
281 | } | ||||
282 | |||||
283 | void SwDataSourceRemovedListener::Dispose() | ||||
284 | { | ||||
285 | m_pDBManager = nullptr; | ||||
286 | } | ||||
287 | |||||
288 | struct SwDBManager::SwDBManager_Impl | ||||
289 | { | ||||
290 | std::unique_ptr<SwDSParam> pMergeData; | ||||
291 | VclPtr<AbstractMailMergeDlg> pMergeDialog; | ||||
292 | rtl::Reference<SwDBManager::ConnectionDisposedListener_Impl> m_xDisposeListener; | ||||
293 | rtl::Reference<SwDataSourceRemovedListener> m_xDataSourceRemovedListener; | ||||
294 | osl::Mutex m_aAllEmailSendMutex; | ||||
295 | uno::Reference< mail::XMailMessage> m_xLastMessage; | ||||
296 | |||||
297 | explicit SwDBManager_Impl(SwDBManager& rDBManager) | ||||
298 | : m_xDisposeListener(new ConnectionDisposedListener_Impl(rDBManager)) | ||||
299 | {} | ||||
300 | |||||
301 | ~SwDBManager_Impl() | ||||
302 | { | ||||
303 | m_xDisposeListener->Dispose(); | ||||
304 | if (m_xDataSourceRemovedListener.is()) | ||||
305 | m_xDataSourceRemovedListener->Dispose(); | ||||
306 | } | ||||
307 | }; | ||||
308 | |||||
309 | static void lcl_InitNumberFormatter(SwDSParam& rParam, uno::Reference<sdbc::XDataSource> const & xSource) | ||||
310 | { | ||||
311 | uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext(); | ||||
312 | rParam.xFormatter = util::NumberFormatter::create(xContext); | ||||
313 | uno::Reference<beans::XPropertySet> xSourceProps( | ||||
314 | (xSource.is() | ||||
315 | ? xSource | ||||
316 | : SwDBManager::getDataSourceAsParent( | ||||
317 | rParam.xConnection, rParam.sDataSource)), | ||||
318 | uno::UNO_QUERY); | ||||
319 | if(!xSourceProps.is()) | ||||
320 | return; | ||||
321 | |||||
322 | uno::Any aFormats = xSourceProps->getPropertyValue("NumberFormatsSupplier"); | ||||
323 | if(!aFormats.hasValue()) | ||||
324 | return; | ||||
325 | |||||
326 | uno::Reference<util::XNumberFormatsSupplier> xSuppl; | ||||
327 | aFormats >>= xSuppl; | ||||
328 | if(xSuppl.is()) | ||||
329 | { | ||||
330 | uno::Reference< beans::XPropertySet > xSettings = xSuppl->getNumberFormatSettings(); | ||||
331 | uno::Any aNull = xSettings->getPropertyValue("NullDate"); | ||||
332 | aNull >>= rParam.aNullDate; | ||||
333 | if(rParam.xFormatter.is()) | ||||
334 | rParam.xFormatter->attachNumberFormatsSupplier(xSuppl); | ||||
335 | } | ||||
336 | } | ||||
337 | |||||
338 | static bool lcl_MoveAbsolute(SwDSParam* pParam, long nAbsPos) | ||||
339 | { | ||||
340 | bool bRet = false; | ||||
341 | try | ||||
342 | { | ||||
343 | if(pParam->aSelection.hasElements()) | ||||
344 | { | ||||
345 | if(pParam->aSelection.getLength() <= nAbsPos) | ||||
346 | { | ||||
347 | pParam->bEndOfDB = true; | ||||
348 | bRet = false; | ||||
349 | } | ||||
350 | else | ||||
351 | { | ||||
352 | pParam->nSelectionIndex = nAbsPos; | ||||
353 | sal_Int32 nPos = 0; | ||||
354 | pParam->aSelection.getConstArray()[ pParam->nSelectionIndex ] >>= nPos; | ||||
355 | pParam->bEndOfDB = !pParam->xResultSet->absolute( nPos ); | ||||
356 | bRet = !pParam->bEndOfDB; | ||||
357 | } | ||||
358 | } | ||||
359 | else if(pParam->bScrollable) | ||||
360 | { | ||||
361 | bRet = pParam->xResultSet->absolute( nAbsPos ); | ||||
362 | } | ||||
363 | else | ||||
364 | { | ||||
365 | OSL_FAIL("no absolute positioning available")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "365" ": "), "%s", "no absolute positioning available"); } } while (false); | ||||
366 | } | ||||
367 | } | ||||
368 | catch(const uno::Exception&) | ||||
369 | { | ||||
370 | } | ||||
371 | return bRet; | ||||
372 | } | ||||
373 | |||||
374 | static void lcl_GetColumnCnt(SwDSParam *pParam, | ||||
375 | const uno::Reference< beans::XPropertySet > &rColumnProps, | ||||
376 | LanguageType nLanguage, OUString &rResult, double* pNumber) | ||||
377 | { | ||||
378 | SwDBFormatData aFormatData; | ||||
379 | if(!pParam->xFormatter.is()) | ||||
380 | { | ||||
381 | uno::Reference<sdbc::XDataSource> xSource = SwDBManager::getDataSourceAsParent( | ||||
382 | pParam->xConnection,pParam->sDataSource); | ||||
383 | lcl_InitNumberFormatter(*pParam, xSource ); | ||||
384 | } | ||||
385 | aFormatData.aNullDate = pParam->aNullDate; | ||||
386 | aFormatData.xFormatter = pParam->xFormatter; | ||||
387 | |||||
388 | aFormatData.aLocale = LanguageTag( nLanguage ).getLocale(); | ||||
389 | |||||
390 | rResult = SwDBManager::GetDBField( rColumnProps, aFormatData, pNumber); | ||||
391 | } | ||||
392 | |||||
393 | static bool lcl_GetColumnCnt(SwDSParam* pParam, const OUString& rColumnName, | ||||
394 | LanguageType nLanguage, OUString& rResult, double* pNumber) | ||||
395 | { | ||||
396 | uno::Reference< sdbcx::XColumnsSupplier > xColsSupp( pParam->xResultSet, uno::UNO_QUERY ); | ||||
397 | uno::Reference<container::XNameAccess> xCols; | ||||
398 | try | ||||
399 | { | ||||
400 | xCols = xColsSupp->getColumns(); | ||||
401 | } | ||||
402 | catch(const lang::DisposedException&) | ||||
403 | { | ||||
404 | } | ||||
405 | if(!xCols.is() || !xCols->hasByName(rColumnName)) | ||||
406 | return false; | ||||
407 | uno::Any aCol = xCols->getByName(rColumnName); | ||||
408 | uno::Reference< beans::XPropertySet > xColumnProps; | ||||
409 | aCol >>= xColumnProps; | ||||
410 | lcl_GetColumnCnt( pParam, xColumnProps, nLanguage, rResult, pNumber ); | ||||
411 | return true; | ||||
412 | }; | ||||
413 | |||||
414 | // import data | ||||
415 | bool SwDBManager::Merge( const SwMergeDescriptor& rMergeDesc ) | ||||
416 | { | ||||
417 | assert( !m_bInMerge && !m_pImpl->pMergeData && "merge already activated!" )(static_cast <bool> (!m_bInMerge && !m_pImpl-> pMergeData && "merge already activated!") ? void (0) : __assert_fail ("!m_bInMerge && !m_pImpl->pMergeData && \"merge already activated!\"" , "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 417, __extension__ __PRETTY_FUNCTION__)); | ||||
418 | |||||
419 | SfxObjectShellLock xWorkObjSh; | ||||
420 | SwWrtShell *pWorkShell = nullptr; | ||||
421 | SwDoc *pWorkDoc = nullptr; | ||||
422 | SwDBManager *pWorkDocOrigDBManager = nullptr; | ||||
423 | |||||
424 | switch( rMergeDesc.nMergeType ) | ||||
425 | { | ||||
426 | case DBMGR_MERGE_PRINTER: | ||||
427 | case DBMGR_MERGE_EMAIL: | ||||
428 | case DBMGR_MERGE_FILE: | ||||
429 | case DBMGR_MERGE_SHELL: | ||||
430 | { | ||||
431 | SwDocShell *pSourceDocSh = rMergeDesc.rSh.GetView().GetDocShell(); | ||||
432 | if( pSourceDocSh->IsModified() ) | ||||
433 | { | ||||
434 | pWorkDocOrigDBManager = this; | ||||
435 | xWorkObjSh = lcl_CreateWorkingDocument( | ||||
436 | WorkingDocType::SOURCE, rMergeDesc.rSh, nullptr, | ||||
437 | &pWorkDocOrigDBManager, nullptr, &pWorkShell, &pWorkDoc ); | ||||
438 | } | ||||
439 | [[fallthrough]]; | ||||
440 | } | ||||
441 | |||||
442 | default: | ||||
443 | if( !xWorkObjSh.Is() ) | ||||
444 | pWorkShell = &rMergeDesc.rSh; | ||||
445 | break; | ||||
446 | } | ||||
447 | |||||
448 | SwDBData aData; | ||||
449 | aData.nCommandType = sdb::CommandType::TABLE; | ||||
450 | uno::Reference<sdbc::XResultSet> xResSet; | ||||
451 | uno::Sequence<uno::Any> aSelection; | ||||
452 | uno::Reference< sdbc::XConnection> xConnection; | ||||
453 | |||||
454 | aData.sDataSource = rMergeDesc.rDescriptor.getDataSource(); | ||||
455 | rMergeDesc.rDescriptor[svx::DataAccessDescriptorProperty::Command] >>= aData.sCommand; | ||||
456 | rMergeDesc.rDescriptor[svx::DataAccessDescriptorProperty::CommandType] >>= aData.nCommandType; | ||||
457 | |||||
458 | if ( rMergeDesc.rDescriptor.has(svx::DataAccessDescriptorProperty::Cursor) ) | ||||
459 | rMergeDesc.rDescriptor[svx::DataAccessDescriptorProperty::Cursor] >>= xResSet; | ||||
460 | if ( rMergeDesc.rDescriptor.has(svx::DataAccessDescriptorProperty::Selection) ) | ||||
461 | rMergeDesc.rDescriptor[svx::DataAccessDescriptorProperty::Selection] >>= aSelection; | ||||
462 | if ( rMergeDesc.rDescriptor.has(svx::DataAccessDescriptorProperty::Connection) ) | ||||
463 | rMergeDesc.rDescriptor[svx::DataAccessDescriptorProperty::Connection] >>= xConnection; | ||||
464 | |||||
465 | if((aData.sDataSource.isEmpty() || aData.sCommand.isEmpty()) && !xResSet.is()) | ||||
466 | { | ||||
467 | return false; | ||||
468 | } | ||||
469 | |||||
470 | m_pImpl->pMergeData.reset(new SwDSParam(aData, xResSet, aSelection)); | ||||
471 | SwDSParam* pTemp = FindDSData(aData, false); | ||||
472 | if(pTemp) | ||||
473 | *pTemp = *m_pImpl->pMergeData; | ||||
474 | else | ||||
475 | { | ||||
476 | // calls from the calculator may have added a connection with an invalid commandtype | ||||
477 | //"real" data base connections added here have to re-use the already available | ||||
478 | //DSData and set the correct CommandType | ||||
479 | aData.nCommandType = -1; | ||||
480 | pTemp = FindDSData(aData, false); | ||||
481 | if(pTemp) | ||||
482 | *pTemp = *m_pImpl->pMergeData; | ||||
483 | else | ||||
484 | { | ||||
485 | m_DataSourceParams.push_back(std::make_unique<SwDSParam>(*m_pImpl->pMergeData)); | ||||
486 | try | ||||
487 | { | ||||
488 | uno::Reference<lang::XComponent> xComponent(m_DataSourceParams.back()->xConnection, uno::UNO_QUERY); | ||||
489 | if(xComponent.is()) | ||||
490 | xComponent->addEventListener(m_pImpl->m_xDisposeListener.get()); | ||||
491 | } | ||||
492 | catch(const uno::Exception&) | ||||
493 | { | ||||
494 | } | ||||
495 | } | ||||
496 | } | ||||
497 | if(!m_pImpl->pMergeData->xConnection.is()) | ||||
498 | m_pImpl->pMergeData->xConnection = xConnection; | ||||
499 | // add an XEventListener | ||||
500 | |||||
501 | lcl_ToNextRecord(m_pImpl->pMergeData.get(), SwDBNextRecord::FIRST); | ||||
502 | |||||
503 | uno::Reference<sdbc::XDataSource> xSource = SwDBManager::getDataSourceAsParent(xConnection,aData.sDataSource); | ||||
504 | |||||
505 | lcl_InitNumberFormatter(*m_pImpl->pMergeData, xSource); | ||||
506 | |||||
507 | pWorkShell->ChgDBData(aData); | ||||
508 | m_bInMerge = true; | ||||
509 | |||||
510 | if (IsInitDBFields()) | ||||
511 | { | ||||
512 | // with database fields without DB-Name, use DB-Name from Doc | ||||
513 | std::vector<OUString> aDBNames; | ||||
514 | aDBNames.emplace_back(); | ||||
515 | SwDBData aInsertData = pWorkShell->GetDBData(); | ||||
516 | OUString sDBName = aInsertData.sDataSource | ||||
517 | + OUStringChar(DB_DELIMu'\x00ff') + aInsertData.sCommand | ||||
518 | + OUStringChar(DB_DELIMu'\x00ff') | ||||
519 | + OUString::number(aInsertData.nCommandType); | ||||
520 | pWorkShell->ChangeDBFields( aDBNames, sDBName); | ||||
521 | SetInitDBFields(false); | ||||
522 | } | ||||
523 | |||||
524 | bool bRet = true; | ||||
525 | switch(rMergeDesc.nMergeType) | ||||
526 | { | ||||
527 | case DBMGR_MERGE: | ||||
528 | pWorkShell->StartAllAction(); | ||||
529 | pWorkShell->SwViewShell::UpdateFields( true ); | ||||
530 | pWorkShell->SetModified(); | ||||
531 | pWorkShell->EndAllAction(); | ||||
532 | break; | ||||
533 | |||||
534 | case DBMGR_MERGE_PRINTER: | ||||
535 | case DBMGR_MERGE_EMAIL: | ||||
536 | case DBMGR_MERGE_FILE: | ||||
537 | case DBMGR_MERGE_SHELL: | ||||
538 | // save files and send them as e-Mail if required | ||||
539 | bRet = MergeMailFiles(pWorkShell, rMergeDesc); | ||||
540 | break; | ||||
541 | |||||
542 | default: | ||||
543 | // insert selected entries | ||||
544 | // (was: InsertRecord) | ||||
545 | ImportFromConnection(pWorkShell); | ||||
546 | break; | ||||
547 | } | ||||
548 | |||||
549 | m_pImpl->pMergeData.reset(); | ||||
550 | |||||
551 | if( xWorkObjSh.Is() ) | ||||
552 | { | ||||
553 | pWorkDoc->SetDBManager( pWorkDocOrigDBManager ); | ||||
554 | xWorkObjSh->DoClose(); | ||||
555 | } | ||||
556 | |||||
557 | m_bInMerge = false; | ||||
558 | |||||
559 | return bRet; | ||||
560 | } | ||||
561 | |||||
562 | void SwDBManager::ImportFromConnection( SwWrtShell* pSh ) | ||||
563 | { | ||||
564 | if(!m_pImpl->pMergeData || m_pImpl->pMergeData->bEndOfDB) | ||||
565 | return; | ||||
566 | |||||
567 | pSh->StartAllAction(); | ||||
568 | pSh->StartUndo(); | ||||
569 | bool bGroupUndo(pSh->DoesGroupUndo()); | ||||
570 | pSh->DoGroupUndo(false); | ||||
571 | |||||
572 | if( pSh->HasSelection() ) | ||||
573 | pSh->DelRight(); | ||||
574 | |||||
575 | std::unique_ptr<SwWait> pWait; | ||||
576 | |||||
577 | { | ||||
578 | sal_uLong i = 0; | ||||
579 | do { | ||||
580 | |||||
581 | ImportDBEntry(pSh); | ||||
582 | if( 10 == ++i ) | ||||
583 | pWait.reset(new SwWait( *pSh->GetView().GetDocShell(), true)); | ||||
584 | |||||
585 | } while(ToNextMergeRecord()); | ||||
586 | } | ||||
587 | |||||
588 | pSh->DoGroupUndo(bGroupUndo); | ||||
589 | pSh->EndUndo(); | ||||
590 | pSh->EndAllAction(); | ||||
591 | } | ||||
592 | |||||
593 | void SwDBManager::ImportDBEntry(SwWrtShell* pSh) | ||||
594 | { | ||||
595 | if(!m_pImpl->pMergeData || m_pImpl->pMergeData->bEndOfDB) | ||||
596 | return; | ||||
597 | |||||
598 | uno::Reference< sdbcx::XColumnsSupplier > xColsSupp( m_pImpl->pMergeData->xResultSet, uno::UNO_QUERY ); | ||||
599 | uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns(); | ||||
600 | OUStringBuffer sStr; | ||||
601 | uno::Sequence<OUString> aColNames = xCols->getElementNames(); | ||||
602 | const OUString* pColNames = aColNames.getConstArray(); | ||||
603 | long nLength = aColNames.getLength(); | ||||
604 | for(long i = 0; i < nLength; i++) | ||||
605 | { | ||||
606 | uno::Any aCol = xCols->getByName(pColNames[i]); | ||||
607 | uno::Reference< beans::XPropertySet > xColumnProp; | ||||
608 | aCol >>= xColumnProp; | ||||
609 | SwDBFormatData aDBFormat; | ||||
610 | sStr.append(GetDBField( xColumnProp, aDBFormat)); | ||||
611 | if (i < nLength - 1) | ||||
612 | sStr.append("\t"); | ||||
613 | } | ||||
614 | pSh->SwEditShell::Insert2(sStr.makeStringAndClear()); | ||||
615 | pSh->SwFEShell::SplitNode(); // line feed | ||||
616 | } | ||||
617 | |||||
618 | bool SwDBManager::GetTableNames(weld::ComboBox& rBox, const OUString& rDBName) | ||||
619 | { | ||||
620 | bool bRet = false; | ||||
621 | OUString sOldTableName(rBox.get_active_text()); | ||||
622 | rBox.clear(); | ||||
623 | SwDSParam* pParam = FindDSConnection(rDBName, false); | ||||
624 | uno::Reference< sdbc::XConnection> xConnection; | ||||
625 | if (pParam && pParam->xConnection.is()) | ||||
626 | xConnection = pParam->xConnection; | ||||
627 | else | ||||
628 | { | ||||
629 | if ( !rDBName.isEmpty() ) | ||||
630 | xConnection = RegisterConnection( rDBName ); | ||||
631 | } | ||||
632 | if (xConnection.is()) | ||||
633 | { | ||||
634 | uno::Reference<sdbcx::XTablesSupplier> xTSupplier(xConnection, uno::UNO_QUERY); | ||||
635 | if(xTSupplier.is()) | ||||
636 | { | ||||
637 | uno::Reference<container::XNameAccess> xTables = xTSupplier->getTables(); | ||||
638 | const uno::Sequence<OUString> aTables = xTables->getElementNames(); | ||||
639 | for (const OUString& rTable : aTables) | ||||
640 | rBox.append("0", rTable); | ||||
641 | } | ||||
642 | uno::Reference<sdb::XQueriesSupplier> xQSupplier(xConnection, uno::UNO_QUERY); | ||||
643 | if(xQSupplier.is()) | ||||
644 | { | ||||
645 | uno::Reference<container::XNameAccess> xQueries = xQSupplier->getQueries(); | ||||
646 | const uno::Sequence<OUString> aQueries = xQueries->getElementNames(); | ||||
647 | for (const OUString& rQuery : aQueries) | ||||
648 | rBox.append("1", rQuery); | ||||
649 | } | ||||
650 | if (!sOldTableName.isEmpty()) | ||||
651 | rBox.set_active_text(sOldTableName); | ||||
652 | bRet = true; | ||||
653 | } | ||||
654 | return bRet; | ||||
655 | } | ||||
656 | |||||
657 | // fill Listbox with column names of a database | ||||
658 | void SwDBManager::GetColumnNames(weld::ComboBox& rBox, | ||||
659 | const OUString& rDBName, const OUString& rTableName) | ||||
660 | { | ||||
661 | SwDBData aData; | ||||
662 | aData.sDataSource = rDBName; | ||||
663 | aData.sCommand = rTableName; | ||||
664 | aData.nCommandType = -1; | ||||
665 | SwDSParam* pParam = FindDSData(aData, false); | ||||
666 | uno::Reference< sdbc::XConnection> xConnection; | ||||
667 | if(pParam && pParam->xConnection.is()) | ||||
668 | xConnection = pParam->xConnection; | ||||
669 | else | ||||
670 | { | ||||
671 | xConnection = RegisterConnection( rDBName ); | ||||
672 | } | ||||
673 | GetColumnNames(rBox, xConnection, rTableName); | ||||
674 | } | ||||
675 | |||||
676 | void SwDBManager::GetColumnNames(weld::ComboBox& rBox, | ||||
677 | uno::Reference< sdbc::XConnection> const & xConnection, | ||||
678 | const OUString& rTableName) | ||||
679 | { | ||||
680 | rBox.clear(); | ||||
681 | uno::Reference< sdbcx::XColumnsSupplier> xColsSupp = SwDBManager::GetColumnSupplier(xConnection, rTableName); | ||||
682 | if(xColsSupp.is()) | ||||
683 | { | ||||
684 | uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns(); | ||||
685 | const uno::Sequence<OUString> aColNames = xCols->getElementNames(); | ||||
686 | for (const OUString& rColName : aColNames) | ||||
687 | { | ||||
688 | rBox.append_text(rColName); | ||||
689 | } | ||||
690 | ::comphelper::disposeComponent( xColsSupp ); | ||||
691 | } | ||||
692 | } | ||||
693 | |||||
694 | SwDBManager::SwDBManager(SwDoc* pDoc) | ||||
695 | : m_aMergeStatus( MergeStatus::Ok ) | ||||
696 | , m_bInitDBFields(false) | ||||
697 | , m_bInMerge(false) | ||||
698 | , m_bMergeSilent(false) | ||||
699 | , m_pImpl(new SwDBManager_Impl(*this)) | ||||
700 | , m_pMergeEvtSrc(nullptr) | ||||
701 | , m_pDoc(pDoc) | ||||
702 | { | ||||
703 | } | ||||
704 | |||||
705 | SwDBManager::~SwDBManager() COVERITY_NOEXCEPT_FALSE | ||||
706 | { | ||||
707 | RevokeLastRegistrations(); | ||||
708 | |||||
709 | // copy required, m_DataSourceParams can be modified while disposing components | ||||
710 | std::vector<uno::Reference<sdbc::XConnection>> aCopiedConnections; | ||||
711 | for (const auto & pParam : m_DataSourceParams) | ||||
712 | { | ||||
713 | if(pParam->xConnection.is()) | ||||
714 | { | ||||
715 | aCopiedConnections.push_back(pParam->xConnection); | ||||
716 | } | ||||
717 | } | ||||
718 | for (const auto & xConnection : aCopiedConnections) | ||||
719 | { | ||||
720 | try | ||||
721 | { | ||||
722 | uno::Reference<lang::XComponent> xComp(xConnection, uno::UNO_QUERY); | ||||
723 | if(xComp.is()) | ||||
724 | xComp->dispose(); | ||||
725 | } | ||||
726 | catch(const uno::RuntimeException&) | ||||
727 | { | ||||
728 | //may be disposed already since multiple entries may have used the same connection | ||||
729 | } | ||||
730 | } | ||||
731 | } | ||||
732 | |||||
733 | static void lcl_RemoveSectionLinks( SwWrtShell& rWorkShell ) | ||||
734 | { | ||||
735 | //reset all links of the sections of synchronized labels | ||||
736 | size_t nSections = rWorkShell.GetSectionFormatCount(); | ||||
737 | for (size_t nSection = 0; nSection < nSections; ++nSection) | ||||
738 | { | ||||
739 | SwSectionData aSectionData( *rWorkShell.GetSectionFormat( nSection ).GetSection() ); | ||||
740 | if( aSectionData.GetType() == SectionType::FileLink ) | ||||
741 | { | ||||
742 | aSectionData.SetType( SectionType::Content ); | ||||
743 | aSectionData.SetLinkFileName( OUString() ); | ||||
744 | rWorkShell.UpdateSection( nSection, aSectionData ); | ||||
745 | } | ||||
746 | } | ||||
747 | rWorkShell.SetLabelDoc( false ); | ||||
748 | } | ||||
749 | |||||
750 | static void lcl_SaveDebugDoc( SfxObjectShell *xTargetDocShell, | ||||
751 | const char *name, int no = 0 ) | ||||
752 | { | ||||
753 | static OUString sTempDirURL; | ||||
754 | if( sTempDirURL.isEmpty() ) | ||||
755 | { | ||||
756 | SvtPathOptions aPathOpt; | ||||
757 | utl::TempFile aTempDir( &aPathOpt.GetTempPath(), true ); | ||||
758 | if( aTempDir.IsValid() ) | ||||
759 | { | ||||
760 | INetURLObject aTempDirURL( aTempDir.GetURL() ); | ||||
761 | sTempDirURL = aTempDirURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ); | ||||
762 | SAL_INFO( "sw.mailmerge", "Dump directory: " << sTempDirURL )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "sw.mailmerge")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "Dump directory: " << sTempDirURL) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "762" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Dump directory: " << sTempDirURL ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Dump directory: " << sTempDirURL; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "762" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Dump directory: " << sTempDirURL) == 1) { :: sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.mailmerge" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "762" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Dump directory: " << sTempDirURL ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Dump directory: " << sTempDirURL; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "762" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
763 | } | ||||
764 | } | ||||
765 | if( sTempDirURL.isEmpty() ) | ||||
766 | return; | ||||
767 | |||||
768 | const OUString sExt( ".odt" ); | ||||
769 | OUString basename = OUString::createFromAscii( name ); | ||||
770 | if (no > 0) | ||||
771 | basename += OUString::number(no) + "-"; | ||||
772 | // aTempFile is not deleted, but that seems to be intentional | ||||
773 | utl::TempFile aTempFile( basename, true, &sExt, &sTempDirURL ); | ||||
774 | INetURLObject aTempFileURL( aTempFile.GetURL() ); | ||||
775 | auto pDstMed = std::make_unique<SfxMedium>( | ||||
776 | aTempFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), | ||||
777 | StreamMode::STD_READWRITE ); | ||||
778 | bool bAnyError = !xTargetDocShell->DoSaveAs( *pDstMed ); | ||||
779 | // xObjectShell->DoSaveCompleted crashes the mail merge unit tests, so skip it | ||||
780 | bAnyError |= (ERRCODE_NONEErrCode(0) != xTargetDocShell->GetError()); | ||||
781 | if( bAnyError ) | ||||
782 | SAL_WARN( "sw.mailmerge", "Error saving: " << aTempFile.GetURL() )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.mailmerge")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "Error saving: " << aTempFile.GetURL()) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "782" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Error saving: " << aTempFile.GetURL ()), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Error saving: " << aTempFile.GetURL(); ::sal ::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "782" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Error saving: " << aTempFile.GetURL()) == 1 ) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "782" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Error saving: " << aTempFile.GetURL ()), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Error saving: " << aTempFile.GetURL(); ::sal ::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "782" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
783 | else | ||||
784 | SAL_INFO( "sw.mailmerge", "Saved doc as: " << aTempFile.GetURL() )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "sw.mailmerge")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "Saved doc as: " << aTempFile.GetURL()) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "784" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Saved doc as: " << aTempFile.GetURL ()), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Saved doc as: " << aTempFile.GetURL(); ::sal ::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.mailmerge" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "784" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Saved doc as: " << aTempFile.GetURL()) == 1 ) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.mailmerge" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "784" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Saved doc as: " << aTempFile.GetURL ()), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Saved doc as: " << aTempFile.GetURL(); ::sal ::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.mailmerge" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "784" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
785 | } | ||||
786 | |||||
787 | static bool lcl_SaveDoc( | ||||
788 | const INetURLObject* pFileURL, | ||||
789 | const std::shared_ptr<const SfxFilter>& pStoreToFilter, | ||||
790 | const OUString* pStoreToFilterOptions, | ||||
791 | const uno::Sequence< beans::PropertyValue >* pSaveToFilterData, | ||||
792 | const bool bIsPDFexport, | ||||
793 | SfxObjectShell* xObjectShell, | ||||
794 | SwWrtShell& rWorkShell, | ||||
795 | OUString * const decodedURL = nullptr ) | ||||
796 | { | ||||
797 | OUString url = pFileURL->GetMainURL( INetURLObject::DecodeMechanism::NONE ); | ||||
798 | if( decodedURL ) | ||||
799 | (*decodedURL) = url; | ||||
800 | |||||
801 | SfxMedium* pDstMed = new SfxMedium( url, StreamMode::STD_READWRITE ); | ||||
802 | pDstMed->SetFilter( pStoreToFilter ); | ||||
803 | if( pDstMed->GetItemSet() ) | ||||
804 | { | ||||
805 | if( pStoreToFilterOptions ) | ||||
806 | pDstMed->GetItemSet()->Put( SfxStringItem(SID_FILE_FILTEROPTIONS(5000 + 527), | ||||
807 | *pStoreToFilterOptions)); | ||||
808 | if( pSaveToFilterData->hasElements() ) | ||||
809 | pDstMed->GetItemSet()->Put( SfxUnoAnyItem(SID_FILTER_DATA(5000 + 1375), | ||||
810 | uno::makeAny(*pSaveToFilterData))); | ||||
811 | } | ||||
812 | |||||
813 | // convert fields to text if we are exporting to PDF. | ||||
814 | // this prevents a second merge while updating the fields | ||||
815 | // in SwXTextDocument::getRendererCount() | ||||
816 | if( bIsPDFexport ) | ||||
817 | rWorkShell.ConvertFieldsToText(); | ||||
818 | |||||
819 | bool bAnyError = !xObjectShell->DoSaveAs(*pDstMed); | ||||
820 | // Actually this should be a bool... so in case of email and individual | ||||
821 | // files, where this is set, we skip the recently used handling | ||||
822 | bAnyError |= !xObjectShell->DoSaveCompleted( pDstMed, !decodedURL ); | ||||
823 | bAnyError |= (ERRCODE_NONEErrCode(0) != xObjectShell->GetError()); | ||||
824 | if( bAnyError ) | ||||
825 | { | ||||
826 | // error message ?? | ||||
827 | ErrorHandler::HandleError( xObjectShell->GetError() ); | ||||
828 | } | ||||
829 | return !bAnyError; | ||||
830 | } | ||||
831 | |||||
832 | static void lcl_PreparePrinterOptions( | ||||
833 | const uno::Sequence< beans::PropertyValue >& rInPrintOptions, | ||||
834 | uno::Sequence< beans::PropertyValue >& rOutPrintOptions) | ||||
835 | { | ||||
836 | // printing should be done synchronously otherwise the document | ||||
837 | // might already become invalid during the process | ||||
838 | |||||
839 | const sal_Int32 nOffset = 1; | ||||
840 | rOutPrintOptions.realloc( nOffset ); | ||||
841 | rOutPrintOptions[ 0 ].Name = "Wait"; | ||||
842 | rOutPrintOptions[ 0 ].Value <<= true; | ||||
843 | |||||
844 | // copy print options | ||||
845 | sal_Int32 nIndex = nOffset; | ||||
846 | for( const beans::PropertyValue& rOption : rInPrintOptions) | ||||
847 | { | ||||
848 | if( rOption.Name == "CopyCount" || rOption.Name == "FileName" | ||||
849 | || rOption.Name == "Collate" || rOption.Name == "Pages" | ||||
850 | || rOption.Name == "Wait" || rOption.Name == "PrinterName" ) | ||||
851 | { | ||||
852 | // add an option | ||||
853 | rOutPrintOptions.realloc( nIndex + 1 ); | ||||
854 | rOutPrintOptions[ nIndex ].Name = rOption.Name; | ||||
855 | rOutPrintOptions[ nIndex++ ].Value = rOption.Value ; | ||||
856 | } | ||||
857 | } | ||||
858 | } | ||||
859 | |||||
860 | static void lcl_PrepareSaveFilterDataOptions( | ||||
861 | const uno::Sequence< beans::PropertyValue >& rInSaveFilterDataptions, | ||||
862 | uno::Sequence< beans::PropertyValue >& rOutSaveFilterDataOptions, | ||||
863 | const OUString& sPassword) | ||||
864 | { | ||||
865 | const sal_Int32 nOffset = 2; | ||||
866 | rOutSaveFilterDataOptions.realloc( nOffset ); | ||||
867 | rOutSaveFilterDataOptions[ 0 ].Name = "EncryptFile"; | ||||
868 | rOutSaveFilterDataOptions[ 0 ].Value <<= true; | ||||
869 | rOutSaveFilterDataOptions[ 1 ].Name = "DocumentOpenPassword"; | ||||
870 | rOutSaveFilterDataOptions[ 1 ].Value <<= sPassword; | ||||
871 | |||||
872 | // copy other options | ||||
873 | sal_Int32 nIndex = nOffset; | ||||
874 | for( const beans::PropertyValue& rOption : rInSaveFilterDataptions) | ||||
875 | { | ||||
876 | rOutSaveFilterDataOptions.realloc( nIndex + 1 ); | ||||
877 | rOutSaveFilterDataOptions[ nIndex ].Name = rOption.Name; | ||||
878 | rOutSaveFilterDataOptions[ nIndex++ ].Value = rOption.Value ; | ||||
879 | } | ||||
880 | |||||
881 | } | ||||
882 | |||||
883 | |||||
884 | static SfxObjectShell* lcl_CreateWorkingDocument( | ||||
885 | // input | ||||
886 | const WorkingDocType aType, const SwWrtShell &rSourceWrtShell, | ||||
887 | // optional input | ||||
888 | const vcl::Window *pSourceWindow, | ||||
889 | // optional in and output to swap the DB manager | ||||
890 | SwDBManager** const ppDBManager, | ||||
891 | // optional output | ||||
892 | SwView** const pView, SwWrtShell** const pWrtShell, SwDoc** const pDoc ) | ||||
893 | { | ||||
894 | const SwDoc *pSourceDoc = rSourceWrtShell.GetDoc(); | ||||
895 | SfxObjectShellRef xWorkObjectShell = pSourceDoc->CreateCopy( true, (aType == WorkingDocType::TARGET) ); | ||||
896 | SfxViewFrame* pWorkFrame = SfxViewFrame::LoadHiddenDocument( *xWorkObjectShell, SFX_INTERFACE_NONE ); | ||||
897 | |||||
898 | if( pSourceWindow
| ||||
899 | { | ||||
900 | // the created window has to be located at the same position as the source window | ||||
901 | vcl::Window& rTargetWindow = pWorkFrame->GetFrame().GetWindow(); | ||||
902 | rTargetWindow.SetPosPixel( pSourceWindow->GetPosPixel() ); | ||||
903 | } | ||||
904 | |||||
905 | SwView* pWorkView = static_cast< SwView* >( pWorkFrame->GetViewShell() ); | ||||
906 | SwWrtShell* pWorkWrtShell = pWorkView->GetWrtShellPtr(); | ||||
907 | pWorkWrtShell->GetViewOptions()->SetIdle( false ); | ||||
908 | pWorkView->AttrChangedNotify(nullptr);// in order for SelectShell to be called | ||||
909 | SwDoc* pWorkDoc = pWorkWrtShell->GetDoc(); | ||||
910 | pWorkDoc->GetIDocumentUndoRedo().DoUndo( false ); | ||||
911 | pWorkDoc->ReplaceDocumentProperties( *pSourceDoc ); | ||||
912 | |||||
913 | // import print settings | ||||
914 | const SwPrintData &rPrintData = pSourceDoc->getIDocumentDeviceAccess().getPrintData(); | ||||
915 | pWorkDoc->getIDocumentDeviceAccess().setPrintData(rPrintData); | ||||
916 | const JobSetup *pJobSetup = pSourceDoc->getIDocumentDeviceAccess().getJobsetup(); | ||||
917 | if (pJobSetup) | ||||
918 | pWorkDoc->getIDocumentDeviceAccess().setJobsetup(*pJobSetup); | ||||
919 | |||||
920 | if( aType
| ||||
921 | { | ||||
922 | assert( !ppDBManager )(static_cast <bool> (!ppDBManager) ? void (0) : __assert_fail ("!ppDBManager", "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 922, __extension__ __PRETTY_FUNCTION__)); | ||||
923 | pWorkDoc->SetInMailMerge( true ); | ||||
924 | pWorkWrtShell->SetLabelDoc( false ); | ||||
925 | } | ||||
926 | else | ||||
927 | { | ||||
928 | // We have to swap the DBmanager of the new doc, so we also need input | ||||
929 | assert(ppDBManager && *ppDBManager)(static_cast <bool> (ppDBManager && *ppDBManager ) ? void (0) : __assert_fail ("ppDBManager && *ppDBManager" , "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 929, __extension__ __PRETTY_FUNCTION__)); | ||||
930 | SwDBManager *pWorkDBManager = pWorkDoc->GetDBManager(); | ||||
931 | pWorkDoc->SetDBManager( *ppDBManager ); | ||||
932 | *ppDBManager = pWorkDBManager; | ||||
933 | |||||
934 | if( aType
| ||||
935 | { | ||||
936 | // the GetDBData call constructs the data, if it's missing - kind of const... | ||||
937 | pWorkWrtShell->ChgDBData( const_cast<SwDoc*>(pSourceDoc)->GetDBData() ); | ||||
938 | // some DocumentSettings are currently not copied by SwDoc::CreateCopy | ||||
939 | pWorkWrtShell->SetLabelDoc( rSourceWrtShell.IsLabelDoc() ); | ||||
940 | pWorkDoc->getIDocumentState().ResetModified(); | ||||
941 | } | ||||
942 | else | ||||
943 | pWorkDoc->getIDocumentLinksAdministration().EmbedAllLinks(); | ||||
944 | } | ||||
945 | |||||
946 | if( pView
| ||||
947 | if( pWrtShell
| ||||
948 | if( pDoc
| ||||
949 | |||||
950 | return xWorkObjectShell.get(); | ||||
| |||||
951 | } | ||||
952 | |||||
953 | static SwMailMessage* lcl_CreateMailFromDoc( | ||||
954 | const SwMergeDescriptor &rMergeDescriptor, | ||||
955 | const OUString &sFileURL, const OUString &sMailRecipient, | ||||
956 | const OUString &sMailBodyMimeType, rtl_TextEncoding sMailEncoding, | ||||
957 | const OUString &sAttachmentMimeType ) | ||||
958 | { | ||||
959 | SwMailMessage* pMessage = new SwMailMessage; | ||||
960 | if( rMergeDescriptor.pMailMergeConfigItem->IsMailReplyTo() ) | ||||
961 | pMessage->setReplyToAddress(rMergeDescriptor.pMailMergeConfigItem->GetMailReplyTo()); | ||||
962 | pMessage->addRecipient( sMailRecipient ); | ||||
963 | pMessage->SetSenderAddress( rMergeDescriptor.pMailMergeConfigItem->GetMailAddress() ); | ||||
964 | |||||
965 | OUStringBuffer sBody; | ||||
966 | if( rMergeDescriptor.bSendAsAttachment ) | ||||
967 | { | ||||
968 | sBody = rMergeDescriptor.sMailBody; | ||||
969 | mail::MailAttachment aAttach; | ||||
970 | aAttach.Data = new SwMailTransferable( sFileURL, | ||||
971 | rMergeDescriptor.sAttachmentName, sAttachmentMimeType ); | ||||
972 | aAttach.ReadableName = rMergeDescriptor.sAttachmentName; | ||||
973 | pMessage->addAttachment( aAttach ); | ||||
974 | } | ||||
975 | else | ||||
976 | { | ||||
977 | //read in the temporary file and use it as mail body | ||||
978 | SfxMedium aMedium( sFileURL, StreamMode::READ ); | ||||
979 | SvStream* pInStream = aMedium.GetInStream(); | ||||
980 | assert( pInStream && "no output file created?" )(static_cast <bool> (pInStream && "no output file created?" ) ? void (0) : __assert_fail ("pInStream && \"no output file created?\"" , "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 980, __extension__ __PRETTY_FUNCTION__)); | ||||
981 | if( !pInStream ) | ||||
982 | return pMessage; | ||||
983 | |||||
984 | pInStream->SetStreamCharSet( sMailEncoding ); | ||||
985 | OString sLine; | ||||
986 | while ( pInStream->ReadLine( sLine ) ) | ||||
987 | { | ||||
988 | sBody.append(OStringToOUString( sLine, sMailEncoding )); | ||||
989 | sBody.append("\n"); | ||||
990 | } | ||||
991 | } | ||||
992 | pMessage->setSubject( rMergeDescriptor.sSubject ); | ||||
993 | uno::Reference< datatransfer::XTransferable> xBody = | ||||
994 | new SwMailTransferable( sBody.makeStringAndClear(), sMailBodyMimeType ); | ||||
995 | pMessage->setBody( xBody ); | ||||
996 | |||||
997 | for( const OUString& sCcRecipient : rMergeDescriptor.aCopiesTo ) | ||||
998 | pMessage->addCcRecipient( sCcRecipient ); | ||||
999 | for( const OUString& sBccRecipient : rMergeDescriptor.aBlindCopiesTo ) | ||||
1000 | pMessage->addBccRecipient( sBccRecipient ); | ||||
1001 | |||||
1002 | return pMessage; | ||||
1003 | } | ||||
1004 | |||||
1005 | class SwDBManager::MailDispatcherListener_Impl : public IMailDispatcherListener | ||||
1006 | { | ||||
1007 | SwDBManager &m_rDBManager; | ||||
1008 | |||||
1009 | public: | ||||
1010 | explicit MailDispatcherListener_Impl( SwDBManager &rDBManager ) | ||||
1011 | : m_rDBManager( rDBManager ) {} | ||||
1012 | |||||
1013 | virtual void idle() override {} | ||||
1014 | |||||
1015 | virtual void mailDelivered( uno::Reference< mail::XMailMessage> xMessage ) override | ||||
1016 | { | ||||
1017 | osl::MutexGuard aGuard( m_rDBManager.m_pImpl->m_aAllEmailSendMutex ); | ||||
1018 | if ( m_rDBManager.m_pImpl->m_xLastMessage == xMessage ) | ||||
1019 | m_rDBManager.m_pImpl->m_xLastMessage.clear(); | ||||
1020 | } | ||||
1021 | |||||
1022 | virtual void mailDeliveryError( ::rtl::Reference<MailDispatcher> xMailDispatcher, | ||||
1023 | uno::Reference< mail::XMailMessage>, const OUString& ) override | ||||
1024 | { | ||||
1025 | osl::MutexGuard aGuard( m_rDBManager.m_pImpl->m_aAllEmailSendMutex ); | ||||
1026 | m_rDBManager.m_aMergeStatus = MergeStatus::Error; | ||||
1027 | m_rDBManager.m_pImpl->m_xLastMessage.clear(); | ||||
1028 | xMailDispatcher->stop(); | ||||
1029 | } | ||||
1030 | }; | ||||
1031 | |||||
1032 | /** | ||||
1033 | * Please have a look at the README in the same directory, before you make | ||||
1034 | * larger changes in this function! | ||||
1035 | */ | ||||
1036 | bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, | ||||
1037 | const SwMergeDescriptor& rMergeDescriptor) | ||||
1038 | { | ||||
1039 | // deconstruct mail merge type for better readability. | ||||
1040 | // uppercase naming is intentional! | ||||
1041 | const bool bMT_EMAIL = rMergeDescriptor.nMergeType == DBMGR_MERGE_EMAIL; | ||||
1042 | const bool bMT_SHELL = rMergeDescriptor.nMergeType == DBMGR_MERGE_SHELL; | ||||
1043 | const bool bMT_PRINTER = rMergeDescriptor.nMergeType == DBMGR_MERGE_PRINTER; | ||||
1044 | const bool bMT_FILE = rMergeDescriptor.nMergeType == DBMGR_MERGE_FILE; | ||||
1045 | |||||
1046 | //check if the doc is synchronized and contains at least one linked section | ||||
1047 | const bool bSynchronizedDoc = pSourceShell->IsLabelDoc() && pSourceShell->GetSectionFormatCount() > 1; | ||||
1048 | const bool bNeedsTempFiles = ( bMT_EMAIL || bMT_FILE ); | ||||
1049 | const bool bIsMergeSilent = IsMergeSilent(); | ||||
1050 | |||||
1051 | bool bCheckSingleFile_ = rMergeDescriptor.bCreateSingleFile; | ||||
1052 | OUString sPrefix_ = rMergeDescriptor.sPrefix; | ||||
1053 | if( bMT_EMAIL ) | ||||
1054 | { | ||||
1055 | assert( !rMergeDescriptor.bPrefixIsFilename )(static_cast <bool> (!rMergeDescriptor.bPrefixIsFilename ) ? void (0) : __assert_fail ("!rMergeDescriptor.bPrefixIsFilename" , "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 1055, __extension__ __PRETTY_FUNCTION__)); | ||||
1056 | assert(!bCheckSingleFile_)(static_cast <bool> (!bCheckSingleFile_) ? void (0) : __assert_fail ("!bCheckSingleFile_", "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 1056, __extension__ __PRETTY_FUNCTION__)); | ||||
1057 | bCheckSingleFile_ = false; | ||||
1058 | } | ||||
1059 | else if( bMT_SHELL || bMT_PRINTER ) | ||||
1060 | { | ||||
1061 | assert(bCheckSingleFile_)(static_cast <bool> (bCheckSingleFile_) ? void (0) : __assert_fail ("bCheckSingleFile_", "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 1061, __extension__ __PRETTY_FUNCTION__)); | ||||
1062 | bCheckSingleFile_ = true; | ||||
1063 | assert(sPrefix_.isEmpty())(static_cast <bool> (sPrefix_.isEmpty()) ? void (0) : __assert_fail ("sPrefix_.isEmpty()", "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 1063, __extension__ __PRETTY_FUNCTION__)); | ||||
1064 | sPrefix_.clear(); | ||||
1065 | } | ||||
1066 | const bool bCreateSingleFile = bCheckSingleFile_; | ||||
1067 | const OUString sDescriptorPrefix = sPrefix_; | ||||
1068 | |||||
1069 | // Setup for dumping debugging documents | ||||
1070 | static const sal_Int32 nMaxDumpDocs = []() { | ||||
1071 | if (const char* sEnv = getenv("SW_DEBUG_MAILMERGE_DOCS")) | ||||
1072 | return OUString(sEnv, strlen(sEnv), osl_getThreadTextEncoding()).toInt32(); | ||||
1073 | else | ||||
1074 | return sal_Int32(0); | ||||
1075 | }(); | ||||
1076 | |||||
1077 | ::rtl::Reference< MailDispatcher > xMailDispatcher; | ||||
1078 | ::rtl::Reference< IMailDispatcherListener > xMailListener; | ||||
1079 | OUString sMailBodyMimeType; | ||||
1080 | rtl_TextEncoding sMailEncoding = ::osl_getThreadTextEncoding(); | ||||
1081 | |||||
1082 | uno::Reference< beans::XPropertySet > xColumnProp; | ||||
1083 | uno::Reference< beans::XPropertySet > xPasswordColumnProp; | ||||
1084 | |||||
1085 | // Check for (mandatory) email or (optional) filename column | ||||
1086 | SwDBFormatData aColumnDBFormat; | ||||
1087 | bool bColumnName = !rMergeDescriptor.sDBcolumn.isEmpty(); | ||||
1088 | bool bPasswordColumnName = !rMergeDescriptor.sDBPasswordColumn.isEmpty(); | ||||
1089 | |||||
1090 | if( ! bColumnName ) | ||||
1091 | { | ||||
1092 | if( bMT_EMAIL ) | ||||
1093 | return false; | ||||
1094 | } | ||||
1095 | else | ||||
1096 | { | ||||
1097 | uno::Reference< sdbcx::XColumnsSupplier > xColsSupp( m_pImpl->pMergeData->xResultSet, uno::UNO_QUERY ); | ||||
1098 | uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns(); | ||||
1099 | if( !xCols->hasByName( rMergeDescriptor.sDBcolumn ) ) | ||||
1100 | return false; | ||||
1101 | uno::Any aCol = xCols->getByName( rMergeDescriptor.sDBcolumn ); | ||||
1102 | aCol >>= xColumnProp; | ||||
1103 | |||||
1104 | if(bPasswordColumnName) | ||||
1105 | { | ||||
1106 | aCol = xCols->getByName( rMergeDescriptor.sDBPasswordColumn ); | ||||
1107 | aCol >>= xPasswordColumnProp; | ||||
1108 | } | ||||
1109 | |||||
1110 | aColumnDBFormat.xFormatter = m_pImpl->pMergeData->xFormatter; | ||||
1111 | aColumnDBFormat.aNullDate = m_pImpl->pMergeData->aNullDate; | ||||
1112 | |||||
1113 | if( bMT_EMAIL ) | ||||
1114 | { | ||||
1115 | // Reset internal mail accounting data | ||||
1116 | m_pImpl->m_xLastMessage.clear(); | ||||
1117 | |||||
1118 | xMailDispatcher.set( new MailDispatcher(rMergeDescriptor.xSmtpServer) ); | ||||
1119 | xMailListener = new MailDispatcherListener_Impl( *this ); | ||||
1120 | xMailDispatcher->addListener( xMailListener ); | ||||
1121 | if(!rMergeDescriptor.bSendAsAttachment && rMergeDescriptor.bSendAsHTML) | ||||
1122 | { | ||||
1123 | sMailBodyMimeType = "text/html; charset=" + OUString::createFromAscii( | ||||
1124 | rtl_getBestMimeCharsetFromTextEncoding( sMailEncoding )); | ||||
1125 | SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get(); | ||||
1126 | sMailEncoding = rHtmlOptions.GetTextEncoding(); | ||||
1127 | } | ||||
1128 | else | ||||
1129 | sMailBodyMimeType = "text/plain; charset=UTF-8; format=flowed"; | ||||
1130 | } | ||||
1131 | } | ||||
1132 | |||||
1133 | SwDocShell *pSourceDocSh = pSourceShell->GetView().GetDocShell(); | ||||
1134 | |||||
1135 | // setup the output format | ||||
1136 | std::shared_ptr<const SfxFilter> pStoreToFilter = SwIoSystem::GetFileFilter( | ||||
1137 | pSourceDocSh->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::NONE)); | ||||
1138 | SfxFilterContainer* pFilterContainer = SwDocShell::Factory().GetFilterContainer(); | ||||
1139 | const OUString* pStoreToFilterOptions = nullptr; | ||||
1140 | |||||
1141 | // if a save_to filter is set then use it - otherwise use the default | ||||
1142 | if( bMT_EMAIL && !rMergeDescriptor.bSendAsAttachment ) | ||||
1143 | { | ||||
1144 | OUString sExtension = rMergeDescriptor.bSendAsHTML ? OUString("html") : OUString("txt"); | ||||
1145 | pStoreToFilter = pFilterContainer->GetFilter4Extension(sExtension, SfxFilterFlags::EXPORT); | ||||
1146 | } | ||||
1147 | else if( !rMergeDescriptor.sSaveToFilter.isEmpty()) | ||||
1148 | { | ||||
1149 | std::shared_ptr<const SfxFilter> pFilter = | ||||
1150 | pFilterContainer->GetFilter4FilterName( rMergeDescriptor.sSaveToFilter ); | ||||
1151 | if(pFilter) | ||||
1152 | { | ||||
1153 | pStoreToFilter = pFilter; | ||||
1154 | if(!rMergeDescriptor.sSaveToFilterOptions.isEmpty()) | ||||
1155 | pStoreToFilterOptions = &rMergeDescriptor.sSaveToFilterOptions; | ||||
1156 | } | ||||
1157 | } | ||||
1158 | const bool bIsPDFexport = pStoreToFilter && pStoreToFilter->GetFilterName() == "writer_pdf_Export"; | ||||
1159 | |||||
1160 | m_aMergeStatus = MergeStatus::Ok; | ||||
1161 | |||||
1162 | // in case of creating a single resulting file this has to be created here | ||||
1163 | SwView* pTargetView = rMergeDescriptor.pMailMergeConfigItem ? | ||||
1164 | rMergeDescriptor.pMailMergeConfigItem->GetTargetView() : nullptr; | ||||
1165 | SwWrtShell* pTargetShell = nullptr; | ||||
1166 | SwDoc* pTargetDoc = nullptr; | ||||
1167 | SfxObjectShellRef xTargetDocShell; | ||||
1168 | |||||
1169 | std::unique_ptr< utl::TempFile > aTempFile; | ||||
1170 | sal_uInt16 nStartingPageNo = 0; | ||||
1171 | |||||
1172 | std::shared_ptr<weld::GenericDialogController> xProgressDlg; | ||||
1173 | |||||
1174 | try | ||||
1175 | { | ||||
1176 | vcl::Window *pSourceWindow = nullptr; | ||||
1177 | if( !bIsMergeSilent ) | ||||
1178 | { | ||||
1179 | // construct the process dialog | ||||
1180 | pSourceWindow = &pSourceShell->GetView().GetEditWin(); | ||||
1181 | if (!bMT_PRINTER) | ||||
1182 | xProgressDlg = std::make_shared<CreateMonitor>(pSourceWindow->GetFrameWeld()); | ||||
1183 | else | ||||
1184 | { | ||||
1185 | xProgressDlg = std::make_shared<PrintMonitor>(pSourceWindow->GetFrameWeld()); | ||||
1186 | static_cast<PrintMonitor*>(xProgressDlg.get())->set_title( | ||||
1187 | pSourceDocSh->GetTitle(22)); | ||||
1188 | } | ||||
1189 | weld::DialogController::runAsync(xProgressDlg, [this, &xProgressDlg](sal_Int32 nResult){ | ||||
1190 | if (nResult == RET_CANCEL) | ||||
1191 | MergeCancel(); | ||||
1192 | xProgressDlg.reset(); | ||||
1193 | }); | ||||
1194 | |||||
1195 | Application::Reschedule( true ); | ||||
1196 | } | ||||
1197 | |||||
1198 | if( bCreateSingleFile && !pTargetView ) | ||||
1199 | { | ||||
1200 | // create a target docshell to put the merged document into | ||||
1201 | xTargetDocShell = lcl_CreateWorkingDocument( WorkingDocType::TARGET, | ||||
1202 | *pSourceShell, bMT_SHELL ? pSourceWindow : nullptr, | ||||
1203 | nullptr, &pTargetView, &pTargetShell, &pTargetDoc ); | ||||
1204 | |||||
1205 | if (nMaxDumpDocs) | ||||
1206 | lcl_SaveDebugDoc( xTargetDocShell.get(), "MergeDoc" ); | ||||
1207 | } | ||||
1208 | else if( pTargetView ) | ||||
1209 | { | ||||
1210 | pTargetShell = pTargetView->GetWrtShellPtr(); | ||||
1211 | pTargetDoc = pTargetShell->GetDoc(); | ||||
1212 | xTargetDocShell = pTargetView->GetDocShell(); | ||||
1213 | } | ||||
1214 | |||||
1215 | if( bCreateSingleFile ) | ||||
1216 | { | ||||
1217 | // determine the page style and number used at the start of the source document | ||||
1218 | pSourceShell->SttEndDoc(true); | ||||
1219 | nStartingPageNo = pSourceShell->GetVirtPageNum(); | ||||
1220 | } | ||||
1221 | |||||
1222 | // Progress, to prohibit KeyInputs | ||||
1223 | SfxProgress aProgress(pSourceDocSh, OUString(), 1); | ||||
1224 | |||||
1225 | // lock all dispatchers | ||||
1226 | SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst(pSourceDocSh); | ||||
1227 | while (pViewFrame) | ||||
1228 | { | ||||
1229 | pViewFrame->GetDispatcher()->Lock(true); | ||||
1230 | pViewFrame = SfxViewFrame::GetNext(*pViewFrame, pSourceDocSh); | ||||
1231 | } | ||||
1232 | |||||
1233 | sal_Int32 nDocNo = 1; | ||||
1234 | |||||
1235 | // For single file mode, the number of pages in the target document so far, which is used | ||||
1236 | // by AppendDoc() to adjust position of page-bound objects. Getting this information directly | ||||
1237 | // from the target doc would require repeated layouts of the doc, which is expensive, but | ||||
1238 | // it can be manually computed from the source documents (for which we do layouts, so the page | ||||
1239 | // count is known, and there is a blank page between each of them in the target document). | ||||
1240 | int targetDocPageCount = 0; | ||||
1241 | |||||
1242 | if( !bIsMergeSilent && !bMT_PRINTER ) | ||||
1243 | { | ||||
1244 | sal_Int32 nRecordCount = 1; | ||||
1245 | lcl_getCountFromResultSet( nRecordCount, m_pImpl->pMergeData.get() ); | ||||
1246 | |||||
1247 | // Synchronized docs don't auto-advance the record set, but there is a | ||||
1248 | // "security" check, which will always advance the record set, if there | ||||
1249 | // is no "next record" field in a synchronized doc => nRecordPerDoc > 0 | ||||
1250 | sal_Int32 nRecordPerDoc = pSourceShell->GetDoc() | ||||
1251 | ->getIDocumentFieldsAccess().GetRecordsPerDocument(); | ||||
1252 | if ( bSynchronizedDoc && (nRecordPerDoc > 1) ) | ||||
1253 | --nRecordPerDoc; | ||||
1254 | assert( nRecordPerDoc > 0 )(static_cast <bool> (nRecordPerDoc > 0) ? void (0) : __assert_fail ("nRecordPerDoc > 0", "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 1254, __extension__ __PRETTY_FUNCTION__)); | ||||
1255 | |||||
1256 | sal_Int32 nMaxDocs = nRecordCount / nRecordPerDoc; | ||||
1257 | if ( 0 != nRecordCount % nRecordPerDoc ) | ||||
1258 | nMaxDocs += 1; | ||||
1259 | static_cast<CreateMonitor*>(xProgressDlg.get())->SetTotalCount(nMaxDocs); | ||||
1260 | } | ||||
1261 | |||||
1262 | long nStartRow, nEndRow; | ||||
1263 | bool bFreezedLayouts = false; | ||||
1264 | // to collect temporary email files | ||||
1265 | std::vector< OUString> aFilesToRemove; | ||||
1266 | |||||
1267 | // The SfxObjectShell will be closed explicitly later but | ||||
1268 | // it is more safe to use SfxObjectShellLock here | ||||
1269 | SfxObjectShellLock xWorkDocSh; | ||||
1270 | SwView* pWorkView = nullptr; | ||||
1271 | SwDoc* pWorkDoc = nullptr; | ||||
1272 | SwDBManager* pWorkDocOrigDBManager = nullptr; | ||||
1273 | SwWrtShell* pWorkShell = nullptr; | ||||
1274 | bool bWorkDocInitialized = false; | ||||
1275 | |||||
1276 | do | ||||
1277 | { | ||||
1278 | nStartRow = m_pImpl->pMergeData ? m_pImpl->pMergeData->xResultSet->getRow() : 0; | ||||
1279 | |||||
1280 | OUString sColumnData; | ||||
1281 | |||||
1282 | // Read the indicated data column, which should contain a valid mail | ||||
1283 | // address or an optional file name | ||||
1284 | if( bMT_EMAIL || bColumnName ) | ||||
1285 | { | ||||
1286 | sColumnData = GetDBField( xColumnProp, aColumnDBFormat ); | ||||
1287 | } | ||||
1288 | |||||
1289 | // create a new temporary file name - only done once in case of bCreateSingleFile | ||||
1290 | if( bNeedsTempFiles && ( !bWorkDocInitialized || !bCreateSingleFile )) | ||||
1291 | { | ||||
1292 | OUString sPrefix = sDescriptorPrefix; | ||||
1293 | OUString sLeading; | ||||
1294 | |||||
1295 | //#i97667# if the name is from a database field then it will be used _as is_ | ||||
1296 | if( bColumnName && !bMT_EMAIL ) | ||||
1297 | { | ||||
1298 | if (!sColumnData.isEmpty()) | ||||
1299 | sLeading = sColumnData; | ||||
1300 | else | ||||
1301 | sLeading = "_"; | ||||
1302 | } | ||||
1303 | else | ||||
1304 | { | ||||
1305 | INetURLObject aEntry( sPrefix ); | ||||
1306 | sLeading = aEntry.GetBase(); | ||||
1307 | aEntry.removeSegment(); | ||||
1308 | sPrefix = aEntry.GetMainURL( INetURLObject::DecodeMechanism::NONE ); | ||||
1309 | } | ||||
1310 | |||||
1311 | OUString sExt(comphelper::string::stripStart(pStoreToFilter->GetDefaultExtension(), '*')); | ||||
1312 | aTempFile.reset( new utl::TempFile(sLeading, sColumnData.isEmpty(), &sExt, &sPrefix, true) ); | ||||
1313 | if( !aTempFile->IsValid() ) | ||||
1314 | { | ||||
1315 | ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTEDErrCode( ErrCodeArea::Io, ErrCodeClass::NotSupported, 12 ) ); | ||||
1316 | m_aMergeStatus = MergeStatus::Error; | ||||
1317 | } | ||||
1318 | } | ||||
1319 | |||||
1320 | uno::Sequence< beans::PropertyValue > aSaveToFilterDataOptions( rMergeDescriptor.aSaveToFilterData ); | ||||
1321 | |||||
1322 | if( bMT_EMAIL || bPasswordColumnName ) | ||||
1323 | { | ||||
1324 | OUString sPasswordColumnData = GetDBField( xPasswordColumnProp, aColumnDBFormat ); | ||||
1325 | lcl_PrepareSaveFilterDataOptions( rMergeDescriptor.aSaveToFilterData, aSaveToFilterDataOptions, sPasswordColumnData ); | ||||
1326 | } | ||||
1327 | |||||
1328 | if( IsMergeOk() ) | ||||
1329 | { | ||||
1330 | std::unique_ptr< INetURLObject > aTempFileURL; | ||||
1331 | if( bNeedsTempFiles ) | ||||
1332 | aTempFileURL.reset( new INetURLObject(aTempFile->GetURL())); | ||||
1333 | if( !bIsMergeSilent ) { | ||||
1334 | if( !bMT_PRINTER ) | ||||
1335 | static_cast<CreateMonitor*>(xProgressDlg.get())->SetCurrentPosition(nDocNo); | ||||
1336 | else { | ||||
1337 | PrintMonitor *pPrintMonDlg = static_cast<PrintMonitor*>(xProgressDlg.get()); | ||||
1338 | pPrintMonDlg->m_xPrinter->set_label(bNeedsTempFiles | ||||
1339 | ? aTempFileURL->GetBase() : pSourceDocSh->GetTitle( 2)); | ||||
1340 | OUString sStat = SwResId(STR_STATSTR_LETTERreinterpret_cast<char const *>("STR_STATSTR_LETTER" "\004" u8"Letter")) + " " + OUString::number( nDocNo ); | ||||
1341 | pPrintMonDlg->m_xPrintInfo->set_label(sStat); | ||||
1342 | } | ||||
1343 | //TODO xProgressDlg->queue_draw(); | ||||
1344 | } | ||||
1345 | |||||
1346 | Scheduler::ProcessEventsToIdle(); | ||||
1347 | |||||
1348 | // Create a copy of the source document and work with that one instead of the source. | ||||
1349 | // If we're not in the single file mode (which requires modifying the document for the merging), | ||||
1350 | // it is enough to do this just once. Currently PDF also has to be treated special. | ||||
1351 | if( !bWorkDocInitialized || bCreateSingleFile || bIsPDFexport ) | ||||
1352 | { | ||||
1353 | assert( !xWorkDocSh.Is())(static_cast <bool> (!xWorkDocSh.Is()) ? void (0) : __assert_fail ("!xWorkDocSh.Is()", "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 1353, __extension__ __PRETTY_FUNCTION__)); | ||||
1354 | pWorkDocOrigDBManager = this; | ||||
1355 | xWorkDocSh = lcl_CreateWorkingDocument( WorkingDocType::COPY, | ||||
1356 | *pSourceShell, nullptr, &pWorkDocOrigDBManager, | ||||
1357 | &pWorkView, &pWorkShell, &pWorkDoc ); | ||||
1358 | if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) ) | ||||
1359 | lcl_SaveDebugDoc( xWorkDocSh, "WorkDoc", nDocNo ); | ||||
1360 | |||||
1361 | // #i69458# lock fields to prevent access to the result set while calculating layout | ||||
1362 | // tdf#92324: and do not unlock: keep document locked during printing to avoid | ||||
1363 | // ExpFields update during printing, generation of preview, etc. | ||||
1364 | pWorkShell->LockExpFields(); | ||||
1365 | pWorkShell->CalcLayout(); | ||||
1366 | // tdf#121168: Now force correct page descriptions applied to page frames. Without | ||||
1367 | // this, e.g., page frames starting with sections could have page descriptions set | ||||
1368 | // wrong. This would lead to wrong page styles applied in SwDoc::AppendDoc below. | ||||
1369 | pWorkShell->GetViewOptions()->SetIdle(true); | ||||
1370 | for (auto aLayout : pWorkShell->GetDoc()->GetAllLayouts()) | ||||
1371 | { | ||||
1372 | aLayout->FreezeLayout(false); | ||||
1373 | aLayout->AllCheckPageDescs(); | ||||
1374 | } | ||||
1375 | } | ||||
1376 | |||||
1377 | lcl_emitEvent(SfxEventHintId::SwEventFieldMerge, STR_SW_EVENT_FIELD_MERGE3, xWorkDocSh); | ||||
1378 | |||||
1379 | // tdf#92324: Allow ExpFields update only by explicit instruction to avoid | ||||
1380 | // database cursor movement on any other fields update, for example during | ||||
1381 | // print preview and other operations | ||||
1382 | if ( pWorkShell->IsExpFieldsLocked() ) | ||||
1383 | pWorkShell->UnlockExpFields(); | ||||
1384 | pWorkShell->SwViewShell::UpdateFields(); | ||||
1385 | pWorkShell->LockExpFields(); | ||||
1386 | |||||
1387 | lcl_emitEvent(SfxEventHintId::SwEventFieldMergeFinished, STR_SW_EVENT_FIELD_MERGE_FINISHED4, xWorkDocSh); | ||||
1388 | |||||
1389 | // also emit MailMergeEvent on XInterface if possible | ||||
1390 | const SwXMailMerge *pEvtSrc = GetMailMergeEvtSrc(); | ||||
1391 | if(pEvtSrc) | ||||
1392 | { | ||||
1393 | rtl::Reference< SwXMailMerge > xRef( | ||||
1394 | const_cast<SwXMailMerge*>(pEvtSrc) ); | ||||
1395 | text::MailMergeEvent aEvt( static_cast<text::XMailMergeBroadcaster*>(xRef.get()), xWorkDocSh->GetModel() ); | ||||
1396 | SolarMutexReleaser rel; | ||||
1397 | xRef->LaunchMailMergeEvent( aEvt ); | ||||
1398 | } | ||||
1399 | |||||
1400 | // working copy is merged - prepare final steps depending on merge options | ||||
1401 | |||||
1402 | if( bCreateSingleFile ) | ||||
1403 | { | ||||
1404 | assert( pTargetShell && "no target shell available!" )(static_cast <bool> (pTargetShell && "no target shell available!" ) ? void (0) : __assert_fail ("pTargetShell && \"no target shell available!\"" , "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 1404, __extension__ __PRETTY_FUNCTION__)); | ||||
1405 | |||||
1406 | // prepare working copy and target to append | ||||
1407 | |||||
1408 | pWorkDoc->RemoveInvisibleContent(); | ||||
1409 | // remove of invisible content has influence on page count and so on fields for page count, | ||||
1410 | // therefore layout has to be updated before fields are converted to text | ||||
1411 | pWorkShell->CalcLayout(); | ||||
1412 | pWorkShell->ConvertFieldsToText(); | ||||
1413 | pWorkShell->SetNumberingRestart(); | ||||
1414 | if( bSynchronizedDoc ) | ||||
1415 | { | ||||
1416 | lcl_RemoveSectionLinks( *pWorkShell ); | ||||
1417 | } | ||||
1418 | |||||
1419 | if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) ) | ||||
1420 | lcl_SaveDebugDoc( xWorkDocSh, "WorkDoc", nDocNo ); | ||||
1421 | |||||
1422 | // append the working document to the target document | ||||
1423 | if( targetDocPageCount % 2 == 1 ) | ||||
1424 | ++targetDocPageCount; // Docs always start on odd pages (so offset must be even). | ||||
1425 | SwNodeIndex appendedDocStart = pTargetDoc->AppendDoc( *pWorkDoc, | ||||
1426 | nStartingPageNo, !bWorkDocInitialized, targetDocPageCount, nDocNo); | ||||
1427 | targetDocPageCount += pWorkShell->GetPageCnt(); | ||||
1428 | |||||
1429 | if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) ) | ||||
1430 | lcl_SaveDebugDoc( xTargetDocShell.get(), "MergeDoc" ); | ||||
1431 | |||||
1432 | if (bMT_SHELL) | ||||
1433 | { | ||||
1434 | SwDocMergeInfo aMergeInfo; | ||||
1435 | // Name of the mark is actually irrelevant, UNO bookmarks have internals names. | ||||
1436 | aMergeInfo.startPageInTarget = pTargetDoc->getIDocumentMarkAccess()->makeMark( | ||||
1437 | appendedDocStart, "", IDocumentMarkAccess::MarkType::UNO_BOOKMARK, | ||||
1438 | ::sw::mark::InsertMode::New); | ||||
1439 | aMergeInfo.nDBRow = nStartRow; | ||||
1440 | rMergeDescriptor.pMailMergeConfigItem->AddMergedDocument( aMergeInfo ); | ||||
1441 | } | ||||
1442 | } | ||||
1443 | else | ||||
1444 | { | ||||
1445 | assert( bNeedsTempFiles )(static_cast <bool> (bNeedsTempFiles) ? void (0) : __assert_fail ("bNeedsTempFiles", "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 1445, __extension__ __PRETTY_FUNCTION__)); | ||||
1446 | assert( pWorkShell->IsExpFieldsLocked() )(static_cast <bool> (pWorkShell->IsExpFieldsLocked() ) ? void (0) : __assert_fail ("pWorkShell->IsExpFieldsLocked()" , "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 1446, __extension__ __PRETTY_FUNCTION__)); | ||||
1447 | |||||
1448 | // fields are locked, so it's fine to | ||||
1449 | // restore the old / empty DB manager for save | ||||
1450 | pWorkDoc->SetDBManager( pWorkDocOrigDBManager ); | ||||
1451 | |||||
1452 | // save merged document | ||||
1453 | OUString sFileURL; | ||||
1454 | if( !lcl_SaveDoc( aTempFileURL.get(), pStoreToFilter, pStoreToFilterOptions, | ||||
1455 | &aSaveToFilterDataOptions, bIsPDFexport, | ||||
1456 | xWorkDocSh, *pWorkShell, &sFileURL ) ) | ||||
1457 | { | ||||
1458 | m_aMergeStatus = MergeStatus::Error; | ||||
1459 | } | ||||
1460 | |||||
1461 | // back to the MM DB manager | ||||
1462 | pWorkDoc->SetDBManager( this ); | ||||
1463 | |||||
1464 | if( bMT_EMAIL && !IsMergeError() ) | ||||
1465 | { | ||||
1466 | // schedule file for later removal | ||||
1467 | aFilesToRemove.push_back( sFileURL ); | ||||
1468 | |||||
1469 | if( !SwMailMergeHelper::CheckMailAddress( sColumnData ) ) | ||||
1470 | { | ||||
1471 | OSL_FAIL("invalid e-Mail address in database column")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1471" ": "), "%s", "invalid e-Mail address in database column" ); } } while (false); | ||||
1472 | } | ||||
1473 | else | ||||
1474 | { | ||||
1475 | uno::Reference< mail::XMailMessage > xMessage = lcl_CreateMailFromDoc( | ||||
1476 | rMergeDescriptor, sFileURL, sColumnData, sMailBodyMimeType, | ||||
1477 | sMailEncoding, pStoreToFilter->GetMimeType() ); | ||||
1478 | if( xMessage.is() ) | ||||
1479 | { | ||||
1480 | osl::MutexGuard aGuard( m_pImpl->m_aAllEmailSendMutex ); | ||||
1481 | m_pImpl->m_xLastMessage.set( xMessage ); | ||||
1482 | xMailDispatcher->enqueueMailMessage( xMessage ); | ||||
1483 | if( !xMailDispatcher->isStarted() ) | ||||
1484 | xMailDispatcher->start(); | ||||
1485 | } | ||||
1486 | } | ||||
1487 | } | ||||
1488 | } | ||||
1489 | if( bCreateSingleFile || bIsPDFexport ) | ||||
1490 | { | ||||
1491 | pWorkDoc->SetDBManager( pWorkDocOrigDBManager ); | ||||
1492 | xWorkDocSh->DoClose(); | ||||
1493 | xWorkDocSh = nullptr; | ||||
1494 | } | ||||
1495 | } | ||||
1496 | |||||
1497 | bWorkDocInitialized = true; | ||||
1498 | nDocNo++; | ||||
1499 | nEndRow = m_pImpl->pMergeData ? m_pImpl->pMergeData->xResultSet->getRow() : 0; | ||||
1500 | |||||
1501 | // Freeze the layouts of the target document after the first inserted | ||||
1502 | // sub-document, to get the correct PageDesc. | ||||
1503 | if(!bFreezedLayouts && bCreateSingleFile) | ||||
1504 | { | ||||
1505 | for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() ) | ||||
1506 | aLayout->FreezeLayout(true); | ||||
1507 | bFreezedLayouts = true; | ||||
1508 | } | ||||
1509 | } while( IsMergeOk() && | ||||
1510 | ((bSynchronizedDoc && (nStartRow != nEndRow)) ? IsValidMergeRecord() : ToNextMergeRecord())); | ||||
1511 | |||||
1512 | if ( xWorkDocSh.Is() && pWorkView->GetWrtShell().IsExpFieldsLocked() ) | ||||
1513 | { | ||||
1514 | // Unlock document fields after merge complete | ||||
1515 | pWorkView->GetWrtShell().UnlockExpFields(); | ||||
1516 | } | ||||
1517 | |||||
1518 | if( !bCreateSingleFile ) | ||||
1519 | { | ||||
1520 | if( bMT_PRINTER ) | ||||
1521 | Printer::FinishPrintJob( pWorkView->GetPrinterController()); | ||||
1522 | if( !bIsPDFexport ) | ||||
1523 | { | ||||
1524 | pWorkDoc->SetDBManager( pWorkDocOrigDBManager ); | ||||
1525 | xWorkDocSh->DoClose(); | ||||
1526 | } | ||||
1527 | } | ||||
1528 | else if( IsMergeOk() ) // && bCreateSingleFile | ||||
1529 | { | ||||
1530 | Application::Reschedule( true ); | ||||
1531 | |||||
1532 | // sw::DocumentLayoutManager::CopyLayoutFormat() did not generate | ||||
1533 | // unique fly names, do it here once. | ||||
1534 | pTargetDoc->SetInMailMerge(false); | ||||
1535 | pTargetDoc->SetAllUniqueFlyNames(); | ||||
1536 | |||||
1537 | // Unfreeze target document layouts and correct all PageDescs. | ||||
1538 | SAL_INFO( "sw.pageframe", "(MergeMailFiles pTargetShell->CalcLayout in" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "sw.pageframe")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "(MergeMailFiles pTargetShell->CalcLayout in" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1538" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "(MergeMailFiles pTargetShell->CalcLayout in" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "(MergeMailFiles pTargetShell->CalcLayout in"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1538" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "(MergeMailFiles pTargetShell->CalcLayout in") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1538" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "(MergeMailFiles pTargetShell->CalcLayout in" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "(MergeMailFiles pTargetShell->CalcLayout in"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1538" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
1539 | pTargetShell->CalcLayout(); | ||||
1540 | SAL_INFO( "sw.pageframe", "MergeMailFiles pTargetShell->CalcLayout out)" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "sw.pageframe")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "MergeMailFiles pTargetShell->CalcLayout out)" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1540" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "MergeMailFiles pTargetShell->CalcLayout out)" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "MergeMailFiles pTargetShell->CalcLayout out)"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1540" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "MergeMailFiles pTargetShell->CalcLayout out)" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1540" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "MergeMailFiles pTargetShell->CalcLayout out)" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "MergeMailFiles pTargetShell->CalcLayout out)"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1540" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
1541 | pTargetShell->GetViewOptions()->SetIdle( true ); | ||||
1542 | pTargetDoc->GetIDocumentUndoRedo().DoUndo( true ); | ||||
1543 | for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() ) | ||||
1544 | { | ||||
1545 | aLayout->FreezeLayout(false); | ||||
1546 | aLayout->AllCheckPageDescs(); | ||||
1547 | } | ||||
1548 | |||||
1549 | Application::Reschedule( true ); | ||||
1550 | |||||
1551 | if( IsMergeOk() && bMT_FILE ) | ||||
1552 | { | ||||
1553 | // save merged document | ||||
1554 | assert( aTempFile )(static_cast <bool> (aTempFile) ? void (0) : __assert_fail ("aTempFile", "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 1554, __extension__ __PRETTY_FUNCTION__)); | ||||
1555 | INetURLObject aTempFileURL; | ||||
1556 | if (sDescriptorPrefix.isEmpty() || !rMergeDescriptor.bPrefixIsFilename) | ||||
1557 | aTempFileURL.SetURL( aTempFile->GetURL() ); | ||||
1558 | else | ||||
1559 | { | ||||
1560 | aTempFileURL.SetURL(sDescriptorPrefix); | ||||
1561 | // remove the unneeded temporary file | ||||
1562 | aTempFile->EnableKillingFile(); | ||||
1563 | } | ||||
1564 | if( !lcl_SaveDoc( &aTempFileURL, pStoreToFilter, | ||||
1565 | pStoreToFilterOptions, &rMergeDescriptor.aSaveToFilterData, | ||||
1566 | bIsPDFexport, xTargetDocShell.get(), *pTargetShell ) ) | ||||
1567 | { | ||||
1568 | m_aMergeStatus = MergeStatus::Error; | ||||
1569 | } | ||||
1570 | } | ||||
1571 | else if( IsMergeOk() && bMT_PRINTER ) | ||||
1572 | { | ||||
1573 | // print the target document | ||||
1574 | uno::Sequence< beans::PropertyValue > aOptions( rMergeDescriptor.aPrintOptions ); | ||||
1575 | lcl_PreparePrinterOptions( rMergeDescriptor.aPrintOptions, aOptions ); | ||||
1576 | pTargetView->ExecPrint( aOptions, bIsMergeSilent, false/*bPrintAsync*/ ); | ||||
1577 | } | ||||
1578 | } | ||||
1579 | |||||
1580 | // we also show canceled documents, as long as there was no error | ||||
1581 | if( !IsMergeError() && bMT_SHELL ) | ||||
1582 | // leave docshell available for caller (e.g. MM wizard) | ||||
1583 | rMergeDescriptor.pMailMergeConfigItem->SetTargetView( pTargetView ); | ||||
1584 | else if( xTargetDocShell.is() ) | ||||
1585 | xTargetDocShell->DoClose(); | ||||
1586 | |||||
1587 | Application::Reschedule( true ); | ||||
1588 | |||||
1589 | if (xProgressDlg) | ||||
1590 | { | ||||
1591 | xProgressDlg->response(RET_OK); | ||||
1592 | } | ||||
1593 | |||||
1594 | // unlock all dispatchers | ||||
1595 | pViewFrame = SfxViewFrame::GetFirst(pSourceDocSh); | ||||
1596 | while (pViewFrame) | ||||
1597 | { | ||||
1598 | pViewFrame->GetDispatcher()->Lock(false); | ||||
1599 | pViewFrame = SfxViewFrame::GetNext(*pViewFrame, pSourceDocSh); | ||||
1600 | } | ||||
1601 | |||||
1602 | SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule ::Writer)))->SetView(&pSourceShell->GetView()); | ||||
1603 | |||||
1604 | if( xMailDispatcher.is() ) | ||||
1605 | { | ||||
1606 | if( IsMergeOk() ) | ||||
1607 | { | ||||
1608 | // TODO: Instead of polling via an AutoTimer, post an Idle event, | ||||
1609 | // if the main loop has been made thread-safe. | ||||
1610 | AutoTimer aEmailDispatcherPollTimer; | ||||
1611 | aEmailDispatcherPollTimer.SetDebugName( | ||||
1612 | "sw::SwDBManager aEmailDispatcherPollTimer" ); | ||||
1613 | aEmailDispatcherPollTimer.SetTimeout( 500 ); | ||||
1614 | aEmailDispatcherPollTimer.Start(); | ||||
1615 | while( IsMergeOk() && m_pImpl->m_xLastMessage.is() ) | ||||
1616 | Application::Yield(); | ||||
1617 | aEmailDispatcherPollTimer.Stop(); | ||||
1618 | } | ||||
1619 | xMailDispatcher->stop(); | ||||
1620 | xMailDispatcher->shutdown(); | ||||
1621 | } | ||||
1622 | |||||
1623 | // remove the temporary files | ||||
1624 | // has to be done after xMailDispatcher is finished, as mails may be | ||||
1625 | // delivered as message attachments! | ||||
1626 | for( const OUString &sFileURL : aFilesToRemove ) | ||||
1627 | SWUnoHelper::UCB_DeleteFile( sFileURL ); | ||||
1628 | } | ||||
1629 | catch (const uno::Exception&) | ||||
1630 | { | ||||
1631 | if (xProgressDlg) | ||||
1632 | { | ||||
1633 | xProgressDlg->response(RET_CANCEL); | ||||
1634 | } | ||||
1635 | } | ||||
1636 | |||||
1637 | return !IsMergeError(); | ||||
1638 | } | ||||
1639 | |||||
1640 | void SwDBManager::MergeCancel() | ||||
1641 | { | ||||
1642 | if (m_aMergeStatus < MergeStatus::Cancel) | ||||
1643 | m_aMergeStatus = MergeStatus::Cancel; | ||||
1644 | } | ||||
1645 | |||||
1646 | // determine the column's Numberformat and transfer to the forwarded Formatter, | ||||
1647 | // if applicable. | ||||
1648 | sal_uLong SwDBManager::GetColumnFormat( const OUString& rDBName, | ||||
1649 | const OUString& rTableName, | ||||
1650 | const OUString& rColNm, | ||||
1651 | SvNumberFormatter* pNFormatr, | ||||
1652 | LanguageType nLanguage ) | ||||
1653 | { | ||||
1654 | sal_uLong nRet = 0; | ||||
1655 | if(pNFormatr) | ||||
1656 | { | ||||
1657 | uno::Reference< sdbc::XDataSource> xSource; | ||||
1658 | uno::Reference< sdbc::XConnection> xConnection; | ||||
1659 | bool bUseMergeData = false; | ||||
1660 | uno::Reference< sdbcx::XColumnsSupplier> xColsSupp; | ||||
1661 | bool bDisposeConnection = false; | ||||
1662 | if(m_pImpl->pMergeData && | ||||
1663 | ((m_pImpl->pMergeData->sDataSource == rDBName && m_pImpl->pMergeData->sCommand == rTableName) || | ||||
1664 | (rDBName.isEmpty() && rTableName.isEmpty()))) | ||||
1665 | { | ||||
1666 | xConnection = m_pImpl->pMergeData->xConnection; | ||||
1667 | xSource = SwDBManager::getDataSourceAsParent(xConnection,rDBName); | ||||
1668 | bUseMergeData = true; | ||||
1669 | xColsSupp.set(m_pImpl->pMergeData->xResultSet, css::uno::UNO_QUERY); | ||||
1670 | } | ||||
1671 | if(!xConnection.is()) | ||||
1672 | { | ||||
1673 | SwDBData aData; | ||||
1674 | aData.sDataSource = rDBName; | ||||
1675 | aData.sCommand = rTableName; | ||||
1676 | aData.nCommandType = -1; | ||||
1677 | SwDSParam* pParam = FindDSData(aData, false); | ||||
1678 | if(pParam && pParam->xConnection.is()) | ||||
1679 | { | ||||
1680 | xConnection = pParam->xConnection; | ||||
1681 | xColsSupp.set(pParam->xResultSet, css::uno::UNO_QUERY); | ||||
1682 | } | ||||
1683 | else | ||||
1684 | { | ||||
1685 | xConnection = RegisterConnection( rDBName ); | ||||
1686 | bDisposeConnection = true; | ||||
1687 | } | ||||
1688 | if(bUseMergeData) | ||||
1689 | m_pImpl->pMergeData->xConnection = xConnection; | ||||
1690 | } | ||||
1691 | bool bDispose = !xColsSupp.is(); | ||||
1692 | if(bDispose) | ||||
1693 | { | ||||
1694 | xColsSupp = SwDBManager::GetColumnSupplier(xConnection, rTableName); | ||||
1695 | } | ||||
1696 | if(xColsSupp.is()) | ||||
1697 | { | ||||
1698 | uno::Reference<container::XNameAccess> xCols; | ||||
1699 | try | ||||
1700 | { | ||||
1701 | xCols = xColsSupp->getColumns(); | ||||
1702 | } | ||||
1703 | catch (const uno::Exception&) | ||||
1704 | { | ||||
1705 | TOOLS_WARN_EXCEPTION("sw.mailmerge", "Exception in getColumns()")do { css::uno::Any tools_warn_exception( DbgGetCaughtException () ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.mailmerge")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "Exception in getColumns()" << " " << exceptionToString(tools_warn_exception )) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ( "sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1705" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "Exception in getColumns()" << " " << exceptionToString(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Exception in getColumns()" << " " << exceptionToString (tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1705" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Exception in getColumns()" << " " << exceptionToString(tools_warn_exception)) == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1705" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "Exception in getColumns()" << " " << exceptionToString(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Exception in getColumns()" << " " << exceptionToString (tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1705" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); } while (false); | ||||
1706 | } | ||||
1707 | if(!xCols.is() || !xCols->hasByName(rColNm)) | ||||
1708 | return nRet; | ||||
1709 | uno::Any aCol = xCols->getByName(rColNm); | ||||
1710 | uno::Reference< beans::XPropertySet > xColumn; | ||||
1711 | aCol >>= xColumn; | ||||
1712 | nRet = GetColumnFormat(xSource, xConnection, xColumn, pNFormatr, nLanguage); | ||||
1713 | if(bDispose) | ||||
1714 | { | ||||
1715 | ::comphelper::disposeComponent( xColsSupp ); | ||||
1716 | } | ||||
1717 | if(bDisposeConnection) | ||||
1718 | { | ||||
1719 | ::comphelper::disposeComponent( xConnection ); | ||||
1720 | } | ||||
1721 | } | ||||
1722 | else | ||||
1723 | nRet = pNFormatr->GetFormatIndex( NF_NUMBER_STANDARD, LANGUAGE_SYSTEMLanguageType(0x0000) ); | ||||
1724 | } | ||||
1725 | return nRet; | ||||
1726 | } | ||||
1727 | |||||
1728 | sal_uLong SwDBManager::GetColumnFormat( uno::Reference< sdbc::XDataSource> const & xSource_in, | ||||
1729 | uno::Reference< sdbc::XConnection> const & xConnection, | ||||
1730 | uno::Reference< beans::XPropertySet> const & xColumn, | ||||
1731 | SvNumberFormatter* pNFormatr, | ||||
1732 | LanguageType nLanguage ) | ||||
1733 | { | ||||
1734 | auto xSource = xSource_in; | ||||
1735 | |||||
1736 | // set the NumberFormat in the doc if applicable | ||||
1737 | sal_uLong nRet = 0; | ||||
1738 | |||||
1739 | if(!xSource.is()) | ||||
1740 | { | ||||
1741 | uno::Reference<container::XChild> xChild(xConnection, uno::UNO_QUERY); | ||||
1742 | if ( xChild.is() ) | ||||
1743 | xSource.set(xChild->getParent(), uno::UNO_QUERY); | ||||
1744 | } | ||||
1745 | if(xSource.is() && xConnection.is() && xColumn.is() && pNFormatr) | ||||
1746 | { | ||||
1747 | SvNumberFormatsSupplierObj* pNumFormat = new SvNumberFormatsSupplierObj( pNFormatr ); | ||||
1748 | uno::Reference< util::XNumberFormatsSupplier > xDocNumFormatsSupplier = pNumFormat; | ||||
1749 | uno::Reference< util::XNumberFormats > xDocNumberFormats = xDocNumFormatsSupplier->getNumberFormats(); | ||||
1750 | uno::Reference< util::XNumberFormatTypes > xDocNumberFormatTypes(xDocNumberFormats, uno::UNO_QUERY); | ||||
1751 | |||||
1752 | css::lang::Locale aLocale( LanguageTag( nLanguage ).getLocale()); | ||||
1753 | |||||
1754 | //get the number formatter of the data source | ||||
1755 | uno::Reference<beans::XPropertySet> xSourceProps(xSource, uno::UNO_QUERY); | ||||
1756 | uno::Reference< util::XNumberFormats > xNumberFormats; | ||||
1757 | if(xSourceProps.is()) | ||||
1758 | { | ||||
1759 | uno::Any aFormats = xSourceProps->getPropertyValue("NumberFormatsSupplier"); | ||||
1760 | if(aFormats.hasValue()) | ||||
1761 | { | ||||
1762 | uno::Reference<util::XNumberFormatsSupplier> xSuppl; | ||||
1763 | aFormats >>= xSuppl; | ||||
1764 | if(xSuppl.is()) | ||||
1765 | { | ||||
1766 | xNumberFormats = xSuppl->getNumberFormats(); | ||||
1767 | } | ||||
1768 | } | ||||
1769 | } | ||||
1770 | bool bUseDefault = true; | ||||
1771 | try | ||||
1772 | { | ||||
1773 | uno::Any aFormatKey = xColumn->getPropertyValue("FormatKey"); | ||||
1774 | if(aFormatKey.hasValue()) | ||||
1775 | { | ||||
1776 | sal_Int32 nFormat = 0; | ||||
1777 | aFormatKey >>= nFormat; | ||||
1778 | if(xNumberFormats.is()) | ||||
1779 | { | ||||
1780 | try | ||||
1781 | { | ||||
1782 | uno::Reference<beans::XPropertySet> xNumProps = xNumberFormats->getByKey( nFormat ); | ||||
1783 | uno::Any aFormatString = xNumProps->getPropertyValue("FormatString"); | ||||
1784 | uno::Any aLocaleVal = xNumProps->getPropertyValue("Locale"); | ||||
1785 | OUString sFormat; | ||||
1786 | aFormatString >>= sFormat; | ||||
1787 | lang::Locale aLoc; | ||||
1788 | aLocaleVal >>= aLoc; | ||||
1789 | nFormat = xDocNumberFormats->queryKey( sFormat, aLoc, false ); | ||||
1790 | if(NUMBERFORMAT_ENTRY_NOT_FOUND == sal::static_int_cast< sal_uInt32, sal_Int32>(nFormat)) | ||||
1791 | nFormat = xDocNumberFormats->addNew( sFormat, aLoc ); | ||||
1792 | nRet = nFormat; | ||||
1793 | bUseDefault = false; | ||||
1794 | } | ||||
1795 | catch (const uno::Exception&) | ||||
1796 | { | ||||
1797 | TOOLS_WARN_EXCEPTION("sw.mailmerge", "illegal number format key")do { css::uno::Any tools_warn_exception( DbgGetCaughtException () ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.mailmerge")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "illegal number format key" << " " << exceptionToString(tools_warn_exception )) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ( "sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1797" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "illegal number format key" << " " << exceptionToString(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "illegal number format key" << " " << exceptionToString (tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1797" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "illegal number format key" << " " << exceptionToString(tools_warn_exception)) == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1797" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "illegal number format key" << " " << exceptionToString(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "illegal number format key" << " " << exceptionToString (tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1797" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); } while (false); | ||||
1798 | } | ||||
1799 | } | ||||
1800 | } | ||||
1801 | } | ||||
1802 | catch(const uno::Exception&) | ||||
1803 | { | ||||
1804 | SAL_WARN("sw.mailmerge", "no FormatKey property found")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.mailmerge")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "no FormatKey property found" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1804" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "no FormatKey property found"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "no FormatKey property found"; ::sal::detail::log( ( ::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1804" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "no FormatKey property found") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1804" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "no FormatKey property found"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "no FormatKey property found"; ::sal::detail::log( ( ::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1804" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
1805 | } | ||||
1806 | if(bUseDefault) | ||||
1807 | nRet = dbtools::getDefaultNumberFormat(xColumn, xDocNumberFormatTypes, aLocale); | ||||
1808 | } | ||||
1809 | return nRet; | ||||
1810 | } | ||||
1811 | |||||
1812 | sal_Int32 SwDBManager::GetColumnType( const OUString& rDBName, | ||||
1813 | const OUString& rTableName, | ||||
1814 | const OUString& rColNm ) | ||||
1815 | { | ||||
1816 | sal_Int32 nRet = sdbc::DataType::SQLNULL; | ||||
1817 | SwDBData aData; | ||||
1818 | aData.sDataSource = rDBName; | ||||
1819 | aData.sCommand = rTableName; | ||||
1820 | aData.nCommandType = -1; | ||||
1821 | SwDSParam* pParam = FindDSData(aData, false); | ||||
1822 | uno::Reference< sdbc::XConnection> xConnection; | ||||
1823 | uno::Reference< sdbcx::XColumnsSupplier > xColsSupp; | ||||
1824 | bool bDispose = false; | ||||
1825 | if(pParam && pParam->xConnection.is()) | ||||
1826 | { | ||||
1827 | xConnection = pParam->xConnection; | ||||
1828 | xColsSupp.set( pParam->xResultSet, uno::UNO_QUERY ); | ||||
1829 | } | ||||
1830 | else | ||||
1831 | { | ||||
1832 | xConnection = RegisterConnection( rDBName ); | ||||
1833 | } | ||||
1834 | if( !xColsSupp.is() ) | ||||
1835 | { | ||||
1836 | xColsSupp = SwDBManager::GetColumnSupplier(xConnection, rTableName); | ||||
1837 | bDispose = true; | ||||
1838 | } | ||||
1839 | if(xColsSupp.is()) | ||||
1840 | { | ||||
1841 | uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns(); | ||||
1842 | if(xCols->hasByName(rColNm)) | ||||
1843 | { | ||||
1844 | uno::Any aCol = xCols->getByName(rColNm); | ||||
1845 | uno::Reference<beans::XPropertySet> xCol; | ||||
1846 | aCol >>= xCol; | ||||
1847 | uno::Any aType = xCol->getPropertyValue("Type"); | ||||
1848 | aType >>= nRet; | ||||
1849 | } | ||||
1850 | if(bDispose) | ||||
1851 | ::comphelper::disposeComponent( xColsSupp ); | ||||
1852 | } | ||||
1853 | return nRet; | ||||
1854 | } | ||||
1855 | |||||
1856 | uno::Reference< sdbc::XConnection> SwDBManager::GetConnection(const OUString& rDataSource, | ||||
1857 | uno::Reference<sdbc::XDataSource>& rxSource, const SwView *pView) | ||||
1858 | { | ||||
1859 | uno::Reference< sdbc::XConnection> xConnection; | ||||
1860 | uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); | ||||
1861 | try | ||||
1862 | { | ||||
1863 | uno::Reference<sdb::XCompletedConnection> xComplConnection(dbtools::getDataSource(rDataSource, xContext), uno::UNO_QUERY); | ||||
1864 | if ( xComplConnection.is() ) | ||||
1865 | { | ||||
1866 | rxSource.set(xComplConnection, uno::UNO_QUERY); | ||||
1867 | weld::Window* pWindow = pView ? pView->GetFrameWeld() : nullptr; | ||||
1868 | uno::Reference< task::XInteractionHandler > xHandler( task::InteractionHandler::createWithParent(xContext, pWindow ? pWindow->GetXWindow() : nullptr), uno::UNO_QUERY_THROW ); | ||||
1869 | xConnection = xComplConnection->connectWithCompletion( xHandler ); | ||||
1870 | } | ||||
1871 | } | ||||
1872 | catch(const uno::Exception&) | ||||
1873 | { | ||||
1874 | } | ||||
1875 | |||||
1876 | return xConnection; | ||||
1877 | } | ||||
1878 | |||||
1879 | uno::Reference< sdbcx::XColumnsSupplier> SwDBManager::GetColumnSupplier(uno::Reference<sdbc::XConnection> const & xConnection, | ||||
1880 | const OUString& rTableOrQuery, | ||||
1881 | SwDBSelect eTableOrQuery) | ||||
1882 | { | ||||
1883 | uno::Reference< sdbcx::XColumnsSupplier> xRet; | ||||
1884 | try | ||||
1885 | { | ||||
1886 | if(eTableOrQuery == SwDBSelect::UNKNOWN) | ||||
1887 | { | ||||
1888 | //search for a table with the given command name | ||||
1889 | uno::Reference<sdbcx::XTablesSupplier> xTSupplier(xConnection, uno::UNO_QUERY); | ||||
1890 | if(xTSupplier.is()) | ||||
1891 | { | ||||
1892 | uno::Reference<container::XNameAccess> xTables = xTSupplier->getTables(); | ||||
1893 | eTableOrQuery = xTables->hasByName(rTableOrQuery) ? | ||||
1894 | SwDBSelect::TABLE : SwDBSelect::QUERY; | ||||
1895 | } | ||||
1896 | } | ||||
1897 | sal_Int32 nCommandType = SwDBSelect::TABLE == eTableOrQuery ? | ||||
1898 | sdb::CommandType::TABLE : sdb::CommandType::QUERY; | ||||
1899 | uno::Reference< lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() ); | ||||
1900 | uno::Reference<sdbc::XRowSet> xRowSet(xMgr->createInstance("com.sun.star.sdb.RowSet"), uno::UNO_QUERY); | ||||
1901 | |||||
1902 | OUString sDataSource; | ||||
1903 | uno::Reference<sdbc::XDataSource> xSource = SwDBManager::getDataSourceAsParent(xConnection, sDataSource); | ||||
1904 | uno::Reference<beans::XPropertySet> xSourceProperties(xSource, uno::UNO_QUERY); | ||||
1905 | if(xSourceProperties.is()) | ||||
1906 | { | ||||
1907 | xSourceProperties->getPropertyValue("Name") >>= sDataSource; | ||||
1908 | } | ||||
1909 | |||||
1910 | uno::Reference<beans::XPropertySet> xRowProperties(xRowSet, uno::UNO_QUERY); | ||||
1911 | xRowProperties->setPropertyValue("DataSourceName", uno::makeAny(sDataSource)); | ||||
1912 | xRowProperties->setPropertyValue("Command", uno::makeAny(rTableOrQuery)); | ||||
1913 | xRowProperties->setPropertyValue("CommandType", uno::makeAny(nCommandType)); | ||||
1914 | xRowProperties->setPropertyValue("FetchSize", uno::makeAny(sal_Int32(10))); | ||||
1915 | xRowProperties->setPropertyValue("ActiveConnection", uno::makeAny(xConnection)); | ||||
1916 | xRowSet->execute(); | ||||
1917 | xRet.set( xRowSet, uno::UNO_QUERY ); | ||||
1918 | } | ||||
1919 | catch (const uno::Exception&) | ||||
1920 | { | ||||
1921 | TOOLS_WARN_EXCEPTION("sw.mailmerge", "Exception in SwDBManager::GetColumnSupplier")do { css::uno::Any tools_warn_exception( DbgGetCaughtException () ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.mailmerge")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "Exception in SwDBManager::GetColumnSupplier" << " " << exceptionToString(tools_warn_exception )) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ( "sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1921" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "Exception in SwDBManager::GetColumnSupplier" << " " << exceptionToString(tools_warn_exception )), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Exception in SwDBManager::GetColumnSupplier" << " " << exceptionToString(tools_warn_exception); ::sal:: detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1921" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Exception in SwDBManager::GetColumnSupplier" << " " << exceptionToString(tools_warn_exception)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1921" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "Exception in SwDBManager::GetColumnSupplier" << " " << exceptionToString(tools_warn_exception )), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Exception in SwDBManager::GetColumnSupplier" << " " << exceptionToString(tools_warn_exception); ::sal:: detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1921" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); } while (false); | ||||
1922 | } | ||||
1923 | |||||
1924 | return xRet; | ||||
1925 | } | ||||
1926 | |||||
1927 | OUString SwDBManager::GetDBField(uno::Reference<beans::XPropertySet> const & xColumnProps, | ||||
1928 | const SwDBFormatData& rDBFormatData, | ||||
1929 | double* pNumber) | ||||
1930 | { | ||||
1931 | uno::Reference< sdb::XColumn > xColumn(xColumnProps, uno::UNO_QUERY); | ||||
1932 | OUString sRet; | ||||
1933 | assert( xColumn.is() && "SwDBManager::::ImportDBField: illegal arguments" )(static_cast <bool> (xColumn.is() && "SwDBManager::::ImportDBField: illegal arguments" ) ? void (0) : __assert_fail ("xColumn.is() && \"SwDBManager::::ImportDBField: illegal arguments\"" , "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 1933, __extension__ __PRETTY_FUNCTION__)); | ||||
1934 | if(!xColumn.is()) | ||||
1935 | return sRet; | ||||
1936 | |||||
1937 | uno::Any aType = xColumnProps->getPropertyValue("Type"); | ||||
1938 | sal_Int32 eDataType = sdbc::DataType::SQLNULL; | ||||
1939 | aType >>= eDataType; | ||||
1940 | switch(eDataType) | ||||
1941 | { | ||||
1942 | case sdbc::DataType::CHAR: | ||||
1943 | case sdbc::DataType::VARCHAR: | ||||
1944 | case sdbc::DataType::LONGVARCHAR: | ||||
1945 | try | ||||
1946 | { | ||||
1947 | sRet = xColumn->getString(); | ||||
1948 | sRet = sRet.replace( '\xb', '\n' ); // MSWord uses \xb as a newline | ||||
1949 | } | ||||
1950 | catch(const sdbc::SQLException&) | ||||
1951 | { | ||||
1952 | } | ||||
1953 | break; | ||||
1954 | case sdbc::DataType::BIT: | ||||
1955 | case sdbc::DataType::BOOLEAN: | ||||
1956 | case sdbc::DataType::TINYINT: | ||||
1957 | case sdbc::DataType::SMALLINT: | ||||
1958 | case sdbc::DataType::INTEGER: | ||||
1959 | case sdbc::DataType::BIGINT: | ||||
1960 | case sdbc::DataType::FLOAT: | ||||
1961 | case sdbc::DataType::REAL: | ||||
1962 | case sdbc::DataType::DOUBLE: | ||||
1963 | case sdbc::DataType::NUMERIC: | ||||
1964 | case sdbc::DataType::DECIMAL: | ||||
1965 | case sdbc::DataType::DATE: | ||||
1966 | case sdbc::DataType::TIME: | ||||
1967 | case sdbc::DataType::TIMESTAMP: | ||||
1968 | { | ||||
1969 | |||||
1970 | try | ||||
1971 | { | ||||
1972 | sRet = dbtools::DBTypeConversion::getFormattedValue( | ||||
1973 | xColumnProps, | ||||
1974 | rDBFormatData.xFormatter, | ||||
1975 | rDBFormatData.aLocale, | ||||
1976 | rDBFormatData.aNullDate); | ||||
1977 | if (pNumber) | ||||
1978 | { | ||||
1979 | double fVal = xColumn->getDouble(); | ||||
1980 | if(!xColumn->wasNull()) | ||||
1981 | { | ||||
1982 | *pNumber = fVal; | ||||
1983 | } | ||||
1984 | } | ||||
1985 | } | ||||
1986 | catch (const uno::Exception&) | ||||
1987 | { | ||||
1988 | TOOLS_WARN_EXCEPTION("sw.mailmerge", "")do { css::uno::Any tools_warn_exception( DbgGetCaughtException () ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.mailmerge")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "" << " " << exceptionToString(tools_warn_exception)) == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1988" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "" << " " << exceptionToString (tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "" << " " << exceptionToString (tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1988" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "" << " " << exceptionToString(tools_warn_exception )) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ( "sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1988" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "" << " " << exceptionToString (tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "" << " " << exceptionToString (tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "1988" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); } while (false); | ||||
1989 | } | ||||
1990 | |||||
1991 | } | ||||
1992 | break; | ||||
1993 | } | ||||
1994 | |||||
1995 | return sRet; | ||||
1996 | } | ||||
1997 | |||||
1998 | // checks if a desired data source table or query is open | ||||
1999 | bool SwDBManager::IsDataSourceOpen(const OUString& rDataSource, | ||||
2000 | const OUString& rTableOrQuery, bool bMergeShell) | ||||
2001 | { | ||||
2002 | if(m_pImpl->pMergeData) | ||||
2003 | { | ||||
2004 | return ((rDataSource == m_pImpl->pMergeData->sDataSource | ||||
2005 | && rTableOrQuery == m_pImpl->pMergeData->sCommand) | ||||
2006 | || (rDataSource.isEmpty() && rTableOrQuery.isEmpty())) | ||||
2007 | && m_pImpl->pMergeData->xResultSet.is(); | ||||
2008 | } | ||||
2009 | else if(!bMergeShell) | ||||
2010 | { | ||||
2011 | SwDBData aData; | ||||
2012 | aData.sDataSource = rDataSource; | ||||
2013 | aData.sCommand = rTableOrQuery; | ||||
2014 | aData.nCommandType = -1; | ||||
2015 | SwDSParam* pFound = FindDSData(aData, false); | ||||
2016 | return (pFound && pFound->xResultSet.is()); | ||||
2017 | } | ||||
2018 | return false; | ||||
2019 | } | ||||
2020 | |||||
2021 | // read column data at a specified position | ||||
2022 | bool SwDBManager::GetColumnCnt(const OUString& rSourceName, const OUString& rTableName, | ||||
2023 | const OUString& rColumnName, sal_uInt32 nAbsRecordId, | ||||
2024 | LanguageType nLanguage, | ||||
2025 | OUString& rResult, double* pNumber) | ||||
2026 | { | ||||
2027 | bool bRet = false; | ||||
2028 | SwDSParam* pFound = nullptr; | ||||
2029 | //check if it's the merge data source | ||||
2030 | if(m_pImpl->pMergeData && | ||||
2031 | rSourceName == m_pImpl->pMergeData->sDataSource && | ||||
2032 | rTableName == m_pImpl->pMergeData->sCommand) | ||||
2033 | { | ||||
2034 | pFound = m_pImpl->pMergeData.get(); | ||||
2035 | } | ||||
2036 | else | ||||
2037 | { | ||||
2038 | SwDBData aData; | ||||
2039 | aData.sDataSource = rSourceName; | ||||
2040 | aData.sCommand = rTableName; | ||||
2041 | aData.nCommandType = -1; | ||||
2042 | pFound = FindDSData(aData, false); | ||||
2043 | } | ||||
2044 | if (!pFound) | ||||
2045 | return false; | ||||
2046 | //check validity of supplied record Id | ||||
2047 | if(pFound->aSelection.hasElements()) | ||||
2048 | { | ||||
2049 | //the destination has to be an element of the selection | ||||
2050 | bool bFound = std::any_of(pFound->aSelection.begin(), pFound->aSelection.end(), | ||||
2051 | [nAbsRecordId](const uno::Any& rSelection) { | ||||
2052 | sal_Int32 nSelection = 0; | ||||
2053 | rSelection >>= nSelection; | ||||
2054 | return nSelection == static_cast<sal_Int32>(nAbsRecordId); | ||||
2055 | }); | ||||
2056 | if(!bFound) | ||||
2057 | return false; | ||||
2058 | } | ||||
2059 | if( pFound->HasValidRecord() ) | ||||
2060 | { | ||||
2061 | sal_Int32 nOldRow = 0; | ||||
2062 | try | ||||
2063 | { | ||||
2064 | nOldRow = pFound->xResultSet->getRow(); | ||||
2065 | } | ||||
2066 | catch(const uno::Exception&) | ||||
2067 | { | ||||
2068 | return false; | ||||
2069 | } | ||||
2070 | //position to the desired index | ||||
2071 | bool bMove = true; | ||||
2072 | if ( nOldRow != static_cast<sal_Int32>(nAbsRecordId) ) | ||||
2073 | bMove = lcl_MoveAbsolute(pFound, nAbsRecordId); | ||||
2074 | if(bMove) | ||||
2075 | bRet = lcl_GetColumnCnt(pFound, rColumnName, nLanguage, rResult, pNumber); | ||||
2076 | if ( nOldRow != static_cast<sal_Int32>(nAbsRecordId) ) | ||||
2077 | lcl_MoveAbsolute(pFound, nOldRow); | ||||
2078 | } | ||||
2079 | return bRet; | ||||
2080 | } | ||||
2081 | |||||
2082 | // reads the column data at the current position | ||||
2083 | bool SwDBManager::GetMergeColumnCnt(const OUString& rColumnName, LanguageType nLanguage, | ||||
2084 | OUString &rResult, double *pNumber) | ||||
2085 | { | ||||
2086 | if( !IsValidMergeRecord() ) | ||||
2087 | { | ||||
2088 | rResult.clear(); | ||||
2089 | return false; | ||||
2090 | } | ||||
2091 | |||||
2092 | bool bRet = lcl_GetColumnCnt(m_pImpl->pMergeData.get(), rColumnName, nLanguage, rResult, pNumber); | ||||
2093 | return bRet; | ||||
2094 | } | ||||
2095 | |||||
2096 | bool SwDBManager::ToNextMergeRecord() | ||||
2097 | { | ||||
2098 | assert( m_pImpl->pMergeData && m_pImpl->pMergeData->xResultSet.is() && "no data source in merge" )(static_cast <bool> (m_pImpl->pMergeData && m_pImpl ->pMergeData->xResultSet.is() && "no data source in merge" ) ? void (0) : __assert_fail ("m_pImpl->pMergeData && m_pImpl->pMergeData->xResultSet.is() && \"no data source in merge\"" , "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 2098, __extension__ __PRETTY_FUNCTION__)); | ||||
2099 | return lcl_ToNextRecord( m_pImpl->pMergeData.get() ); | ||||
2100 | } | ||||
2101 | |||||
2102 | bool SwDBManager::FillCalcWithMergeData( SvNumberFormatter *pDocFormatter, | ||||
2103 | LanguageType nLanguage, SwCalc &rCalc ) | ||||
2104 | { | ||||
2105 | if( !IsValidMergeRecord() ) | ||||
2106 | return false; | ||||
2107 | |||||
2108 | uno::Reference< sdbcx::XColumnsSupplier > xColsSupp( m_pImpl->pMergeData->xResultSet, uno::UNO_QUERY ); | ||||
2109 | if( !xColsSupp.is() ) | ||||
2110 | return false; | ||||
2111 | |||||
2112 | { | ||||
2113 | uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns(); | ||||
2114 | const uno::Sequence<OUString> aColNames = xCols->getElementNames(); | ||||
2115 | OUString aString; | ||||
2116 | |||||
2117 | // add the "record number" variable, as SwCalc::VarLook would. | ||||
2118 | rCalc.VarChange( GetAppCharClass().lowercase( | ||||
2119 | SwFieldType::GetTypeStr(SwFieldTypesEnum::DatabaseSetNumber) ), GetSelectedRecordId() ); | ||||
2120 | |||||
2121 | for( const OUString& rColName : aColNames ) | ||||
2122 | { | ||||
2123 | // get the column type | ||||
2124 | sal_Int32 nColumnType = sdbc::DataType::SQLNULL; | ||||
2125 | uno::Any aCol = xCols->getByName( rColName ); | ||||
2126 | uno::Reference<beans::XPropertySet> xColumnProps; | ||||
2127 | aCol >>= xColumnProps; | ||||
2128 | uno::Any aType = xColumnProps->getPropertyValue( "Type" ); | ||||
2129 | aType >>= nColumnType; | ||||
2130 | double aNumber = DBL_MAX1.7976931348623157e+308; | ||||
2131 | |||||
2132 | lcl_GetColumnCnt( m_pImpl->pMergeData.get(), xColumnProps, nLanguage, aString, &aNumber ); | ||||
2133 | |||||
2134 | sal_uInt32 nFormat = GetColumnFormat( m_pImpl->pMergeData->sDataSource, | ||||
2135 | m_pImpl->pMergeData->sCommand, | ||||
2136 | rColName, pDocFormatter, nLanguage ); | ||||
2137 | // aNumber is overwritten by SwDBField::FormatValue, so store initial status | ||||
2138 | bool colIsNumber = aNumber != DBL_MAX1.7976931348623157e+308; | ||||
2139 | bool bValidValue = SwDBField::FormatValue( pDocFormatter, aString, nFormat, | ||||
2140 | aNumber, nColumnType ); | ||||
2141 | if( colIsNumber ) | ||||
2142 | { | ||||
2143 | if( bValidValue ) | ||||
2144 | { | ||||
2145 | SwSbxValue aValue; | ||||
2146 | aValue.PutDouble( aNumber ); | ||||
2147 | aValue.SetDBvalue( true ); | ||||
2148 | SAL_INFO( "sw.ui", "'" << rColName << "': " << aNumber << " / " << aString )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "sw.ui")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "'" << rColName << "': " << aNumber << " / " << aString) == 1) { ::sal_detail_log( ( ::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ui"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2148" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "'" << rColName << "': " << aNumber << " / " << aString), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "'" << rColName << "': " << aNumber << " / " << aString; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.ui"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2148" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "'" << rColName << "': " << aNumber << " / " << aString) == 1) { ::sal_detail_log( ( ::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ui"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2148" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "'" << rColName << "': " << aNumber << " / " << aString), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "'" << rColName << "': " << aNumber << " / " << aString; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.ui"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2148" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
2149 | rCalc.VarChange( rColName, aValue ); | ||||
2150 | } | ||||
2151 | } | ||||
2152 | else | ||||
2153 | { | ||||
2154 | SwSbxValue aValue; | ||||
2155 | aValue.PutString( aString ); | ||||
2156 | aValue.SetDBvalue( true ); | ||||
2157 | SAL_INFO( "sw.ui", "'" << rColName << "': " << aString )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "sw.ui")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "'" << rColName << "': " << aString ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ui" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2157" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "'" << rColName << "': " << aString), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "'" << rColName << "': " << aString; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.ui"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2157" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "'" << rColName << "': " << aString ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ui" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2157" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "'" << rColName << "': " << aString), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "'" << rColName << "': " << aString; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.ui"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2157" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
2158 | rCalc.VarChange( rColName, aValue ); | ||||
2159 | } | ||||
2160 | } | ||||
2161 | } | ||||
2162 | |||||
2163 | return true; | ||||
2164 | } | ||||
2165 | |||||
2166 | void SwDBManager::ToNextRecord( | ||||
2167 | const OUString& rDataSource, const OUString& rCommand) | ||||
2168 | { | ||||
2169 | SwDSParam* pFound = nullptr; | ||||
2170 | if(m_pImpl->pMergeData && | ||||
2171 | rDataSource == m_pImpl->pMergeData->sDataSource && | ||||
2172 | rCommand == m_pImpl->pMergeData->sCommand) | ||||
2173 | { | ||||
2174 | pFound = m_pImpl->pMergeData.get(); | ||||
2175 | } | ||||
2176 | else | ||||
2177 | { | ||||
2178 | SwDBData aData; | ||||
2179 | aData.sDataSource = rDataSource; | ||||
2180 | aData.sCommand = rCommand; | ||||
2181 | aData.nCommandType = -1; | ||||
2182 | pFound = FindDSData(aData, false); | ||||
2183 | } | ||||
2184 | lcl_ToNextRecord( pFound ); | ||||
2185 | } | ||||
2186 | |||||
2187 | static bool lcl_ToNextRecord( SwDSParam* pParam, const SwDBNextRecord action ) | ||||
2188 | { | ||||
2189 | bool bRet = true; | ||||
2190 | |||||
2191 | assert( SwDBNextRecord::NEXT == action ||(static_cast <bool> (SwDBNextRecord::NEXT == action || ( SwDBNextRecord::FIRST == action && pParam)) ? void (0 ) : __assert_fail ("SwDBNextRecord::NEXT == action || (SwDBNextRecord::FIRST == action && pParam)" , "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 2192, __extension__ __PRETTY_FUNCTION__)) | ||||
2192 | (SwDBNextRecord::FIRST == action && pParam) )(static_cast <bool> (SwDBNextRecord::NEXT == action || ( SwDBNextRecord::FIRST == action && pParam)) ? void (0 ) : __assert_fail ("SwDBNextRecord::NEXT == action || (SwDBNextRecord::FIRST == action && pParam)" , "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 2192, __extension__ __PRETTY_FUNCTION__)); | ||||
2193 | if( nullptr == pParam ) | ||||
2194 | return false; | ||||
2195 | |||||
2196 | if( action == SwDBNextRecord::FIRST ) | ||||
2197 | { | ||||
2198 | pParam->nSelectionIndex = 0; | ||||
2199 | pParam->bEndOfDB = false; | ||||
2200 | } | ||||
2201 | |||||
2202 | if( !pParam->HasValidRecord() ) | ||||
2203 | return false; | ||||
2204 | |||||
2205 | try | ||||
2206 | { | ||||
2207 | if( pParam->aSelection.hasElements() ) | ||||
2208 | { | ||||
2209 | if( pParam->nSelectionIndex >= pParam->aSelection.getLength() ) | ||||
2210 | pParam->bEndOfDB = true; | ||||
2211 | else | ||||
2212 | { | ||||
2213 | sal_Int32 nPos = 0; | ||||
2214 | pParam->aSelection.getConstArray()[ pParam->nSelectionIndex ] >>= nPos; | ||||
2215 | pParam->bEndOfDB = !pParam->xResultSet->absolute( nPos ); | ||||
2216 | } | ||||
2217 | } | ||||
2218 | else if( action == SwDBNextRecord::FIRST ) | ||||
2219 | { | ||||
2220 | pParam->bEndOfDB = !pParam->xResultSet->first(); | ||||
2221 | } | ||||
2222 | else | ||||
2223 | { | ||||
2224 | sal_Int32 nBefore = pParam->xResultSet->getRow(); | ||||
2225 | pParam->bEndOfDB = !pParam->xResultSet->next(); | ||||
2226 | if( !pParam->bEndOfDB && nBefore == pParam->xResultSet->getRow() ) | ||||
2227 | { | ||||
2228 | // next returned true but it didn't move | ||||
2229 | ::dbtools::throwFunctionSequenceException( pParam->xResultSet ); | ||||
2230 | } | ||||
2231 | } | ||||
2232 | |||||
2233 | ++pParam->nSelectionIndex; | ||||
2234 | bRet = !pParam->bEndOfDB; | ||||
2235 | } | ||||
2236 | catch( const uno::Exception & ) | ||||
2237 | { | ||||
2238 | // we allow merging with empty databases, so don't warn on init | ||||
2239 | TOOLS_WARN_EXCEPTION_IF(action == SwDBNextRecord::NEXT,do { css::uno::Any tools_warn_exception( DbgGetCaughtException () ); do { if (true && (action == SwDBNextRecord::NEXT )) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.mailmerge")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "exception in ToNextRecord()" << " " << exceptionToString(tools_warn_exception )) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ( "sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2240" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "exception in ToNextRecord()" << " " << exceptionToString(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "exception in ToNextRecord()" << " " << exceptionToString(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2240" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "exception in ToNextRecord()" << " " << exceptionToString(tools_warn_exception)) == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2240" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "exception in ToNextRecord()" << " " << exceptionToString(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "exception in ToNextRecord()" << " " << exceptionToString(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2240" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); } while (false) | ||||
2240 | "sw.mailmerge", "exception in ToNextRecord()")do { css::uno::Any tools_warn_exception( DbgGetCaughtException () ); do { if (true && (action == SwDBNextRecord::NEXT )) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.mailmerge")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "exception in ToNextRecord()" << " " << exceptionToString(tools_warn_exception )) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ( "sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2240" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "exception in ToNextRecord()" << " " << exceptionToString(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "exception in ToNextRecord()" << " " << exceptionToString(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2240" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "exception in ToNextRecord()" << " " << exceptionToString(tools_warn_exception)) == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2240" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "exception in ToNextRecord()" << " " << exceptionToString(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "exception in ToNextRecord()" << " " << exceptionToString(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2240" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); } while (false); | ||||
2241 | pParam->bEndOfDB = true; | ||||
2242 | bRet = false; | ||||
2243 | } | ||||
2244 | return bRet; | ||||
2245 | } | ||||
2246 | |||||
2247 | // synchronized labels contain a next record field at their end | ||||
2248 | // to assure that the next page can be created in mail merge | ||||
2249 | // the cursor position must be validated | ||||
2250 | bool SwDBManager::IsValidMergeRecord() const | ||||
2251 | { | ||||
2252 | return( m_pImpl->pMergeData && m_pImpl->pMergeData->HasValidRecord() ); | ||||
2253 | } | ||||
2254 | |||||
2255 | sal_uInt32 SwDBManager::GetSelectedRecordId() | ||||
2256 | { | ||||
2257 | sal_uInt32 nRet = 0; | ||||
2258 | assert( m_pImpl->pMergeData &&(static_cast <bool> (m_pImpl->pMergeData && m_pImpl ->pMergeData->xResultSet.is() && "no data source in merge" ) ? void (0) : __assert_fail ("m_pImpl->pMergeData && m_pImpl->pMergeData->xResultSet.is() && \"no data source in merge\"" , "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 2259, __extension__ __PRETTY_FUNCTION__)) | ||||
2259 | m_pImpl->pMergeData->xResultSet.is() && "no data source in merge" )(static_cast <bool> (m_pImpl->pMergeData && m_pImpl ->pMergeData->xResultSet.is() && "no data source in merge" ) ? void (0) : __assert_fail ("m_pImpl->pMergeData && m_pImpl->pMergeData->xResultSet.is() && \"no data source in merge\"" , "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 2259, __extension__ __PRETTY_FUNCTION__)); | ||||
2260 | if(!m_pImpl->pMergeData || !m_pImpl->pMergeData->xResultSet.is()) | ||||
2261 | return 0; | ||||
2262 | try | ||||
2263 | { | ||||
2264 | nRet = m_pImpl->pMergeData->xResultSet->getRow(); | ||||
2265 | } | ||||
2266 | catch(const uno::Exception&) | ||||
2267 | { | ||||
2268 | } | ||||
2269 | return nRet; | ||||
2270 | } | ||||
2271 | |||||
2272 | bool SwDBManager::ToRecordId(sal_Int32 nSet) | ||||
2273 | { | ||||
2274 | assert( m_pImpl->pMergeData &&(static_cast <bool> (m_pImpl->pMergeData && m_pImpl ->pMergeData->xResultSet.is() && "no data source in merge" ) ? void (0) : __assert_fail ("m_pImpl->pMergeData && m_pImpl->pMergeData->xResultSet.is() && \"no data source in merge\"" , "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 2275, __extension__ __PRETTY_FUNCTION__)) | ||||
2275 | m_pImpl->pMergeData->xResultSet.is() && "no data source in merge" )(static_cast <bool> (m_pImpl->pMergeData && m_pImpl ->pMergeData->xResultSet.is() && "no data source in merge" ) ? void (0) : __assert_fail ("m_pImpl->pMergeData && m_pImpl->pMergeData->xResultSet.is() && \"no data source in merge\"" , "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 2275, __extension__ __PRETTY_FUNCTION__)); | ||||
2276 | if(!m_pImpl->pMergeData || !m_pImpl->pMergeData->xResultSet.is()|| nSet < 0) | ||||
2277 | return false; | ||||
2278 | bool bRet = false; | ||||
2279 | sal_Int32 nAbsPos = nSet; | ||||
2280 | assert(nAbsPos >= 0)(static_cast <bool> (nAbsPos >= 0) ? void (0) : __assert_fail ("nAbsPos >= 0", "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 2280, __extension__ __PRETTY_FUNCTION__)); | ||||
2281 | bRet = lcl_MoveAbsolute(m_pImpl->pMergeData.get(), nAbsPos); | ||||
2282 | m_pImpl->pMergeData->bEndOfDB = !bRet; | ||||
2283 | return bRet; | ||||
2284 | } | ||||
2285 | |||||
2286 | bool SwDBManager::OpenDataSource(const OUString& rDataSource, const OUString& rTableOrQuery) | ||||
2287 | { | ||||
2288 | SwDBData aData; | ||||
2289 | aData.sDataSource = rDataSource; | ||||
2290 | aData.sCommand = rTableOrQuery; | ||||
2291 | aData.nCommandType = -1; | ||||
2292 | |||||
2293 | SwDSParam* pFound = FindDSData(aData, true); | ||||
2294 | if(pFound->xResultSet.is()) | ||||
2295 | return true; | ||||
2296 | SwDSParam* pParam = FindDSConnection(rDataSource, false); | ||||
2297 | if(pParam && pParam->xConnection.is()) | ||||
2298 | pFound->xConnection = pParam->xConnection; | ||||
2299 | if(pFound->xConnection.is()) | ||||
2300 | { | ||||
2301 | try | ||||
2302 | { | ||||
2303 | uno::Reference< sdbc::XDatabaseMetaData > xMetaData = pFound->xConnection->getMetaData(); | ||||
2304 | try | ||||
2305 | { | ||||
2306 | pFound->bScrollable = xMetaData | ||||
2307 | ->supportsResultSetType(sal_Int32(sdbc::ResultSetType::SCROLL_INSENSITIVE)); | ||||
2308 | } | ||||
2309 | catch(const uno::Exception&) | ||||
2310 | { | ||||
2311 | // DB driver may not be ODBC 3.0 compliant | ||||
2312 | pFound->bScrollable = true; | ||||
2313 | } | ||||
2314 | pFound->xStatement = pFound->xConnection->createStatement(); | ||||
2315 | OUString aQuoteChar = xMetaData->getIdentifierQuoteString(); | ||||
2316 | OUString sStatement = "SELECT * FROM " + aQuoteChar + rTableOrQuery + aQuoteChar; | ||||
2317 | pFound->xResultSet = pFound->xStatement->executeQuery( sStatement ); | ||||
2318 | |||||
2319 | //after executeQuery the cursor must be positioned | ||||
2320 | pFound->bEndOfDB = !pFound->xResultSet->next(); | ||||
2321 | ++pFound->nSelectionIndex; | ||||
2322 | } | ||||
2323 | catch (const uno::Exception&) | ||||
2324 | { | ||||
2325 | pFound->xResultSet = nullptr; | ||||
2326 | pFound->xStatement = nullptr; | ||||
2327 | pFound->xConnection = nullptr; | ||||
2328 | } | ||||
2329 | } | ||||
2330 | return pFound->xResultSet.is(); | ||||
2331 | } | ||||
2332 | |||||
2333 | uno::Reference< sdbc::XConnection> const & SwDBManager::RegisterConnection(OUString const& rDataSource) | ||||
2334 | { | ||||
2335 | SwDSParam* pFound = SwDBManager::FindDSConnection(rDataSource, true); | ||||
2336 | uno::Reference< sdbc::XDataSource> xSource; | ||||
2337 | if(!pFound->xConnection.is()) | ||||
2338 | { | ||||
2339 | SwView* pView = (m_pDoc && m_pDoc->GetDocShell()) ? m_pDoc->GetDocShell()->GetView() : nullptr; | ||||
2340 | pFound->xConnection = SwDBManager::GetConnection(rDataSource, xSource, pView); | ||||
2341 | try | ||||
2342 | { | ||||
2343 | uno::Reference<lang::XComponent> xComponent(pFound->xConnection, uno::UNO_QUERY); | ||||
2344 | if(xComponent.is()) | ||||
2345 | xComponent->addEventListener(m_pImpl->m_xDisposeListener.get()); | ||||
2346 | } | ||||
2347 | catch(const uno::Exception&) | ||||
2348 | { | ||||
2349 | } | ||||
2350 | } | ||||
2351 | return pFound->xConnection; | ||||
2352 | } | ||||
2353 | |||||
2354 | sal_uInt32 SwDBManager::GetSelectedRecordId( | ||||
2355 | const OUString& rDataSource, const OUString& rTableOrQuery, sal_Int32 nCommandType) | ||||
2356 | { | ||||
2357 | sal_uInt32 nRet = 0xffffffff; | ||||
2358 | //check for merge data source first | ||||
2359 | if(m_pImpl->pMergeData && | ||||
2360 | ((rDataSource == m_pImpl->pMergeData->sDataSource && | ||||
2361 | rTableOrQuery == m_pImpl->pMergeData->sCommand) || | ||||
2362 | (rDataSource.isEmpty() && rTableOrQuery.isEmpty())) && | ||||
2363 | (nCommandType == -1 || nCommandType == m_pImpl->pMergeData->nCommandType) && | ||||
2364 | m_pImpl->pMergeData->xResultSet.is()) | ||||
2365 | { | ||||
2366 | nRet = GetSelectedRecordId(); | ||||
2367 | } | ||||
2368 | else | ||||
2369 | { | ||||
2370 | SwDBData aData; | ||||
2371 | aData.sDataSource = rDataSource; | ||||
2372 | aData.sCommand = rTableOrQuery; | ||||
2373 | aData.nCommandType = nCommandType; | ||||
2374 | SwDSParam* pFound = FindDSData(aData, false); | ||||
2375 | if(pFound && pFound->xResultSet.is()) | ||||
2376 | { | ||||
2377 | try | ||||
2378 | { //if a selection array is set the current row at the result set may not be set yet | ||||
2379 | if(pFound->aSelection.hasElements()) | ||||
2380 | { | ||||
2381 | sal_Int32 nSelIndex = pFound->nSelectionIndex; | ||||
2382 | if(nSelIndex >= pFound->aSelection.getLength()) | ||||
2383 | nSelIndex = pFound->aSelection.getLength() -1; | ||||
2384 | pFound->aSelection.getConstArray()[nSelIndex] >>= nRet; | ||||
2385 | |||||
2386 | } | ||||
2387 | else | ||||
2388 | nRet = pFound->xResultSet->getRow(); | ||||
2389 | } | ||||
2390 | catch(const uno::Exception&) | ||||
2391 | { | ||||
2392 | } | ||||
2393 | } | ||||
2394 | } | ||||
2395 | return nRet; | ||||
2396 | } | ||||
2397 | |||||
2398 | // close all data sources - after fields were updated | ||||
2399 | void SwDBManager::CloseAll(bool bIncludingMerge) | ||||
2400 | { | ||||
2401 | //the only thing done here is to reset the selection index | ||||
2402 | //all connections stay open | ||||
2403 | for (auto & pParam : m_DataSourceParams) | ||||
2404 | { | ||||
2405 | if (bIncludingMerge || pParam.get() != m_pImpl->pMergeData.get()) | ||||
2406 | { | ||||
2407 | pParam->nSelectionIndex = 0; | ||||
2408 | pParam->bEndOfDB = false; | ||||
2409 | try | ||||
2410 | { | ||||
2411 | if(!m_bInMerge && pParam->xResultSet.is()) | ||||
2412 | pParam->xResultSet->first(); | ||||
2413 | } | ||||
2414 | catch(const uno::Exception&) | ||||
2415 | {} | ||||
2416 | } | ||||
2417 | } | ||||
2418 | } | ||||
2419 | |||||
2420 | SwDSParam* SwDBManager::FindDSData(const SwDBData& rData, bool bCreate) | ||||
2421 | { | ||||
2422 | //prefer merge data if available | ||||
2423 | if(m_pImpl->pMergeData && | ||||
2424 | ((rData.sDataSource == m_pImpl->pMergeData->sDataSource && | ||||
2425 | rData.sCommand == m_pImpl->pMergeData->sCommand) || | ||||
2426 | (rData.sDataSource.isEmpty() && rData.sCommand.isEmpty())) && | ||||
2427 | (rData.nCommandType == -1 || rData.nCommandType == m_pImpl->pMergeData->nCommandType || | ||||
2428 | (bCreate && m_pImpl->pMergeData->nCommandType == -1))) | ||||
2429 | { | ||||
2430 | return m_pImpl->pMergeData.get(); | ||||
2431 | } | ||||
2432 | |||||
2433 | SwDSParam* pFound = nullptr; | ||||
2434 | for (size_t nPos = m_DataSourceParams.size(); nPos; nPos--) | ||||
2435 | { | ||||
2436 | SwDSParam* pParam = m_DataSourceParams[nPos - 1].get(); | ||||
2437 | if(rData.sDataSource == pParam->sDataSource && | ||||
2438 | rData.sCommand == pParam->sCommand && | ||||
2439 | (rData.nCommandType == -1 || rData.nCommandType == pParam->nCommandType || | ||||
2440 | (bCreate && pParam->nCommandType == -1))) | ||||
2441 | { | ||||
2442 | // calls from the calculator may add a connection with an invalid commandtype | ||||
2443 | //later added "real" data base connections have to re-use the already available | ||||
2444 | //DSData and set the correct CommandType | ||||
2445 | if(bCreate && pParam->nCommandType == -1) | ||||
2446 | pParam->nCommandType = rData.nCommandType; | ||||
2447 | pFound = pParam; | ||||
2448 | break; | ||||
2449 | } | ||||
2450 | } | ||||
2451 | if(bCreate && !pFound) | ||||
2452 | { | ||||
2453 | pFound = new SwDSParam(rData); | ||||
2454 | m_DataSourceParams.push_back(std::unique_ptr<SwDSParam>(pFound)); | ||||
2455 | try | ||||
2456 | { | ||||
2457 | uno::Reference<lang::XComponent> xComponent(pFound->xConnection, uno::UNO_QUERY); | ||||
2458 | if(xComponent.is()) | ||||
2459 | xComponent->addEventListener(m_pImpl->m_xDisposeListener.get()); | ||||
2460 | } | ||||
2461 | catch(const uno::Exception&) | ||||
2462 | { | ||||
2463 | } | ||||
2464 | } | ||||
2465 | return pFound; | ||||
2466 | } | ||||
2467 | |||||
2468 | SwDSParam* SwDBManager::FindDSConnection(const OUString& rDataSource, bool bCreate) | ||||
2469 | { | ||||
2470 | //prefer merge data if available | ||||
2471 | if(m_pImpl->pMergeData && rDataSource == m_pImpl->pMergeData->sDataSource ) | ||||
2472 | { | ||||
2473 | SetAsUsed(rDataSource); | ||||
2474 | return m_pImpl->pMergeData.get(); | ||||
2475 | } | ||||
2476 | SwDSParam* pFound = nullptr; | ||||
2477 | for (const auto & pParam : m_DataSourceParams) | ||||
2478 | { | ||||
2479 | if(rDataSource == pParam->sDataSource) | ||||
2480 | { | ||||
2481 | SetAsUsed(rDataSource); | ||||
2482 | pFound = pParam.get(); | ||||
2483 | break; | ||||
2484 | } | ||||
2485 | } | ||||
2486 | if(bCreate && !pFound) | ||||
2487 | { | ||||
2488 | SwDBData aData; | ||||
2489 | aData.sDataSource = rDataSource; | ||||
2490 | pFound = new SwDSParam(aData); | ||||
2491 | SetAsUsed(rDataSource); | ||||
2492 | m_DataSourceParams.push_back(std::unique_ptr<SwDSParam>(pFound)); | ||||
2493 | try | ||||
2494 | { | ||||
2495 | uno::Reference<lang::XComponent> xComponent(pFound->xConnection, uno::UNO_QUERY); | ||||
2496 | if(xComponent.is()) | ||||
2497 | xComponent->addEventListener(m_pImpl->m_xDisposeListener.get()); | ||||
2498 | } | ||||
2499 | catch(const uno::Exception&) | ||||
2500 | { | ||||
2501 | } | ||||
2502 | } | ||||
2503 | return pFound; | ||||
2504 | } | ||||
2505 | |||||
2506 | const SwDBData& SwDBManager::GetAddressDBName() | ||||
2507 | { | ||||
2508 | return SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule ::Writer)))->GetDBConfig()->GetAddressSource(); | ||||
2509 | } | ||||
2510 | |||||
2511 | uno::Sequence<OUString> SwDBManager::GetExistingDatabaseNames() | ||||
2512 | { | ||||
2513 | uno::Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() ); | ||||
2514 | uno::Reference<sdb::XDatabaseContext> xDBContext = sdb::DatabaseContext::create(xContext); | ||||
2515 | return xDBContext->getElementNames(); | ||||
2516 | } | ||||
2517 | |||||
2518 | namespace sw | ||||
2519 | { | ||||
2520 | DBConnURIType GetDBunoType(const INetURLObject &rURL) | ||||
2521 | { | ||||
2522 | OUString sExt(rURL.GetFileExtension()); | ||||
2523 | DBConnURIType type = DBConnURIType::UNKNOWN; | ||||
2524 | |||||
2525 | if (sExt == "odb") | ||||
2526 | { | ||||
2527 | type = DBConnURIType::ODB; | ||||
2528 | } | ||||
2529 | else if (sExt.equalsIgnoreAsciiCase("sxc") | ||||
2530 | || sExt.equalsIgnoreAsciiCase("ods") | ||||
2531 | || sExt.equalsIgnoreAsciiCase("xls") | ||||
2532 | || sExt.equalsIgnoreAsciiCase("xlsx")) | ||||
2533 | { | ||||
2534 | type = DBConnURIType::CALC; | ||||
2535 | } | ||||
2536 | else if (sExt.equalsIgnoreAsciiCase("sxw") || sExt.equalsIgnoreAsciiCase("odt") || sExt.equalsIgnoreAsciiCase("doc") || sExt.equalsIgnoreAsciiCase("docx")) | ||||
2537 | { | ||||
2538 | type = DBConnURIType::WRITER; | ||||
2539 | } | ||||
2540 | else if (sExt.equalsIgnoreAsciiCase("dbf")) | ||||
2541 | { | ||||
2542 | type = DBConnURIType::DBASE; | ||||
2543 | } | ||||
2544 | else if (sExt.equalsIgnoreAsciiCase("csv") || sExt.equalsIgnoreAsciiCase("txt")) | ||||
2545 | { | ||||
2546 | type = DBConnURIType::FLAT; | ||||
2547 | } | ||||
2548 | #ifdef _WIN32 | ||||
2549 | else if (sExt.equalsIgnoreAsciiCase("mdb") || sExt.equalsIgnoreAsciiCase("mde")) | ||||
2550 | { | ||||
2551 | type = DBConnURIType::MSJET; | ||||
2552 | } | ||||
2553 | else if (sExt.equalsIgnoreAsciiCase("accdb") || sExt.equalsIgnoreAsciiCase("accde")) | ||||
2554 | { | ||||
2555 | type = DBConnURIType::MSACE; | ||||
2556 | } | ||||
2557 | #endif | ||||
2558 | return type; | ||||
2559 | } | ||||
2560 | } | ||||
2561 | |||||
2562 | namespace | ||||
2563 | { | ||||
2564 | uno::Any GetDBunoURI(const INetURLObject &rURL, DBConnURIType& rType) | ||||
2565 | { | ||||
2566 | uno::Any aURLAny; | ||||
2567 | |||||
2568 | if (rType == DBConnURIType::UNKNOWN) | ||||
2569 | rType = GetDBunoType(rURL); | ||||
2570 | |||||
2571 | switch (rType) { | ||||
2572 | case DBConnURIType::UNKNOWN: | ||||
2573 | case DBConnURIType::ODB: | ||||
2574 | break; | ||||
2575 | case DBConnURIType::CALC: | ||||
2576 | { | ||||
2577 | OUString sDBURL = "sdbc:calc:" + | ||||
2578 | rURL.GetMainURL(INetURLObject::DecodeMechanism::NONE); | ||||
2579 | aURLAny <<= sDBURL; | ||||
2580 | } | ||||
2581 | break; | ||||
2582 | case DBConnURIType::WRITER: | ||||
2583 | { | ||||
2584 | OUString sDBURL = "sdbc:writer:" + | ||||
2585 | rURL.GetMainURL(INetURLObject::DecodeMechanism::NONE); | ||||
2586 | aURLAny <<= sDBURL; | ||||
2587 | } | ||||
2588 | break; | ||||
2589 | case DBConnURIType::DBASE: | ||||
2590 | { | ||||
2591 | INetURLObject aUrlTmp(rURL); | ||||
2592 | aUrlTmp.removeSegment(); | ||||
2593 | aUrlTmp.removeFinalSlash(); | ||||
2594 | OUString sDBURL = "sdbc:dbase:" + | ||||
2595 | aUrlTmp.GetMainURL(INetURLObject::DecodeMechanism::NONE); | ||||
2596 | aURLAny <<= sDBURL; | ||||
2597 | } | ||||
2598 | break; | ||||
2599 | case DBConnURIType::FLAT: | ||||
2600 | { | ||||
2601 | INetURLObject aUrlTmp(rURL); | ||||
2602 | aUrlTmp.removeSegment(); | ||||
2603 | aUrlTmp.removeFinalSlash(); | ||||
2604 | OUString sDBURL = "sdbc:flat:" + | ||||
2605 | //only the 'path' has to be added | ||||
2606 | aUrlTmp.GetMainURL(INetURLObject::DecodeMechanism::NONE); | ||||
2607 | aURLAny <<= sDBURL; | ||||
2608 | } | ||||
2609 | break; | ||||
2610 | case DBConnURIType::MSJET: | ||||
2611 | #ifdef _WIN32 | ||||
2612 | { | ||||
2613 | OUString sDBURL("sdbc:ado:access:PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=" + rURL.PathToFileName()); | ||||
2614 | aURLAny <<= sDBURL; | ||||
2615 | } | ||||
2616 | #endif | ||||
2617 | break; | ||||
2618 | case DBConnURIType::MSACE: | ||||
2619 | #ifdef _WIN32 | ||||
2620 | { | ||||
2621 | OUString sDBURL("sdbc:ado:PROVIDER=Microsoft.ACE.OLEDB.12.0;DATA SOURCE=" + rURL.PathToFileName()); | ||||
2622 | aURLAny <<= sDBURL; | ||||
2623 | } | ||||
2624 | #endif | ||||
2625 | break; | ||||
2626 | } | ||||
2627 | return aURLAny; | ||||
2628 | } | ||||
2629 | |||||
2630 | /// Returns the URL of this SwDoc. | ||||
2631 | OUString getOwnURL(SfxObjectShell const * pDocShell) | ||||
2632 | { | ||||
2633 | OUString aRet; | ||||
2634 | |||||
2635 | if (!pDocShell) | ||||
2636 | return aRet; | ||||
2637 | |||||
2638 | const INetURLObject& rURLObject = pDocShell->GetMedium()->GetURLObject(); | ||||
2639 | aRet = rURLObject.GetMainURL(INetURLObject::DecodeMechanism::NONE); | ||||
2640 | return aRet; | ||||
2641 | } | ||||
2642 | |||||
2643 | /** | ||||
2644 | Loads a data source from file and registers it. | ||||
2645 | |||||
2646 | In case of success it returns the registered name, otherwise an empty string. | ||||
2647 | Optionally add a prefix to the registered DB name. | ||||
2648 | */ | ||||
2649 | OUString LoadAndRegisterDataSource_Impl(DBConnURIType type, const uno::Reference< beans::XPropertySet > *pSettings, | ||||
2650 | const INetURLObject &rURL, const OUString *pDestDir, SfxObjectShell* pDocShell) | ||||
2651 | { | ||||
2652 | OUString sExt(rURL.GetFileExtension()); | ||||
2653 | uno::Any aTableFilterAny; | ||||
2654 | uno::Any aSuppressVersionsAny; | ||||
2655 | uno::Any aInfoAny; | ||||
2656 | bool bStore = true; | ||||
2657 | OUString sFind; | ||||
2658 | uno::Sequence<OUString> aFilters(1); | ||||
2659 | |||||
2660 | uno::Any aURLAny = GetDBunoURI(rURL, type); | ||||
2661 | switch (type) { | ||||
2662 | case DBConnURIType::UNKNOWN: | ||||
2663 | case DBConnURIType::CALC: | ||||
2664 | case DBConnURIType::WRITER: | ||||
2665 | break; | ||||
2666 | case DBConnURIType::ODB: | ||||
2667 | bStore = false; | ||||
2668 | break; | ||||
2669 | case DBConnURIType::FLAT: | ||||
2670 | case DBConnURIType::DBASE: | ||||
2671 | //set the filter to the file name without extension | ||||
2672 | aFilters[0] = rURL.getBase(INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset); | ||||
2673 | aTableFilterAny <<= aFilters; | ||||
2674 | break; | ||||
2675 | case DBConnURIType::MSJET: | ||||
2676 | case DBConnURIType::MSACE: | ||||
2677 | aSuppressVersionsAny <<= true; | ||||
2678 | break; | ||||
2679 | } | ||||
2680 | |||||
2681 | try | ||||
2682 | { | ||||
2683 | uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext()); | ||||
2684 | uno::Reference<sdb::XDatabaseContext> xDBContext = sdb::DatabaseContext::create(xContext); | ||||
2685 | |||||
2686 | OUString sNewName = rURL.getName( | ||||
2687 | INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::Unambiguous); | ||||
2688 | sal_Int32 nExtLen = sExt.getLength(); | ||||
2689 | sNewName = sNewName.replaceAt(sNewName.getLength() - nExtLen - 1, nExtLen + 1, ""); | ||||
2690 | |||||
2691 | //find a unique name if sNewName already exists | ||||
2692 | sFind = sNewName; | ||||
2693 | sal_Int32 nIndex = 0; | ||||
2694 | while (xDBContext->hasByName(sFind)) | ||||
2695 | sFind = sNewName + OUString::number(++nIndex); | ||||
2696 | |||||
2697 | uno::Reference<uno::XInterface> xNewInstance; | ||||
2698 | if (!bStore) | ||||
2699 | { | ||||
2700 | //odb-file | ||||
2701 | uno::Any aDataSource = xDBContext->getByName(rURL.GetMainURL(INetURLObject::DecodeMechanism::NONE)); | ||||
2702 | aDataSource >>= xNewInstance; | ||||
2703 | } | ||||
2704 | else | ||||
2705 | { | ||||
2706 | xNewInstance = xDBContext->createInstance(); | ||||
2707 | uno::Reference<beans::XPropertySet> xDataProperties(xNewInstance, uno::UNO_QUERY); | ||||
2708 | |||||
2709 | if (aURLAny.hasValue()) | ||||
2710 | xDataProperties->setPropertyValue("URL", aURLAny); | ||||
2711 | if (aTableFilterAny.hasValue()) | ||||
2712 | xDataProperties->setPropertyValue("TableFilter", aTableFilterAny); | ||||
2713 | if (aSuppressVersionsAny.hasValue()) | ||||
2714 | xDataProperties->setPropertyValue("SuppressVersionColumns", aSuppressVersionsAny); | ||||
2715 | if (aInfoAny.hasValue()) | ||||
2716 | xDataProperties->setPropertyValue("Info", aInfoAny); | ||||
2717 | |||||
2718 | if (DBConnURIType::FLAT == type && pSettings) | ||||
2719 | { | ||||
2720 | uno::Any aSettings = xDataProperties->getPropertyValue("Settings"); | ||||
2721 | uno::Reference < beans::XPropertySet > xDSSettings; | ||||
2722 | aSettings >>= xDSSettings; | ||||
2723 | ::comphelper::copyProperties(*pSettings, xDSSettings); | ||||
2724 | xDSSettings->setPropertyValue("Extension", uno::makeAny(sExt)); | ||||
2725 | } | ||||
2726 | |||||
2727 | uno::Reference<sdb::XDocumentDataSource> xDS(xNewInstance, uno::UNO_QUERY_THROW); | ||||
2728 | uno::Reference<frame::XStorable> xStore(xDS->getDatabaseDocument(), uno::UNO_QUERY_THROW); | ||||
2729 | OUString aOwnURL = getOwnURL(pDocShell); | ||||
2730 | if (aOwnURL.isEmpty()) | ||||
2731 | { | ||||
2732 | // Cannot embed, as embedded data source would need the URL of the parent document. | ||||
2733 | OUString const sOutputExt = ".odb"; | ||||
2734 | OUString sHomePath(SvtPathOptions().GetWorkPath()); | ||||
2735 | utl::TempFile aTempFile(sNewName, true, &sOutputExt, pDestDir ? pDestDir : &sHomePath); | ||||
2736 | const OUString& sTmpName = aTempFile.GetURL(); | ||||
2737 | xStore->storeAsURL(sTmpName, uno::Sequence<beans::PropertyValue>()); | ||||
2738 | } | ||||
2739 | else | ||||
2740 | { | ||||
2741 | // Embed. | ||||
2742 | OUString aStreamRelPath = "EmbeddedDatabase"; | ||||
2743 | uno::Reference<embed::XStorage> xStorage = pDocShell->GetStorage(); | ||||
2744 | |||||
2745 | // Refer to the sub-storage name in the document settings, so | ||||
2746 | // we can load it again next time the file is imported. | ||||
2747 | uno::Reference<lang::XMultiServiceFactory> xFactory(pDocShell->GetModel(), uno::UNO_QUERY); | ||||
2748 | uno::Reference<beans::XPropertySet> xPropertySet(xFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY); | ||||
2749 | xPropertySet->setPropertyValue("EmbeddedDatabaseName", uno::makeAny(aStreamRelPath)); | ||||
2750 | |||||
2751 | // Store it only after setting the above property, so that only one data source gets registered. | ||||
2752 | SwDBManager::StoreEmbeddedDataSource(xStore, xStorage, aStreamRelPath, aOwnURL); | ||||
2753 | } | ||||
2754 | } | ||||
2755 | xDBContext->registerObject(sFind, xNewInstance); | ||||
2756 | } | ||||
2757 | catch (const uno::Exception&) | ||||
2758 | { | ||||
2759 | sFind.clear(); | ||||
2760 | } | ||||
2761 | return sFind; | ||||
2762 | } | ||||
2763 | |||||
2764 | // Construct vnd.sun.star.pkg:// URL | ||||
2765 | OUString ConstructVndSunStarPkgUrl(const OUString& rMainURL, const OUString& rStreamRelPath) | ||||
2766 | { | ||||
2767 | auto xContext(comphelper::getProcessComponentContext()); | ||||
2768 | auto xUri = css::uri::UriReferenceFactory::create(xContext)->parse(rMainURL); | ||||
2769 | assert(xUri.is())(static_cast <bool> (xUri.is()) ? void (0) : __assert_fail ("xUri.is()", "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 2769, __extension__ __PRETTY_FUNCTION__)); | ||||
2770 | xUri = css::uri::VndSunStarPkgUrlReferenceFactory::create(xContext) | ||||
2771 | ->createVndSunStarPkgUrlReference(xUri); | ||||
2772 | assert(xUri.is())(static_cast <bool> (xUri.is()) ? void (0) : __assert_fail ("xUri.is()", "/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" , 2772, __extension__ __PRETTY_FUNCTION__)); | ||||
2773 | return xUri->getUriReference() + "/" | ||||
2774 | + INetURLObject::encode( | ||||
2775 | rStreamRelPath, INetURLObject::PART_FPATH, | ||||
2776 | INetURLObject::EncodeMechanism::All); | ||||
2777 | } | ||||
2778 | } | ||||
2779 | |||||
2780 | OUString SwDBManager::LoadAndRegisterDataSource(weld::Window* pParent, SwDocShell* pDocShell) | ||||
2781 | { | ||||
2782 | sfx2::FileDialogHelper aDlgHelper(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, pParent); | ||||
2783 | uno::Reference < ui::dialogs::XFilePicker3 > xFP = aDlgHelper.GetFilePicker(); | ||||
2784 | |||||
2785 | OUString sHomePath(SvtPathOptions().GetWorkPath()); | ||||
2786 | aDlgHelper.SetDisplayDirectory( sHomePath ); | ||||
2787 | |||||
2788 | OUString sFilterAll(SwResId(STR_FILTER_ALLreinterpret_cast<char const *>("STR_FILTER_ALL" "\004" u8"All files" ))); | ||||
2789 | OUString sFilterAllData(SwResId(STR_FILTER_ALL_DATAreinterpret_cast<char const *>("STR_FILTER_ALL_DATA" "\004" u8"Address lists(*.*)"))); | ||||
2790 | OUString sFilterSXB(SwResId(STR_FILTER_SXBreinterpret_cast<char const *>("STR_FILTER_SXB" "\004" u8"%PRODUCTNAME Base (*.odb)" ))); | ||||
2791 | OUString sFilterSXC(SwResId(STR_FILTER_SXCreinterpret_cast<char const *>("STR_FILTER_SXC" "\004" u8"%PRODUCTNAME Calc (*.ods;*.sxc)" ))); | ||||
2792 | OUString sFilterSXW(SwResId(STR_FILTER_SXWreinterpret_cast<char const *>("STR_FILTER_SXW" "\004" u8"%PRODUCTNAME Writer (*.odt;*.sxw)" ))); | ||||
2793 | OUString sFilterDBF(SwResId(STR_FILTER_DBFreinterpret_cast<char const *>("STR_FILTER_DBF" "\004" u8"dBase (*.dbf)" ))); | ||||
2794 | OUString sFilterXLS(SwResId(STR_FILTER_XLSreinterpret_cast<char const *>("STR_FILTER_XLS" "\004" u8"Microsoft Excel (*.xls;*.xlsx)" ))); | ||||
2795 | OUString sFilterDOC(SwResId(STR_FILTER_DOCreinterpret_cast<char const *>("STR_FILTER_DOC" "\004" u8"Microsoft Word (*.doc;*.docx)" ))); | ||||
2796 | OUString sFilterTXT(SwResId(STR_FILTER_TXTreinterpret_cast<char const *>("STR_FILTER_TXT" "\004" u8"Plain text (*.txt)" ))); | ||||
2797 | OUString sFilterCSV(SwResId(STR_FILTER_CSVreinterpret_cast<char const *>("STR_FILTER_CSV" "\004" u8"Text Comma Separated (*.csv)" ))); | ||||
2798 | #ifdef _WIN32 | ||||
2799 | OUString sFilterMDB(SwResId(STR_FILTER_MDBreinterpret_cast<char const *>("STR_FILTER_MDB" "\004" u8"Microsoft Access (*.mdb;*.mde)" ))); | ||||
2800 | OUString sFilterACCDB(SwResId(STR_FILTER_ACCDBreinterpret_cast<char const *>("STR_FILTER_ACCDB" "\004" u8"Microsoft Access 2007 (*.accdb,*.accde)"))); | ||||
2801 | #endif | ||||
2802 | xFP->appendFilter( sFilterAll, "*" ); | ||||
2803 | xFP->appendFilter( sFilterAllData, "*.ods;*.sxc;*.odt;*.sxw;*.dbf;*.xls;*.xlsx;*.doc;*.docx;*.txt;*.csv"); | ||||
2804 | |||||
2805 | xFP->appendFilter( sFilterSXB, "*.odb" ); | ||||
2806 | xFP->appendFilter( sFilterSXC, "*.ods;*.sxc" ); | ||||
2807 | xFP->appendFilter( sFilterSXW, "*.odt;*.sxw" ); | ||||
2808 | xFP->appendFilter( sFilterDBF, "*.dbf" ); | ||||
2809 | xFP->appendFilter( sFilterXLS, "*.xls;*.xlsx" ); | ||||
2810 | xFP->appendFilter( sFilterDOC, "*.doc;*.docx" ); | ||||
2811 | xFP->appendFilter( sFilterTXT, "*.txt" ); | ||||
2812 | xFP->appendFilter( sFilterCSV, "*.csv" ); | ||||
2813 | #ifdef _WIN32 | ||||
2814 | xFP->appendFilter(sFilterMDB, "*.mdb;*.mde"); | ||||
2815 | xFP->appendFilter(sFilterACCDB, "*.accdb;*.accde"); | ||||
2816 | #endif | ||||
2817 | |||||
2818 | xFP->setCurrentFilter( sFilterAll ) ; | ||||
2819 | OUString sFind; | ||||
2820 | if( ERRCODE_NONEErrCode(0) == aDlgHelper.Execute() ) | ||||
2821 | { | ||||
2822 | uno::Reference< beans::XPropertySet > aSettings; | ||||
2823 | const INetURLObject aURL( xFP->getSelectedFiles().getConstArray()[0] ); | ||||
2824 | const DBConnURIType type = GetDBunoType( aURL ); | ||||
2825 | |||||
2826 | if( DBConnURIType::FLAT == type ) | ||||
2827 | { | ||||
2828 | uno::Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() ); | ||||
2829 | uno::Reference < sdb::XTextConnectionSettings > xSettingsDlg = sdb::TextConnectionSettings::create(xContext); | ||||
2830 | if( xSettingsDlg->execute() ) | ||||
2831 | aSettings.set( uno::Reference < beans::XPropertySet >( xSettingsDlg, uno::UNO_QUERY_THROW ) ); | ||||
2832 | } | ||||
2833 | sFind = LoadAndRegisterDataSource_Impl( type, DBConnURIType::FLAT == type ? &aSettings : nullptr, aURL, nullptr, pDocShell ); | ||||
2834 | |||||
2835 | m_aUncommittedRegistrations.push_back(std::pair<SwDocShell*, OUString>(pDocShell, sFind)); | ||||
2836 | } | ||||
2837 | return sFind; | ||||
2838 | } | ||||
2839 | |||||
2840 | void SwDBManager::StoreEmbeddedDataSource(const uno::Reference<frame::XStorable>& xStorable, | ||||
2841 | const uno::Reference<embed::XStorage>& xStorage, | ||||
2842 | const OUString& rStreamRelPath, | ||||
2843 | const OUString& rOwnURL, bool bCopyTo) | ||||
2844 | { | ||||
2845 | // Construct vnd.sun.star.pkg:// URL for later loading, and TargetStorage/StreamRelPath for storing. | ||||
2846 | OUString const sTmpName = ConstructVndSunStarPkgUrl(rOwnURL, rStreamRelPath); | ||||
2847 | |||||
2848 | uno::Sequence<beans::PropertyValue> aSequence = comphelper::InitPropertySequence( | ||||
2849 | { | ||||
2850 | {"TargetStorage", uno::makeAny(xStorage)}, | ||||
2851 | {"StreamRelPath", uno::makeAny(rStreamRelPath)}, | ||||
2852 | {"BaseURI", uno::makeAny(rOwnURL)} | ||||
2853 | }); | ||||
2854 | if (bCopyTo) | ||||
2855 | xStorable->storeToURL(sTmpName, aSequence); | ||||
2856 | else | ||||
2857 | xStorable->storeAsURL(sTmpName, aSequence); | ||||
2858 | } | ||||
2859 | |||||
2860 | OUString SwDBManager::LoadAndRegisterDataSource(const OUString &rURI, const OUString *pDestDir) | ||||
2861 | { | ||||
2862 | return LoadAndRegisterDataSource_Impl( DBConnURIType::UNKNOWN, nullptr, INetURLObject(rURI), pDestDir, nullptr ); | ||||
2863 | } | ||||
2864 | |||||
2865 | namespace | ||||
2866 | { | ||||
2867 | // tdf#117824 switch the embedded database away from using its current storage and point it to temporary storage | ||||
2868 | // which allows the original storage to be deleted | ||||
2869 | void switchEmbeddedDatabaseStorage(const uno::Reference<sdb::XDatabaseContext>& rDatabaseContext, const OUString& rName) | ||||
2870 | { | ||||
2871 | uno::Reference<sdb::XDocumentDataSource> xDS(rDatabaseContext->getByName(rName), uno::UNO_QUERY); | ||||
2872 | if (!xDS) | ||||
2873 | return; | ||||
2874 | uno::Reference<document::XStorageBasedDocument> xStorageDoc(xDS->getDatabaseDocument(), uno::UNO_QUERY); | ||||
2875 | if (!xStorageDoc) | ||||
2876 | return; | ||||
2877 | xStorageDoc->switchToStorage(comphelper::OStorageHelper::GetTemporaryStorage()); | ||||
2878 | } | ||||
2879 | } | ||||
2880 | |||||
2881 | void SwDBManager::RevokeDataSource(const OUString& rName) | ||||
2882 | { | ||||
2883 | uno::Reference<sdb::XDatabaseContext> xDatabaseContext = sdb::DatabaseContext::create(comphelper::getProcessComponentContext()); | ||||
2884 | if (xDatabaseContext->hasByName(rName)) | ||||
2885 | { | ||||
2886 | switchEmbeddedDatabaseStorage(xDatabaseContext, rName); | ||||
2887 | xDatabaseContext->revokeObject(rName); | ||||
2888 | } | ||||
2889 | } | ||||
2890 | |||||
2891 | void SwDBManager::LoadAndRegisterEmbeddedDataSource(const SwDBData& rData, const SwDocShell& rDocShell) | ||||
2892 | { | ||||
2893 | uno::Reference<sdb::XDatabaseContext> xDatabaseContext = sdb::DatabaseContext::create(comphelper::getProcessComponentContext()); | ||||
2894 | |||||
2895 | OUString sDataSource = rData.sDataSource; | ||||
2896 | |||||
2897 | // Fallback, just in case the document would contain an embedded data source, but no DB fields. | ||||
2898 | if (sDataSource.isEmpty()) | ||||
2899 | sDataSource = "EmbeddedDatabase"; | ||||
2900 | |||||
2901 | SwDBManager::RevokeDataSource( sDataSource ); | ||||
2902 | |||||
2903 | // Encode the stream name and the real path into a single URL. | ||||
2904 | const INetURLObject& rURLObject = rDocShell.GetMedium()->GetURLObject(); | ||||
2905 | OUString const aURL = ConstructVndSunStarPkgUrl( | ||||
2906 | rURLObject.GetMainURL(INetURLObject::DecodeMechanism::NONE), | ||||
2907 | m_sEmbeddedName); | ||||
2908 | |||||
2909 | uno::Reference<uno::XInterface> xDataSource(xDatabaseContext->getByName(aURL), uno::UNO_QUERY); | ||||
2910 | xDatabaseContext->registerObject( sDataSource, xDataSource ); | ||||
2911 | |||||
2912 | // temp file - don't remember connection | ||||
2913 | if (rData.sDataSource.isEmpty()) | ||||
2914 | m_aUncommittedRegistrations.push_back(std::pair<SwDocShell*, OUString>(nullptr, sDataSource)); | ||||
2915 | } | ||||
2916 | |||||
2917 | void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh, | ||||
2918 | const uno::Sequence<beans::PropertyValue>& rProperties) | ||||
2919 | { | ||||
2920 | //prevent second call | ||||
2921 | if(m_pImpl->pMergeDialog) | ||||
2922 | return ; | ||||
2923 | OUString sDataSource, sDataTableOrQuery; | ||||
2924 | uno::Sequence<uno::Any> aSelection; | ||||
2925 | |||||
2926 | sal_Int32 nCmdType = sdb::CommandType::TABLE; | ||||
2927 | uno::Reference< sdbc::XConnection> xConnection; | ||||
2928 | |||||
2929 | svx::ODataAccessDescriptor aDescriptor(rProperties); | ||||
2930 | sDataSource = aDescriptor.getDataSource(); | ||||
2931 | OSL_VERIFY(aDescriptor[svx::DataAccessDescriptorProperty::Command] >>= sDataTableOrQuery)do { if (!(aDescriptor[svx::DataAccessDescriptorProperty::Command ] >>= sDataTableOrQuery)) do { if (true && (!(0 ))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2931" ": "), "OSL_ASSERT: %s", "0"); } } while (false); } while (0); | ||||
2932 | OSL_VERIFY(aDescriptor[svx::DataAccessDescriptorProperty::CommandType] >>= nCmdType)do { if (!(aDescriptor[svx::DataAccessDescriptorProperty::CommandType ] >>= nCmdType)) do { if (true && (!(0))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2932" ": "), "OSL_ASSERT: %s", "0"); } } while (false); } while (0); | ||||
2933 | |||||
2934 | if ( aDescriptor.has(svx::DataAccessDescriptorProperty::Selection) ) | ||||
2935 | aDescriptor[svx::DataAccessDescriptorProperty::Selection] >>= aSelection; | ||||
2936 | if ( aDescriptor.has(svx::DataAccessDescriptorProperty::Connection) ) | ||||
2937 | aDescriptor[svx::DataAccessDescriptorProperty::Connection] >>= xConnection; | ||||
2938 | |||||
2939 | if(sDataSource.isEmpty() || sDataTableOrQuery.isEmpty()) | ||||
2940 | { | ||||
2941 | OSL_FAIL("PropertyValues missing or unset")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "2941" ": "), "%s", "PropertyValues missing or unset"); } } while (false); | ||||
2942 | return; | ||||
2943 | } | ||||
2944 | |||||
2945 | //always create a connection for the dialog and dispose it after the dialog has been closed | ||||
2946 | SwDSParam* pFound = nullptr; | ||||
2947 | if(!xConnection.is()) | ||||
2948 | { | ||||
2949 | xConnection = SwDBManager::RegisterConnection(sDataSource); | ||||
2950 | pFound = FindDSConnection(sDataSource, true); | ||||
2951 | } | ||||
2952 | SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); | ||||
2953 | m_pImpl->pMergeDialog = pFact->CreateMailMergeDlg(rSh.GetView().GetViewFrame()->GetWindow().GetFrameWeld(), rSh, | ||||
2954 | sDataSource, | ||||
2955 | sDataTableOrQuery, | ||||
2956 | nCmdType, | ||||
2957 | xConnection); | ||||
2958 | if(m_pImpl->pMergeDialog->Execute() == RET_OK) | ||||
2959 | { | ||||
2960 | aDescriptor[svx::DataAccessDescriptorProperty::Selection] <<= m_pImpl->pMergeDialog->GetSelection(); | ||||
2961 | |||||
2962 | uno::Reference<sdbc::XResultSet> xResSet = m_pImpl->pMergeDialog->GetResultSet(); | ||||
2963 | if(xResSet.is()) | ||||
2964 | aDescriptor[svx::DataAccessDescriptorProperty::Cursor] <<= xResSet; | ||||
2965 | |||||
2966 | // SfxObjectShellRef is ok, since there should be no control over the document lifetime here | ||||
2967 | SfxObjectShellRef xDocShell = rSh.GetView().GetViewFrame()->GetObjectShell(); | ||||
2968 | |||||
2969 | lcl_emitEvent(SfxEventHintId::SwMailMerge, STR_SW_EVENT_MAIL_MERGE1, xDocShell.get()); | ||||
2970 | |||||
2971 | // prepare mail merge descriptor | ||||
2972 | SwMergeDescriptor aMergeDesc( m_pImpl->pMergeDialog->GetMergeType(), rSh, aDescriptor ); | ||||
2973 | aMergeDesc.sSaveToFilter = m_pImpl->pMergeDialog->GetSaveFilter(); | ||||
2974 | aMergeDesc.bCreateSingleFile = m_pImpl->pMergeDialog->IsSaveSingleDoc(); | ||||
2975 | aMergeDesc.bPrefixIsFilename = aMergeDesc.bCreateSingleFile; | ||||
2976 | aMergeDesc.sPrefix = m_pImpl->pMergeDialog->GetTargetURL(); | ||||
2977 | |||||
2978 | if(!aMergeDesc.bCreateSingleFile) | ||||
2979 | { | ||||
2980 | if(m_pImpl->pMergeDialog->IsGenerateFromDataBase()) | ||||
2981 | aMergeDesc.sDBcolumn = m_pImpl->pMergeDialog->GetColumnName(); | ||||
2982 | |||||
2983 | if(m_pImpl->pMergeDialog->IsFileEncryptedFromDataBase()) | ||||
2984 | aMergeDesc.sDBPasswordColumn = m_pImpl->pMergeDialog->GetPasswordColumnName(); | ||||
2985 | } | ||||
2986 | |||||
2987 | Merge( aMergeDesc ); | ||||
2988 | |||||
2989 | lcl_emitEvent(SfxEventHintId::SwMailMergeEnd, STR_SW_EVENT_MAIL_MERGE_END2, xDocShell.get()); | ||||
2990 | |||||
2991 | // reset the cursor inside | ||||
2992 | xResSet = nullptr; | ||||
2993 | aDescriptor[svx::DataAccessDescriptorProperty::Cursor] <<= xResSet; | ||||
2994 | } | ||||
2995 | if(pFound) | ||||
2996 | { | ||||
2997 | for (const auto & pParam : m_DataSourceParams) | ||||
2998 | { | ||||
2999 | if (pParam.get() == pFound) | ||||
3000 | { | ||||
3001 | try | ||||
3002 | { | ||||
3003 | uno::Reference<lang::XComponent> xComp(pParam->xConnection, uno::UNO_QUERY); | ||||
3004 | if(xComp.is()) | ||||
3005 | xComp->dispose(); | ||||
3006 | } | ||||
3007 | catch(const uno::RuntimeException&) | ||||
3008 | { | ||||
3009 | //may be disposed already since multiple entries may have used the same connection | ||||
3010 | } | ||||
3011 | break; | ||||
3012 | } | ||||
3013 | //pFound doesn't need to be removed/deleted - | ||||
3014 | //this has been done by the SwConnectionDisposedListener_Impl already | ||||
3015 | } | ||||
3016 | } | ||||
3017 | m_pImpl->pMergeDialog.disposeAndClear(); | ||||
3018 | } | ||||
3019 | |||||
3020 | void SwDBManager::InsertText(SwWrtShell& rSh, | ||||
3021 | const uno::Sequence< beans::PropertyValue>& rProperties) | ||||
3022 | { | ||||
3023 | OUString sDataSource, sDataTableOrQuery; | ||||
3024 | uno::Reference<sdbc::XResultSet> xResSet; | ||||
3025 | uno::Sequence<uno::Any> aSelection; | ||||
3026 | sal_Int16 nCmdType = sdb::CommandType::TABLE; | ||||
3027 | uno::Reference< sdbc::XConnection> xConnection; | ||||
3028 | for(const beans::PropertyValue& rValue : rProperties) | ||||
3029 | { | ||||
3030 | if ( rValue.Name == "DataSourceName" ) | ||||
3031 | rValue.Value >>= sDataSource; | ||||
3032 | else if ( rValue.Name == "Command" ) | ||||
3033 | rValue.Value >>= sDataTableOrQuery; | ||||
3034 | else if ( rValue.Name == "Cursor" ) | ||||
3035 | rValue.Value >>= xResSet; | ||||
3036 | else if ( rValue.Name == "Selection" ) | ||||
3037 | rValue.Value >>= aSelection; | ||||
3038 | else if ( rValue.Name == "CommandType" ) | ||||
3039 | rValue.Value >>= nCmdType; | ||||
3040 | else if ( rValue.Name == "ActiveConnection" ) | ||||
3041 | rValue.Value >>= xConnection; | ||||
3042 | } | ||||
3043 | if(sDataSource.isEmpty() || sDataTableOrQuery.isEmpty() || !xResSet.is()) | ||||
3044 | { | ||||
3045 | OSL_FAIL("PropertyValues missing or unset")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "3045" ": "), "%s", "PropertyValues missing or unset"); } } while (false); | ||||
3046 | return; | ||||
3047 | } | ||||
3048 | uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); | ||||
3049 | uno::Reference<sdbc::XDataSource> xSource; | ||||
3050 | uno::Reference<container::XChild> xChild(xConnection, uno::UNO_QUERY); | ||||
3051 | if(xChild.is()) | ||||
3052 | xSource.set(xChild->getParent(), uno::UNO_QUERY); | ||||
3053 | if(!xSource.is()) | ||||
3054 | xSource = dbtools::getDataSource(sDataSource, xContext); | ||||
3055 | uno::Reference< sdbcx::XColumnsSupplier > xColSupp( xResSet, uno::UNO_QUERY ); | ||||
3056 | SwDBData aDBData; | ||||
3057 | aDBData.sDataSource = sDataSource; | ||||
3058 | aDBData.sCommand = sDataTableOrQuery; | ||||
3059 | aDBData.nCommandType = nCmdType; | ||||
3060 | |||||
3061 | SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); | ||||
3062 | ScopedVclPtr<AbstractSwInsertDBColAutoPilot> pDlg(pFact->CreateSwInsertDBColAutoPilot( rSh.GetView(), | ||||
3063 | xSource, | ||||
3064 | xColSupp, | ||||
3065 | aDBData )); | ||||
3066 | if( RET_OK != pDlg->Execute() ) | ||||
3067 | return; | ||||
3068 | |||||
3069 | OUString sDummy; | ||||
3070 | if(!xConnection.is()) | ||||
3071 | xConnection = xSource->getConnection(sDummy, sDummy); | ||||
3072 | try | ||||
3073 | { | ||||
3074 | pDlg->DataToDoc( aSelection , xSource, xConnection, xResSet); | ||||
3075 | } | ||||
3076 | catch (const uno::Exception&) | ||||
3077 | { | ||||
3078 | TOOLS_WARN_EXCEPTION("sw.mailmerge", "")do { css::uno::Any tools_warn_exception( DbgGetCaughtException () ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.mailmerge")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "" << " " << exceptionToString(tools_warn_exception)) == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "3078" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "" << " " << exceptionToString (tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "" << " " << exceptionToString (tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "3078" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "" << " " << exceptionToString(tools_warn_exception )) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ( "sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "3078" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "" << " " << exceptionToString (tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "" << " " << exceptionToString (tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "3078" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); } while (false); | ||||
3079 | } | ||||
3080 | } | ||||
3081 | |||||
3082 | uno::Reference<sdbc::XDataSource> SwDBManager::getDataSourceAsParent(const uno::Reference< sdbc::XConnection>& _xConnection,const OUString& _sDataSourceName) | ||||
3083 | { | ||||
3084 | uno::Reference<sdbc::XDataSource> xSource; | ||||
3085 | try | ||||
3086 | { | ||||
3087 | uno::Reference<container::XChild> xChild(_xConnection, uno::UNO_QUERY); | ||||
3088 | if ( xChild.is() ) | ||||
3089 | xSource.set(xChild->getParent(), uno::UNO_QUERY); | ||||
3090 | if ( !xSource.is() ) | ||||
3091 | xSource = dbtools::getDataSource(_sDataSourceName, ::comphelper::getProcessComponentContext()); | ||||
3092 | } | ||||
3093 | catch (const uno::Exception&) | ||||
3094 | { | ||||
3095 | TOOLS_WARN_EXCEPTION("sw.mailmerge", "getDataSourceAsParent()")do { css::uno::Any tools_warn_exception( DbgGetCaughtException () ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.mailmerge")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "getDataSourceAsParent()" << " " << exceptionToString(tools_warn_exception )) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ( "sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "3095" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "getDataSourceAsParent()" << " " << exceptionToString(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "getDataSourceAsParent()" << " " << exceptionToString (tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "3095" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "getDataSourceAsParent()" << " " << exceptionToString (tools_warn_exception)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "3095" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "getDataSourceAsParent()" << " " << exceptionToString(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "getDataSourceAsParent()" << " " << exceptionToString (tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "3095" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); } while (false); | ||||
3096 | } | ||||
3097 | return xSource; | ||||
3098 | } | ||||
3099 | |||||
3100 | uno::Reference<sdbc::XResultSet> SwDBManager::createCursor(const OUString& _sDataSourceName, | ||||
3101 | const OUString& _sCommand, | ||||
3102 | sal_Int32 _nCommandType, | ||||
3103 | const uno::Reference<sdbc::XConnection>& _xConnection, | ||||
3104 | const SwView* pView) | ||||
3105 | { | ||||
3106 | uno::Reference<sdbc::XResultSet> xResultSet; | ||||
3107 | try | ||||
3108 | { | ||||
3109 | uno::Reference< lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() ); | ||||
3110 | if( xMgr.is() ) | ||||
3111 | { | ||||
3112 | uno::Reference<uno::XInterface> xInstance = xMgr->createInstance("com.sun.star.sdb.RowSet"); | ||||
3113 | uno::Reference<beans::XPropertySet> xRowSetPropSet(xInstance, uno::UNO_QUERY); | ||||
3114 | if(xRowSetPropSet.is()) | ||||
3115 | { | ||||
3116 | xRowSetPropSet->setPropertyValue("DataSourceName", uno::makeAny(_sDataSourceName)); | ||||
3117 | xRowSetPropSet->setPropertyValue("ActiveConnection", uno::makeAny(_xConnection)); | ||||
3118 | xRowSetPropSet->setPropertyValue("Command", uno::makeAny(_sCommand)); | ||||
3119 | xRowSetPropSet->setPropertyValue("CommandType", uno::makeAny(_nCommandType)); | ||||
3120 | |||||
3121 | uno::Reference< sdb::XCompletedExecution > xRowSet(xInstance, uno::UNO_QUERY); | ||||
3122 | |||||
3123 | if ( xRowSet.is() ) | ||||
3124 | { | ||||
3125 | weld::Window* pWindow = pView ? pView->GetFrameWeld() : nullptr; | ||||
3126 | uno::Reference< task::XInteractionHandler > xHandler( task::InteractionHandler::createWithParent(comphelper::getComponentContext(xMgr), pWindow ? pWindow->GetXWindow() : nullptr), uno::UNO_QUERY_THROW ); | ||||
3127 | xRowSet->executeWithCompletion(xHandler); | ||||
3128 | } | ||||
3129 | xResultSet.set(xRowSet, uno::UNO_QUERY); | ||||
3130 | } | ||||
3131 | } | ||||
3132 | } | ||||
3133 | catch (const uno::Exception&) | ||||
3134 | { | ||||
3135 | TOOLS_WARN_EXCEPTION("sw.mailmerge", "Caught exception while creating a new RowSet")do { css::uno::Any tools_warn_exception( DbgGetCaughtException () ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.mailmerge")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "Caught exception while creating a new RowSet" << " " << exceptionToString(tools_warn_exception )) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ( "sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "3135" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "Caught exception while creating a new RowSet" << " " << exceptionToString(tools_warn_exception )), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Caught exception while creating a new RowSet" << " " << exceptionToString(tools_warn_exception); ::sal:: detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "3135" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Caught exception while creating a new RowSet" << " " << exceptionToString(tools_warn_exception)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge" ), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "3135" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "Caught exception while creating a new RowSet" << " " << exceptionToString(tools_warn_exception )), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Caught exception while creating a new RowSet" << " " << exceptionToString(tools_warn_exception); ::sal:: detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.mailmerge"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/dbui/dbmgr.cxx" ":" "3135" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); } while (false); | ||||
3136 | } | ||||
3137 | return xResultSet; | ||||
3138 | } | ||||
3139 | |||||
3140 | void SwDBManager::setEmbeddedName(const OUString& rEmbeddedName, SwDocShell& rDocShell) | ||||
3141 | { | ||||
3142 | bool bLoad = m_sEmbeddedName != rEmbeddedName && !rEmbeddedName.isEmpty(); | ||||
3143 | bool bRegisterListener = m_sEmbeddedName.isEmpty() && !rEmbeddedName.isEmpty(); | ||||
3144 | |||||
3145 | m_sEmbeddedName = rEmbeddedName; | ||||
3146 | |||||
3147 | if (bLoad) | ||||
3148 | { | ||||
3149 | uno::Reference<embed::XStorage> xStorage = rDocShell.GetStorage(); | ||||
3150 | // It's OK that we don't have the named sub-storage yet, in case | ||||
3151 | // we're in the process of creating it. | ||||
3152 | if (xStorage->hasByName(rEmbeddedName)) | ||||
3153 | LoadAndRegisterEmbeddedDataSource(rDocShell.GetDoc()->GetDBData(), rDocShell); | ||||
3154 | } | ||||
3155 | |||||
3156 | if (bRegisterListener) | ||||
3157 | // Register a remove listener, so we know when the embedded data source is removed. | ||||
3158 | m_pImpl->m_xDataSourceRemovedListener = new SwDataSourceRemovedListener(*this); | ||||
3159 | } | ||||
3160 | |||||
3161 | const OUString& SwDBManager::getEmbeddedName() const | ||||
3162 | { | ||||
3163 | return m_sEmbeddedName; | ||||
3164 | } | ||||
3165 | |||||
3166 | SwDoc* SwDBManager::getDoc() const | ||||
3167 | { | ||||
3168 | return m_pDoc; | ||||
3169 | } | ||||
3170 | |||||
3171 | void SwDBManager::releaseRevokeListener() | ||||
3172 | { | ||||
3173 | if (m_pImpl->m_xDataSourceRemovedListener.is()) | ||||
3174 | { | ||||
3175 | m_pImpl->m_xDataSourceRemovedListener->Dispose(); | ||||
3176 | m_pImpl->m_xDataSourceRemovedListener.clear(); | ||||
3177 | } | ||||
3178 | } | ||||
3179 | |||||
3180 | SwDBManager::ConnectionDisposedListener_Impl::ConnectionDisposedListener_Impl(SwDBManager& rManager) | ||||
3181 | : m_pDBManager(&rManager) | ||||
3182 | { | ||||
3183 | } | ||||
3184 | |||||
3185 | void SwDBManager::ConnectionDisposedListener_Impl::disposing( const lang::EventObject& rSource ) | ||||
3186 | { | ||||
3187 | ::SolarMutexGuard aGuard; | ||||
3188 | |||||
3189 | if (!m_pDBManager) return; // we're disposed too! | ||||
3190 | |||||
3191 | uno::Reference<sdbc::XConnection> xSource(rSource.Source, uno::UNO_QUERY); | ||||
3192 | for (size_t nPos = m_pDBManager->m_DataSourceParams.size(); nPos; nPos--) | ||||
3193 | { | ||||
3194 | SwDSParam* pParam = m_pDBManager->m_DataSourceParams[nPos - 1].get(); | ||||
3195 | if(pParam->xConnection.is() && | ||||
3196 | (xSource == pParam->xConnection)) | ||||
3197 | { | ||||
3198 | m_pDBManager->m_DataSourceParams.erase( | ||||
3199 | m_pDBManager->m_DataSourceParams.begin() + nPos - 1); | ||||
3200 | } | ||||
3201 | } | ||||
3202 | } | ||||
3203 | |||||
3204 | std::shared_ptr<SwMailMergeConfigItem> SwDBManager::PerformMailMerge(SwView const * pView) | ||||
3205 | { | ||||
3206 | std::shared_ptr<SwMailMergeConfigItem> xConfigItem = pView->GetMailMergeConfigItem(); | ||||
3207 | if (!xConfigItem) | ||||
| |||||
3208 | return xConfigItem; | ||||
3209 | |||||
3210 | svx::ODataAccessDescriptor aDescriptor; | ||||
3211 | aDescriptor.setDataSource(xConfigItem->GetCurrentDBData().sDataSource); | ||||
3212 | aDescriptor[ svx::DataAccessDescriptorProperty::Connection ] <<= xConfigItem->GetConnection().getTyped(); | ||||
3213 | aDescriptor[ svx::DataAccessDescriptorProperty::Cursor ] <<= xConfigItem->GetResultSet(); | ||||
3214 | aDescriptor[ svx::DataAccessDescriptorProperty::Command ] <<= xConfigItem->GetCurrentDBData().sCommand; | ||||
3215 | aDescriptor[ svx::DataAccessDescriptorProperty::CommandType ] <<= xConfigItem->GetCurrentDBData().nCommandType; | ||||
3216 | aDescriptor[ svx::DataAccessDescriptorProperty::Selection ] <<= xConfigItem->GetSelection(); | ||||
3217 | |||||
3218 | SwWrtShell& rSh = pView->GetWrtShell(); | ||||
3219 | xConfigItem->SetTargetView(nullptr); | ||||
3220 | |||||
3221 | SwMergeDescriptor aMergeDesc(DBMGR_MERGE_SHELL, rSh, aDescriptor); | ||||
3222 | aMergeDesc.pMailMergeConfigItem = xConfigItem.get(); | ||||
3223 | aMergeDesc.bCreateSingleFile = true; | ||||
3224 | rSh.GetDBManager()->Merge(aMergeDesc); | ||||
3225 | |||||
3226 | return xConfigItem; | ||||
3227 | } | ||||
3228 | |||||
3229 | void SwDBManager::RevokeLastRegistrations() | ||||
3230 | { | ||||
3231 | if (m_aUncommittedRegistrations.empty()) | ||||
3232 | return; | ||||
3233 | |||||
3234 | SwView* pView = ( m_pDoc && m_pDoc->GetDocShell() ) ? m_pDoc->GetDocShell()->GetView() : nullptr; | ||||
3235 | if (pView) | ||||
3236 | { | ||||
3237 | const std::shared_ptr<SwMailMergeConfigItem>& xConfigItem = pView->GetMailMergeConfigItem(); | ||||
3238 | if (xConfigItem) | ||||
3239 | { | ||||
3240 | xConfigItem->DisposeResultSet(); | ||||
3241 | xConfigItem->DocumentReloaded(); | ||||
3242 | } | ||||
3243 | } | ||||
3244 | |||||
3245 | for (auto it = m_aUncommittedRegistrations.begin(); it != m_aUncommittedRegistrations.end();) | ||||
3246 | { | ||||
3247 | if ((m_pDoc && it->first == m_pDoc->GetDocShell()) || it->first == nullptr) | ||||
3248 | { | ||||
3249 | RevokeDataSource(it->second); | ||||
3250 | it = m_aUncommittedRegistrations.erase(it); | ||||
3251 | } | ||||
3252 | else | ||||
3253 | ++it; | ||||
3254 | } | ||||
3255 | } | ||||
3256 | |||||
3257 | void SwDBManager::CommitLastRegistrations() | ||||
3258 | { | ||||
3259 | for (auto aIt = m_aUncommittedRegistrations.begin(); aIt != m_aUncommittedRegistrations.end();) | ||||
3260 | { | ||||
3261 | if (aIt->first == m_pDoc->GetDocShell() || aIt->first == nullptr) | ||||
3262 | { | ||||
3263 | m_aNotUsedConnections.push_back(aIt->second); | ||||
3264 | aIt = m_aUncommittedRegistrations.erase(aIt); | ||||
3265 | } | ||||
3266 | else | ||||
3267 | aIt++; | ||||
3268 | } | ||||
3269 | } | ||||
3270 | |||||
3271 | void SwDBManager::SetAsUsed(const OUString& rName) | ||||
3272 | { | ||||
3273 | auto aFound = std::find(m_aNotUsedConnections.begin(), m_aNotUsedConnections.end(), rName); | ||||
3274 | if (aFound != m_aNotUsedConnections.end()) | ||||
3275 | m_aNotUsedConnections.erase(aFound); | ||||
3276 | } | ||||
3277 | |||||
3278 | void SwDBManager::RevokeNotUsedConnections() | ||||
3279 | { | ||||
3280 | for (auto aIt = m_aNotUsedConnections.begin(); aIt != m_aNotUsedConnections.end();) | ||||
3281 | { | ||||
3282 | RevokeDataSource(*aIt); | ||||
3283 | aIt = m_aNotUsedConnections.erase(aIt); | ||||
3284 | } | ||||
3285 | } | ||||
3286 | |||||
3287 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_TOOLS_REF_HXX | ||||
20 | #define INCLUDED_TOOLS_REF_HXX | ||||
21 | |||||
22 | #include <sal/config.h> | ||||
23 | #include <cassert> | ||||
24 | #include <tools/toolsdllapi.h> | ||||
25 | #include <utility> | ||||
26 | |||||
27 | /** | ||||
28 | This implements similar functionality to boost::intrusive_ptr | ||||
29 | */ | ||||
30 | |||||
31 | namespace tools { | ||||
32 | |||||
33 | /** T must be a class that extends SvRefBase */ | ||||
34 | template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final { | ||||
35 | public: | ||||
36 | SvRef(): pObj(nullptr) {} | ||||
37 | |||||
38 | SvRef(SvRef&& rObj) noexcept | ||||
39 | { | ||||
40 | pObj = rObj.pObj; | ||||
41 | rObj.pObj = nullptr; | ||||
42 | } | ||||
43 | |||||
44 | SvRef(SvRef const & rObj): pObj(rObj.pObj) | ||||
45 | { | ||||
46 | if (pObj != nullptr) pObj->AddNextRef(); | ||||
47 | } | ||||
48 | |||||
49 | SvRef(T * pObjP): pObj(pObjP) | ||||
50 | { | ||||
51 | if (pObj != nullptr) pObj->AddFirstRef(); | ||||
52 | } | ||||
53 | |||||
54 | ~SvRef() | ||||
55 | { | ||||
56 | if (pObj != nullptr) pObj->ReleaseRef(); | ||||
57 | } | ||||
58 | |||||
59 | void clear() | ||||
60 | { | ||||
61 | if (pObj != nullptr) { | ||||
62 | T * pRefObj = pObj; | ||||
63 | pObj = nullptr; | ||||
64 | pRefObj->ReleaseRef(); | ||||
65 | } | ||||
66 | } | ||||
67 | |||||
68 | SvRef & operator =(SvRef const & rObj) | ||||
69 | { | ||||
70 | if (rObj.pObj != nullptr) { | ||||
71 | rObj.pObj->AddNextRef(); | ||||
72 | } | ||||
73 | T * pRefObj = pObj; | ||||
74 | pObj = rObj.pObj; | ||||
75 | if (pRefObj != nullptr) { | ||||
76 | pRefObj->ReleaseRef(); | ||||
77 | } | ||||
78 | return *this; | ||||
79 | } | ||||
80 | |||||
81 | SvRef & operator =(SvRef && rObj) | ||||
82 | { | ||||
83 | if (pObj != nullptr) { | ||||
84 | pObj->ReleaseRef(); | ||||
85 | } | ||||
86 | pObj = rObj.pObj; | ||||
87 | rObj.pObj = nullptr; | ||||
88 | return *this; | ||||
89 | } | ||||
90 | |||||
91 | bool is() const { return pObj != nullptr; } | ||||
92 | |||||
93 | explicit operator bool() const { return is(); } | ||||
94 | |||||
95 | T * get() const { return pObj; } | ||||
96 | |||||
97 | T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 97, __extension__ __PRETTY_FUNCTION__)); return pObj; } | ||||
98 | |||||
99 | T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 99, __extension__ __PRETTY_FUNCTION__)); return *pObj; } | ||||
100 | |||||
101 | bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; } | ||||
102 | bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); } | ||||
103 | |||||
104 | private: | ||||
105 | T * pObj; | ||||
106 | }; | ||||
107 | |||||
108 | /** | ||||
109 | * This implements similar functionality to std::make_shared. | ||||
110 | */ | ||||
111 | template<typename T, typename... Args> | ||||
112 | SvRef<T> make_ref(Args&& ... args) | ||||
113 | { | ||||
114 | return SvRef<T>(new T(std::forward<Args>(args)...)); | ||||
115 | } | ||||
116 | |||||
117 | } | ||||
118 | |||||
119 | /** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */ | ||||
120 | class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase | ||||
121 | { | ||||
122 | // work around a clang 3.5 optimization bug: if the bNoDelete is *first* | ||||
123 | // it mis-compiles "if (--nRefCount == 0)" and never deletes any object | ||||
124 | unsigned int nRefCount : 31; | ||||
125 | // the only reason this is not bool is because MSVC cannot handle mixed type bitfields | ||||
126 | unsigned int bNoDelete : 1; | ||||
127 | |||||
128 | protected: | ||||
129 | virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE; | ||||
130 | |||||
131 | public: | ||||
132 | SvRefBase() : nRefCount(0), bNoDelete(1) {} | ||||
133 | SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {} | ||||
134 | |||||
135 | SvRefBase & operator=(const SvRefBase &) { return *this; } | ||||
136 | |||||
137 | void RestoreNoDelete() | ||||
138 | { bNoDelete = 1; } | ||||
139 | |||||
140 | void AddNextRef() | ||||
141 | { | ||||
142 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 142, __extension__ __PRETTY_FUNCTION__)); | ||||
143 | ++nRefCount; | ||||
144 | } | ||||
145 | |||||
146 | void AddFirstRef() | ||||
147 | { | ||||
148 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 148, __extension__ __PRETTY_FUNCTION__)); | ||||
149 | if( bNoDelete ) | ||||
150 | bNoDelete = 0; | ||||
151 | ++nRefCount; | ||||
152 | } | ||||
153 | |||||
154 | void ReleaseRef() | ||||
155 | { | ||||
156 | assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail ("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 156, __extension__ __PRETTY_FUNCTION__)); | ||||
157 | if( --nRefCount == 0 && !bNoDelete
| ||||
158 | { | ||||
159 | // I'm not sure about the original purpose of this line, but right now | ||||
160 | // it serves the purpose that anything that attempts to do an AddRef() | ||||
161 | // after an object is deleted will trip an assert. | ||||
162 | nRefCount = 1 << 30; | ||||
163 | delete this; | ||||
164 | } | ||||
165 | } | ||||
166 | |||||
167 | unsigned int GetRefCount() const | ||||
168 | { return nRefCount; } | ||||
169 | }; | ||||
170 | |||||
171 | template<typename T> | ||||
172 | class SvCompatWeakBase; | ||||
173 | |||||
174 | /** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T. | ||||
175 | */ | ||||
176 | template<typename T> | ||||
177 | class SvCompatWeakHdl final : public SvRefBase | ||||
178 | { | ||||
179 | friend class SvCompatWeakBase<T>; | ||||
180 | T* _pObj; | ||||
181 | |||||
182 | SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {} | ||||
183 | |||||
184 | public: | ||||
185 | void ResetWeakBase( ) { _pObj = nullptr; } | ||||
186 | T* GetObj() { return _pObj; } | ||||
187 | }; | ||||
188 | |||||
189 | /** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame. | ||||
190 | Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted. | ||||
191 | */ | ||||
192 | template<typename T> | ||||
193 | class SvCompatWeakBase | ||||
194 | { | ||||
195 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; | ||||
196 | |||||
197 | public: | ||||
198 | /** Does not use initializer due to compiler warnings, | ||||
199 | because the lifetime of the _xHdl object can exceed the lifetime of this class. | ||||
200 | */ | ||||
201 | SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); } | ||||
202 | |||||
203 | ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); } | ||||
204 | |||||
205 | SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); } | ||||
206 | }; | ||||
207 | |||||
208 | /** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak. | ||||
209 | */ | ||||
210 | template<typename T> | ||||
211 | class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef | ||||
212 | { | ||||
213 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; | ||||
214 | public: | ||||
215 | SvCompatWeakRef( ) {} | ||||
216 | SvCompatWeakRef( T* pObj ) | ||||
217 | { if( pObj ) _xHdl = pObj->GetHdl(); } | ||||
218 | #if defined(__COVERITY__) | ||||
219 | ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {} | ||||
220 | #endif | ||||
221 | SvCompatWeakRef& operator = ( T * pObj ) | ||||
222 | { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; } | ||||
223 | bool is() const | ||||
224 | { return _xHdl.is() && _xHdl->GetObj(); } | ||||
225 | explicit operator bool() const { return is(); } | ||||
226 | T* operator -> () const | ||||
227 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } | ||||
228 | operator T* () const | ||||
229 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } | ||||
230 | }; | ||||
231 | |||||
232 | #endif | ||||
233 | |||||
234 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |