LibreOffice Module sw (master) 1
mmlayoutpage.cxx
Go to the documentation of this file.
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 <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>
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/file.hxx>
52#include <vcl/settings.hxx>
53#include <unoprnms.hxx>
54
55#include <dbui.hrc>
56
57using namespace osl;
58using namespace svt;
59using namespace ::com::sun::star;
60using namespace ::com::sun::star::uno;
61using namespace ::com::sun::star::text;
62using namespace ::com::sun::star::frame;
63using namespace ::com::sun::star::lang;
64using namespace ::com::sun::star::view;
65
71
73 : vcl::OWizardPage(pPage, pWizard, "modules/swriter/ui/mmlayoutpage.ui", "MMLayoutPage")
74 , m_pExampleWrtShell(nullptr)
75 , m_pAddressBlockFormat(nullptr)
76 , m_bIsGreetingInserted(false)
77 , m_pWizard(pWizard)
78 , m_xPosition(m_xBuilder->weld_container("addresspos"))
79 , m_xAlignToBodyCB(m_xBuilder->weld_check_button("align"))
80 , m_xLeftFT(m_xBuilder->weld_label("leftft"))
81 , m_xLeftMF(m_xBuilder->weld_metric_spin_button("left", FieldUnit::CM))
82 , m_xTopMF(m_xBuilder->weld_metric_spin_button("top", FieldUnit::CM))
83 , m_xGreetingLine(m_xBuilder->weld_container("greetingspos"))
84 , m_xUpPB(m_xBuilder->weld_button("up"))
85 , m_xDownPB(m_xBuilder->weld_button("down"))
86 , m_xZoomLB(m_xBuilder->weld_combo_box("zoom"))
87{
88 std::shared_ptr<const SfxFilter> pSfxFlt =
89 SwDocShell::Factory().GetFilterContainer()->
90 GetFilter4FilterName("writer8", SfxFilterFlags::EXPORT);
91
92 //save the current document into a temporary file
93 {
94 //temp file needs its own block
95 //creating with extension is not supported by a static method :-(
96 OUString const sExt(
97 comphelper::string::stripStart(pSfxFlt->GetDefaultExtension(),'*'));
98 utl::TempFileNamed aTempFile( u"", true, sExt );
99 aTempFile.EnableKillingFile();
100 m_sExampleURL = aTempFile.GetURL();
101 }
102 SwView* pView = m_pWizard->GetSwView();
103 // Don't save embedded data set! It would steal it from current document.
104 uno::Sequence< beans::PropertyValue > aValues =
105 {
106 comphelper::makePropertyValue("FilterName", pSfxFlt->GetFilterName()),
107 comphelper::makePropertyValue("NoEmbDataSet", true)
108 };
109
110 uno::Reference< frame::XStorable > xStore( pView->GetDocShell()->GetModel(), uno::UNO_QUERY);
111 xStore->storeToURL( m_sExampleURL, aValues );
112
113 Link<SwOneExampleFrame&,void> aLink(LINK(this, SwMailMergeLayoutPage, PreviewLoadedHdl_Impl));
116
117 Size aSize = m_xExampleFrame->GetDrawingArea()->get_ref_device().LogicToPixel(
118 Size(124, 159), MapMode(MapUnit::MapAppFont));
119 m_xExampleFrame->set_size_request(aSize.Width(), aSize.Height());
120
122
123 m_xLeftMF->set_value(m_xLeftMF->normalize(DEFAULT_LEFT_DISTANCE), FieldUnit::TWIP);
124 m_xTopMF->set_value(m_xTopMF->normalize(DEFAULT_TOP_DISTANCE), FieldUnit::TWIP);
125
127 m_xZoomLB->append_text(unicode::formatPercent(50, rLang));
128 m_xZoomLB->append_text(unicode::formatPercent(75, rLang));
129 m_xZoomLB->append_text(unicode::formatPercent(100, rLang));
130 m_xZoomLB->set_active(0); //page size
131 m_xZoomLB->connect_changed(LINK(this, SwMailMergeLayoutPage, ZoomHdl_Impl));
132
133 Link<weld::MetricSpinButton&,void> aFrameHdl = LINK(this, SwMailMergeLayoutPage, ChangeAddressHdl_Impl);
134 m_xLeftMF->connect_value_changed(aFrameHdl);
135 m_xTopMF->connect_value_changed(aFrameHdl);
136
137 FieldUnit eFieldUnit = ::GetDfltMetric(false);
138 ::SetFieldUnit( *m_xLeftMF, eFieldUnit );
139 ::SetFieldUnit( *m_xTopMF, eFieldUnit );
140
141 Link<weld::Button&,void> aUpDownHdl = LINK(this, SwMailMergeLayoutPage, GreetingsHdl_Impl );
142 m_xUpPB->connect_clicked(aUpDownHdl);
143 m_xDownPB->connect_clicked(aUpDownHdl);
144 m_xAlignToBodyCB->connect_toggled(LINK(this, SwMailMergeLayoutPage, AlignToTextHdl_Impl));
145 m_xAlignToBodyCB->set_active(true);
146}
147
149{
150 File::remove( m_sExampleURL );
151}
152
154{
156 bool bGreetingLine = rConfigItem.IsGreetingLine(false) && !rConfigItem.IsGreetingInserted();
157 bool bAddressBlock = rConfigItem.IsAddressBlock() && !rConfigItem.IsAddressInserted();
158
159 m_xPosition->set_sensitive(bAddressBlock);
160 AlignToTextHdl_Impl(*m_xAlignToBodyCB);
161
162 m_xGreetingLine->set_sensitive(bGreetingLine);
163
164 //check if greeting and/or address frame have to be inserted/removed
165 if(!m_pExampleWrtShell) // initially there's nothing to check
166 return;
167
168 if(!rConfigItem.IsGreetingInserted() &&
169 m_bIsGreetingInserted != bGreetingLine )
170 {
172 {
174 m_bIsGreetingInserted = false;
175 }
176 else
177 {
180 }
181 }
182 if(!rConfigItem.IsAddressInserted() &&
183 rConfigItem.IsAddressBlock() != ( nullptr != m_pAddressBlockFormat ))
184 {
186 {
190 m_pAddressBlockFormat = nullptr;
192 }
193 else
194 {
195 tools::Long nLeft = static_cast< tools::Long >(m_xLeftMF->denormalize(m_xLeftMF->get_value(FieldUnit::TWIP)));
196 tools::Long nTop = static_cast< tools::Long >(m_xTopMF->denormalize(m_xTopMF->get_value(FieldUnit::TWIP)));
199 Point(nLeft, nTop),
200 m_xAlignToBodyCB->get_active(), true);
201 }
202 }
203 m_xExampleFrame->Invalidate();
204}
205
207{
208 //now insert the frame and the greeting
210 if (eReason == ::vcl::WizardTypes::eTravelForward || eReason == ::vcl::WizardTypes::eFinish)
211 {
212 tools::Long nLeft = static_cast< tools::Long >(m_xLeftMF->denormalize(m_xLeftMF->get_value(FieldUnit::TWIP)));
213 tools::Long nTop = static_cast< tools::Long >(m_xTopMF->denormalize(m_xTopMF->get_value(FieldUnit::TWIP)));
216 rConfigItem,
217 Point(nLeft, nTop),
218 m_xAlignToBodyCB->get_active());
219 }
220 return true;
221}
222
224 SwMailMergeConfigItem& rConfigItem,
225 const Point& rAddressPosition,
226 bool bAlignToBody)
227{
228 SwFrameFormat* pAddressBlockFormat = nullptr;
230 if(rConfigItem.IsAddressBlock() && !rConfigItem.IsAddressInserted())
231 {
232 //insert the frame
234 if(rAddressPosition.X() > 0 && rAddressPosition.Y() > 0)
235 aAddressPosition = rAddressPosition;
236 pAddressBlockFormat = InsertAddressFrame( pView->GetWrtShell(),
237 rConfigItem,
238 aAddressPosition, bAlignToBody, false);
239 rConfigItem.SetAddressInserted();
240 }
241 //now the greeting
242 if(rConfigItem.IsGreetingLine(false) && !rConfigItem.IsGreetingInserted())
243 {
244 InsertGreeting( pView->GetWrtShell(), rConfigItem, false);
245 rConfigItem.SetGreetingInserted();
246 }
248 return pAddressBlockFormat;
249}
250
252 SwWrtShell& rShell,
253 SwMailMergeConfigItem const & rConfigItem,
254 const Point& rDestination,
255 bool bAlignLeft,
256 bool bExample)
257{
258 // insert the address block and the greeting line
262 RES_BOX, RES_BOX> aSet( rShell.GetAttrPool() );
263 aSet.Put(SwFormatAnchor(RndStdIds::FLY_AT_PAGE, 1));
264 if(bAlignLeft)
265 aSet.Put(SwFormatHoriOrient( 0, text::HoriOrientation::NONE, text::RelOrientation::PAGE_PRINT_AREA ));
266 else
267 aSet.Put(SwFormatHoriOrient( rDestination.X(), text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME ));
268 aSet.Put(SwFormatVertOrient( rDestination.Y(), text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME ));
270 // the example gets a border around the frame, the real document doesn't get one
271 if(!bExample)
272 aSet.Put(SvxBoxItem( RES_BOX ));
273 aSet.Put(SwFormatSurround( css::text::WrapTextMode_NONE ));
274
275 rShell.NewFlyFrame(aSet, true );
276 SwFrameFormat* pRet = rShell.GetFlyFrameFormat();
277 OSL_ENSURE( pRet, "Fly not inserted" );
278
279 rShell.UnSelectFrame();
280 const Sequence< OUString> aBlocks = rConfigItem.GetAddressBlocks();
281 if(bExample)
282 {
283 rShell.Insert(aBlocks[0]);
284 }
285 else
286 {
287 //the placeholders should be replaced by the appropriate fields
288 SwFieldMgr aFieldMgr(&rShell);
289 //create a database string source.command.commandtype.column
290 const SwDBData& rData = rConfigItem.GetCurrentDBData();
291 OUString sDBName(rData.sDataSource + OUStringChar(DB_DELIM)
292 + rData.sCommand + OUStringChar(DB_DELIM));
293 const OUString sDatabaseConditionPrefix(sDBName.replace(DB_DELIM, '.'));
294 sDBName += OUString::number(rData.nCommandType) + OUStringChar(DB_DELIM);
295
296 // if only the country is in an address line the
297 // paragraph has to be hidden depending on the
298 // IsIncludeCountry()/GetExcludeCountry() settings
299
300 bool bIncludeCountry = rConfigItem.IsIncludeCountry();
301 bool bHideEmptyParagraphs = rConfigItem.IsHideEmptyParagraphs();
302 const OUString rExcludeCountry = rConfigItem.GetExcludeCountry();
303 bool bSpecialReplacementForCountry = (!bIncludeCountry || !rExcludeCountry.isEmpty());
304
305 const std::vector<std::pair<OUString, int>>& rHeaders = rConfigItem.GetDefaultAddressHeaders();
306 Sequence< OUString> aAssignment =
307 rConfigItem.GetColumnAssignment( rConfigItem.GetCurrentDBData() );
308 const OUString* pAssignment = aAssignment.getConstArray();
309 const OUString sCountryColumn(
310 (aAssignment.getLength() > MM_PART_COUNTRY && !aAssignment[MM_PART_COUNTRY].isEmpty())
311 ? aAssignment[MM_PART_COUNTRY]
312 : rHeaders[MM_PART_COUNTRY].first);
313
314 OUString sHideParagraphsExpression;
315 SwAddressIterator aIter(aBlocks[0]);
316 while(aIter.HasMore())
317 {
318 SwMergeAddressItem aItem = aIter.Next();
319 if(aItem.bIsColumn)
320 {
321 OUString sConvertedColumn = aItem.sText;
322 auto nSize = std::min(static_cast<sal_uInt32>(rHeaders.size()),
323 static_cast<sal_uInt32>(aAssignment.getLength()));
324 for(sal_uInt32 nColumn = 0; nColumn < nSize; ++nColumn)
325 {
326 if (rHeaders[nColumn].first == aItem.sText &&
327 !pAssignment[nColumn].isEmpty())
328 {
329 sConvertedColumn = pAssignment[nColumn];
330 break;
331 }
332 }
333 const OUString sDB(sDBName + sConvertedColumn);
334
335 if(!sHideParagraphsExpression.isEmpty())
336 sHideParagraphsExpression += " AND ";
337 sHideParagraphsExpression += "![" + sDatabaseConditionPrefix + sConvertedColumn + "]";
338
339 if( bSpecialReplacementForCountry && sCountryColumn == sConvertedColumn )
340 {
341 // now insert a hidden paragraph field
342 if( !rExcludeCountry.isEmpty() )
343 {
344 const OUString sExpression("[" + sDatabaseConditionPrefix + sCountryColumn + "]");
346 sExpression + " != \"" + rExcludeCountry + "\"",
347 sExpression,
348 0, &rShell );
349 aFieldMgr.InsertField( aData );
350 }
351 else
352 {
354 aFieldMgr.InsertField( aData );
355 }
356 }
357 else
358 {
359 SwInsertField_Data aData(SwFieldTypesEnum::Database, 0, sDB, OUString(), 0, &rShell);
360 aFieldMgr.InsertField( aData );
361 }
362 }
363 else if(!aItem.bIsReturn)
364 {
365 rShell.Insert(aItem.sText);
366 }
367 else
368 {
369 if(bHideEmptyParagraphs)
370 {
371 SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sHideParagraphsExpression, OUString(), 0, &rShell);
372 aFieldMgr.InsertField( aData );
373 }
374 sHideParagraphsExpression.clear();
375 //now add a new paragraph
376 rShell.SplitNode();
377 }
378 }
379 if(bHideEmptyParagraphs && !sHideParagraphsExpression.isEmpty())
380 {
381 SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sHideParagraphsExpression, OUString(), 0, &rShell);
382 aFieldMgr.InsertField( aData );
383 }
384 }
385 return pRet;
386}
387
388void SwMailMergeLayoutPage::InsertGreeting(SwWrtShell& rShell, SwMailMergeConfigItem const & rConfigItem, bool bExample)
389{
390 //set the cursor to the desired position - if no text content is here then
391 //new paragraphs are inserted
392 const SwRect& rPageRect = rShell.GetAnyCurRect(CurRectType::Page);
393 const Point aGreetingPos( DEFAULT_LEFT_DISTANCE + rPageRect.Left(), GREETING_TOP_DISTANCE );
394
395 const bool bRet = rShell.SetShadowCursorPos( aGreetingPos, SwFillMode::TabSpace );
396
397 if(!bRet)
398 {
399 //there's already text at the desired position
400 //go to start of the doc, directly!
401 rShell.SttEndDoc(true);
402 //and go by paragraph until the position is reached
403 tools::Long nYPos = rShell.GetCharRect().Top();
404 while(nYPos < GREETING_TOP_DISTANCE)
405 {
406 if(!rShell.FwdPara())
407 break;
408 nYPos = rShell.GetCharRect().Top();
409 }
410 //text needs to be appended
411 while(nYPos < GREETING_TOP_DISTANCE)
412 {
413 if(!rShell.AppendTextNode())
414 break;
415 nYPos = rShell.GetCharRect().Top();
416 }
417 }
418 else
419 {
420 //we may end up inside of a paragraph if the left margin is not at DEFAULT_LEFT_DISTANCE
422 }
423 bool bSplitNode = !rShell.IsEndPara();
424 SwNodeOffset nMoves(rConfigItem.GetGreetingMoves());
425 if( !bExample && SwNodeOffset(0) != nMoves )
426 {
427 if(nMoves < SwNodeOffset(0))
428 {
429 rShell.MoveParagraph( nMoves );
430 }
431 else
432 while(nMoves)
433 {
434 bool bMoved = rShell.MoveParagraph();
435 if(!bMoved)
436 {
437 //insert a new paragraph before the greeting line
438 rShell.SplitNode();
439 }
440 --nMoves;
441 }
442 }
443 //now insert the greeting text - if we have any?
444 const bool bIndividual = rConfigItem.IsIndividualGreeting(false);
445 if(bIndividual)
446 {
447 //lock expression fields - prevents hiding of the paragraph to insert into
448 rShell.LockExpFields();
449 if(bExample)
450 {
452 eGender <= SwMailMergeConfigItem::NEUTRAL; ++eGender)
453 {
454 Sequence< OUString > aEntries =
455 rConfigItem.GetGreetings(static_cast<SwMailMergeConfigItem::Gender>(eGender));
456 sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(static_cast<SwMailMergeConfigItem::Gender>(eGender));
457 if( nCurrent >= 0 && nCurrent < aEntries.getLength())
458 {
459 // Greeting
460 rShell.Insert(aEntries[nCurrent]);
461 break;
462 }
463 }
464 }
465 else
466 {
467 SwFieldMgr aFieldMgr(&rShell);
468 //three paragraphs, each with an appropriate hidden paragraph field
469 //are to be inserted
470
471 //name of the gender column
472 const OUString sGenderColumn = rConfigItem.GetAssignedColumn(MM_PART_GENDER);
473 const OUString sNameColumn = rConfigItem.GetAssignedColumn(MM_PART_LASTNAME);
474
475 const OUString& rFemaleGenderValue = rConfigItem.GetFemaleGenderValue();
476 bool bHideEmptyParagraphs = rConfigItem.IsHideEmptyParagraphs();
477 const SwDBData& rData = rConfigItem.GetCurrentDBData();
478 const OUString sCommonBase(rData.sDataSource + "." + rData.sCommand + ".");
479 const OUString sConditionBase("[" + sCommonBase + sGenderColumn + "]");
480 const OUString sNameColumnBase("[" + sCommonBase + sNameColumn + "]");
481
482 const OUString sDBName(rData.sDataSource + OUStringChar(DB_DELIM)
483 + rData.sCommand + OUStringChar(DB_DELIM)
484 + OUString::number(rData.nCommandType) + OUStringChar(DB_DELIM));
485
486// Female: [database.sGenderColumn] != "rFemaleGenderValue" && [database.NameColumn]
487// Male: [database.sGenderColumn] == "rFemaleGenderValue" && [database.rGenderColumn]
488// Neutral: [database.sNameColumn]
489 OSL_ENSURE(!sGenderColumn.isEmpty() && !rFemaleGenderValue.isEmpty(),
490 "gender settings not available - how to form the condition?");
491 //column used as lastname
493 eGender <= SwMailMergeConfigItem::NEUTRAL; ++eGender)
494 {
495 Sequence< OUString> aEntries = rConfigItem.GetGreetings(static_cast<SwMailMergeConfigItem::Gender>(eGender));
496 sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(static_cast<SwMailMergeConfigItem::Gender>(eGender));
497 if( nCurrent >= 0 && nCurrent < aEntries.getLength())
498 {
499 const OUString sGreeting = aEntries[nCurrent];
500 OUString sCondition;
501 OUString sHideParagraphsExpression;
502 switch(eGender)
503 {
505 sCondition = sConditionBase + " != \"" + rFemaleGenderValue
506 + "\" OR NOT " + sNameColumnBase;
507 sHideParagraphsExpression = "!" + sNameColumnBase;
508 break;
510 sCondition = sConditionBase + " == \"" + rFemaleGenderValue
511 + "\" OR NOT " + sNameColumnBase;
512 break;
514 sCondition = sNameColumnBase;
515 break;
516 }
517
518 if(bHideEmptyParagraphs && !sHideParagraphsExpression.isEmpty())
519 {
520 OUString sComplete = "(" + sCondition + ") OR (" + sHideParagraphsExpression + ")";
521 SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sComplete, OUString(), 0, &rShell);
522 aFieldMgr.InsertField( aData );
523 }
524 else
525 {
526 SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sCondition, OUString(), 0, &rShell);
527 aFieldMgr.InsertField( aData );
528 }
529 //now the text has to be inserted
530 const std::vector<std::pair<OUString, int>>& rHeaders = rConfigItem.GetDefaultAddressHeaders();
531 Sequence< OUString> aAssignment =
532 rConfigItem.GetColumnAssignment( rConfigItem.GetCurrentDBData() );
533 const OUString* pAssignment = aAssignment.getConstArray();
534 SwAddressIterator aIter(sGreeting);
535 while(aIter.HasMore())
536 {
537 SwMergeAddressItem aItem = aIter.Next();
538 if(aItem.bIsColumn)
539 {
540 OUString sConvertedColumn = aItem.sText;
541 auto nSize = std::min(static_cast<sal_uInt32>(rHeaders.size()),
542 static_cast<sal_uInt32>(aAssignment.getLength()));
543 for(sal_uInt32 nColumn = 0; nColumn < nSize; ++nColumn)
544 {
545 if (rHeaders[nColumn].first == aItem.sText &&
546 !pAssignment[nColumn].isEmpty())
547 {
548 sConvertedColumn = pAssignment[nColumn];
549 break;
550 }
551 }
553 sDBName + sConvertedColumn,
554 OUString(), 0, &rShell);
555 aFieldMgr.InsertField( aData );
556 }
557 else
558 {
559 rShell.Insert(aItem.sText);
560 }
561 }
562 //now add a new paragraph
563 rShell.SplitNode();
564 }
565 }
566
567 }
568 rShell.UnlockExpFields();
569 }
570 else
571 {
572 Sequence< OUString> aEntries = rConfigItem.GetGreetings(SwMailMergeConfigItem::NEUTRAL);
573 sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(SwMailMergeConfigItem::NEUTRAL);
574 // Greeting
575 rShell.Insert(( nCurrent >= 0 && nCurrent < aEntries.getLength() )
576 ? aEntries[nCurrent] : OUString());
577 }
578 // now insert a new paragraph here if necessary
579 if(bSplitNode)
580 {
581 rShell.Push();
582 rShell.SplitNode();
584 }
585 //put the cursor to the start of the paragraph
586 rShell.SttPara();
587
588 OSL_ENSURE(nullptr == rShell.GetTableFormat(), "What to do with a table here?");
589}
590
592{
593 m_xExampleContainerWIN->show();
594
595 Reference< XModel > & xModel = m_xExampleFrame->GetModel();
596 //now the ViewOptions should be set properly
597 Reference< XViewSettingsSupplier > xSettings(xModel->getCurrentController(), UNO_QUERY);
598 m_xViewProperties = xSettings->getViewSettings();
599 auto pXDoc = comphelper::getFromUnoTunnel<SwXTextDocument>(xModel);
600 SwDocShell* pDocShell = pXDoc->GetDocShell();
601 m_pExampleWrtShell = pDocShell->GetWrtShell();
602 OSL_ENSURE(m_pExampleWrtShell, "No SwWrtShell found!");
603 if(!m_pExampleWrtShell)
604 return;
605
606 SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem();
607 if(rConfigItem.IsAddressBlock())
608 {
609 m_pAddressBlockFormat = InsertAddressFrame(
610 *m_pExampleWrtShell, rConfigItem,
612 m_xAlignToBodyCB->get_active(), true);
613 }
614 if(rConfigItem.IsGreetingLine(false))
615 {
616 InsertGreeting(*m_pExampleWrtShell, rConfigItem, true);
617 m_bIsGreetingInserted = true;
618 }
619
620 ZoomHdl_Impl(*m_xZoomLB);
621
622 const SwFormatFrameSize& rPageSize = m_pExampleWrtShell->GetPageDesc(
623 m_pExampleWrtShell->GetCurPageDesc()).GetMaster().GetFrameSize();
624 m_xLeftMF->set_max(rPageSize.GetWidth() - DEFAULT_LEFT_DISTANCE, FieldUnit::NONE);
625 m_xTopMF->set_max(rPageSize.GetHeight() - DEFAULT_TOP_DISTANCE, FieldUnit::NONE);
626}
627
629{
630 if (!m_pExampleWrtShell)
631 return;
632
633 sal_Int16 eType = DocumentZoomType::BY_VALUE;
634 short nZoom = 50;
635 switch (rBox.get_active())
636 {
637 case 0 : eType = DocumentZoomType::ENTIRE_PAGE; break;
638 case 1 : nZoom = 50; break;
639 case 2 : nZoom = 75; break;
640 case 3 : nZoom = 100; break;
641 }
642 Any aZoom;
643 aZoom <<= eType;
644 m_xViewProperties->setPropertyValue(UNO_NAME_ZOOM_TYPE, aZoom);
645 aZoom <<= nZoom;
646 m_xViewProperties->setPropertyValue(UNO_NAME_ZOOM_VALUE, aZoom);
647
648 m_xExampleFrame->Invalidate();
649}
650
652{
653 if(!(m_pExampleWrtShell && m_pAddressBlockFormat))
654 return;
655
656 tools::Long nLeft = static_cast< tools::Long >(m_xLeftMF->denormalize(m_xLeftMF->get_value(FieldUnit::TWIP)));
657 tools::Long nTop = static_cast< tools::Long >(m_xTopMF->denormalize(m_xTopMF->get_value(FieldUnit::TWIP)));
658
660 m_pExampleWrtShell->GetAttrPool());
661 if (m_xAlignToBodyCB->get_active())
662 aSet.Put(SwFormatHoriOrient( 0, text::HoriOrientation::NONE, text::RelOrientation::PAGE_PRINT_AREA ));
663 else
664 aSet.Put(SwFormatHoriOrient( nLeft, text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME ));
665 aSet.Put(SwFormatVertOrient( nTop, text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME ));
666 m_pExampleWrtShell->GetDoc()->SetFlyFrameAttr( *m_pAddressBlockFormat, aSet );
667 m_xExampleFrame->Invalidate();
668}
669
670IMPL_LINK(SwMailMergeLayoutPage, GreetingsHdl_Impl, weld::Button&, rButton, void)
671{
672 bool bDown = &rButton == m_xDownPB.get();
673 bool bMoved = m_pExampleWrtShell->MoveParagraph( SwNodeOffset(bDown ? 1 : -1) );
674 if (bMoved || bDown)
675 m_pWizard->GetConfigItem().MoveGreeting(bDown ? 1 : -1 );
676 if(!bMoved && bDown)
677 {
678 //insert a new paragraph before the greeting line
679 m_pExampleWrtShell->SplitNode();
680 }
681 m_xExampleFrame->Invalidate();
682}
683
684IMPL_LINK(SwMailMergeLayoutPage, AlignToTextHdl_Impl, weld::Toggleable&, rBox, void)
685{
686 bool bCheck = rBox.get_active() && rBox.get_sensitive();
687 m_xLeftFT->set_sensitive(!bCheck);
688 m_xLeftMF->set_sensitive(!bCheck);
689 ChangeAddressHdl_Impl( *m_xLeftMF );
690}
691
692/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const LanguageTag & GetUILanguageTag() const
static const AllSettings & GetSettings()
std::unique_ptr< weld::Builder > m_xBuilder
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
css::uno::Reference< css::frame::XModel3 > GetModel() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
tools::Long GetHeight() const
tools::Long GetWidth() const
SwMergeAddressItem Next()
void Push()
store a copy of the current cursor on the cursor stack
Definition: crsrsh.cxx:2251
const SwRect & GetCharRect() const
Definition: crsrsh.hxx:532
bool SttEndDoc(bool bStt)
Definition: crsrsh.cxx:573
bool MovePara(SwWhichPara, SwMoveFnCollection const &)
Definition: crsrsh.cxx:696
bool IsEndPara() const
Definition: crsrsh.cxx:1114
bool SetShadowCursorPos(const Point &rPt, SwFillMode eFillMode)
Definition: crstrvl.cxx:2177
SwWrtShell * GetWrtShell()
Access to the SwWrtShell belonging to SwView.
Definition: docsh.hxx:225
SwUndoId StartUndo(SwUndoId eUndoId=SwUndoId::EMPTY, const SwRewriter *pRewriter=nullptr)
Undo: set up Undo parenthesis, return nUndoId of this parenthesis.
Definition: edws.cxx:223
SwFrameFormat * GetTableFormat()
Definition: edws.cxx:183
bool MoveParagraph(SwNodeOffset nOffset=SwNodeOffset(1))
Definition: ednumber.cxx:364
bool AppendTextNode()
Definition: editsh.cxx:204
void LockExpFields()
Definition: edfld.cxx:343
void UnlockExpFields()
Definition: edfld.cxx:348
SwUndoId EndUndo(SwUndoId eUndoId=SwUndoId::EMPTY, const SwRewriter *pRewriter=nullptr)
Closes parenthesis of nUndoId, not used by UI.
Definition: edws.cxx:234
bool DelFullPara()
Remove a complete paragraph.
Definition: eddel.cxx:341
const SwFrameFormat * NewFlyFrame(const SfxItemSet &rSet, bool bAnchValid=false, SwFrameFormat *pParent=nullptr)
Definition: fefly1.cxx:660
const SwRect & GetAnyCurRect(CurRectType eType, const Point *pPt=nullptr, const css::uno::Reference< css::embed::XEmbeddedObject > &=css::uno::Reference< css::embed::XEmbeddedObject >()) const
Definition: fews.cxx:90
const SwFrameFormat * GetFlyFrameFormat() const
Get FlyFrameFormat; for UI macro linkage at Flys.
Definition: fefly1.cxx:1270
bool InsertField(SwInsertField_Data &rData)
Definition: fldmgr.cxx:895
FlyAnchors.
Definition: fmtanchr.hxx:37
Defines the horizontal position of a fly frame.
Definition: fmtornt.hxx:73
Defines the vertical position of a fly frame.
Definition: fmtornt.hxx:37
const OUString & GetName() const
Definition: format.hxx:131
Style of a layout element.
Definition: frmfmt.hxx:62
const SwDBData & GetCurrentDBData() const
css::uno::Sequence< OUString > GetAddressBlocks() const
css::uno::Sequence< OUString > GetGreetings(Gender eType) const
bool IsHideEmptyParagraphs() const
bool IsIncludeCountry() const
bool IsAddressInserted() const
bool IsGreetingInserted() const
OUString & GetExcludeCountry() const
bool IsAddressBlock() const
const std::vector< std::pair< OUString, int > > & GetDefaultAddressHeaders() const
bool IsGreetingLine(bool bInEMail) const
sal_Int32 GetGreetingMoves() const
bool IsIndividualGreeting(bool bInEMail) const
css::uno::Sequence< OUString > GetColumnAssignment(const SwDBData &rDBData) const
sal_Int32 GetCurrentGreeting(Gender eType) const
const OUString & GetFemaleGenderValue() const
OUString GetAssignedColumn(sal_uInt32 nColumn) const
std::unique_ptr< weld::Button > m_xUpPB
static void InsertGreeting(SwWrtShell &rShell, SwMailMergeConfigItem const &rConfigItem, bool bExample)
std::unique_ptr< weld::Container > m_xGreetingLine
std::unique_ptr< weld::CustomWeld > m_xExampleContainerWIN
std::unique_ptr< weld::MetricSpinButton > m_xLeftMF
std::unique_ptr< weld::MetricSpinButton > m_xTopMF
std::unique_ptr< SwOneExampleFrame > m_xExampleFrame
static SwFrameFormat * InsertAddressFrame(SwWrtShell &rShell, SwMailMergeConfigItem const &rConfigItem, const Point &rDestination, bool bAlignToBody, bool bExample)
std::unique_ptr< weld::Container > m_xPosition
virtual bool commitPage(::vcl::WizardTypes::CommitPageReason _eReason) override
SwWrtShell * m_pExampleWrtShell
static SwFrameFormat * InsertAddressAndGreeting(SwView const *pView, SwMailMergeConfigItem &rConfigItem, const Point &rAddressPos, bool bAlignToBody)
virtual ~SwMailMergeLayoutPage() override
SwMailMergeLayoutPage(weld::Container *pPage, SwMailMergeWizard *pWizard)
std::unique_ptr< weld::CheckButton > m_xAlignToBodyCB
std::unique_ptr< weld::Button > m_xDownPB
SwMailMergeWizard * m_pWizard
std::unique_ptr< weld::ComboBox > m_xZoomLB
virtual void Activate() override
SwFrameFormat * m_pAddressBlockFormat
SwMailMergeConfigItem & GetConfigItem()
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
void Top(const tools::Long nTop)
Definition: swrect.hxx:206
void Left(const tools::Long nLeft)
Definition: swrect.hxx:197
const SfxItemPool & GetAttrPool() const
Definition: viewsh.hxx:624
Definition: view.hxx:146
SwWrtShell & GetWrtShell() const
Definition: view.hxx:416
SwDocShell * GetDocShell()
Definition: view.cxx:1160
Used by the UI to modify the document model.
Definition: wrtsh.hxx:97
bool FwdPara()
Definition: wrtsh.hxx:234
bool SttPara(bool bSelect=false)
Definition: move.cxx:356
bool GotoFly(const OUString &rName, FlyCntType eType=FLYCNTTYPE_ALL, bool bSelFrame=true)
Definition: move.cxx:599
void Insert(const OUString &)
Definition: wrtsh1.cxx:224
void SplitNode(bool bAutoFormat=false)
Definition: wrtsh1.cxx:1297
bool DelRight(bool isReplaceHeuristic=false)
Definition: delete.cxx:291
void UnSelectFrame()
Definition: select.cxx:323
bool Pop(SwCursorShell::PopMode, ::std::optional< SwCallLink > &roLink)
Definition: wrtsh1.cxx:2030
static OUString formatPercent(double dNumber, const LanguageTag &rLangTag)
void EnableKillingFile(bool bEnable=true)
OUString const & GetURL() const
@ TabSpace
fill with spaces and tabs
float u
ScXMLEditAttributeMap::Entry const aEntries[]
@ Page
Rect of current page.
FieldUnit
DocumentType eType
@ Minimum
Value in Var-direction gives minimum (can be exceeded but not be less).
constexpr TypedWhichId< SwFormatSurround > RES_SURROUND(101)
constexpr TypedWhichId< SwFormatFrameSize > RES_FRM_SIZE(89)
constexpr TypedWhichId< SwFormatAnchor > RES_ANCHOR(104)
constexpr TypedWhichId< SvxBoxItem > RES_BOX(106)
constexpr tools::Long DEFAULT_ADDRESS_WIDTH
constexpr tools::Long DEFAULT_TOP_DISTANCE
IMPL_LINK(SwMailMergeLayoutPage, ZoomHdl_Impl, weld::ComboBox &, rBox, void)
constexpr tools::Long DEFAULT_ADDRESS_HEIGHT
constexpr tools::Long GREETING_TOP_DISTANCE
IMPL_LINK_NOARG(SwMailMergeLayoutPage, PreviewLoadedHdl_Impl, SwOneExampleFrame &, void)
constexpr tools::Long DEFAULT_LEFT_DISTANCE
constexpr OUStringLiteral aData
Definition: ww8scan.hxx:48
OString stripStart(const OString &rIn, char c)
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
constexpr OUStringLiteral first
constexpr auto toTwips(N number, Length from)
long Long
o3tl::strong_int< sal_Int32, struct Tag_SwNodeOffset > SwNodeOffset
Definition: nodeoffset.hxx:16
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
bool GoCurrPara(SwPaM &rPam, SwMoveFnCollection const &aPosPara)
Definition: pam.cxx:1224
SwMoveFnCollection const & fnParaStart
Definition: paminit.cxx:48
sal_Int32 nCommandType
Definition: swdbdata.hxx:32
OUString sDataSource
Definition: swdbdata.hxx:30
OUString sCommand
Definition: swdbdata.hxx:31
Reference< XModel > xModel
#define DB_DELIM
Definition: swtypes.hxx:130
signed char sal_Int8
SW_DLLPUBLIC FieldUnit GetDfltMetric(bool bWeb)
Definition: uitool.cxx:755
#define UNO_NAME_ZOOM_VALUE
Definition: unoprnms.hxx:426
#define UNO_NAME_ZOOM_TYPE
Definition: unoprnms.hxx:427
#define EX_SHOW_DEFAULT_PAGE
Definition: unotools.hxx:37