ITEM: Refactor ItemType
[LibreOffice.git] / sw / source / ui / dbui / mmlayoutpage.cxx
blob4948cdfe5c59f89d3b8a825c938b8159ecb95307
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <swtypes.hxx>
21 #include "mmlayoutpage.hxx"
22 #include <mailmergewizard.hxx>
23 #include <mmconfigitem.hxx>
24 #include <mailmergehelper.hxx>
25 #include <unotools.hxx>
26 #include <comphelper/string.hxx>
27 #include <comphelper/propertyvalue.hxx>
28 #include <comphelper/servicehelper.hxx>
29 #include <i18nutil/unicode.hxx>
30 #include <unotools/tempfile.hxx>
31 #include <uitool.hxx>
32 #include <view.hxx>
33 #include <swundo.hxx>
34 #include <sfx2/docfilt.hxx>
35 #include <sfx2/fcontnr.hxx>
36 #include <svtools/unitconv.hxx>
37 #include <com/sun/star/view/XViewSettingsSupplier.hpp>
38 #include <com/sun/star/view/DocumentZoomType.hpp>
39 #include <fldmgr.hxx>
40 #include <fldbas.hxx>
41 #include <unotxdoc.hxx>
42 #include <docsh.hxx>
43 #include <doc.hxx>
44 #include <wrtsh.hxx>
45 #include <fmtsrnd.hxx>
46 #include <pagedesc.hxx>
47 #include <fmtanchr.hxx>
48 #include <fmtornt.hxx>
49 #include <fmtfsize.hxx>
50 #include <editeng/boxitem.hxx>
51 #include <osl/diagnose.h>
52 #include <osl/file.hxx>
53 #include <vcl/settings.hxx>
54 #include <unoprnms.hxx>
56 #include <dbui.hrc>
58 using namespace osl;
59 using namespace ::com::sun::star;
60 using namespace ::com::sun::star::uno;
61 using namespace ::com::sun::star::text;
62 using namespace ::com::sun::star::frame;
63 using namespace ::com::sun::star::view;
65 constexpr tools::Long DEFAULT_LEFT_DISTANCE = o3tl::toTwips(25, o3tl::Length::mm); // 2,5 cm
66 constexpr tools::Long DEFAULT_TOP_DISTANCE = o3tl::toTwips(55, o3tl::Length::mm); // 5,5 cm
67 constexpr tools::Long GREETING_TOP_DISTANCE = o3tl::toTwips(125, o3tl::Length::mm); //12,5 cm
68 constexpr tools::Long DEFAULT_ADDRESS_WIDTH = o3tl::toTwips(75, o3tl::Length::mm); // 7,5 cm
69 constexpr tools::Long DEFAULT_ADDRESS_HEIGHT = o3tl::toTwips(35, o3tl::Length::mm); // 3,5cm
71 SwMailMergeLayoutPage::SwMailMergeLayoutPage(weld::Container* pPage, SwMailMergeWizard* pWizard)
72 : vcl::OWizardPage(pPage, pWizard, u"modules/swriter/ui/mmlayoutpage.ui"_ustr, u"MMLayoutPage"_ustr)
73 , m_pExampleWrtShell(nullptr)
74 , m_pAddressBlockFormat(nullptr)
75 , m_bIsGreetingInserted(false)
76 , m_pWizard(pWizard)
77 , m_xPosition(m_xBuilder->weld_container(u"addresspos"_ustr))
78 , m_xAlignToBodyCB(m_xBuilder->weld_check_button(u"align"_ustr))
79 , m_xLeftFT(m_xBuilder->weld_label(u"leftft"_ustr))
80 , m_xLeftMF(m_xBuilder->weld_metric_spin_button(u"left"_ustr, FieldUnit::CM))
81 , m_xTopMF(m_xBuilder->weld_metric_spin_button(u"top"_ustr, FieldUnit::CM))
82 , m_xGreetingLine(m_xBuilder->weld_container(u"greetingspos"_ustr))
83 , m_xUpPB(m_xBuilder->weld_button(u"up"_ustr))
84 , m_xDownPB(m_xBuilder->weld_button(u"down"_ustr))
85 , m_xZoomLB(m_xBuilder->weld_combo_box(u"zoom"_ustr))
87 std::shared_ptr<const SfxFilter> pSfxFlt =
88 SwDocShell::Factory().GetFilterContainer()->
89 GetFilter4FilterName(u"writer8"_ustr, SfxFilterFlags::EXPORT);
91 //save the current document into a temporary file
93 //temp file needs its own block
94 //creating with extension is not supported by a static method :-(
95 OUString const sExt(
96 comphelper::string::stripStart(pSfxFlt->GetDefaultExtension(),'*'));
97 utl::TempFileNamed aTempFile( u"", true, sExt );
98 aTempFile.EnableKillingFile();
99 m_sExampleURL = aTempFile.GetURL();
101 SwView* pView = m_pWizard->GetSwView();
102 // Don't save embedded data set! It would steal it from current document.
103 uno::Sequence< beans::PropertyValue > aValues =
105 comphelper::makePropertyValue(u"FilterName"_ustr, pSfxFlt->GetFilterName()),
106 comphelper::makePropertyValue(u"NoEmbDataSet"_ustr, true)
109 uno::Reference< frame::XStorable > xStore( pView->GetDocShell()->GetModel(), uno::UNO_QUERY);
110 xStore->storeToURL( m_sExampleURL, aValues );
112 Link<SwOneExampleFrame&,void> aLink(LINK(this, SwMailMergeLayoutPage, PreviewLoadedHdl_Impl));
113 m_xExampleFrame.reset(new SwOneExampleFrame(EX_SHOW_DEFAULT_PAGE, &aLink, &m_sExampleURL));
114 m_xExampleContainerWIN.reset(new weld::CustomWeld(*m_xBuilder, u"example"_ustr, *m_xExampleFrame));
116 Size aSize = m_xExampleFrame->GetDrawingArea()->get_ref_device().LogicToPixel(
117 Size(124, 159), MapMode(MapUnit::MapAppFont));
118 m_xExampleFrame->set_size_request(aSize.Width(), aSize.Height());
120 m_xExampleContainerWIN->hide();
122 m_xLeftMF->set_value(m_xLeftMF->normalize(DEFAULT_LEFT_DISTANCE), FieldUnit::TWIP);
123 m_xTopMF->set_value(m_xTopMF->normalize(DEFAULT_TOP_DISTANCE), FieldUnit::TWIP);
125 const LanguageTag& rLang = Application::GetSettings().GetUILanguageTag();
126 m_xZoomLB->append_text(unicode::formatPercent(50, rLang));
127 m_xZoomLB->append_text(unicode::formatPercent(75, rLang));
128 m_xZoomLB->append_text(unicode::formatPercent(100, rLang));
129 m_xZoomLB->set_active(0); //page size
130 m_xZoomLB->connect_changed(LINK(this, SwMailMergeLayoutPage, ZoomHdl_Impl));
132 Link<weld::MetricSpinButton&,void> aFrameHdl = LINK(this, SwMailMergeLayoutPage, ChangeAddressHdl_Impl);
133 m_xLeftMF->connect_value_changed(aFrameHdl);
134 m_xTopMF->connect_value_changed(aFrameHdl);
136 FieldUnit eFieldUnit = ::GetDfltMetric(false);
137 ::SetFieldUnit( *m_xLeftMF, eFieldUnit );
138 ::SetFieldUnit( *m_xTopMF, eFieldUnit );
140 Link<weld::Button&,void> aUpDownHdl = LINK(this, SwMailMergeLayoutPage, GreetingsHdl_Impl );
141 m_xUpPB->connect_clicked(aUpDownHdl);
142 m_xDownPB->connect_clicked(aUpDownHdl);
143 m_xAlignToBodyCB->connect_toggled(LINK(this, SwMailMergeLayoutPage, AlignToTextHdl_Impl));
144 m_xAlignToBodyCB->set_active(true);
147 SwMailMergeLayoutPage::~SwMailMergeLayoutPage()
149 File::remove( m_sExampleURL );
152 void SwMailMergeLayoutPage::Activate()
154 SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem();
155 bool bGreetingLine = rConfigItem.IsGreetingLine(false) && !rConfigItem.IsGreetingInserted();
156 bool bAddressBlock = rConfigItem.IsAddressBlock() && !rConfigItem.IsAddressInserted();
158 m_xPosition->set_sensitive(bAddressBlock);
159 AlignToTextHdl_Impl(*m_xAlignToBodyCB);
161 m_xGreetingLine->set_sensitive(bGreetingLine);
163 //check if greeting and/or address frame have to be inserted/removed
164 if(!m_pExampleWrtShell) // initially there's nothing to check
165 return;
167 if(!rConfigItem.IsGreetingInserted() &&
168 m_bIsGreetingInserted != bGreetingLine )
170 if( m_bIsGreetingInserted )
172 m_pExampleWrtShell->DelFullPara();
173 m_bIsGreetingInserted = false;
175 else
177 InsertGreeting(*m_pExampleWrtShell, m_pWizard->GetConfigItem(), true);
178 m_bIsGreetingInserted = true;
181 if(!rConfigItem.IsAddressInserted() &&
182 rConfigItem.IsAddressBlock() != ( nullptr != m_pAddressBlockFormat ))
184 if( m_pAddressBlockFormat )
186 m_pExampleWrtShell->Push();
187 m_pExampleWrtShell->GotoFly( m_pAddressBlockFormat->GetName() );
188 m_pExampleWrtShell->DelRight();
189 m_pAddressBlockFormat = nullptr;
190 m_pExampleWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
192 else
194 tools::Long nLeft = static_cast< tools::Long >(m_xLeftMF->denormalize(m_xLeftMF->get_value(FieldUnit::TWIP)));
195 tools::Long nTop = static_cast< tools::Long >(m_xTopMF->denormalize(m_xTopMF->get_value(FieldUnit::TWIP)));
196 m_pAddressBlockFormat = InsertAddressFrame(
197 *m_pExampleWrtShell, m_pWizard->GetConfigItem(),
198 Point(nLeft, nTop),
199 m_xAlignToBodyCB->get_active(), true);
202 m_xExampleFrame->Invalidate();
205 bool SwMailMergeLayoutPage::commitPage(::vcl::WizardTypes::CommitPageReason eReason)
207 //now insert the frame and the greeting
208 SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem();
209 if (eReason == ::vcl::WizardTypes::eTravelForward || eReason == ::vcl::WizardTypes::eFinish)
211 tools::Long nLeft = static_cast< tools::Long >(m_xLeftMF->denormalize(m_xLeftMF->get_value(FieldUnit::TWIP)));
212 tools::Long nTop = static_cast< tools::Long >(m_xTopMF->denormalize(m_xTopMF->get_value(FieldUnit::TWIP)));
213 InsertAddressAndGreeting(
214 m_pWizard->GetSwView(),
215 rConfigItem,
216 Point(nLeft, nTop),
217 m_xAlignToBodyCB->get_active());
219 return true;
222 SwFrameFormat* SwMailMergeLayoutPage::InsertAddressAndGreeting(SwView const * pView,
223 SwMailMergeConfigItem& rConfigItem,
224 const Point& rAddressPosition,
225 bool bAlignToBody)
227 SwFrameFormat* pAddressBlockFormat = nullptr;
228 pView->GetWrtShell().StartUndo(SwUndoId::INSERT);
229 if(rConfigItem.IsAddressBlock() && !rConfigItem.IsAddressInserted())
231 //insert the frame
232 Point aAddressPosition(DEFAULT_LEFT_DISTANCE, DEFAULT_TOP_DISTANCE);
233 if(rAddressPosition.X() > 0 && rAddressPosition.Y() > 0)
234 aAddressPosition = rAddressPosition;
235 pAddressBlockFormat = InsertAddressFrame( pView->GetWrtShell(),
236 rConfigItem,
237 aAddressPosition, bAlignToBody, false);
238 rConfigItem.SetAddressInserted();
240 //now the greeting
241 if(rConfigItem.IsGreetingLine(false) && !rConfigItem.IsGreetingInserted())
243 InsertGreeting( pView->GetWrtShell(), rConfigItem, false);
244 rConfigItem.SetGreetingInserted();
246 pView->GetWrtShell().EndUndo(SwUndoId::INSERT);
247 return pAddressBlockFormat;
250 SwFrameFormat* SwMailMergeLayoutPage::InsertAddressFrame(
251 SwWrtShell& rShell,
252 SwMailMergeConfigItem const & rConfigItem,
253 const Point& rDestination,
254 bool bAlignLeft,
255 bool bExample)
257 // insert the address block and the greeting line
258 SfxItemSetFixed<
259 RES_FRM_SIZE, RES_FRM_SIZE,
260 RES_SURROUND, RES_ANCHOR,
261 RES_BOX, RES_BOX> aSet( rShell.GetAttrPool() );
262 aSet.Put(SwFormatAnchor(RndStdIds::FLY_AT_PAGE, 1));
263 if(bAlignLeft)
264 aSet.Put(SwFormatHoriOrient( 0, text::HoriOrientation::NONE, text::RelOrientation::PAGE_PRINT_AREA ));
265 else
266 aSet.Put(SwFormatHoriOrient( rDestination.X(), text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME ));
267 aSet.Put(SwFormatVertOrient( rDestination.Y(), text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME ));
268 aSet.Put(SwFormatFrameSize( SwFrameSize::Minimum, DEFAULT_ADDRESS_WIDTH, DEFAULT_ADDRESS_HEIGHT ));
269 // the example gets a border around the frame, the real document doesn't get one
270 if(!bExample)
271 aSet.Put(SvxBoxItem( RES_BOX ));
272 aSet.Put(SwFormatSurround( css::text::WrapTextMode_NONE ));
274 rShell.NewFlyFrame(aSet, true );
275 SwFrameFormat* pRet = rShell.GetFlyFrameFormat();
276 OSL_ENSURE( pRet, "Fly not inserted" );
278 rShell.UnSelectFrame();
279 const Sequence< OUString> aBlocks = rConfigItem.GetAddressBlocks();
280 if(bExample)
282 rShell.Insert(aBlocks[0]);
284 else
286 //the placeholders should be replaced by the appropriate fields
287 SwFieldMgr aFieldMgr(&rShell);
288 //create a database string source.command.commandtype.column
289 const SwDBData& rData = rConfigItem.GetCurrentDBData();
290 OUString sDBName(rData.sDataSource + OUStringChar(DB_DELIM)
291 + rData.sCommand + OUStringChar(DB_DELIM));
292 const OUString sDatabaseConditionPrefix(sDBName.replace(DB_DELIM, '.'));
293 sDBName += OUString::number(rData.nCommandType) + OUStringChar(DB_DELIM);
295 // if only the country is in an address line the
296 // paragraph has to be hidden depending on the
297 // IsIncludeCountry()/GetExcludeCountry() settings
299 bool bIncludeCountry = rConfigItem.IsIncludeCountry();
300 bool bHideEmptyParagraphs = rConfigItem.IsHideEmptyParagraphs();
301 const OUString& rExcludeCountry = rConfigItem.GetExcludeCountry();
302 bool bSpecialReplacementForCountry = (!bIncludeCountry || !rExcludeCountry.isEmpty());
304 const std::vector<std::pair<OUString, int>>& rHeaders = rConfigItem.GetDefaultAddressHeaders();
305 Sequence< OUString> aAssignment =
306 rConfigItem.GetColumnAssignment( rConfigItem.GetCurrentDBData() );
307 const OUString* pAssignment = aAssignment.getConstArray();
308 const OUString sCountryColumn(
309 (aAssignment.getLength() > MM_PART_COUNTRY && !aAssignment[MM_PART_COUNTRY].isEmpty())
310 ? aAssignment[MM_PART_COUNTRY]
311 : rHeaders[MM_PART_COUNTRY].first);
313 OUString sHideParagraphsExpression;
314 SwAddressIterator aIter(aBlocks[0]);
315 while(aIter.HasMore())
317 SwMergeAddressItem aItem = aIter.Next();
318 if(aItem.bIsColumn)
320 OUString sConvertedColumn = aItem.sText;
321 auto nSize = std::min(static_cast<sal_uInt32>(rHeaders.size()),
322 static_cast<sal_uInt32>(aAssignment.getLength()));
323 for(sal_uInt32 nColumn = 0; nColumn < nSize; ++nColumn)
325 if (rHeaders[nColumn].first == aItem.sText &&
326 !pAssignment[nColumn].isEmpty())
328 sConvertedColumn = pAssignment[nColumn];
329 break;
332 const OUString sDB(sDBName + sConvertedColumn);
334 if(!sHideParagraphsExpression.isEmpty())
335 sHideParagraphsExpression += " AND ";
336 sHideParagraphsExpression += "![" + sDatabaseConditionPrefix + sConvertedColumn + "]";
338 if( bSpecialReplacementForCountry && sCountryColumn == sConvertedColumn )
340 // now insert a hidden paragraph field
341 if( !rExcludeCountry.isEmpty() )
343 const OUString sExpression("[" + sDatabaseConditionPrefix + sCountryColumn + "]");
344 SwInsertField_Data aData(SwFieldTypesEnum::ConditionalText, 0,
345 sExpression + " != \"" + rExcludeCountry + "\"",
346 sExpression,
347 0, &rShell );
348 aFieldMgr.InsertField( aData );
350 else
352 SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, u""_ustr, u""_ustr, 0, &rShell );
353 aFieldMgr.InsertField( aData );
356 else
358 SwInsertField_Data aData(SwFieldTypesEnum::Database, 0, sDB, OUString(), 0, &rShell);
359 aFieldMgr.InsertField( aData );
362 else if(!aItem.bIsReturn)
364 rShell.Insert(aItem.sText);
366 else
368 if(bHideEmptyParagraphs)
370 SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sHideParagraphsExpression, OUString(), 0, &rShell);
371 aFieldMgr.InsertField( aData );
373 sHideParagraphsExpression.clear();
374 //now add a new paragraph
375 rShell.SplitNode();
378 if(bHideEmptyParagraphs && !sHideParagraphsExpression.isEmpty())
380 SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sHideParagraphsExpression, OUString(), 0, &rShell);
381 aFieldMgr.InsertField( aData );
384 return pRet;
387 void SwMailMergeLayoutPage::InsertGreeting(SwWrtShell& rShell, SwMailMergeConfigItem const & rConfigItem, bool bExample)
389 //set the cursor to the desired position - if no text content is here then
390 //new paragraphs are inserted
391 const SwRect& rPageRect = rShell.GetAnyCurRect(CurRectType::Page);
392 const Point aGreetingPos( DEFAULT_LEFT_DISTANCE + rPageRect.Left(), GREETING_TOP_DISTANCE );
394 const bool bRet = rShell.SetShadowCursorPos( aGreetingPos, SwFillMode::TabSpace );
396 if(!bRet)
398 //there's already text at the desired position
399 //go to start of the doc, directly!
400 rShell.SttEndDoc(true);
401 //and go by paragraph until the position is reached
402 tools::Long nYPos = rShell.GetCharRect().Top();
403 while(nYPos < GREETING_TOP_DISTANCE)
405 if(!rShell.FwdPara())
406 break;
407 nYPos = rShell.GetCharRect().Top();
409 //text needs to be appended
410 while(nYPos < GREETING_TOP_DISTANCE)
412 if(!rShell.AppendTextNode())
413 break;
414 nYPos = rShell.GetCharRect().Top();
417 else
419 //we may end up inside of a paragraph if the left margin is not at DEFAULT_LEFT_DISTANCE
420 rShell.MovePara(GoCurrPara, fnParaStart);
422 bool bSplitNode = !rShell.IsEndPara();
423 SwNodeOffset nMoves(rConfigItem.GetGreetingMoves());
424 if( !bExample && SwNodeOffset(0) != nMoves )
426 if(nMoves < SwNodeOffset(0))
428 rShell.MoveParagraph( nMoves );
430 else
431 while(nMoves)
433 bool bMoved = rShell.MoveParagraph();
434 if(!bMoved)
436 //insert a new paragraph before the greeting line
437 rShell.SplitNode();
439 --nMoves;
442 //now insert the greeting text - if we have any?
443 const bool bIndividual = rConfigItem.IsIndividualGreeting(false);
444 if(bIndividual)
446 //lock expression fields - prevents hiding of the paragraph to insert into
447 rShell.LockExpFields();
448 if(bExample)
450 for(sal_Int8 eGender = SwMailMergeConfigItem::FEMALE;
451 eGender <= SwMailMergeConfigItem::NEUTRAL; ++eGender)
453 Sequence< OUString > aEntries =
454 rConfigItem.GetGreetings(static_cast<SwMailMergeConfigItem::Gender>(eGender));
455 sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(static_cast<SwMailMergeConfigItem::Gender>(eGender));
456 if( nCurrent >= 0 && nCurrent < aEntries.getLength())
458 // Greeting
459 rShell.Insert(aEntries[nCurrent]);
460 break;
464 else
466 SwFieldMgr aFieldMgr(&rShell);
467 //three paragraphs, each with an appropriate hidden paragraph field
468 //are to be inserted
470 //name of the gender column
471 const OUString sGenderColumn = rConfigItem.GetAssignedColumn(MM_PART_GENDER);
472 const OUString sNameColumn = rConfigItem.GetAssignedColumn(MM_PART_LASTNAME);
474 const OUString& rFemaleGenderValue = rConfigItem.GetFemaleGenderValue();
475 bool bHideEmptyParagraphs = rConfigItem.IsHideEmptyParagraphs();
476 const SwDBData& rData = rConfigItem.GetCurrentDBData();
477 const OUString sCommonBase(rData.sDataSource + "." + rData.sCommand + ".");
478 const OUString sConditionBase("[" + sCommonBase + sGenderColumn + "]");
479 const OUString sNameColumnBase("[" + sCommonBase + sNameColumn + "]");
481 const OUString sDBName(rData.sDataSource + OUStringChar(DB_DELIM)
482 + rData.sCommand + OUStringChar(DB_DELIM)
483 + OUString::number(rData.nCommandType) + OUStringChar(DB_DELIM));
485 // Female: [database.sGenderColumn] != "rFemaleGenderValue" && [database.NameColumn]
486 // Male: [database.sGenderColumn] == "rFemaleGenderValue" && [database.rGenderColumn]
487 // Neutral: [database.sNameColumn]
488 OSL_ENSURE(!sGenderColumn.isEmpty() && !rFemaleGenderValue.isEmpty(),
489 "gender settings not available - how to form the condition?");
490 //column used as lastname
491 for(sal_Int8 eGender = SwMailMergeConfigItem::FEMALE;
492 eGender <= SwMailMergeConfigItem::NEUTRAL; ++eGender)
494 Sequence< OUString> aEntries = rConfigItem.GetGreetings(static_cast<SwMailMergeConfigItem::Gender>(eGender));
495 sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(static_cast<SwMailMergeConfigItem::Gender>(eGender));
496 if( nCurrent >= 0 && nCurrent < aEntries.getLength())
498 const OUString& sGreeting = aEntries[nCurrent];
499 OUString sCondition;
500 OUString sHideParagraphsExpression;
501 switch(eGender)
503 case SwMailMergeConfigItem::FEMALE:
504 sCondition = sConditionBase + " != \"" + rFemaleGenderValue
505 + "\" OR NOT " + sNameColumnBase;
506 sHideParagraphsExpression = "!" + sNameColumnBase;
507 break;
508 case SwMailMergeConfigItem::MALE:
509 sCondition = sConditionBase + " == \"" + rFemaleGenderValue
510 + "\" OR NOT " + sNameColumnBase;
511 break;
512 case SwMailMergeConfigItem::NEUTRAL:
513 sCondition = sNameColumnBase;
514 break;
517 if(bHideEmptyParagraphs && !sHideParagraphsExpression.isEmpty())
519 OUString sComplete = "(" + sCondition + ") OR (" + sHideParagraphsExpression + ")";
520 SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sComplete, OUString(), 0, &rShell);
521 aFieldMgr.InsertField( aData );
523 else
525 SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sCondition, OUString(), 0, &rShell);
526 aFieldMgr.InsertField( aData );
528 //now the text has to be inserted
529 const std::vector<std::pair<OUString, int>>& rHeaders = rConfigItem.GetDefaultAddressHeaders();
530 Sequence< OUString> aAssignment =
531 rConfigItem.GetColumnAssignment( rConfigItem.GetCurrentDBData() );
532 const OUString* pAssignment = aAssignment.getConstArray();
533 SwAddressIterator aIter(sGreeting);
534 while(aIter.HasMore())
536 SwMergeAddressItem aItem = aIter.Next();
537 if(aItem.bIsColumn)
539 OUString sConvertedColumn = aItem.sText;
540 auto nSize = std::min(static_cast<sal_uInt32>(rHeaders.size()),
541 static_cast<sal_uInt32>(aAssignment.getLength()));
542 for(sal_uInt32 nColumn = 0; nColumn < nSize; ++nColumn)
544 if (rHeaders[nColumn].first == aItem.sText &&
545 !pAssignment[nColumn].isEmpty())
547 sConvertedColumn = pAssignment[nColumn];
548 break;
551 SwInsertField_Data aData(SwFieldTypesEnum::Database, 0,
552 sDBName + sConvertedColumn,
553 OUString(), 0, &rShell);
554 aFieldMgr.InsertField( aData );
556 else
558 rShell.Insert(aItem.sText);
561 //now add a new paragraph
562 rShell.SplitNode();
567 rShell.UnlockExpFields();
569 else
571 Sequence< OUString> aEntries = rConfigItem.GetGreetings(SwMailMergeConfigItem::NEUTRAL);
572 sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(SwMailMergeConfigItem::NEUTRAL);
573 // Greeting
574 rShell.Insert(( nCurrent >= 0 && nCurrent < aEntries.getLength() )
575 ? aEntries[nCurrent] : OUString());
577 // now insert a new paragraph here if necessary
578 if(bSplitNode)
580 rShell.Push();
581 rShell.SplitNode();
582 rShell.Pop(SwCursorShell::PopMode::DeleteCurrent);
584 //put the cursor to the start of the paragraph
585 rShell.SttPara();
587 OSL_ENSURE(nullptr == rShell.GetTableFormat(), "What to do with a table here?");
590 IMPL_LINK_NOARG(SwMailMergeLayoutPage, PreviewLoadedHdl_Impl, SwOneExampleFrame&, void)
592 m_xExampleContainerWIN->show();
594 rtl::Reference< SwXTextDocument > & xModel = m_xExampleFrame->GetModel();
595 //now the ViewOptions should be set properly
596 Reference< XViewSettingsSupplier > xSettings(xModel->getCurrentController(), UNO_QUERY);
597 m_xViewProperties = xSettings->getViewSettings();
598 SwDocShell* pDocShell = xModel->GetDocShell();
599 m_pExampleWrtShell = pDocShell->GetWrtShell();
600 OSL_ENSURE(m_pExampleWrtShell, "No SwWrtShell found!");
601 if(!m_pExampleWrtShell)
602 return;
604 SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem();
605 if(rConfigItem.IsAddressBlock())
607 m_pAddressBlockFormat = InsertAddressFrame(
608 *m_pExampleWrtShell, rConfigItem,
609 Point(DEFAULT_LEFT_DISTANCE, DEFAULT_TOP_DISTANCE),
610 m_xAlignToBodyCB->get_active(), true);
612 if(rConfigItem.IsGreetingLine(false))
614 InsertGreeting(*m_pExampleWrtShell, rConfigItem, true);
615 m_bIsGreetingInserted = true;
618 ZoomHdl_Impl(*m_xZoomLB);
620 const SwFormatFrameSize& rPageSize = m_pExampleWrtShell->GetPageDesc(
621 m_pExampleWrtShell->GetCurPageDesc()).GetMaster().GetFrameSize();
622 m_xLeftMF->set_max(rPageSize.GetWidth() - DEFAULT_LEFT_DISTANCE, FieldUnit::NONE);
623 m_xTopMF->set_max(rPageSize.GetHeight() - DEFAULT_TOP_DISTANCE, FieldUnit::NONE);
626 IMPL_LINK(SwMailMergeLayoutPage, ZoomHdl_Impl, weld::ComboBox&, rBox, void)
628 if (!m_pExampleWrtShell)
629 return;
631 sal_Int16 eType = DocumentZoomType::BY_VALUE;
632 short nZoom = 50;
633 switch (rBox.get_active())
635 case 0 : eType = DocumentZoomType::ENTIRE_PAGE; break;
636 case 1 : nZoom = 50; break;
637 case 2 : nZoom = 75; break;
638 case 3 : nZoom = 100; break;
640 Any aZoom;
641 aZoom <<= eType;
642 m_xViewProperties->setPropertyValue(UNO_NAME_ZOOM_TYPE, aZoom);
643 aZoom <<= nZoom;
644 m_xViewProperties->setPropertyValue(UNO_NAME_ZOOM_VALUE, aZoom);
646 m_xExampleFrame->Invalidate();
649 IMPL_LINK_NOARG(SwMailMergeLayoutPage, ChangeAddressHdl_Impl, weld::MetricSpinButton&, void)
651 if(!(m_pExampleWrtShell && m_pAddressBlockFormat))
652 return;
654 tools::Long nLeft = static_cast< tools::Long >(m_xLeftMF->denormalize(m_xLeftMF->get_value(FieldUnit::TWIP)));
655 tools::Long nTop = static_cast< tools::Long >(m_xTopMF->denormalize(m_xTopMF->get_value(FieldUnit::TWIP)));
657 SfxItemSetFixed<RES_VERT_ORIENT, RES_ANCHOR> aSet(
658 m_pExampleWrtShell->GetAttrPool());
659 if (m_xAlignToBodyCB->get_active())
660 aSet.Put(SwFormatHoriOrient( 0, text::HoriOrientation::NONE, text::RelOrientation::PAGE_PRINT_AREA ));
661 else
662 aSet.Put(SwFormatHoriOrient( nLeft, text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME ));
663 aSet.Put(SwFormatVertOrient( nTop, text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME ));
664 m_pExampleWrtShell->GetDoc()->SetFlyFrameAttr( *m_pAddressBlockFormat, aSet );
665 m_xExampleFrame->Invalidate();
668 IMPL_LINK(SwMailMergeLayoutPage, GreetingsHdl_Impl, weld::Button&, rButton, void)
670 bool bDown = &rButton == m_xDownPB.get();
671 bool bMoved = m_pExampleWrtShell->MoveParagraph( SwNodeOffset(bDown ? 1 : -1) );
672 if (bMoved || bDown)
673 m_pWizard->GetConfigItem().MoveGreeting(bDown ? 1 : -1 );
674 if(!bMoved && bDown)
676 //insert a new paragraph before the greeting line
677 m_pExampleWrtShell->SplitNode();
679 m_xExampleFrame->Invalidate();
682 IMPL_LINK(SwMailMergeLayoutPage, AlignToTextHdl_Impl, weld::Toggleable&, rBox, void)
684 bool bCheck = rBox.get_active() && rBox.get_sensitive();
685 m_xLeftFT->set_sensitive(!bCheck);
686 m_xLeftMF->set_sensitive(!bCheck);
687 ChangeAddressHdl_Impl( *m_xLeftMF );
690 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */