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>
27 #include <i18nutil/unicode.hxx>
28 #include <unotools/tempfile.hxx>
29 #include <uitool.hxx>
30 #include <svx/dlgutil.hxx>
31 #include <view.hxx>
32 #include <swundo.hxx>
33 #include <sfx2/dispatch.hxx>
34 #include <svl/stritem.hxx>
35 #include <sfx2/docfilt.hxx>
36 #include <svtools/unitconv.hxx>
37 #include <com/sun/star/text/XParagraphCursor.hpp>
38 #include <com/sun/star/view/XViewSettingsSupplier.hpp>
39 #include <com/sun/star/view/DocumentZoomType.hpp>
40 #include <fldmgr.hxx>
41 #include <fldbas.hxx>
42 #include <poolfmt.hxx>
43 #include <unotxdoc.hxx>
44 #include <docsh.hxx>
45 #include <doc.hxx>
46 #include <wrtsh.hxx>
47 #include <fmtsrnd.hxx>
48 #include <pagedesc.hxx>
49 #include <fmtanchr.hxx>
50 #include <fmtornt.hxx>
51 #include <fmtfsize.hxx>
52 #include <editeng/boxitem.hxx>
53 #include <svl/urihelper.hxx>
54 #include <shellio.hxx>
55 #include <osl/file.hxx>
56 #include <vcl/settings.hxx>
57 #include <unoprnms.hxx>
58 #include <iodetect.hxx>
59 
60 #include <dbui.hrc>
61 #include <unomid.h>
62 
63 using namespace osl;
64 using namespace svt;
65 using namespace ::com::sun::star;
66 using namespace ::com::sun::star::uno;
67 using namespace ::com::sun::star::text;
68 using namespace ::com::sun::star::frame;
69 using namespace ::com::sun::star::lang;
70 using namespace ::com::sun::star::view;
71 
72 #define DEFAULT_LEFT_DISTANCE (MM50*5) // 2,5 cm
73 #define DEFAULT_TOP_DISTANCE (MM50*11) // 5,5 cm
74 #define GREETING_TOP_DISTANCE (MM50*25) //12,5 cm
75 #define DEFAULT_ADDRESS_WIDTH (MM50*15)// 7,5 cm
76 #define DEFAULT_ADDRESS_HEIGHT (MM50*7) // 3,5cm
77 
79  svt::OWizardPage(_pParent, "MMLayoutPage",
80  "modules/swriter/ui/mmlayoutpage.ui")
81  , m_pExampleWrtShell(nullptr)
82  , m_pAddressBlockFormat(nullptr)
83  , m_bIsGreetingInserted(false)
84  , m_pWizard(_pParent)
85 {
86  get(m_pPosition, "addresspos");
87  get(m_pGreetingLine, "greetingspos");
88  get(m_pAlignToBodyCB, "align");
89  get(m_pLeftFT, "leftft");
90  get(m_pLeftMF, "left");
91  get(m_pTopMF, "top");
92  get(m_pUpPB, "up");
93  get(m_pDownPB, "down");
94  get(m_pExampleContainerWIN, "example");
95  Size aSize(LogicToPixel(Size(124, 159), MapMode(MapUnit::MapAppFont)));
98  get(m_pZoomLB, "zoom");
99 
100  std::shared_ptr<const SfxFilter> pSfxFlt = SwIoSystem::GetFilterOfFormat(
101  FILTER_XML,
102  SwDocShell::Factory().GetFilterContainer() );
103  //save the current document into a temporary file
104  {
105  //temp file needs its own block
106  //creating with extension is not supported by a static method :-(
107  OUString const sExt(
108  comphelper::string::stripStart(pSfxFlt->GetDefaultExtension(),'*'));
109  utl::TempFile aTempFile( OUString(), true, &sExt );
110  m_sExampleURL = aTempFile.GetURL();
111  aTempFile.EnableKillingFile();
112  }
113  SwView* pView = m_pWizard->GetSwView();
114  uno::Sequence< beans::PropertyValue > aValues(2);
115  beans::PropertyValue* pValues = aValues.getArray();
116  pValues[0].Name = "FilterName";
117  pValues[0].Value <<= pSfxFlt->GetFilterName();
118  // Don't save embedded data set! It would steal it from current document.
119  pValues[1].Name = "NoEmbDataSet";
120  pValues[1].Value <<= true;
121 
122  uno::Reference< frame::XStorable > xStore( pView->GetDocShell()->GetModel(), uno::UNO_QUERY);
123  xStore->storeToURL( m_sExampleURL, aValues );
124 
125  Link<SwOneExampleFrame&,void> aLink(LINK(this, SwMailMergeLayoutPage, PreviewLoadedHdl_Impl));
127  EX_SHOW_DEFAULT_PAGE, &aLink, &m_sExampleURL ) );
128 
130 
133 
138  m_pZoomLB->SelectEntryPos(0); //page size
139  m_pZoomLB->SetSelectHdl(LINK(this, SwMailMergeLayoutPage, ZoomHdl_Impl));
140 
141  Link<SpinField&,void> aFrameHdl = LINK(this, SwMailMergeLayoutPage, ChangeAddressHdl_Impl);
142  Link<Control&,void> aFocusHdl = LINK(this, SwMailMergeLayoutPage, ChangeAddressLoseFocusHdl_Impl);
143  m_pLeftMF->SetUpHdl(aFrameHdl);
144  m_pLeftMF->SetDownHdl(aFrameHdl);
145  m_pLeftMF->SetLoseFocusHdl(aFocusHdl);
146  m_pTopMF->SetUpHdl(aFrameHdl);
147  m_pTopMF->SetDownHdl(aFrameHdl);
148  m_pTopMF->SetLoseFocusHdl(aFocusHdl);
149 
150  FieldUnit eFieldUnit = ::GetDfltMetric(false);
151  ::SetFieldUnit( *m_pLeftMF, eFieldUnit );
152  ::SetFieldUnit( *m_pTopMF, eFieldUnit );
153 
154  Link<Button*,void> aUpDownHdl = LINK(this, SwMailMergeLayoutPage, GreetingsHdl_Impl );
155  m_pUpPB->SetClickHdl(aUpDownHdl);
156  m_pDownPB->SetClickHdl(aUpDownHdl);
157  m_pAlignToBodyCB->SetClickHdl(LINK(this, SwMailMergeLayoutPage, AlignToTextHdl_Impl));
159 }
160 
162 {
163  disposeOnce();
164 }
165 
167 {
168  m_pExampleFrame.reset();
169  File::remove( m_sExampleURL );
170  m_pPosition.clear();
172  m_pLeftFT.clear();
173  m_pLeftMF.clear();
174  m_pTopMF.clear();
176  m_pUpPB.clear();
177  m_pDownPB.clear();
179  m_pZoomLB.clear();
180  m_pWizard.clear();
182 }
183 
185 {
187  bool bGreetingLine = rConfigItem.IsGreetingLine(false) && !rConfigItem.IsGreetingInserted();
188  bool bAddressBlock = rConfigItem.IsAddressBlock() && !rConfigItem.IsAddressInserted();
189 
190  m_pPosition->Enable(bAddressBlock);
191  AlignToTextHdl_Impl(m_pAlignToBodyCB);
192 
193  m_pGreetingLine->Enable(bGreetingLine);
194 
195  //check if greeting and/or address frame have to be inserted/removed
196  if(m_pExampleWrtShell) // initially there's nothing to check
197  {
198  if(!rConfigItem.IsGreetingInserted() &&
199  m_bIsGreetingInserted != bGreetingLine )
200  {
202  {
204  m_bIsGreetingInserted = false;
205  }
206  else
207  {
209  m_bIsGreetingInserted = true;
210  }
211  }
212  if(!rConfigItem.IsAddressInserted() &&
213  rConfigItem.IsAddressBlock() != ( nullptr != m_pAddressBlockFormat ))
214  {
216  {
220  m_pAddressBlockFormat = nullptr;
222  }
223  else
224  {
225  long nLeft = static_cast< long >(m_pLeftMF->Denormalize(m_pLeftMF->GetValue(FieldUnit::TWIP)));
226  long nTop = static_cast< long >(m_pTopMF->Denormalize(m_pTopMF->GetValue(FieldUnit::TWIP)));
229  Point(nLeft, nTop),
230  m_pAlignToBodyCB->IsChecked(), true);
231  }
232  }
233 
234  }
235 }
236 
238 {
239  //now insert the frame and the greeting
241  if (eReason == ::svt::WizardTypes::eTravelForward || eReason == ::svt::WizardTypes::eFinish)
242  {
243  long nLeft = static_cast< long >(m_pLeftMF->Denormalize(m_pLeftMF->GetValue(FieldUnit::TWIP)));
244  long nTop = static_cast< long >(m_pTopMF->Denormalize(m_pTopMF->GetValue(FieldUnit::TWIP)));
246  m_pWizard->GetSwView(),
247  rConfigItem,
248  Point(nLeft, nTop),
250  }
251  return true;
252 }
253 
255  SwMailMergeConfigItem& rConfigItem,
256  const Point& rAddressPosition,
257  bool bAlignToBody)
258 {
259  SwFrameFormat* pAddressBlockFormat = nullptr;
261  if(rConfigItem.IsAddressBlock() && !rConfigItem.IsAddressInserted())
262  {
263  //insert the frame
265  if(rAddressPosition.X() > 0 && rAddressPosition.Y() > 0)
266  aAddressPosition = rAddressPosition;
267  pAddressBlockFormat = InsertAddressFrame( pView->GetWrtShell(),
268  rConfigItem,
269  aAddressPosition, bAlignToBody, false);
270  rConfigItem.SetAddressInserted();
271  }
272  //now the greeting
273  if(rConfigItem.IsGreetingLine(false) && !rConfigItem.IsGreetingInserted())
274  {
275  InsertGreeting( pView->GetWrtShell(), rConfigItem, false);
276  rConfigItem.SetGreetingInserted();
277  }
279  return pAddressBlockFormat;
280 }
281 
283  SwWrtShell& rShell,
284  SwMailMergeConfigItem const & rConfigItem,
285  const Point& rDestination,
286  bool bAlignLeft,
287  bool bExample)
288 {
289  // insert the address block and the greeting line
290  SfxItemSet aSet(
291  rShell.GetAttrPool(),
292  svl::Items<
295  RES_BOX, RES_BOX>{} );
296  aSet.Put(SwFormatAnchor(RndStdIds::FLY_AT_PAGE, 1));
297  if(bAlignLeft)
298  aSet.Put(SwFormatHoriOrient( 0, text::HoriOrientation::NONE, text::RelOrientation::PAGE_PRINT_AREA ));
299  else
300  aSet.Put(SwFormatHoriOrient( rDestination.X(), text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME ));
301  aSet.Put(SwFormatVertOrient( rDestination.Y(), text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME ));
303  // the example gets a border around the frame, the real document doesn't get one
304  if(!bExample)
305  aSet.Put(SvxBoxItem( RES_BOX ));
306  aSet.Put(SwFormatSurround( css::text::WrapTextMode_NONE ));
307 
308  rShell.NewFlyFrame(aSet, true );
309  SwFrameFormat* pRet = rShell.GetFlyFrameFormat();
310  OSL_ENSURE( pRet, "Fly not inserted" );
311 
312  rShell.UnSelectFrame();
313  const Sequence< OUString> aBlocks = rConfigItem.GetAddressBlocks();
314  if(bExample)
315  {
316  rShell.Insert(aBlocks[0]);
317  }
318  else
319  {
320  //the placeholders should be replaced by the appropriate fields
321  SwFieldMgr aFieldMgr(&rShell);
322  //create a database string source.command.commandtype.column
323  const SwDBData& rData = rConfigItem.GetCurrentDBData();
324  OUString sDBName(rData.sDataSource + OUStringLiteral1(DB_DELIM)
325  + rData.sCommand + OUStringLiteral1(DB_DELIM));
326  const OUString sDatabaseConditionPrefix(sDBName.replace(DB_DELIM, '.'));
327  sDBName += OUString::number(rData.nCommandType) + OUStringLiteral1(DB_DELIM);
328 
329  // if only the country is in an address line the
330  // paragraph has to be hidden depending on the
331  // IsIncludeCountry()/GetExcludeCountry() settings
332 
333  bool bIncludeCountry = rConfigItem.IsIncludeCountry();
334  bool bHideEmptyParagraphs = rConfigItem.IsHideEmptyParagraphs();
335  const OUString rExcludeCountry = rConfigItem.GetExcludeCountry();
336  bool bSpecialReplacementForCountry = (!bIncludeCountry || !rExcludeCountry.isEmpty());
337 
338  const std::vector<std::pair<OUString, int>>& rHeaders = rConfigItem.GetDefaultAddressHeaders();
339  Sequence< OUString> aAssignment =
340  rConfigItem.GetColumnAssignment( rConfigItem.GetCurrentDBData() );
341  const OUString* pAssignment = aAssignment.getConstArray();
342  const OUString sCountryColumn(
343  (aAssignment.getLength() > MM_PART_COUNTRY && !aAssignment[MM_PART_COUNTRY].isEmpty())
344  ? aAssignment[MM_PART_COUNTRY]
345  : rHeaders[MM_PART_COUNTRY].first);
346 
347  OUString sHideParagraphsExpression;
348  SwAddressIterator aIter(aBlocks[0]);
349  while(aIter.HasMore())
350  {
351  SwMergeAddressItem aItem = aIter.Next();
352  if(aItem.bIsColumn)
353  {
354  OUString sConvertedColumn = aItem.sText;
355  for(sal_uInt32 nColumn = 0;
356  nColumn < rHeaders.size() &&
357  nColumn < static_cast<sal_uInt32>(aAssignment.getLength());
358  ++nColumn)
359  {
360  if (rHeaders[nColumn].first == aItem.sText &&
361  !pAssignment[nColumn].isEmpty())
362  {
363  sConvertedColumn = pAssignment[nColumn];
364  break;
365  }
366  }
367  const OUString sDB(sDBName + sConvertedColumn);
368 
369  if(!sHideParagraphsExpression.isEmpty())
370  sHideParagraphsExpression += " AND ";
371  sHideParagraphsExpression += "![" + sDatabaseConditionPrefix + sConvertedColumn + "]";
372 
373  if( bSpecialReplacementForCountry && sCountryColumn == sConvertedColumn )
374  {
375  // now insert a hidden paragraph field
376  if( !rExcludeCountry.isEmpty() )
377  {
378  const OUString sExpression("[" + sDatabaseConditionPrefix + sCountryColumn + "]");
380  sExpression + " != \"" + rExcludeCountry + "\"",
381  sExpression,
382  0, &rShell );
383  aFieldMgr.InsertField( aData );
384  }
385  else
386  {
387  SwInsertField_Data aData(TYP_HIDDENPARAFLD, 0, "", "", 0, &rShell );
388  aFieldMgr.InsertField( aData );
389  }
390  }
391  else
392  {
393  SwInsertField_Data aData(TYP_DBFLD, 0, sDB, OUString(), 0, &rShell);
394  aFieldMgr.InsertField( aData );
395  }
396  }
397  else if(!aItem.bIsReturn)
398  {
399  rShell.Insert(aItem.sText);
400  }
401  else
402  {
403  if(bHideEmptyParagraphs)
404  {
405  SwInsertField_Data aData(TYP_HIDDENPARAFLD, 0, sHideParagraphsExpression, OUString(), 0, &rShell);
406  aFieldMgr.InsertField( aData );
407  }
408  sHideParagraphsExpression.clear();
409  //now add a new paragraph
410  rShell.SplitNode();
411  }
412  }
413  if(bHideEmptyParagraphs && !sHideParagraphsExpression.isEmpty())
414  {
415  SwInsertField_Data aData(TYP_HIDDENPARAFLD, 0, sHideParagraphsExpression, OUString(), 0, &rShell);
416  aFieldMgr.InsertField( aData );
417  }
418  }
419  return pRet;
420 }
421 
422 void SwMailMergeLayoutPage::InsertGreeting(SwWrtShell& rShell, SwMailMergeConfigItem const & rConfigItem, bool bExample)
423 {
424  //set the cursor to the desired position - if no text content is here then
425  //new paragraphs are inserted
426  const SwRect& rPageRect = rShell.GetAnyCurRect(CurRectType::Page);
427  const Point aGreetingPos( DEFAULT_LEFT_DISTANCE + rPageRect.Left(), GREETING_TOP_DISTANCE );
428 
429  const bool bRet = rShell.SetShadowCursorPos( aGreetingPos, FILL_TAB_SPACE );
430 
431  if(!bRet)
432  {
433  //there's already text at the desired position
434  //go to start of the doc, directly!
435  rShell.SttEndDoc(true);
436  //and go by paragraph until the position is reached
437  long nYPos = rShell.GetCharRect().Top();
438  while(nYPos < GREETING_TOP_DISTANCE)
439  {
440  if(!rShell.FwdPara())
441  break;
442  nYPos = rShell.GetCharRect().Top();
443  }
444  //text needs to be appended
445  while(nYPos < GREETING_TOP_DISTANCE)
446  {
447  if(!rShell.AppendTextNode())
448  break;
449  nYPos = rShell.GetCharRect().Top();
450  }
451  }
452  else
453  {
454  //we may end up inside of a paragraph if the left margin is not at DEFAULT_LEFT_DISTANCE
456  }
457  bool bSplitNode = !rShell.IsEndPara();
458  sal_Int32 nMoves = rConfigItem.GetGreetingMoves();
459  if( !bExample && 0 != nMoves )
460  {
461  if(nMoves < 0)
462  {
463  rShell.MoveParagraph( nMoves );
464  }
465  else
466  while(nMoves)
467  {
468  bool bMoved = rShell.MoveParagraph();
469  if(!bMoved)
470  {
471  //insert a new paragraph before the greeting line
472  rShell.SplitNode();
473  }
474  --nMoves;
475  }
476  }
477  //now insert the greeting text - if we have any?
478  const bool bIndividual = rConfigItem.IsIndividualGreeting(false);
479  if(bIndividual)
480  {
481  //lock expression fields - prevents hiding of the paragraph to insert into
482  rShell.LockExpFields();
483  if(bExample)
484  {
486  eGender <= SwMailMergeConfigItem::NEUTRAL; ++eGender)
487  {
489  rConfigItem.GetGreetings(static_cast<SwMailMergeConfigItem::Gender>(eGender));
490  sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(static_cast<SwMailMergeConfigItem::Gender>(eGender));
491  if( nCurrent >= 0 && nCurrent < aEntries.getLength())
492  {
493  // Greeting
494  rShell.Insert(aEntries[nCurrent]);
495  break;
496  }
497  }
498  }
499  else
500  {
501  SwFieldMgr aFieldMgr(&rShell);
502  //three paragraphs, each with an appropriate hidden paragraph field
503  //are to be inserted
504 
505  //name of the gender column
506  const OUString sGenderColumn = rConfigItem.GetAssignedColumn(MM_PART_GENDER);
507  const OUString sNameColumn = rConfigItem.GetAssignedColumn(MM_PART_LASTNAME);
508 
509  const OUString& rFemaleGenderValue = rConfigItem.GetFemaleGenderValue();
510  bool bHideEmptyParagraphs = rConfigItem.IsHideEmptyParagraphs();
511  const SwDBData& rData = rConfigItem.GetCurrentDBData();
512  const OUString sCommonBase(rData.sDataSource + "." + rData.sCommand + ".");
513  const OUString sConditionBase("[" + sCommonBase + sGenderColumn + "]");
514  const OUString sNameColumnBase("[" + sCommonBase + sNameColumn + "]");
515 
516  const OUString sDBName(rData.sDataSource + OUStringLiteral1(DB_DELIM)
517  + rData.sCommand + OUStringLiteral1(DB_DELIM)
518  + OUString::number(rData.nCommandType) + OUStringLiteral1(DB_DELIM));
519 
520 // Female: [database.sGenderColumn] != "rFemaleGenderValue" && [database.NameColumn]
521 // Male: [database.sGenderColumn] == "rFemaleGenderValue" && [database.rGenderColumn]
522 // Neutral: [database.sNameColumn]
523  OSL_ENSURE(!sGenderColumn.isEmpty() && !rFemaleGenderValue.isEmpty(),
524  "gender settings not available - how to form the condition?");
525  //column used as lastname
527  eGender <= SwMailMergeConfigItem::NEUTRAL; ++eGender)
528  {
529  Sequence< OUString> aEntries = rConfigItem.GetGreetings(static_cast<SwMailMergeConfigItem::Gender>(eGender));
530  sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(static_cast<SwMailMergeConfigItem::Gender>(eGender));
531  if( nCurrent >= 0 && nCurrent < aEntries.getLength())
532  {
533  const OUString sGreeting = aEntries[nCurrent];
534  OUString sCondition;
535  OUString sHideParagraphsExpression;
536  switch(eGender)
537  {
539  sCondition = sConditionBase + " != \"" + rFemaleGenderValue
540  + "\" OR NOT " + sNameColumnBase;
541  sHideParagraphsExpression = "!" + sNameColumnBase;
542  break;
544  sCondition = sConditionBase + " == \"" + rFemaleGenderValue
545  + "\" OR NOT " + sNameColumnBase;
546  break;
548  sCondition = sNameColumnBase;
549  break;
550  }
551 
552  if(bHideEmptyParagraphs && !sHideParagraphsExpression.isEmpty())
553  {
554  OUString sComplete = "(" + sCondition + ") OR (" + sHideParagraphsExpression + ")";
555  SwInsertField_Data aData(TYP_HIDDENPARAFLD, 0, sComplete, OUString(), 0, &rShell);
556  aFieldMgr.InsertField( aData );
557  }
558  else
559  {
560  SwInsertField_Data aData(TYP_HIDDENPARAFLD, 0, sCondition, OUString(), 0, &rShell);
561  aFieldMgr.InsertField( aData );
562  }
563  //now the text has to be inserted
564  const std::vector<std::pair<OUString, int>>& rHeaders = rConfigItem.GetDefaultAddressHeaders();
565  Sequence< OUString> aAssignment =
566  rConfigItem.GetColumnAssignment( rConfigItem.GetCurrentDBData() );
567  const OUString* pAssignment = aAssignment.getConstArray();
568  SwAddressIterator aIter(sGreeting);
569  while(aIter.HasMore())
570  {
571  SwMergeAddressItem aItem = aIter.Next();
572  if(aItem.bIsColumn)
573  {
574  OUString sConvertedColumn = aItem.sText;
575  for(sal_uInt32 nColumn = 0;
576  nColumn < rHeaders.size() &&
577  nColumn < static_cast<sal_uInt32>(aAssignment.getLength());
578  ++nColumn)
579  {
580  if (rHeaders[nColumn].first == aItem.sText &&
581  !pAssignment[nColumn].isEmpty())
582  {
583  sConvertedColumn = pAssignment[nColumn];
584  break;
585  }
586  }
588  sDBName + sConvertedColumn,
589  OUString(), 0, &rShell);
590  aFieldMgr.InsertField( aData );
591  }
592  else
593  {
594  rShell.Insert(aItem.sText);
595  }
596  }
597  //now add a new paragraph
598  rShell.SplitNode();
599  }
600  }
601 
602  }
603  rShell.UnlockExpFields();
604  }
605  else
606  {
608  sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(SwMailMergeConfigItem::NEUTRAL);
609  // Greeting
610  rShell.Insert(( nCurrent >= 0 && nCurrent < aEntries.getLength() )
611  ? aEntries[nCurrent] : OUString());
612  }
613  // now insert a new paragraph here if necessary
614  if(bSplitNode)
615  {
616  rShell.Push();
617  rShell.SplitNode();
619  }
620  //put the cursor to the start of the paragraph
621  rShell.SttPara();
622 
623  OSL_ENSURE(nullptr == rShell.GetTableFormat(), "What to do with a table here?");
624 }
625 
627 {
628  m_pExampleContainerWIN->Show();
629 
630  Reference< XModel > & xModel = m_pExampleFrame->GetModel();
631  //now the ViewOptions should be set properly
632  Reference< XViewSettingsSupplier > xSettings(xModel->getCurrentController(), UNO_QUERY);
633  m_xViewProperties = xSettings->getViewSettings();
634  Reference< XUnoTunnel > xDocTunnel(xModel, UNO_QUERY);
635  SwXTextDocument* pXDoc = reinterpret_cast<SwXTextDocument*>(xDocTunnel->getSomething(SwXTextDocument::getUnoTunnelId()));
636  SwDocShell* pDocShell = pXDoc->GetDocShell();
637  m_pExampleWrtShell = pDocShell->GetWrtShell();
638  OSL_ENSURE(m_pExampleWrtShell, "No SwWrtShell found!");
639  if(!m_pExampleWrtShell)
640  return;
641 
642  SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem();
643  if(rConfigItem.IsAddressBlock())
644  {
645  m_pAddressBlockFormat = InsertAddressFrame(
646  *m_pExampleWrtShell, rConfigItem,
648  m_pAlignToBodyCB->IsChecked(), true);
649  }
650  if(rConfigItem.IsGreetingLine(false))
651  {
652  InsertGreeting(*m_pExampleWrtShell, rConfigItem, true);
653  m_bIsGreetingInserted = true;
654  }
655 
656  Any aZoom;
657  aZoom <<= sal_Int16(DocumentZoomType::ENTIRE_PAGE);
658  m_xViewProperties->setPropertyValue(UNO_NAME_ZOOM_TYPE, aZoom);
659 
660  const SwFormatFrameSize& rPageSize = m_pExampleWrtShell->GetPageDesc(
661  m_pExampleWrtShell->GetCurPageDesc()).GetMaster().GetFrameSize();
662  m_pLeftMF->SetMax(rPageSize.GetWidth() - DEFAULT_LEFT_DISTANCE);
663  m_pTopMF->SetMax(rPageSize.GetHeight() - DEFAULT_TOP_DISTANCE);
664 }
665 
666 IMPL_LINK(SwMailMergeLayoutPage, ZoomHdl_Impl, ListBox&, rBox, void)
667 {
668  if(m_pExampleWrtShell)
669  {
670  sal_Int16 eType = DocumentZoomType::BY_VALUE;
671  short nZoom = 50;
672  switch(rBox.GetSelectedEntryPos())
673  {
674  case 0 : eType = DocumentZoomType::ENTIRE_PAGE; break;
675  case 1 : nZoom = 50; break;
676  case 2 : nZoom = 75; break;
677  case 3 : nZoom = 100; break;
678  }
679  Any aZoom;
680  aZoom <<= eType;
681  m_xViewProperties->setPropertyValue(UNO_NAME_ZOOM_TYPE, aZoom);
682  aZoom <<= nZoom;
683  m_xViewProperties->setPropertyValue(UNO_NAME_ZOOM_VALUE, aZoom);
684 
685  }
686 }
687 
688 IMPL_LINK_NOARG(SwMailMergeLayoutPage, ChangeAddressLoseFocusHdl_Impl, Control&, void)
689 {
690  ChangeAddressHdl_Impl(*m_pLeftMF);
691 }
692 IMPL_LINK_NOARG(SwMailMergeLayoutPage, ChangeAddressHdl_Impl, SpinField&, void)
693 {
694  if(m_pExampleWrtShell && m_pAddressBlockFormat)
695  {
696  long nLeft = static_cast< long >(m_pLeftMF->Denormalize(m_pLeftMF->GetValue(FieldUnit::TWIP)));
697  long nTop = static_cast< long >(m_pTopMF->Denormalize(m_pTopMF->GetValue(FieldUnit::TWIP)));
698 
699  SfxItemSet aSet(
700  m_pExampleWrtShell->GetAttrPool(),
702  if(m_pAlignToBodyCB->IsChecked())
703  aSet.Put(SwFormatHoriOrient( 0, text::HoriOrientation::NONE, text::RelOrientation::PAGE_PRINT_AREA ));
704  else
705  aSet.Put(SwFormatHoriOrient( nLeft, text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME ));
706  aSet.Put(SwFormatVertOrient( nTop, text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME ));
707  m_pExampleWrtShell->GetDoc()->SetFlyFrameAttr( *m_pAddressBlockFormat, aSet );
708  }
709 }
710 
711 IMPL_LINK(SwMailMergeLayoutPage, GreetingsHdl_Impl, Button*, pButton, void)
712 {
713  bool bDown = pButton == m_pDownPB;
714  bool bMoved = m_pExampleWrtShell->MoveParagraph( bDown ? 1 : -1 );
715  if (bMoved || bDown)
716  m_pWizard->GetConfigItem().MoveGreeting(bDown ? 1 : -1 );
717  if(!bMoved && bDown)
718  {
719  //insert a new paragraph before the greeting line
720  m_pExampleWrtShell->SplitNode();
721  }
722 }
723 
724 IMPL_LINK(SwMailMergeLayoutPage, AlignToTextHdl_Impl, Button*, pBox, void)
725 {
726  bool bCheck = static_cast<CheckBox*>(pBox)->IsChecked() && pBox->IsEnabled();
727  m_pLeftFT->Enable(!bCheck);
728  m_pLeftMF->Enable(!bCheck);
729  ChangeAddressHdl_Impl( *m_pLeftMF );
730 }
731 
732 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
SwMergeAddressItem Next()
bool HasMore() const
bool IsHideEmptyParagraphs() const
virtual void dispose() override
bool AppendTextNode()
Definition: editsh.cxx:210
bool SttPara(bool bSelect=false)
Definition: move.cxx:348
FieldUnit
#define RES_FRM_SIZE
Definition: hintids.hxx:194
sal_Int32 nCommandType
Definition: swdbdata.hxx:32
void SplitNode(bool bAutoFormat=false)
Definition: wrtsh1.cxx:966
bool IsAddressInserted() const
#define DEFAULT_LEFT_DISTANCE
bool DelFullPara()
Remove a complete paragraph.
Definition: eddel.cxx:337
#define UNO_NAME_ZOOM_VALUE
Definition: unoprnms.hxx:425
#define EX_SHOW_DEFAULT_PAGE
Definition: unotools.hxx:51
SwMailMergeConfigItem & GetConfigItem()
#define DEFAULT_ADDRESS_WIDTH
void SetClickHdl(const Link< Button *, void > &rLink)
bool SttEndDoc(bool bStt)
Definition: crsrsh.cxx:563
fill with spaces and tabs
Definition: crstate.hxx:29
bool GoCurrPara(SwPaM &rPam, SwMoveFnCollection const &aPosPara)
Definition: pam.cxx:949
const LanguageTag & GetUILanguageTag() const
long Height() const
signed char sal_Int8
void Insert(SwField const &)
Definition: wrtsh2.cxx:71
long GetWidth() const
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:92
#define UNO_NAME_ZOOM_TYPE
Definition: unoprnms.hxx:426
OUString & GetExcludeCountry() const
OUString sDataSource
Definition: swdbdata.hxx:30
static const AllSettings & GetSettings()
#define RES_SURROUND
Definition: hintids.hxx:206
bool Pop(SwCursorShell::PopMode=SwCursorShell::PopMode::DeleteStack)
Definition: wrtsh1.cxx:1690
SwMoveFnCollection const & fnParaStart
Definition: paminit.cxx:46
VclPtr< VclContainer > m_pGreetingLine
SwUndoId EndUndo(SwUndoId eUndoId=SwUndoId::EMPTY, const SwRewriter *pRewriter=nullptr)
Closes parenthesis of nUndoId, not used by UI.
Definition: edws.cxx:233
void set_height_request(sal_Int32 nHeightRequest)
#define DEFAULT_ADDRESS_HEIGHT
const SwDBData & GetCurrentDBData() const
VclPtr< MetricField > m_pLeftMF
sal_Int32 GetGreetingMoves() const
css::uno::Reference< css::frame::XModel > GetModel() const
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
bool InsertField(const SwInsertField_Data &rData)
Definition: fldmgr.cxx:906
virtual bool commitPage(::svt::WizardTypes::CommitPageReason _eReason) override
bool DelRight()
Definition: delete.cxx:292
SwWrtShell & GetWrtShell() const
Definition: view.hxx:400
Used by the UI to modify the document model.
Definition: wrtsh.hxx:86
bool GotoFly(const OUString &rName, FlyCntType eType=FLYCNTTYPE_ALL, bool bSelFrame=true)
Definition: move.cxx:590
Value in Var-direction gives minimum (can be exceeded but not be less).
Definition: fmtfsize.hxx:39
void Top(const long nTop)
Definition: swrect.hxx:202
void Enable(bool bEnable=true, bool bChild=true)
#define GREETING_TOP_DISTANCE
static SwFrameFormat * InsertAddressFrame(SwWrtShell &rShell, SwMailMergeConfigItem const &rConfigItem, const Point &rDestination, bool bAlignToBody, bool bExample)
static SwFrameFormat * InsertAddressAndGreeting(SwView const *pView, SwMailMergeConfigItem &rConfigItem, const Point &rAddressPos, bool bAlignToBody)
#define DEFAULT_TOP_DISTANCE
VclPtr< vcl::Window > m_pExampleContainerWIN
const OUString & GetName() const
Definition: format.hxx:111
VclPtr< VclContainer > m_pPosition
static void InsertGreeting(SwWrtShell &rShell, SwMailMergeConfigItem const &rConfigItem, bool bExample)
void set_width_request(sal_Int32 nWidthRequest)
VclPtr< PushButton > m_pUpPB
static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId()
Definition: unotxdoc.cxx:293
bool MovePara(SwWhichPara, SwMoveFnCollection const &)
Definition: crsrsh.cxx:684
bool IsGreetingInserted() const
const SfxItemPool & GetAttrPool() const
Definition: viewsh.hxx:614
const std::vector< std::pair< OUString, int > > & GetDefaultAddressHeaders() const
void clear()
static SW_DLLPUBLIC std::shared_ptr< const SfxFilter > GetFilterOfFormat(const OUString &rFormat, const SfxFilterContainer *pCnt=nullptr)
find for an internal format name the corresponding filter entry
Definition: iodetect.cxx:68
bool SetShadowCursorPos(const Point &rPt, SwFillMode eFillMode)
Definition: crstrvl.cxx:2042
VclPtr< PushButton > m_pDownPB
Style of a layout element.
Definition: frmfmt.hxx:57
#define RES_ANCHOR
Definition: hintids.hxx:209
SW_DLLPUBLIC FieldUnit GetDfltMetric(bool bWeb)
Definition: uitool.cxx:691
OUString const & GetURL() const
void Push()
store a copy of the current cursor on the cursor stack
Definition: crsrsh.cxx:2143
void SelectEntryPos(sal_Int32 nPos, bool bSelect=true)
sal_Int64 Normalize(sal_Int64 nValue) const
FlyAnchors.
Definition: fmtanchr.hxx:34
virtual ~SwMailMergeLayoutPage() override
SwUndoId StartUndo(SwUndoId eUndoId=SwUndoId::EMPTY, const SwRewriter *pRewriter=nullptr)
Undo: set up Undo parenthesis, return nUndoId of this parenthesis.
Definition: edws.cxx:222
OString stripStart(const OString &rIn, sal_Char c)
bool MoveParagraph(long nOffset=1)
Definition: ednumber.cxx:397
bool IsChecked() const
SwDocShell * GetDocShell()
Definition: unotxdoc.hxx:464
SwWrtShell * GetWrtShell()
Access to the SwWrtShell belonging to SwView.
Definition: docsh.hxx:223
sal_Int32 InsertEntry(const OUString &rStr, sal_Int32 nPos=LISTBOX_APPEND)
GUIDCNamePair const aData
virtual void ActivatePage() override
void Check(bool bCheck=true)
void SetSelectHdl(const Link< ListBox &, void > &rLink)
DocumentType const eType
void UnlockExpFields()
Definition: edfld.cxx:360
sal_Int64 Denormalize(sal_Int64 nValue) const
#define DB_DELIM
Definition: swtypes.hxx:141
long X() const
SwDocShell * GetDocShell()
Definition: view.cxx:1115
SwFrameFormat * GetTableFormat()
Definition: edws.cxx:182
css::uno::Sequence< OUString > GetColumnAssignment(const SwDBData &rDBData) const
Rect of current page.
sal_Int32 GetCurrentGreeting(Gender eType) const
void Left(const long nLeft)
Definition: swrect.hxx:193
SwMailMergeLayoutPage(SwMailMergeWizard *_pParent)
bool IsIndividualGreeting(bool bInEMail) const
const SwFrameFormat * NewFlyFrame(const SfxItemSet &rSet, bool bAnchValid=false, SwFrameFormat *pParent=nullptr)
Definition: fefly1.cxx:632
static OUString formatPercent(double dNumber, const LanguageTag &rLangTag)
VclPtr< CheckBox > m_pAlignToBodyCB
VclPtr< ListBox > m_pZoomLB
VclPtr< FixedText > m_pLeftFT
#define FILTER_XML
XML filter.
Definition: iodetect.hxx:35
void SetLoseFocusHdl(const Link< Control &, void > &rLink)
IMPL_LINK_NOARG(SwMailMergeLayoutPage, PreviewLoadedHdl_Impl, SwOneExampleFrame &, void)
VclPtr< MetricField > m_pTopMF
OUString GetAssignedColumn(sal_uInt32 nColumn) const
const css::uno::Sequence< OUString > GetAddressBlocks() const
const SwRect & GetCharRect() const
Definition: crsrsh.hxx:518
bool IsGreetingLine(bool bInEMail) const
void UnSelectFrame()
Definition: select.cxx:327
virtual void SetValue(sal_Int64 nNewValue, FieldUnit eInUnit)
const OUString & GetFemaleGenderValue() const
bool IsIncludeCountry() const
VclPtr< SwMailMergeWizard > m_pWizard
#define RES_BOX
Definition: hintids.hxx:211
void SAL_CALL first(const css::awt::SpinEvent &rEvent) override
void SetUpHdl(const Link< SpinField &, void > &rLink)
ScXMLEditAttributeMap::Entry const aEntries[]
bool IsEnabled() const
const SwFrameFormat * GetFlyFrameFormat() const
Get FlyFrameFormat; for UI macro linkage at Flys.
Definition: fefly1.cxx:1235
SwWrtShell * m_pExampleWrtShell
void SetDownHdl(const Link< SpinField &, void > &rLink)
Reference< XModel > xModel
bool IsAddressBlock() const
virtual void dispose() override
bool IsEndPara() const
Definition: crsrsh.cxx:1102
std::unique_ptr< SwOneExampleFrame > m_pExampleFrame
sal_Int64 GetValue(FieldUnit eOutUnit) const
long GetHeight() const
IMPL_LINK(SwMailMergeLayoutPage, ZoomHdl_Impl, ListBox &, rBox, void)
bool FwdPara()
Definition: wrtsh.hxx:223
OUString sCommand
Definition: swdbdata.hxx:31
void EnableKillingFile(bool bEnable=true)
void LockExpFields()
Definition: edfld.cxx:355
Definition: view.hxx:146
long Y() const
SwFrameFormat * m_pAddressBlockFormat
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
const css::uno::Sequence< OUString > GetGreetings(Gender eType) const