diff options
Diffstat (limited to 'sw/source/ui/dbui/mmlayoutpage.cxx')
-rw-r--r-- | sw/source/ui/dbui/mmlayoutpage.cxx | 692 |
1 files changed, 692 insertions, 0 deletions
diff --git a/sw/source/ui/dbui/mmlayoutpage.cxx b/sw/source/ui/dbui/mmlayoutpage.cxx new file mode 100644 index 0000000000..2e01e49ec9 --- /dev/null +++ b/sw/source/ui/dbui/mmlayoutpage.cxx @@ -0,0 +1,692 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <swtypes.hxx> +#include "mmlayoutpage.hxx" +#include <mailmergewizard.hxx> +#include <mmconfigitem.hxx> +#include <mailmergehelper.hxx> +#include <unotools.hxx> +#include <comphelper/string.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/servicehelper.hxx> +#include <i18nutil/unicode.hxx> +#include <unotools/tempfile.hxx> +#include <uitool.hxx> +#include <view.hxx> +#include <swundo.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/fcontnr.hxx> +#include <svtools/unitconv.hxx> +#include <com/sun/star/view/XViewSettingsSupplier.hpp> +#include <com/sun/star/view/DocumentZoomType.hpp> +#include <fldmgr.hxx> +#include <fldbas.hxx> +#include <unotxdoc.hxx> +#include <docsh.hxx> +#include <doc.hxx> +#include <wrtsh.hxx> +#include <fmtsrnd.hxx> +#include <pagedesc.hxx> +#include <fmtanchr.hxx> +#include <fmtornt.hxx> +#include <fmtfsize.hxx> +#include <editeng/boxitem.hxx> +#include <osl/file.hxx> +#include <vcl/settings.hxx> +#include <unoprnms.hxx> + +#include <dbui.hrc> + +using namespace osl; +using namespace svt; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::view; + +constexpr tools::Long DEFAULT_LEFT_DISTANCE = o3tl::toTwips(25, o3tl::Length::mm); // 2,5 cm +constexpr tools::Long DEFAULT_TOP_DISTANCE = o3tl::toTwips(55, o3tl::Length::mm); // 5,5 cm +constexpr tools::Long GREETING_TOP_DISTANCE = o3tl::toTwips(125, o3tl::Length::mm); //12,5 cm +constexpr tools::Long DEFAULT_ADDRESS_WIDTH = o3tl::toTwips(75, o3tl::Length::mm); // 7,5 cm +constexpr tools::Long DEFAULT_ADDRESS_HEIGHT = o3tl::toTwips(35, o3tl::Length::mm); // 3,5cm + +SwMailMergeLayoutPage::SwMailMergeLayoutPage(weld::Container* pPage, SwMailMergeWizard* pWizard) + : vcl::OWizardPage(pPage, pWizard, "modules/swriter/ui/mmlayoutpage.ui", "MMLayoutPage") + , m_pExampleWrtShell(nullptr) + , m_pAddressBlockFormat(nullptr) + , m_bIsGreetingInserted(false) + , m_pWizard(pWizard) + , m_xPosition(m_xBuilder->weld_container("addresspos")) + , m_xAlignToBodyCB(m_xBuilder->weld_check_button("align")) + , m_xLeftFT(m_xBuilder->weld_label("leftft")) + , m_xLeftMF(m_xBuilder->weld_metric_spin_button("left", FieldUnit::CM)) + , m_xTopMF(m_xBuilder->weld_metric_spin_button("top", FieldUnit::CM)) + , m_xGreetingLine(m_xBuilder->weld_container("greetingspos")) + , m_xUpPB(m_xBuilder->weld_button("up")) + , m_xDownPB(m_xBuilder->weld_button("down")) + , m_xZoomLB(m_xBuilder->weld_combo_box("zoom")) +{ + std::shared_ptr<const SfxFilter> pSfxFlt = + SwDocShell::Factory().GetFilterContainer()-> + GetFilter4FilterName("writer8", SfxFilterFlags::EXPORT); + + //save the current document into a temporary file + { + //temp file needs its own block + //creating with extension is not supported by a static method :-( + OUString const sExt( + comphelper::string::stripStart(pSfxFlt->GetDefaultExtension(),'*')); + utl::TempFileNamed aTempFile( u"", true, sExt ); + aTempFile.EnableKillingFile(); + m_sExampleURL = aTempFile.GetURL(); + } + SwView* pView = m_pWizard->GetSwView(); + // Don't save embedded data set! It would steal it from current document. + uno::Sequence< beans::PropertyValue > aValues = + { + comphelper::makePropertyValue("FilterName", pSfxFlt->GetFilterName()), + comphelper::makePropertyValue("NoEmbDataSet", true) + }; + + uno::Reference< frame::XStorable > xStore( pView->GetDocShell()->GetModel(), uno::UNO_QUERY); + xStore->storeToURL( m_sExampleURL, aValues ); + + Link<SwOneExampleFrame&,void> aLink(LINK(this, SwMailMergeLayoutPage, PreviewLoadedHdl_Impl)); + m_xExampleFrame.reset(new SwOneExampleFrame(EX_SHOW_DEFAULT_PAGE, &aLink, &m_sExampleURL)); + m_xExampleContainerWIN.reset(new weld::CustomWeld(*m_xBuilder, "example", *m_xExampleFrame)); + + Size aSize = m_xExampleFrame->GetDrawingArea()->get_ref_device().LogicToPixel( + Size(124, 159), MapMode(MapUnit::MapAppFont)); + m_xExampleFrame->set_size_request(aSize.Width(), aSize.Height()); + + m_xExampleContainerWIN->hide(); + + m_xLeftMF->set_value(m_xLeftMF->normalize(DEFAULT_LEFT_DISTANCE), FieldUnit::TWIP); + m_xTopMF->set_value(m_xTopMF->normalize(DEFAULT_TOP_DISTANCE), FieldUnit::TWIP); + + const LanguageTag& rLang = Application::GetSettings().GetUILanguageTag(); + m_xZoomLB->append_text(unicode::formatPercent(50, rLang)); + m_xZoomLB->append_text(unicode::formatPercent(75, rLang)); + m_xZoomLB->append_text(unicode::formatPercent(100, rLang)); + m_xZoomLB->set_active(0); //page size + m_xZoomLB->connect_changed(LINK(this, SwMailMergeLayoutPage, ZoomHdl_Impl)); + + Link<weld::MetricSpinButton&,void> aFrameHdl = LINK(this, SwMailMergeLayoutPage, ChangeAddressHdl_Impl); + m_xLeftMF->connect_value_changed(aFrameHdl); + m_xTopMF->connect_value_changed(aFrameHdl); + + FieldUnit eFieldUnit = ::GetDfltMetric(false); + ::SetFieldUnit( *m_xLeftMF, eFieldUnit ); + ::SetFieldUnit( *m_xTopMF, eFieldUnit ); + + Link<weld::Button&,void> aUpDownHdl = LINK(this, SwMailMergeLayoutPage, GreetingsHdl_Impl ); + m_xUpPB->connect_clicked(aUpDownHdl); + m_xDownPB->connect_clicked(aUpDownHdl); + m_xAlignToBodyCB->connect_toggled(LINK(this, SwMailMergeLayoutPage, AlignToTextHdl_Impl)); + m_xAlignToBodyCB->set_active(true); +} + +SwMailMergeLayoutPage::~SwMailMergeLayoutPage() +{ + File::remove( m_sExampleURL ); +} + +void SwMailMergeLayoutPage::Activate() +{ + SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem(); + bool bGreetingLine = rConfigItem.IsGreetingLine(false) && !rConfigItem.IsGreetingInserted(); + bool bAddressBlock = rConfigItem.IsAddressBlock() && !rConfigItem.IsAddressInserted(); + + m_xPosition->set_sensitive(bAddressBlock); + AlignToTextHdl_Impl(*m_xAlignToBodyCB); + + m_xGreetingLine->set_sensitive(bGreetingLine); + + //check if greeting and/or address frame have to be inserted/removed + if(!m_pExampleWrtShell) // initially there's nothing to check + return; + + if(!rConfigItem.IsGreetingInserted() && + m_bIsGreetingInserted != bGreetingLine ) + { + if( m_bIsGreetingInserted ) + { + m_pExampleWrtShell->DelFullPara(); + m_bIsGreetingInserted = false; + } + else + { + InsertGreeting(*m_pExampleWrtShell, m_pWizard->GetConfigItem(), true); + m_bIsGreetingInserted = true; + } + } + if(!rConfigItem.IsAddressInserted() && + rConfigItem.IsAddressBlock() != ( nullptr != m_pAddressBlockFormat )) + { + if( m_pAddressBlockFormat ) + { + m_pExampleWrtShell->Push(); + m_pExampleWrtShell->GotoFly( m_pAddressBlockFormat->GetName() ); + m_pExampleWrtShell->DelRight(); + m_pAddressBlockFormat = nullptr; + m_pExampleWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent); + } + else + { + tools::Long nLeft = static_cast< tools::Long >(m_xLeftMF->denormalize(m_xLeftMF->get_value(FieldUnit::TWIP))); + tools::Long nTop = static_cast< tools::Long >(m_xTopMF->denormalize(m_xTopMF->get_value(FieldUnit::TWIP))); + m_pAddressBlockFormat = InsertAddressFrame( + *m_pExampleWrtShell, m_pWizard->GetConfigItem(), + Point(nLeft, nTop), + m_xAlignToBodyCB->get_active(), true); + } + } + m_xExampleFrame->Invalidate(); +} + +bool SwMailMergeLayoutPage::commitPage(::vcl::WizardTypes::CommitPageReason eReason) +{ + //now insert the frame and the greeting + SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem(); + if (eReason == ::vcl::WizardTypes::eTravelForward || eReason == ::vcl::WizardTypes::eFinish) + { + tools::Long nLeft = static_cast< tools::Long >(m_xLeftMF->denormalize(m_xLeftMF->get_value(FieldUnit::TWIP))); + tools::Long nTop = static_cast< tools::Long >(m_xTopMF->denormalize(m_xTopMF->get_value(FieldUnit::TWIP))); + InsertAddressAndGreeting( + m_pWizard->GetSwView(), + rConfigItem, + Point(nLeft, nTop), + m_xAlignToBodyCB->get_active()); + } + return true; +} + +SwFrameFormat* SwMailMergeLayoutPage::InsertAddressAndGreeting(SwView const * pView, + SwMailMergeConfigItem& rConfigItem, + const Point& rAddressPosition, + bool bAlignToBody) +{ + SwFrameFormat* pAddressBlockFormat = nullptr; + pView->GetWrtShell().StartUndo(SwUndoId::INSERT); + if(rConfigItem.IsAddressBlock() && !rConfigItem.IsAddressInserted()) + { + //insert the frame + Point aAddressPosition(DEFAULT_LEFT_DISTANCE, DEFAULT_TOP_DISTANCE); + if(rAddressPosition.X() > 0 && rAddressPosition.Y() > 0) + aAddressPosition = rAddressPosition; + pAddressBlockFormat = InsertAddressFrame( pView->GetWrtShell(), + rConfigItem, + aAddressPosition, bAlignToBody, false); + rConfigItem.SetAddressInserted(); + } + //now the greeting + if(rConfigItem.IsGreetingLine(false) && !rConfigItem.IsGreetingInserted()) + { + InsertGreeting( pView->GetWrtShell(), rConfigItem, false); + rConfigItem.SetGreetingInserted(); + } + pView->GetWrtShell().EndUndo(SwUndoId::INSERT); + return pAddressBlockFormat; +} + +SwFrameFormat* SwMailMergeLayoutPage::InsertAddressFrame( + SwWrtShell& rShell, + SwMailMergeConfigItem const & rConfigItem, + const Point& rDestination, + bool bAlignLeft, + bool bExample) +{ + // insert the address block and the greeting line + SfxItemSetFixed< + RES_FRM_SIZE, RES_FRM_SIZE, + RES_SURROUND, RES_ANCHOR, + RES_BOX, RES_BOX> aSet( rShell.GetAttrPool() ); + aSet.Put(SwFormatAnchor(RndStdIds::FLY_AT_PAGE, 1)); + if(bAlignLeft) + aSet.Put(SwFormatHoriOrient( 0, text::HoriOrientation::NONE, text::RelOrientation::PAGE_PRINT_AREA )); + else + aSet.Put(SwFormatHoriOrient( rDestination.X(), text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME )); + aSet.Put(SwFormatVertOrient( rDestination.Y(), text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME )); + aSet.Put(SwFormatFrameSize( SwFrameSize::Minimum, DEFAULT_ADDRESS_WIDTH, DEFAULT_ADDRESS_HEIGHT )); + // the example gets a border around the frame, the real document doesn't get one + if(!bExample) + aSet.Put(SvxBoxItem( RES_BOX )); + aSet.Put(SwFormatSurround( css::text::WrapTextMode_NONE )); + + rShell.NewFlyFrame(aSet, true ); + SwFrameFormat* pRet = rShell.GetFlyFrameFormat(); + OSL_ENSURE( pRet, "Fly not inserted" ); + + rShell.UnSelectFrame(); + const Sequence< OUString> aBlocks = rConfigItem.GetAddressBlocks(); + if(bExample) + { + rShell.Insert(aBlocks[0]); + } + else + { + //the placeholders should be replaced by the appropriate fields + SwFieldMgr aFieldMgr(&rShell); + //create a database string source.command.commandtype.column + const SwDBData& rData = rConfigItem.GetCurrentDBData(); + OUString sDBName(rData.sDataSource + OUStringChar(DB_DELIM) + + rData.sCommand + OUStringChar(DB_DELIM)); + const OUString sDatabaseConditionPrefix(sDBName.replace(DB_DELIM, '.')); + sDBName += OUString::number(rData.nCommandType) + OUStringChar(DB_DELIM); + + // if only the country is in an address line the + // paragraph has to be hidden depending on the + // IsIncludeCountry()/GetExcludeCountry() settings + + bool bIncludeCountry = rConfigItem.IsIncludeCountry(); + bool bHideEmptyParagraphs = rConfigItem.IsHideEmptyParagraphs(); + const OUString rExcludeCountry = rConfigItem.GetExcludeCountry(); + bool bSpecialReplacementForCountry = (!bIncludeCountry || !rExcludeCountry.isEmpty()); + + const std::vector<std::pair<OUString, int>>& rHeaders = rConfigItem.GetDefaultAddressHeaders(); + Sequence< OUString> aAssignment = + rConfigItem.GetColumnAssignment( rConfigItem.GetCurrentDBData() ); + const OUString* pAssignment = aAssignment.getConstArray(); + const OUString sCountryColumn( + (aAssignment.getLength() > MM_PART_COUNTRY && !aAssignment[MM_PART_COUNTRY].isEmpty()) + ? aAssignment[MM_PART_COUNTRY] + : rHeaders[MM_PART_COUNTRY].first); + + OUString sHideParagraphsExpression; + SwAddressIterator aIter(aBlocks[0]); + while(aIter.HasMore()) + { + SwMergeAddressItem aItem = aIter.Next(); + if(aItem.bIsColumn) + { + OUString sConvertedColumn = aItem.sText; + auto nSize = std::min(static_cast<sal_uInt32>(rHeaders.size()), + static_cast<sal_uInt32>(aAssignment.getLength())); + for(sal_uInt32 nColumn = 0; nColumn < nSize; ++nColumn) + { + if (rHeaders[nColumn].first == aItem.sText && + !pAssignment[nColumn].isEmpty()) + { + sConvertedColumn = pAssignment[nColumn]; + break; + } + } + const OUString sDB(sDBName + sConvertedColumn); + + if(!sHideParagraphsExpression.isEmpty()) + sHideParagraphsExpression += " AND "; + sHideParagraphsExpression += "![" + sDatabaseConditionPrefix + sConvertedColumn + "]"; + + if( bSpecialReplacementForCountry && sCountryColumn == sConvertedColumn ) + { + // now insert a hidden paragraph field + if( !rExcludeCountry.isEmpty() ) + { + const OUString sExpression("[" + sDatabaseConditionPrefix + sCountryColumn + "]"); + SwInsertField_Data aData(SwFieldTypesEnum::ConditionalText, 0, + sExpression + " != \"" + rExcludeCountry + "\"", + sExpression, + 0, &rShell ); + aFieldMgr.InsertField( aData ); + } + else + { + SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, "", "", 0, &rShell ); + aFieldMgr.InsertField( aData ); + } + } + else + { + SwInsertField_Data aData(SwFieldTypesEnum::Database, 0, sDB, OUString(), 0, &rShell); + aFieldMgr.InsertField( aData ); + } + } + else if(!aItem.bIsReturn) + { + rShell.Insert(aItem.sText); + } + else + { + if(bHideEmptyParagraphs) + { + SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sHideParagraphsExpression, OUString(), 0, &rShell); + aFieldMgr.InsertField( aData ); + } + sHideParagraphsExpression.clear(); + //now add a new paragraph + rShell.SplitNode(); + } + } + if(bHideEmptyParagraphs && !sHideParagraphsExpression.isEmpty()) + { + SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sHideParagraphsExpression, OUString(), 0, &rShell); + aFieldMgr.InsertField( aData ); + } + } + return pRet; +} + +void SwMailMergeLayoutPage::InsertGreeting(SwWrtShell& rShell, SwMailMergeConfigItem const & rConfigItem, bool bExample) +{ + //set the cursor to the desired position - if no text content is here then + //new paragraphs are inserted + const SwRect& rPageRect = rShell.GetAnyCurRect(CurRectType::Page); + const Point aGreetingPos( DEFAULT_LEFT_DISTANCE + rPageRect.Left(), GREETING_TOP_DISTANCE ); + + const bool bRet = rShell.SetShadowCursorPos( aGreetingPos, SwFillMode::TabSpace ); + + if(!bRet) + { + //there's already text at the desired position + //go to start of the doc, directly! + rShell.SttEndDoc(true); + //and go by paragraph until the position is reached + tools::Long nYPos = rShell.GetCharRect().Top(); + while(nYPos < GREETING_TOP_DISTANCE) + { + if(!rShell.FwdPara()) + break; + nYPos = rShell.GetCharRect().Top(); + } + //text needs to be appended + while(nYPos < GREETING_TOP_DISTANCE) + { + if(!rShell.AppendTextNode()) + break; + nYPos = rShell.GetCharRect().Top(); + } + } + else + { + //we may end up inside of a paragraph if the left margin is not at DEFAULT_LEFT_DISTANCE + rShell.MovePara(GoCurrPara, fnParaStart); + } + bool bSplitNode = !rShell.IsEndPara(); + SwNodeOffset nMoves(rConfigItem.GetGreetingMoves()); + if( !bExample && SwNodeOffset(0) != nMoves ) + { + if(nMoves < SwNodeOffset(0)) + { + rShell.MoveParagraph( nMoves ); + } + else + while(nMoves) + { + bool bMoved = rShell.MoveParagraph(); + if(!bMoved) + { + //insert a new paragraph before the greeting line + rShell.SplitNode(); + } + --nMoves; + } + } + //now insert the greeting text - if we have any? + const bool bIndividual = rConfigItem.IsIndividualGreeting(false); + if(bIndividual) + { + //lock expression fields - prevents hiding of the paragraph to insert into + rShell.LockExpFields(); + if(bExample) + { + for(sal_Int8 eGender = SwMailMergeConfigItem::FEMALE; + eGender <= SwMailMergeConfigItem::NEUTRAL; ++eGender) + { + Sequence< OUString > aEntries = + rConfigItem.GetGreetings(static_cast<SwMailMergeConfigItem::Gender>(eGender)); + sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(static_cast<SwMailMergeConfigItem::Gender>(eGender)); + if( nCurrent >= 0 && nCurrent < aEntries.getLength()) + { + // Greeting + rShell.Insert(aEntries[nCurrent]); + break; + } + } + } + else + { + SwFieldMgr aFieldMgr(&rShell); + //three paragraphs, each with an appropriate hidden paragraph field + //are to be inserted + + //name of the gender column + const OUString sGenderColumn = rConfigItem.GetAssignedColumn(MM_PART_GENDER); + const OUString sNameColumn = rConfigItem.GetAssignedColumn(MM_PART_LASTNAME); + + const OUString& rFemaleGenderValue = rConfigItem.GetFemaleGenderValue(); + bool bHideEmptyParagraphs = rConfigItem.IsHideEmptyParagraphs(); + const SwDBData& rData = rConfigItem.GetCurrentDBData(); + const OUString sCommonBase(rData.sDataSource + "." + rData.sCommand + "."); + const OUString sConditionBase("[" + sCommonBase + sGenderColumn + "]"); + const OUString sNameColumnBase("[" + sCommonBase + sNameColumn + "]"); + + const OUString sDBName(rData.sDataSource + OUStringChar(DB_DELIM) + + rData.sCommand + OUStringChar(DB_DELIM) + + OUString::number(rData.nCommandType) + OUStringChar(DB_DELIM)); + +// Female: [database.sGenderColumn] != "rFemaleGenderValue" && [database.NameColumn] +// Male: [database.sGenderColumn] == "rFemaleGenderValue" && [database.rGenderColumn] +// Neutral: [database.sNameColumn] + OSL_ENSURE(!sGenderColumn.isEmpty() && !rFemaleGenderValue.isEmpty(), + "gender settings not available - how to form the condition?"); + //column used as lastname + for(sal_Int8 eGender = SwMailMergeConfigItem::FEMALE; + eGender <= SwMailMergeConfigItem::NEUTRAL; ++eGender) + { + Sequence< OUString> aEntries = rConfigItem.GetGreetings(static_cast<SwMailMergeConfigItem::Gender>(eGender)); + sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(static_cast<SwMailMergeConfigItem::Gender>(eGender)); + if( nCurrent >= 0 && nCurrent < aEntries.getLength()) + { + const OUString sGreeting = aEntries[nCurrent]; + OUString sCondition; + OUString sHideParagraphsExpression; + switch(eGender) + { + case SwMailMergeConfigItem::FEMALE: + sCondition = sConditionBase + " != \"" + rFemaleGenderValue + + "\" OR NOT " + sNameColumnBase; + sHideParagraphsExpression = "!" + sNameColumnBase; + break; + case SwMailMergeConfigItem::MALE: + sCondition = sConditionBase + " == \"" + rFemaleGenderValue + + "\" OR NOT " + sNameColumnBase; + break; + case SwMailMergeConfigItem::NEUTRAL: + sCondition = sNameColumnBase; + break; + } + + if(bHideEmptyParagraphs && !sHideParagraphsExpression.isEmpty()) + { + OUString sComplete = "(" + sCondition + ") OR (" + sHideParagraphsExpression + ")"; + SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sComplete, OUString(), 0, &rShell); + aFieldMgr.InsertField( aData ); + } + else + { + SwInsertField_Data aData(SwFieldTypesEnum::HiddenParagraph, 0, sCondition, OUString(), 0, &rShell); + aFieldMgr.InsertField( aData ); + } + //now the text has to be inserted + const std::vector<std::pair<OUString, int>>& rHeaders = rConfigItem.GetDefaultAddressHeaders(); + Sequence< OUString> aAssignment = + rConfigItem.GetColumnAssignment( rConfigItem.GetCurrentDBData() ); + const OUString* pAssignment = aAssignment.getConstArray(); + SwAddressIterator aIter(sGreeting); + while(aIter.HasMore()) + { + SwMergeAddressItem aItem = aIter.Next(); + if(aItem.bIsColumn) + { + OUString sConvertedColumn = aItem.sText; + auto nSize = std::min(static_cast<sal_uInt32>(rHeaders.size()), + static_cast<sal_uInt32>(aAssignment.getLength())); + for(sal_uInt32 nColumn = 0; nColumn < nSize; ++nColumn) + { + if (rHeaders[nColumn].first == aItem.sText && + !pAssignment[nColumn].isEmpty()) + { + sConvertedColumn = pAssignment[nColumn]; + break; + } + } + SwInsertField_Data aData(SwFieldTypesEnum::Database, 0, + sDBName + sConvertedColumn, + OUString(), 0, &rShell); + aFieldMgr.InsertField( aData ); + } + else + { + rShell.Insert(aItem.sText); + } + } + //now add a new paragraph + rShell.SplitNode(); + } + } + + } + rShell.UnlockExpFields(); + } + else + { + Sequence< OUString> aEntries = rConfigItem.GetGreetings(SwMailMergeConfigItem::NEUTRAL); + sal_Int32 nCurrent = rConfigItem.GetCurrentGreeting(SwMailMergeConfigItem::NEUTRAL); + // Greeting + rShell.Insert(( nCurrent >= 0 && nCurrent < aEntries.getLength() ) + ? aEntries[nCurrent] : OUString()); + } + // now insert a new paragraph here if necessary + if(bSplitNode) + { + rShell.Push(); + rShell.SplitNode(); + rShell.Pop(SwCursorShell::PopMode::DeleteCurrent); + } + //put the cursor to the start of the paragraph + rShell.SttPara(); + + OSL_ENSURE(nullptr == rShell.GetTableFormat(), "What to do with a table here?"); +} + +IMPL_LINK_NOARG(SwMailMergeLayoutPage, PreviewLoadedHdl_Impl, SwOneExampleFrame&, void) +{ + m_xExampleContainerWIN->show(); + + Reference< XModel > & xModel = m_xExampleFrame->GetModel(); + //now the ViewOptions should be set properly + Reference< XViewSettingsSupplier > xSettings(xModel->getCurrentController(), UNO_QUERY); + m_xViewProperties = xSettings->getViewSettings(); + auto pXDoc = comphelper::getFromUnoTunnel<SwXTextDocument>(xModel); + SwDocShell* pDocShell = pXDoc->GetDocShell(); + m_pExampleWrtShell = pDocShell->GetWrtShell(); + OSL_ENSURE(m_pExampleWrtShell, "No SwWrtShell found!"); + if(!m_pExampleWrtShell) + return; + + SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem(); + if(rConfigItem.IsAddressBlock()) + { + m_pAddressBlockFormat = InsertAddressFrame( + *m_pExampleWrtShell, rConfigItem, + Point(DEFAULT_LEFT_DISTANCE, DEFAULT_TOP_DISTANCE), + m_xAlignToBodyCB->get_active(), true); + } + if(rConfigItem.IsGreetingLine(false)) + { + InsertGreeting(*m_pExampleWrtShell, rConfigItem, true); + m_bIsGreetingInserted = true; + } + + ZoomHdl_Impl(*m_xZoomLB); + + const SwFormatFrameSize& rPageSize = m_pExampleWrtShell->GetPageDesc( + m_pExampleWrtShell->GetCurPageDesc()).GetMaster().GetFrameSize(); + m_xLeftMF->set_max(rPageSize.GetWidth() - DEFAULT_LEFT_DISTANCE, FieldUnit::NONE); + m_xTopMF->set_max(rPageSize.GetHeight() - DEFAULT_TOP_DISTANCE, FieldUnit::NONE); +} + +IMPL_LINK(SwMailMergeLayoutPage, ZoomHdl_Impl, weld::ComboBox&, rBox, void) +{ + if (!m_pExampleWrtShell) + return; + + sal_Int16 eType = DocumentZoomType::BY_VALUE; + short nZoom = 50; + switch (rBox.get_active()) + { + case 0 : eType = DocumentZoomType::ENTIRE_PAGE; break; + case 1 : nZoom = 50; break; + case 2 : nZoom = 75; break; + case 3 : nZoom = 100; break; + } + Any aZoom; + aZoom <<= eType; + m_xViewProperties->setPropertyValue(UNO_NAME_ZOOM_TYPE, aZoom); + aZoom <<= nZoom; + m_xViewProperties->setPropertyValue(UNO_NAME_ZOOM_VALUE, aZoom); + + m_xExampleFrame->Invalidate(); +} + +IMPL_LINK_NOARG(SwMailMergeLayoutPage, ChangeAddressHdl_Impl, weld::MetricSpinButton&, void) +{ + if(!(m_pExampleWrtShell && m_pAddressBlockFormat)) + return; + + tools::Long nLeft = static_cast< tools::Long >(m_xLeftMF->denormalize(m_xLeftMF->get_value(FieldUnit::TWIP))); + tools::Long nTop = static_cast< tools::Long >(m_xTopMF->denormalize(m_xTopMF->get_value(FieldUnit::TWIP))); + + SfxItemSetFixed<RES_VERT_ORIENT, RES_ANCHOR> aSet( + m_pExampleWrtShell->GetAttrPool()); + if (m_xAlignToBodyCB->get_active()) + aSet.Put(SwFormatHoriOrient( 0, text::HoriOrientation::NONE, text::RelOrientation::PAGE_PRINT_AREA )); + else + aSet.Put(SwFormatHoriOrient( nLeft, text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME )); + aSet.Put(SwFormatVertOrient( nTop, text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME )); + m_pExampleWrtShell->GetDoc()->SetFlyFrameAttr( *m_pAddressBlockFormat, aSet ); + m_xExampleFrame->Invalidate(); +} + +IMPL_LINK(SwMailMergeLayoutPage, GreetingsHdl_Impl, weld::Button&, rButton, void) +{ + bool bDown = &rButton == m_xDownPB.get(); + bool bMoved = m_pExampleWrtShell->MoveParagraph( SwNodeOffset(bDown ? 1 : -1) ); + if (bMoved || bDown) + m_pWizard->GetConfigItem().MoveGreeting(bDown ? 1 : -1 ); + if(!bMoved && bDown) + { + //insert a new paragraph before the greeting line + m_pExampleWrtShell->SplitNode(); + } + m_xExampleFrame->Invalidate(); +} + +IMPL_LINK(SwMailMergeLayoutPage, AlignToTextHdl_Impl, weld::Toggleable&, rBox, void) +{ + bool bCheck = rBox.get_active() && rBox.get_sensitive(); + m_xLeftFT->set_sensitive(!bCheck); + m_xLeftMF->set_sensitive(!bCheck); + ChangeAddressHdl_Impl( *m_xLeftMF ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |