1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "mmaddressblockpage.hxx"
21 #include <mailmergewizard.hxx>
22 #include <swtypes.hxx>
23 #include "addresslistdialog.hxx"
24 #include <editeng/eeitem.hxx>
25 #include <o3tl/safeint.hxx>
26 #include <svl/grabbagitem.hxx>
27 #include <svl/itemset.hxx>
29 #include <vcl/commandevent.hxx>
30 #include <vcl/event.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/weld.hxx>
33 #include <vcl/transfer.hxx>
34 #include <mmconfigitem.hxx>
35 #include <com/sun/star/container/XNameAccess.hpp>
36 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
37 #include <com/sun/star/sdbc/SQLException.hpp>
38 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
39 #include <com/sun/star/sdb/XColumn.hpp>
40 #include <comphelper/sequence.hxx>
41 #include <comphelper/string.hxx>
42 #include <comphelper/diagnose_ex.hxx>
45 #include <strings.hrc>
46 #include <mmaddressblockpage.hrc>
49 using namespace ::com::sun::star
;
50 using namespace ::com::sun::star::container
;
51 using namespace ::com::sun::star::sdb
;
52 using namespace ::com::sun::star::sdbc
;
53 using namespace ::com::sun::star::sdbcx
;
55 SwMailMergeAddressBlockPage::SwMailMergeAddressBlockPage(weld::Container
* pPage
, SwMailMergeWizard
* pWizard
)
56 : vcl::OWizardPage(pPage
, pWizard
, "modules/swriter/ui/mmaddressblockpage.ui", "MMAddressBlockPage")
58 , m_xAddressListPB(m_xBuilder
->weld_button("addresslist"))
59 , m_xCurrentAddressFI(m_xBuilder
->weld_label("currentaddress"))
60 , m_xStep2(m_xBuilder
->weld_container("step2"))
61 , m_xStep3(m_xBuilder
->weld_container("step3"))
62 , m_xStep4(m_xBuilder
->weld_container("step4"))
63 , m_xSettingsFI(m_xBuilder
->weld_label("settingsft"))
64 , m_xAddressCB(m_xBuilder
->weld_check_button("address"))
65 , m_xSettingsPB(m_xBuilder
->weld_button("settings"))
66 , m_xHideEmptyParagraphsCB(m_xBuilder
->weld_check_button("hideempty"))
67 , m_xAssignPB(m_xBuilder
->weld_button("assign"))
68 , m_xDocumentIndexFI(m_xBuilder
->weld_label("documentindex"))
69 , m_xPrevSetIB(m_xBuilder
->weld_button("prev"))
70 , m_xNextSetIB(m_xBuilder
->weld_button("next"))
71 , m_xDifferentlist(m_xBuilder
->weld_button("differentlist"))
72 , m_xSettings(new SwAddressPreview(m_xBuilder
->weld_scrolled_window("settingspreviewwin", true)))
73 , m_xPreview(new SwAddressPreview(m_xBuilder
->weld_scrolled_window("addresspreviewwin", true)))
74 , m_xSettingsWIN(new weld::CustomWeld(*m_xBuilder
, "settingspreview", *m_xSettings
))
75 , m_xPreviewWIN(new weld::CustomWeld(*m_xBuilder
, "addresspreview", *m_xPreview
))
77 m_xSettingsWIN
->set_size_request(m_xDifferentlist
->get_approximate_digit_width() * 40,
78 m_xDifferentlist
->get_text_height() * 6);
79 m_xPreviewWIN
->set_size_request(m_xDifferentlist
->get_approximate_digit_width() * 44,
80 m_xDifferentlist
->get_text_height() * 6);
81 m_sChangeAddress
= m_xDifferentlist
->get_label();
82 m_sDocument
= m_xDocumentIndexFI
->get_label();
84 m_sCurrentAddress
= m_xCurrentAddressFI
->get_label();
85 m_xAddressListPB
->connect_clicked(LINK(this, SwMailMergeAddressBlockPage
, AddressListHdl_Impl
));
86 m_xSettingsPB
->connect_clicked(LINK(this, SwMailMergeAddressBlockPage
, SettingsHdl_Impl
));
87 m_xAssignPB
->connect_clicked(LINK(this, SwMailMergeAddressBlockPage
, AssignHdl_Impl
));
88 m_xAddressCB
->connect_toggled(LINK(this, SwMailMergeAddressBlockPage
, AddressBlockHdl_Impl
));
89 m_xSettings
->SetSelectHdl(LINK(this, SwMailMergeAddressBlockPage
, AddressBlockSelectHdl_Impl
));
90 m_xHideEmptyParagraphsCB
->connect_toggled(LINK(this, SwMailMergeAddressBlockPage
, HideParagraphsHdl_Impl
));
92 Link
<weld::Button
&,void> aLink
= LINK(this, SwMailMergeAddressBlockPage
, InsertDataHdl_Impl
);
93 m_xPrevSetIB
->connect_clicked(aLink
);
94 m_xNextSetIB
->connect_clicked(aLink
);
96 // lock in preferred size including current address line
97 Size
aSize1(m_xContainer
->get_preferred_size());
99 OUString sOrigLabel
= m_xAddressListPB
->get_label();
100 m_xAddressListPB
->set_label(m_sChangeAddress
);
101 Size
aSize2(m_xContainer
->get_preferred_size());
102 m_xAddressListPB
->set_label(sOrigLabel
);
104 m_xCurrentAddressFI
->hide();
106 m_xContainer
->set_size_request(std::max(aSize1
.Width(), aSize2
.Width()),
107 std::max(aSize1
.Height(), aSize2
.Height()));
110 SwMailMergeAddressBlockPage::~SwMailMergeAddressBlockPage()
112 m_xPreviewWIN
.reset();
113 m_xSettingsWIN
.reset();
118 bool SwMailMergeAddressBlockPage::canAdvance() const
120 return m_pWizard
->GetConfigItem().GetResultSet().is();
123 void SwMailMergeAddressBlockPage::Activate()
125 SwMailMergeConfigItem
& rConfigItem
= m_pWizard
->GetConfigItem();
126 bool bIsLetter
= rConfigItem
.IsOutputToLetter();
128 //no address block is created for e-Mail
129 m_xStep2
->set_visible(bIsLetter
);
130 m_xStep3
->set_visible(bIsLetter
);
131 m_xStep4
->set_visible(bIsLetter
);
136 m_xHideEmptyParagraphsCB
->set_active( rConfigItem
.IsHideEmptyParagraphs() );
137 m_xDocumentIndexFI
->set_label(m_sDocument
.replaceFirst("%1", "1"));
139 m_xSettings
->Clear();
140 const uno::Sequence
< OUString
> aBlocks
=
141 m_pWizard
->GetConfigItem().GetAddressBlocks();
142 for(const auto& rAddress
: aBlocks
)
143 m_xSettings
->AddAddress(rAddress
);
144 m_xSettings
->SelectAddress(o3tl::narrowing
<sal_uInt16
>(rConfigItem
.GetCurrentAddressBlockIndex()));
145 m_xAddressCB
->set_active(rConfigItem
.IsAddressBlock());
146 AddressBlockHdl_Impl(*m_xAddressCB
);
147 m_xSettings
->SetLayout(1, 2);
148 InsertDataHdl(nullptr);
151 bool SwMailMergeAddressBlockPage::commitPage( ::vcl::WizardTypes::CommitPageReason _eReason
)
153 return ::vcl::WizardTypes::eTravelForward
!= _eReason
|| m_pWizard
->GetConfigItem().GetResultSet().is();
156 IMPL_LINK_NOARG(SwMailMergeAddressBlockPage
, AddressListHdl_Impl
, weld::Button
&, void)
160 SwAddressListDialog
aAddrDialog(this);
161 if (RET_OK
== aAddrDialog
.run())
163 SwMailMergeConfigItem
& rConfigItem
= m_pWizard
->GetConfigItem();
164 rConfigItem
.SetCurrentConnection(
165 aAddrDialog
.GetSource(),
166 aAddrDialog
.GetConnection(),
167 aAddrDialog
.GetColumnsSupplier(),
168 aAddrDialog
.GetDBData());
169 OUString sFilter
= aAddrDialog
.GetFilter();
170 rConfigItem
.SetFilter( sFilter
);
171 InsertDataHdl(nullptr);
172 GetWizard()->UpdateRoadmap();
173 GetWizard()->enableButtons(WizardButtonFlags::NEXT
, GetWizard()->isStateEnabled(MM_GREETINGSPAGE
));
176 catch (const uno::Exception
& e
)
178 TOOLS_WARN_EXCEPTION("sw", "");
179 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(m_pWizard
->getDialog(),
180 VclMessageType::Warning
, VclButtonsType::Ok
, e
.Message
));
185 IMPL_LINK_NOARG(SwMailMergeAddressBlockPage
, SettingsHdl_Impl
, weld::Button
&, void)
187 SwSelectAddressBlockDialog
aDlg(m_pWizard
->getDialog(), m_pWizard
->GetConfigItem());
188 SwMailMergeConfigItem
& rConfig
= m_pWizard
->GetConfigItem();
189 aDlg
.SetAddressBlocks(rConfig
.GetAddressBlocks(), m_xSettings
->GetSelectedAddress());
190 aDlg
.SetSettings(rConfig
.IsIncludeCountry(), rConfig
.GetExcludeCountry());
191 if (aDlg
.run() == RET_OK
)
193 //the dialog provides the selected address at the first position!
194 const uno::Sequence
< OUString
> aBlocks
= aDlg
.GetAddressBlocks();
195 rConfig
.SetAddressBlocks(aBlocks
);
196 m_xSettings
->Clear();
197 for(const auto& rAddress
: aBlocks
)
198 m_xSettings
->AddAddress(rAddress
);
199 m_xSettings
->SelectAddress(0);
200 m_xSettings
->Invalidate(); // #i40408
201 rConfig
.SetCountrySettings(aDlg
.IsIncludeCountry(), aDlg
.GetCountry());
202 InsertDataHdl(nullptr);
204 GetWizard()->UpdateRoadmap();
205 GetWizard()->enableButtons(WizardButtonFlags::NEXT
, GetWizard()->isStateEnabled(MM_GREETINGSPAGE
));
208 IMPL_LINK_NOARG(SwMailMergeAddressBlockPage
, AssignHdl_Impl
, weld::Button
&, void)
210 SwMailMergeConfigItem
& rConfigItem
= m_pWizard
->GetConfigItem();
211 const sal_uInt16 nSel
= m_xSettings
->GetSelectedAddress();
212 const uno::Sequence
< OUString
> aBlocks
= rConfigItem
.GetAddressBlocks();
213 SwAssignFieldsDialog
aDlg(m_pWizard
->getDialog(), m_pWizard
->GetConfigItem(), aBlocks
[nSel
], true);
214 if(RET_OK
== aDlg
.run())
217 InsertDataHdl(nullptr);
218 GetWizard()->UpdateRoadmap();
219 GetWizard()->enableButtons(WizardButtonFlags::NEXT
, GetWizard()->isStateEnabled(MM_GREETINGSPAGE
));
223 void SwMailMergeAddressBlockPage::EnableAddressBlock(bool bAll
, bool bSelective
)
225 m_xSettingsFI
->set_sensitive(bAll
);
226 m_xAddressCB
->set_sensitive(bAll
);
228 m_xHideEmptyParagraphsCB
->set_sensitive(bSelective
);
229 m_xSettingsWIN
->set_sensitive(bSelective
);
230 m_xSettingsPB
->set_sensitive(bSelective
);
231 m_xStep3
->set_sensitive(bSelective
);
232 m_xStep4
->set_sensitive(bSelective
);
235 IMPL_LINK(SwMailMergeAddressBlockPage
, AddressBlockHdl_Impl
, weld::Toggleable
&, rBox
, void)
237 EnableAddressBlock(rBox
.get_sensitive(), rBox
.get_active());
238 SwMailMergeConfigItem
& rConfigItem
= m_pWizard
->GetConfigItem();
239 rConfigItem
.SetAddressBlock(m_xAddressCB
->get_active());
240 m_pWizard
->UpdateRoadmap();
241 GetWizard()->enableButtons(WizardButtonFlags::NEXT
, GetWizard()->isStateEnabled(MM_GREETINGSPAGE
));
244 IMPL_LINK_NOARG(SwMailMergeAddressBlockPage
, AddressBlockSelectHdl_Impl
, LinkParamNone
*, void)
246 const sal_uInt16 nSel
= m_xSettings
->GetSelectedAddress();
247 const uno::Sequence
< OUString
> aBlocks
=
248 m_pWizard
->GetConfigItem().GetAddressBlocks();
249 m_xPreview
->SetAddress(SwAddressPreview::FillData(aBlocks
[nSel
],
250 m_pWizard
->GetConfigItem()));
251 m_pWizard
->GetConfigItem().SetCurrentAddressBlockIndex( nSel
);
252 GetWizard()->UpdateRoadmap();
253 GetWizard()->enableButtons(WizardButtonFlags::NEXT
, GetWizard()->isStateEnabled(MM_GREETINGSPAGE
));
256 IMPL_LINK(SwMailMergeAddressBlockPage
, HideParagraphsHdl_Impl
, weld::Toggleable
&, rBox
, void)
258 SwMailMergeConfigItem
& rConfigItem
= m_pWizard
->GetConfigItem();
259 rConfigItem
.SetHideEmptyParagraphs(rBox
.get_active());
262 void SwMailMergeAddressBlockPage::InsertDataHdl(const weld::Button
* pButton
)
264 //if no pButton is given, the first set has to be pre-set
265 SwMailMergeConfigItem
& rConfig
= m_pWizard
->GetConfigItem();
266 std::unique_ptr
<weld::WaitObject
> xWaitObj(new weld::WaitObject(m_pWizard
->getDialog()));
269 rConfig
.GetResultSet();
273 bool bNext
= pButton
== m_xNextSetIB
.get();
274 sal_Int32 nPos
= rConfig
.GetResultSetPosition();
275 rConfig
.MoveResultSet( bNext
? ++nPos
: --nPos
);
278 sal_Int32 nPos
= rConfig
.GetResultSetPosition();
287 //if output type is letter
288 if (m_xSettings
->IsVisible())
290 //Fill data into preview
291 const sal_uInt16 nSel
= m_xSettings
->GetSelectedAddress();
292 const uno::Sequence
< OUString
> aBlocks
=
293 m_pWizard
->GetConfigItem().GetAddressBlocks();
294 m_xPreview
->SetAddress(SwAddressPreview::FillData(aBlocks
[nSel
], rConfig
));
297 m_xPrevSetIB
->set_sensitive(bEnable
);
298 m_xDocumentIndexFI
->set_label(m_sDocument
.replaceFirst("%1", OUString::number(nPos
)));
300 GetWizard()->enableButtons(WizardButtonFlags::NEXT
, GetWizard()->isStateEnabled(MM_GREETINGSPAGE
));
301 bool bHasResultSet
= rConfig
.GetResultSet().is();
302 m_xCurrentAddressFI
->set_visible(bHasResultSet
);
305 m_xCurrentAddressFI
->set_label(m_sCurrentAddress
.replaceFirst("%1", rConfig
.GetCurrentDBData().sDataSource
));
306 m_xAddressListPB
->set_label(m_sChangeAddress
);
308 EnableAddressBlock(bHasResultSet
, m_xAddressCB
->get_active());
311 IMPL_LINK(SwMailMergeAddressBlockPage
, InsertDataHdl_Impl
, weld::Button
&, rButton
, void)
313 InsertDataHdl(&rButton
);
316 SwSelectAddressBlockDialog::SwSelectAddressBlockDialog(weld::Window
* pParent
, SwMailMergeConfigItem
& rConfig
)
317 : SfxDialogController(pParent
, "modules/swriter/ui/selectblockdialog.ui", "SelectBlockDialog")
319 , m_xPreview(new SwAddressPreview(m_xBuilder
->weld_scrolled_window("previewwin", true)))
320 , m_xNewPB(m_xBuilder
->weld_button("new"))
321 , m_xCustomizePB(m_xBuilder
->weld_button("edit"))
322 , m_xDeletePB(m_xBuilder
->weld_button("delete"))
323 , m_xNeverRB(m_xBuilder
->weld_radio_button("never"))
324 , m_xAlwaysRB(m_xBuilder
->weld_radio_button("always"))
325 , m_xDependentRB(m_xBuilder
->weld_radio_button("dependent"))
326 , m_xCountryED(m_xBuilder
->weld_entry("country"))
327 , m_xPreviewWin(new weld::CustomWeld(*m_xBuilder
, "preview", *m_xPreview
))
329 m_xPreviewWin
->set_size_request(m_xCountryED
->get_approximate_digit_width() * 45,
330 m_xCountryED
->get_text_height() * 12);
332 Link
<weld::Button
&,void> aCustomizeHdl
= LINK(this, SwSelectAddressBlockDialog
, NewCustomizeHdl_Impl
);
333 m_xNewPB
->connect_clicked(aCustomizeHdl
);
334 m_xCustomizePB
->connect_clicked(aCustomizeHdl
);
336 m_xDeletePB
->connect_clicked(LINK(this, SwSelectAddressBlockDialog
, DeleteHdl_Impl
));
338 Link
<weld::Toggleable
&,void> aLk
= LINK(this, SwSelectAddressBlockDialog
, IncludeHdl_Impl
);
339 m_xNeverRB
->connect_toggled(aLk
);
340 m_xAlwaysRB
->connect_toggled(aLk
);
341 m_xDependentRB
->connect_toggled(aLk
);
342 m_xPreview
->SetLayout(2, 2);
343 m_xPreview
->EnableScrollBar();
346 SwSelectAddressBlockDialog::~SwSelectAddressBlockDialog()
350 void SwSelectAddressBlockDialog::SetAddressBlocks(const uno::Sequence
< OUString
>& rBlocks
,
351 sal_uInt16 nSelectedAddress
)
353 m_aAddressBlocks
= rBlocks
;
354 for (const auto& rAddressBlock
: std::as_const(m_aAddressBlocks
))
355 m_xPreview
->AddAddress(rAddressBlock
);
356 m_xPreview
->SelectAddress(nSelectedAddress
);
359 // return the address blocks and put the selected one to the first position
360 const uno::Sequence
< OUString
>& SwSelectAddressBlockDialog::GetAddressBlocks()
362 //put the selected block to the first position
363 const sal_Int32 nSelect
= static_cast<sal_Int32
>(m_xPreview
->GetSelectedAddress());
366 uno::Sequence
< OUString
>aTemp(m_aAddressBlocks
.getLength());
367 auto it
= aTemp
.getArray();
368 *it
= std::as_const(m_aAddressBlocks
)[nSelect
];
369 it
= std::copy_n(std::cbegin(m_aAddressBlocks
), nSelect
- 1, std::next(it
));
370 std::copy(std::next(std::cbegin(m_aAddressBlocks
), nSelect
+ 1), std::cend(m_aAddressBlocks
), it
);
371 m_aAddressBlocks
= aTemp
;
373 return m_aAddressBlocks
;
376 void SwSelectAddressBlockDialog::SetSettings(
377 bool bIsCountry
, const OUString
& rCountry
)
379 weld::RadioButton
*pActive
= m_xNeverRB
.get();
382 pActive
= !rCountry
.isEmpty() ? m_xDependentRB
.get() : m_xAlwaysRB
.get();
383 m_xCountryED
->set_text(rCountry
);
385 pActive
->set_active(true);
386 IncludeHdl_Impl(*pActive
);
387 m_xDeletePB
->set_sensitive(m_aAddressBlocks
.getLength() > 1);
390 OUString
SwSelectAddressBlockDialog::GetCountry() const
392 if (m_xDependentRB
->get_active())
393 return m_xCountryED
->get_text();
397 IMPL_LINK(SwSelectAddressBlockDialog
, DeleteHdl_Impl
, weld::Button
&, rButton
, void)
399 if (m_aAddressBlocks
.getLength())
401 const sal_Int32 nSelected
= static_cast<sal_Int32
>(m_xPreview
->GetSelectedAddress());
402 comphelper::removeElementAt(m_aAddressBlocks
, nSelected
);
403 if (m_aAddressBlocks
.getLength() <= 1)
404 rButton
.set_sensitive(false);
405 m_xPreview
->RemoveSelectedAddress();
409 IMPL_LINK(SwSelectAddressBlockDialog
, NewCustomizeHdl_Impl
, weld::Button
&, rButton
, void)
411 bool bCustomize
= &rButton
== m_xCustomizePB
.get();
412 SwCustomizeAddressBlockDialog::DialogType nType
= bCustomize
?
413 SwCustomizeAddressBlockDialog::ADDRESSBLOCK_EDIT
:
414 SwCustomizeAddressBlockDialog::ADDRESSBLOCK_NEW
;
415 std::unique_ptr
<SwCustomizeAddressBlockDialog
> xDlg(new SwCustomizeAddressBlockDialog(&rButton
,
419 xDlg
->SetAddress(m_aAddressBlocks
[m_xPreview
->GetSelectedAddress()]);
421 if (RET_OK
!= xDlg
->run())
424 const OUString sNew
= xDlg
->GetAddress();
427 m_xPreview
->ReplaceSelectedAddress(sNew
);
428 m_aAddressBlocks
.getArray()[m_xPreview
->GetSelectedAddress()] = sNew
;
432 m_xPreview
->AddAddress(sNew
);
433 m_aAddressBlocks
.realloc(m_aAddressBlocks
.getLength() + 1);
434 const sal_Int32 nSelect
= m_aAddressBlocks
.getLength() - 1;
435 m_aAddressBlocks
.getArray()[nSelect
] = sNew
;
436 m_xPreview
->SelectAddress(o3tl::narrowing
<sal_uInt16
>(nSelect
));
438 m_xDeletePB
->set_sensitive(m_aAddressBlocks
.getLength() > 1);
441 IMPL_LINK_NOARG(SwSelectAddressBlockDialog
, IncludeHdl_Impl
, weld::Toggleable
&, void)
443 m_xCountryED
->set_sensitive(m_xDependentRB
->get_active());
446 #define USER_DATA_SALUTATION -1
447 #define USER_DATA_PUNCTUATION -2
448 #define USER_DATA_TEXT -3
449 #define USER_DATA_NONE -4
451 IMPL_LINK(SwCustomizeAddressBlockDialog
, TextFilterHdl
, OUString
&, rTest
, bool)
453 rTest
= m_aTextFilter
.filter(rTest
);
457 SwCustomizeAddressBlockDialog::SwCustomizeAddressBlockDialog(
458 weld::Widget
* pParent
, SwMailMergeConfigItem
& rConfig
, DialogType eType
)
459 : SfxDialogController(pParent
, "modules/swriter/ui/addressblockdialog.ui",
460 "AddressBlockDialog")
461 , m_aTextFilter("<>")
462 , m_rConfigItem(rConfig
)
464 , m_aSelectionChangedIdle("SwCustomizeAddressBlockDialog m_aSelectionChangedIdle")
465 , m_xAddressElementsFT(m_xBuilder
->weld_label("addressesft"))
466 , m_xAddressElementsLB(m_xBuilder
->weld_tree_view("addresses"))
467 , m_xInsertFieldIB(m_xBuilder
->weld_button("toaddr"))
468 , m_xRemoveFieldIB(m_xBuilder
->weld_button("fromaddr"))
469 , m_xDragFT(m_xBuilder
->weld_label("addressdestft"))
470 , m_xUpIB(m_xBuilder
->weld_button("up"))
471 , m_xLeftIB(m_xBuilder
->weld_button("left"))
472 , m_xRightIB(m_xBuilder
->weld_button("right"))
473 , m_xDownIB(m_xBuilder
->weld_button("down"))
474 , m_xFieldFT(m_xBuilder
->weld_label("customft"))
475 , m_xFieldCB(m_xBuilder
->weld_combo_box("custom"))
476 , m_xOK(m_xBuilder
->weld_button("ok"))
477 , m_xPreview(new SwAddressPreview(m_xBuilder
->weld_scrolled_window("previewwin", true)))
478 , m_xPreviewWIN(new weld::CustomWeld(*m_xBuilder
, "addrpreview", *m_xPreview
))
479 , m_xDragED(new AddressMultiLineEdit(this))
480 , m_xDragWIN(new weld::CustomWeld(*m_xBuilder
, "addressdest", *m_xDragED
))
482 m_aSelectionChangedIdle
.SetInvokeHandler( LINK( this, SwCustomizeAddressBlockDialog
, SelectionChangedIdleHdl
) );
484 Size
aSize(m_xDragED
->GetDrawingArea()->get_size_request());
485 m_xPreview
->set_size_request(aSize
.Width(), aSize
.Height());
487 m_xFieldCB
->connect_entry_insert_text(LINK(this, SwCustomizeAddressBlockDialog
, TextFilterHdl
));
488 m_xAddressElementsLB
->set_size_request(-1, m_xAddressElementsLB
->get_height_rows(16));
490 if( eType
>= GREETING_FEMALE
)
494 m_xAddressElementsLB
->append(OUString::number(USER_DATA_SALUTATION
), SwResId(ST_SALUTATION
));
495 m_xAddressElementsLB
->append(OUString::number(USER_DATA_PUNCTUATION
), SwResId(ST_PUNCTUATION
));
496 m_xAddressElementsLB
->append(OUString::number(USER_DATA_TEXT
), SwResId(ST_TEXT
));
497 for (auto const& aID
: RA_SALUTATION
)
498 m_aSalutations
.push_back(SwResId(aID
));
499 for (auto const& aID
: RA_PUNCTUATION
)
500 m_aPunctuations
.push_back(SwResId(aID
));
501 m_xDragED
->SetText(" ");
502 m_xDialog
->set_title(SwResId(eType
== GREETING_MALE
? ST_TITLE_MALE
: ST_TITLE_FEMALE
));
503 m_xAddressElementsFT
->set_label(SwResId(ST_SALUTATIONELEMENTS
));
504 m_xInsertFieldIB
->set_tooltip_text(SwResId(ST_INSERTSALUTATIONFIELD
));
505 m_xRemoveFieldIB
->set_tooltip_text(SwResId(ST_REMOVESALUTATIONFIELD
));
506 m_xDragFT
->set_label(SwResId(ST_DRAGSALUTATION
));
510 if (eType
== ADDRESSBLOCK_EDIT
)
511 m_xDialog
->set_title(SwResId(ST_TITLE_EDIT
));
512 m_xDragED
->SetText("\n\n\n\n\n");
513 /* Set custom HIDs for swriter/01/mm_newaddblo.xhp */
514 m_xAddressElementsLB
->set_help_id( HID_MM_ADDBLOCK_ELEMENTS
);
515 m_xInsertFieldIB
->set_help_id( HID_MM_ADDBLOCK_INSERT
);
516 m_xRemoveFieldIB
->set_help_id( HID_MM_ADDBLOCK_REMOVE
);
517 m_xDragWIN
->set_help_id( HID_MM_ADDBLOCK_DRAG
);
518 m_xPreviewWIN
->set_help_id( HID_MM_ADDBLOCK_PREVIEW
);
519 m_xRightIB
->set_help_id( HID_MM_ADDBLOCK_MOVEBUTTONS
);
520 m_xLeftIB
->set_help_id( HID_MM_ADDBLOCK_MOVEBUTTONS
);
521 m_xDownIB
->set_help_id( HID_MM_ADDBLOCK_MOVEBUTTONS
);
522 m_xUpIB
->set_help_id( HID_MM_ADDBLOCK_MOVEBUTTONS
);
525 const std::vector
<std::pair
<OUString
, int>>& rHeaders
= m_rConfigItem
.GetDefaultAddressHeaders();
526 for (size_t i
= 0; i
< rHeaders
.size(); ++i
)
527 m_xAddressElementsLB
->append(OUString::number(i
), rHeaders
[i
].first
);
528 m_xOK
->connect_clicked(LINK(this, SwCustomizeAddressBlockDialog
, OKHdl_Impl
));
529 m_xAddressElementsLB
->connect_changed(LINK(this, SwCustomizeAddressBlockDialog
, ListBoxSelectHdl_Impl
));
530 if (m_xAddressElementsLB
->n_children())
531 m_xAddressElementsLB
->select(0);
532 m_xDragED
->SetModifyHdl(LINK(this, SwCustomizeAddressBlockDialog
, EditModifyHdl_Impl
));
533 m_xDragED
->SetSelectionChangedHdl( LINK( this, SwCustomizeAddressBlockDialog
, SelectionChangedHdl_Impl
));
534 m_xFieldCB
->connect_changed(LINK(this, SwCustomizeAddressBlockDialog
, FieldChangeComboBoxHdl_Impl
));
535 Link
<weld::Button
&,void> aImgButtonHdl
= LINK(this, SwCustomizeAddressBlockDialog
, ImageButtonHdl_Impl
);
536 m_xInsertFieldIB
->connect_clicked(aImgButtonHdl
);
537 m_xRemoveFieldIB
->connect_clicked(aImgButtonHdl
);
538 m_xUpIB
->connect_clicked(aImgButtonHdl
);
539 m_xLeftIB
->connect_clicked(aImgButtonHdl
);
540 m_xRightIB
->connect_clicked(aImgButtonHdl
);
541 m_xDownIB
->connect_clicked(aImgButtonHdl
);
542 UpdateImageButtons_Impl();
545 bool SwCustomizeAddressBlockDialog::SetCursorLogicPosition(const Point
& rPosition
)
547 return m_xDragED
->SetCursorLogicPosition(rPosition
);
550 void SwCustomizeAddressBlockDialog::UpdateFields()
552 m_xDragED
->UpdateFields();
555 SwCustomizeAddressBlockDialog::~SwCustomizeAddressBlockDialog()
557 m_xDragED
->EndDropTarget();
560 IMPL_LINK_NOARG(SwCustomizeAddressBlockDialog
, OKHdl_Impl
, weld::Button
&, void)
562 m_xDialog
->response(RET_OK
);
565 IMPL_LINK(SwCustomizeAddressBlockDialog
, ListBoxSelectHdl_Impl
, weld::TreeView
&, rBox
, void)
567 sal_Int32 nUserData
= rBox
.get_selected_id().toInt32();
568 // Check if the selected entry is already in the address and then forbid inserting
569 m_xInsertFieldIB
->set_sensitive(nUserData
>= 0 || !HasItem(nUserData
));
572 IMPL_LINK_NOARG(SwCustomizeAddressBlockDialog
, EditModifyHdl_Impl
, AddressMultiLineEdit
&, void)
574 m_xPreview
->SetAddress(SwAddressPreview::FillData(GetAddress(), m_rConfigItem
));
575 UpdateImageButtons_Impl();
578 IMPL_LINK(SwCustomizeAddressBlockDialog
, ImageButtonHdl_Impl
, weld::Button
&, rButton
, void)
580 if (m_xInsertFieldIB
.get() == &rButton
)
582 int nEntry
= m_xAddressElementsLB
->get_selected_index();
585 m_xDragED
->InsertNewEntry("<" + m_xAddressElementsLB
->get_text(nEntry
) + ">");
588 else if (m_xRemoveFieldIB
.get() == &rButton
)
590 m_xDragED
->RemoveCurrentEntry();
594 MoveItemFlags nMove
= MoveItemFlags::Down
;
595 if (m_xUpIB
.get() == &rButton
)
596 nMove
= MoveItemFlags::Up
;
597 else if (m_xLeftIB
.get() == &rButton
)
598 nMove
= MoveItemFlags::Left
;
599 else if (m_xRightIB
.get() == &rButton
)
600 nMove
= MoveItemFlags::Right
;
601 m_xDragED
->MoveCurrentItem(nMove
);
603 UpdateImageButtons_Impl();
606 sal_Int32
SwCustomizeAddressBlockDialog::GetSelectedItem_Impl() const
608 sal_Int32 nRet
= USER_DATA_NONE
;
609 const OUString sSelected
= m_xDragED
->GetCurrentItem();
610 if(!sSelected
.isEmpty())
612 for (int i
= 0, nEntryCount
= m_xAddressElementsLB
->n_children(); i
< nEntryCount
; ++i
)
614 const OUString sEntry
= m_xAddressElementsLB
->get_text(i
);
615 if( sEntry
== sSelected
.subView( 1, sSelected
.getLength() - 2 ) )
617 nRet
= m_xAddressElementsLB
->get_id(i
).toInt32();
625 bool SwCustomizeAddressBlockDialog::HasItem(sal_Int32 nUserData
)
627 //get the entry from the ListBox
629 for (int i
= 0, nEntryCount
= m_xAddressElementsLB
->n_children(); i
< nEntryCount
; ++i
)
631 if (m_xAddressElementsLB
->get_id(i
).toInt32() == nUserData
)
633 sEntry
= m_xAddressElementsLB
->get_text(i
);
637 //search for this entry in the content
638 return m_xDragED
->GetText().indexOf(Concat2View("<" + sEntry
+ ">")) >= 0;
641 IMPL_LINK_NOARG(SwCustomizeAddressBlockDialog
, SelectionChangedIdleHdl
, Timer
*, void)
643 // called in case the selection of the edit field changes.
644 // determine selection - if it's one of the editable fields then
645 // enable the related ComboBox and fill it
647 // don't trigger outself again
648 m_xDragED
->SetSelectionChangedHdl(Link
<bool, void>());
650 sal_Int32 nSelected
= GetSelectedItem_Impl();
651 if (USER_DATA_NONE
!= nSelected
)
652 m_xDragED
->SelectCurrentItem();
654 if(m_xFieldCB
->get_visible() && (USER_DATA_NONE
!= nSelected
) && (nSelected
< 0))
656 //search in ListBox if it's one of the first entries
658 std::vector
<OUString
>* pVector
= nullptr;
660 case USER_DATA_SALUTATION
:
661 sSelect
= m_sCurrentSalutation
;
662 pVector
= &m_aSalutations
;
664 case USER_DATA_PUNCTUATION
:
665 sSelect
= m_sCurrentPunctuation
;
666 pVector
= &m_aPunctuations
;
669 sSelect
= m_sCurrentText
;
674 for (const auto& rItem
: *pVector
)
675 m_xFieldCB
->append_text(rItem
);
677 m_xFieldCB
->set_entry_text(sSelect
);
678 m_xFieldCB
->set_sensitive(true);
679 m_xFieldFT
->set_sensitive(true);
683 m_xFieldCB
->set_sensitive(false);
684 m_xFieldFT
->set_sensitive(false);
687 UpdateImageButtons_Impl();
688 m_xDragED
->SetSelectionChangedHdl( LINK( this, SwCustomizeAddressBlockDialog
, SelectionChangedHdl_Impl
));
691 IMPL_LINK(SwCustomizeAddressBlockDialog
, SelectionChangedHdl_Impl
, bool, bIdle
, void)
694 m_aSelectionChangedIdle
.Start();
697 m_aSelectionChangedIdle
.Stop();
698 SelectionChangedIdleHdl(nullptr);
702 IMPL_LINK_NOARG(SwCustomizeAddressBlockDialog
, FieldChangeComboBoxHdl_Impl
, weld::ComboBox
&, void)
704 //changing the field content changes the related members, too
705 sal_Int32 nSelected
= GetSelectedItem_Impl();
706 const OUString sContent
= m_xFieldCB
->get_active_text();
708 case USER_DATA_SALUTATION
:
709 m_sCurrentSalutation
= sContent
;
711 case USER_DATA_PUNCTUATION
:
712 m_sCurrentPunctuation
= sContent
;
715 m_sCurrentText
= sContent
;
718 UpdateImageButtons_Impl();
719 m_xPreview
->SetAddress(GetAddress());
720 EditModifyHdl_Impl(*m_xDragED
);
723 void SwCustomizeAddressBlockDialog::UpdateImageButtons_Impl()
725 MoveItemFlags nMove
= m_xDragED
->IsCurrentItemMoveable();
726 m_xUpIB
->set_sensitive( bool(nMove
& MoveItemFlags::Up
) );
727 m_xLeftIB
->set_sensitive( bool(nMove
& MoveItemFlags::Left
) );
728 m_xRightIB
->set_sensitive( bool(nMove
& MoveItemFlags::Right
) );
729 m_xDownIB
->set_sensitive( bool(nMove
& MoveItemFlags::Down
) );
730 m_xRemoveFieldIB
->set_sensitive(m_xDragED
->HasCurrentItem());
731 int nEntry
= m_xAddressElementsLB
->get_selected_index();
732 m_xInsertFieldIB
->set_sensitive( nEntry
!= -1 &&
733 (m_xAddressElementsLB
->get_id(nEntry
).toInt32() >= 0 || !m_xFieldCB
->get_active_text().isEmpty()));
736 void SwCustomizeAddressBlockDialog::SetAddress(const OUString
& rAddress
)
738 m_xDragED
->SetText(rAddress
);
739 UpdateImageButtons_Impl();
740 EditModifyHdl_Impl(*m_xDragED
);
743 OUString
SwCustomizeAddressBlockDialog::GetAddress() const
745 OUString
sAddress(m_xDragED
->GetAddress());
746 //remove placeholders by the actual content
747 if (m_xFieldFT
->get_visible())
749 for (int i
= 0, nEntryCount
= m_xAddressElementsLB
->n_children(); i
< nEntryCount
; ++i
)
751 const OUString sEntry
= "<" + m_xAddressElementsLB
->get_text(i
) + ">";
752 sal_Int32 nUserData
= m_xAddressElementsLB
->get_id(i
).toInt32();
755 case USER_DATA_SALUTATION
:
756 sAddress
= sAddress
.replaceFirst(sEntry
, m_sCurrentSalutation
);
758 case USER_DATA_PUNCTUATION
:
759 sAddress
= sAddress
.replaceFirst(sEntry
, m_sCurrentPunctuation
);
762 sAddress
= sAddress
.replaceFirst(sEntry
, m_sCurrentText
);
772 struct SwAssignFragment
774 std::unique_ptr
<weld::Builder
> m_xBuilder
;
775 std::unique_ptr
<weld::Label
> m_xLabel
;
776 std::unique_ptr
<weld::ComboBox
> m_xComboBox
;
777 std::unique_ptr
<weld::Label
> m_xPreview
;
779 SwAssignFragment(weld::Container
* pGrid
, int nLine
)
780 : m_xBuilder(Application::CreateBuilder(pGrid
, "modules/swriter/ui/assignfragment.ui"))
781 , m_xLabel(m_xBuilder
->weld_label("label"))
782 , m_xComboBox(m_xBuilder
->weld_combo_box("combobox"))
783 , m_xPreview(m_xBuilder
->weld_label("preview"))
785 m_xLabel
->set_grid_left_attach(0);
786 m_xLabel
->set_grid_top_attach(nLine
);
788 m_xComboBox
->set_grid_left_attach(1);
789 m_xComboBox
->set_grid_top_attach(nLine
);
791 m_xPreview
->set_grid_left_attach(2);
792 m_xPreview
->set_grid_top_attach(nLine
);
798 class SwAssignFieldsControl
800 friend class SwAssignFieldsDialog
;
801 std::unique_ptr
<weld::ScrolledWindow
> m_xVScroll
;
802 std::unique_ptr
<weld::Container
> m_xGrid
;
804 std::vector
<SwAssignFragment
> m_aFields
;
806 SwMailMergeConfigItem
* m_rConfigItem
;
808 Link
<LinkParamNone
*,void> m_aModifyHdl
;
810 DECL_LINK(MatchHdl_Impl
, weld::ComboBox
&, void);
811 DECL_LINK(GotFocusHdl_Impl
, weld::Widget
&, void);
813 void MakeVisible(const tools::Rectangle
& rRect
);
815 SwAssignFieldsControl(std::unique_ptr
<weld::ScrolledWindow
> xWindow
,
816 std::unique_ptr
<weld::Container
> xGrid
);
818 void Init(SwAssignFieldsDialog
* pDialog
, SwMailMergeConfigItem
& rConfigItem
);
819 void SetModifyHdl(const Link
<LinkParamNone
*,void>& rModifyHdl
)
821 m_aModifyHdl
= rModifyHdl
;
822 m_aModifyHdl
.Call(nullptr);
826 SwAssignFieldsControl::SwAssignFieldsControl(std::unique_ptr
<weld::ScrolledWindow
> xWindow
,
827 std::unique_ptr
<weld::Container
> xGrid
)
828 : m_xVScroll(std::move(xWindow
))
829 , m_xGrid(std::move(xGrid
))
830 , m_rConfigItem(nullptr)
834 void SwAssignFieldsControl::Init(SwAssignFieldsDialog
* pDialog
, SwMailMergeConfigItem
& rConfigItem
)
836 m_rConfigItem
= &rConfigItem
;
838 //get the name of the default headers
839 const std::vector
<std::pair
<OUString
, int>>& rHeaders
= rConfigItem
.GetDefaultAddressHeaders();
840 //get the actual data
841 uno::Reference
< XColumnsSupplier
> xColsSupp( rConfigItem
.GetResultSet(), uno::UNO_QUERY
);
842 //get the name of the actual columns
843 uno::Reference
<XNameAccess
> xColAccess
= xColsSupp
.is() ? xColsSupp
->getColumns() : nullptr;
844 uno::Sequence
< OUString
> aFields
;
846 aFields
= xColAccess
->getElementNames();
848 //get the current assignment list
849 //each position in this sequence matches the position in the header array rHeaders
850 //if no assignment is available an empty sequence will be returned
851 uno::Sequence
< OUString
> aAssignments
= rConfigItem
.GetColumnAssignment( rConfigItem
.GetCurrentDBData() );
852 Link
<weld::ComboBox
&,void> aMatchHdl
= LINK(this, SwAssignFieldsControl
, MatchHdl_Impl
);
853 Link
<weld::Widget
&,void> aFocusHdl
= LINK(this, SwAssignFieldsControl
, GotFocusHdl_Impl
);
855 int nLabelWidth(0), nComboBoxWidth(0), nPreviewWidth(0);
858 for (size_t i
= 0; i
< rHeaders
.size(); ++i
)
860 m_aFields
.emplace_back(m_xGrid
.get(), i
);
862 const OUString rHeader
= rHeaders
[i
].first
;
863 weld::ComboBox
& rNewLB
= *m_aFields
.back().m_xComboBox
;
864 rNewLB
.append_text(SwResId(SW_STR_NONE
));
865 rNewLB
.set_active(0);
867 for (const OUString
& rField
: std::as_const(aFields
))
868 rNewLB
.append_text(rField
);
870 //if there is an assignment
871 if(o3tl::make_unsigned(aAssignments
.getLength()) > i
&& !aAssignments
[i
].isEmpty())
872 rNewLB
.set_active_text(aAssignments
[i
]);
873 else //otherwise the current column name may match one of the db columns
874 rNewLB
.set_active_text(rHeader
);
876 weld::Label
& rNewText
= *m_aFields
.back().m_xLabel
;
877 rNewText
.set_label("<" + rHeader
+ ">");
879 weld::Label
& rNewPreview
= *m_aFields
.back().m_xPreview
;
880 //then the preview can be filled accordingly
881 if (xColAccess
.is() && rNewLB
.get_active() > 0 &&
882 xColAccess
->hasByName(rNewLB
.get_active_text()))
884 uno::Any aCol
= xColAccess
->getByName(rNewLB
.get_active_text());
885 uno::Reference
< XColumn
> xColumn
;
891 rNewPreview
.set_label(xColumn
->getString());
893 catch (const SQLException
&)
901 auto nLineHeight
= m_xGrid
->get_preferred_size().Height();
902 m_xVScroll
->set_size_request(m_xVScroll
->get_approximate_digit_width() * 65,
904 nComboBoxWidth
= rNewLB
.get_preferred_size().Width();
907 nLabelWidth
= std::max
<int>(nLabelWidth
, rNewText
.get_preferred_size().Width());
908 nPreviewWidth
= std::max
<int>(nPreviewWidth
, rNewPreview
.get_preferred_size().Width());
910 rNewLB
.connect_changed(aMatchHdl
);
911 rNewLB
.connect_focus_in(aFocusHdl
);
916 pDialog
->ConnectSizeGroups(nLabelWidth
, nComboBoxWidth
, nPreviewWidth
);
919 void SwAssignFieldsControl::MakeVisible(const tools::Rectangle
& rRect
)
921 //determine range of visible positions
922 auto nMinVisiblePos
= m_xVScroll
->vadjustment_get_value();
923 auto nMaxVisiblePos
= nMinVisiblePos
+ m_xVScroll
->vadjustment_get_page_size();
924 if (rRect
.Top() < nMinVisiblePos
|| rRect
.Bottom() > nMaxVisiblePos
)
925 m_xVScroll
->vadjustment_set_value(rRect
.Top());
928 IMPL_LINK(SwAssignFieldsControl
, MatchHdl_Impl
, weld::ComboBox
&, rBox
, void)
930 const OUString sColumn
= rBox
.get_active_text();
931 uno::Reference
< XColumnsSupplier
> xColsSupp( m_rConfigItem
->GetResultSet(), uno::UNO_QUERY
);
932 uno::Reference
<XNameAccess
> xColAccess
= xColsSupp
.is() ? xColsSupp
->getColumns() : nullptr;
934 if(xColAccess
.is() && xColAccess
->hasByName(sColumn
))
936 uno::Any aCol
= xColAccess
->getByName(sColumn
);
937 uno::Reference
< XColumn
> xColumn
;
943 sPreview
= xColumn
->getString();
945 catch (const sdbc::SQLException
&)
950 auto aLBIter
= std::find_if(m_aFields
.begin(), m_aFields
.end(), [&rBox
](const SwAssignFragment
& rFragment
){
951 return &rBox
== rFragment
.m_xComboBox
.get(); });
952 if (aLBIter
!= m_aFields
.end())
954 auto nIndex
= static_cast<sal_Int32
>(std::distance(m_aFields
.begin(), aLBIter
));
955 m_aFields
[nIndex
].m_xPreview
->set_label(sPreview
);
957 m_aModifyHdl
.Call(nullptr);
960 IMPL_LINK(SwAssignFieldsControl
, GotFocusHdl_Impl
, weld::Widget
&, rBox
, void)
962 int x
, y
, width
, height
;
963 rBox
.get_extents_relative_to(*m_xGrid
, x
, y
, width
, height
);
964 // the container has a border of 3 in the .ui
965 tools::Rectangle
aRect(Point(x
- 3, y
- 3), Size(width
+ 6, height
+ 6));
969 SwAssignFieldsDialog::SwAssignFieldsDialog(
970 weld::Window
* pParent
, SwMailMergeConfigItem
& rConfigItem
,
972 bool bIsAddressBlock
)
973 : SfxDialogController(pParent
, "modules/swriter/ui/assignfieldsdialog.ui", "AssignFieldsDialog")
974 , m_sNone(SwResId(SW_STR_NONE
))
975 , m_rPreviewString(std::move(aPreview
))
976 , m_rConfigItem(rConfigItem
)
977 , m_xPreview(new SwAddressPreview(m_xBuilder
->weld_scrolled_window("previewwin", true)))
978 , m_xMatchingFI(m_xBuilder
->weld_label("MATCHING_LABEL"))
979 , m_xAddressTitle(m_xBuilder
->weld_label("addresselem"))
980 , m_xMatchTitle(m_xBuilder
->weld_label("matchelem"))
981 , m_xPreviewTitle(m_xBuilder
->weld_label("previewelem"))
982 , m_xPreviewFI(m_xBuilder
->weld_label("PREVIEW_LABEL"))
983 , m_xOK(m_xBuilder
->weld_button("ok"))
984 , m_xPreviewWin(new weld::CustomWeld(*m_xBuilder
, "PREVIEW", *m_xPreview
))
985 , m_xFieldsControl(new SwAssignFieldsControl(m_xBuilder
->weld_scrolled_window("scroll"),
986 m_xBuilder
->weld_container("FIELDS")))
988 m_xPreviewWin
->set_size_request(m_xMatchingFI
->get_approximate_digit_width() * 45,
989 m_xMatchingFI
->get_text_height() * 5);
990 m_xFieldsControl
->Init(this, rConfigItem
);
992 const OUString
sMatchesTo( SwResId(ST_MATCHESTO
) );
993 if (!bIsAddressBlock
)
995 m_xPreviewFI
->set_label(SwResId(ST_SALUTATIONPREVIEW
));
996 m_xMatchingFI
->set_label(SwResId(ST_SALUTATIONMATCHING
));
997 m_xAddressTitle
->set_label(SwResId(ST_SALUTATIONELEMENT
));
1000 m_xFieldsControl
->SetModifyHdl(LINK(this, SwAssignFieldsDialog
, AssignmentModifyHdl_Impl
));
1001 m_xMatchingFI
->set_label(m_xMatchingFI
->get_label().replaceAll("%1", sMatchesTo
));
1002 m_xOK
->connect_clicked(LINK(this, SwAssignFieldsDialog
, OkHdl_Impl
));
1005 SwAssignFieldsDialog::~SwAssignFieldsDialog()
1009 uno::Sequence
< OUString
> SwAssignFieldsDialog::CreateAssignments()
1011 uno::Sequence
< OUString
> aAssignments(
1012 m_rConfigItem
.GetDefaultAddressHeaders().size());
1013 OUString
* pAssignments
= aAssignments
.getArray();
1014 sal_Int32 nIndex
= 0;
1015 for (const auto& rLBItem
: m_xFieldsControl
->m_aFields
)
1017 const OUString sSelect
= rLBItem
.m_xComboBox
->get_active_text();
1018 pAssignments
[nIndex
] = (m_sNone
!= sSelect
) ? sSelect
: OUString();
1021 return aAssignments
;
1024 IMPL_LINK_NOARG(SwAssignFieldsDialog
, OkHdl_Impl
, weld::Button
&, void)
1026 m_rConfigItem
.SetColumnAssignment(
1027 m_rConfigItem
.GetCurrentDBData(),
1028 CreateAssignments() );
1029 m_xDialog
->response(RET_OK
);
1032 IMPL_LINK_NOARG(SwAssignFieldsDialog
, AssignmentModifyHdl_Impl
, LinkParamNone
*, void)
1034 uno::Sequence
< OUString
> aAssignments
= CreateAssignments();
1035 const OUString sPreview
= SwAddressPreview::FillData(
1036 m_rPreviewString
, m_rConfigItem
, &aAssignments
);
1037 m_xPreview
->SetAddress(sPreview
);
1040 void SwAssignFieldsDialog::ConnectSizeGroups(int nLabelWidth
, int nComboBoxWidth
, int nPreviewWidth
)
1042 m_xAddressTitle
->set_size_request(nLabelWidth
, -1);
1043 m_xMatchTitle
->set_size_request(nComboBoxWidth
, -1);
1044 m_xPreviewTitle
->set_size_request(nPreviewWidth
, -1);
1049 const EECharAttrib
* FindCharAttrib(int nStartPosition
, std::vector
<EECharAttrib
>& rAttribList
)
1051 for (auto it
= rAttribList
.rbegin(); it
!= rAttribList
.rend(); ++it
)
1053 const auto& rTextAtr
= *it
;
1054 if (rTextAtr
.pAttr
->Which() != EE_CHAR_GRABBAG
)
1056 if (rTextAtr
.nStart
<= nStartPosition
&& rTextAtr
.nEnd
>= nStartPosition
)
1066 AddressMultiLineEdit::AddressMultiLineEdit(SwCustomizeAddressBlockDialog
*pParent
)
1067 : m_pParentDialog(pParent
)
1071 void AddressMultiLineEdit::EndDropTarget()
1073 if (m_xDropTarget
.is())
1075 m_xEditEngine
->RemoveView(m_xEditView
.get());
1076 auto xRealDropTarget
= GetDrawingArea()->get_drop_target();
1077 uno::Reference
<css::datatransfer::dnd::XDropTargetListener
> xListener(m_xDropTarget
, uno::UNO_QUERY
);
1078 xRealDropTarget
->removeDropTargetListener(xListener
);
1079 m_xDropTarget
.clear();
1083 AddressMultiLineEdit::~AddressMultiLineEdit()
1085 assert(!m_xDropTarget
.is());
1088 void AddressMultiLineEdit::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
1090 Size
aSize(pDrawingArea
->get_ref_device().LogicToPixel(Size(160, 60), MapMode(MapUnit::MapAppFont
)));
1091 pDrawingArea
->set_size_request(aSize
.Width(), aSize
.Height());
1092 WeldEditView::SetDrawingArea(pDrawingArea
);
1095 bool AddressMultiLineEdit::KeyInput(const KeyEvent
& rKEvt
)
1097 if (rKEvt
.GetKeyCode().GetCode() == KEY_ESCAPE
)
1098 return false; // we want default esc behaviour
1099 if (rKEvt
.GetCharCode())
1100 return true; // handled
1101 return WeldEditView::KeyInput(rKEvt
);
1104 bool AddressMultiLineEdit::Command(const CommandEvent
& rCEvt
)
1106 if (rCEvt
.GetCommand() == CommandEventId::StartExtTextInput
||
1107 rCEvt
.GetCommand() == CommandEventId::EndExtTextInput
||
1108 rCEvt
.GetCommand() == CommandEventId::ExtTextInput
)
1112 return WeldEditView::Command(rCEvt
);
1115 bool AddressMultiLineEdit::MouseButtonDown(const MouseEvent
& rMEvt
)
1117 if (rMEvt
.GetClicks() >= 2)
1118 return true; // handled
1119 return WeldEditView::MouseButtonDown(rMEvt
);
1122 OUString
AddressMultiLineEdit::GetText() const
1124 return m_xEditEngine
->GetText();
1127 void AddressMultiLineEdit::SetText( const OUString
& rStr
)
1129 m_xEditEngine
->SetText(rStr
);
1130 //set attributes to all address tokens
1132 sal_Int32
nSequence(0);
1133 SfxGrabBagItem
aProtectAttr(EE_CHAR_GRABBAG
);
1134 const sal_uInt32 nParaCount
= m_xEditEngine
->GetParagraphCount();
1135 for(sal_uInt32 nPara
= 0; nPara
< nParaCount
; ++nPara
)
1137 sal_Int32 nIndex
= 0;
1138 const OUString sPara
= m_xEditEngine
->GetText( nPara
);
1139 if (!sPara
.isEmpty() && !sPara
.endsWith(" "))
1141 ESelection
aPaM(nPara
, sPara
.getLength(), nPara
, sPara
.getLength());
1142 m_xEditEngine
->QuickInsertText(" ", aPaM
);
1146 const sal_Int32 nStart
= sPara
.indexOf( '<', nIndex
);
1149 const sal_Int32 nEnd
= sPara
.indexOf( '>', nStart
);
1153 SfxItemSet
aSet(m_xEditEngine
->GetEmptyItemSet());
1154 // make each one different, so they are not collapsed together
1156 aProtectAttr
.GetGrabBag()["Index"] <<= nSequence
++;
1157 aSet
.Put(aProtectAttr
);
1158 m_xEditEngine
->QuickSetAttribs(aSet
, ESelection(nPara
, nStart
, nPara
, nEnd
+ 1));
1162 // add two empty paragraphs at the end
1163 if(m_pParentDialog
->m_eType
== SwCustomizeAddressBlockDialog::ADDRESSBLOCK_NEW
||
1164 m_pParentDialog
->m_eType
== SwCustomizeAddressBlockDialog::ADDRESSBLOCK_EDIT
)
1166 sal_Int32 nLastLen
= m_xEditEngine
->GetText(nParaCount
- 1).getLength();
1169 int nPara
= nParaCount
? nParaCount
- 1 : 0;
1170 ESelection
aPaM(nPara
, nLastLen
, nPara
, nLastLen
);
1171 m_xEditEngine
->QuickInsertText("\n \n ", aPaM
);
1175 m_xEditView
->SetSelection(ESelection(0, 0, 0, 0));
1178 // Insert the new entry in front of the entry at the beginning of the selection
1179 void AddressMultiLineEdit::InsertNewEntry( const OUString
& rStr
)
1181 // insert new entry after current selected one.
1182 ESelection aSelection
= m_xEditView
->GetSelection();
1183 const sal_uInt32 nPara
= aSelection
.nStartPara
;
1185 std::vector
<EECharAttrib
> aAttribList
;
1186 m_xEditEngine
->GetCharAttribs(nPara
, aAttribList
);
1188 sal_Int32 nIndex
= aSelection
.nEndPara
;
1189 const EECharAttrib
* pAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1190 if(nullptr != pAttrib
)
1191 nIndex
= pAttrib
->nEnd
;
1192 InsertNewEntryAtPosition( rStr
, nPara
, nIndex
);
1194 // select the new entry
1195 m_xEditEngine
->GetCharAttribs(nPara
, aAttribList
);
1196 pAttrib
= FindCharAttrib(nIndex
, aAttribList
);
1197 const sal_Int32 nEnd
= pAttrib
? pAttrib
->nEnd
: nIndex
;
1198 ESelection
aEntrySel(nPara
, nIndex
, nPara
, nEnd
);
1199 m_xEditView
->SetSelection(aEntrySel
);
1201 m_aModifyLink
.Call(*this);
1204 void AddressMultiLineEdit::InsertNewEntryAtPosition( const OUString
& rStr
, sal_uLong nPara
, sal_uInt16 nIndex
)
1206 ESelection
aInsertPos(nPara
, nIndex
, nPara
, nIndex
);
1207 m_xEditEngine
->QuickInsertText(rStr
, aInsertPos
);
1209 //restore the attributes
1210 SetText( GetAddress() );
1212 //select the newly inserted/moved element
1213 m_xEditView
->SetSelection(aInsertPos
);
1214 m_aSelectionLink
.Call(false);
1217 void AddressMultiLineEdit::RemoveCurrentEntry()
1219 ESelection aSelection
= m_xEditView
->GetSelection();
1221 std::vector
<EECharAttrib
> aAttribList
;
1222 m_xEditEngine
->GetCharAttribs(aSelection
.nStartPara
, aAttribList
);
1224 const EECharAttrib
* pBeginAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1226 (pBeginAttrib
->nStart
<= aSelection
.nStartPos
1227 && pBeginAttrib
->nEnd
>= aSelection
.nEndPos
))
1229 const sal_uInt32 nPara
= aSelection
.nStartPara
;
1230 ESelection
aEntrySel(nPara
, pBeginAttrib
->nStart
, nPara
, pBeginAttrib
->nEnd
);
1231 m_xEditEngine
->QuickInsertText(OUString(), aEntrySel
);
1232 //restore the attributes
1233 SetText( GetAddress() );
1234 m_aModifyLink
.Call(*this);
1238 void AddressMultiLineEdit::MoveCurrentItem(MoveItemFlags nMove
)
1240 ESelection aSelection
= m_xEditView
->GetSelection();
1242 std::vector
<EECharAttrib
> aAttribList
;
1243 m_xEditEngine
->GetCharAttribs(aSelection
.nStartPara
, aAttribList
);
1245 const EECharAttrib
* pBeginAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1247 pBeginAttrib
->nStart
> aSelection
.nStartPos
||
1248 pBeginAttrib
->nEnd
< aSelection
.nEndPos
)
1251 //current item has been found
1252 sal_Int32 nPara
= aSelection
.nStartPara
;
1253 sal_Int32 nIndex
= pBeginAttrib
->nStart
;
1254 ESelection
aEntrySel(nPara
, pBeginAttrib
->nStart
, nPara
, pBeginAttrib
->nEnd
);
1255 const OUString sCurrentItem
= m_xEditEngine
->GetText(aEntrySel
);
1256 m_xEditEngine
->RemoveAttribs(aEntrySel
, false, EE_CHAR_GRABBAG
);
1257 m_xEditEngine
->QuickInsertText(OUString(), aEntrySel
);
1258 m_xEditEngine
->GetCharAttribs(nPara
, aAttribList
);
1261 case MoveItemFlags::Left
:
1264 //go left to find a predecessor or simple text
1266 const OUString sPara
= m_xEditEngine
->GetText( nPara
);
1267 sal_Int32 nSearchIndex
= sPara
.lastIndexOf( '>', nIndex
+1 );
1268 if( nSearchIndex
!= -1 && nSearchIndex
== nIndex
)
1270 nSearchIndex
= sPara
.lastIndexOf( '<', nIndex
);
1271 if( nSearchIndex
!= -1 )
1272 nIndex
= nSearchIndex
;
1276 case MoveItemFlags::Right
:
1278 //go right to find a successor or simple text
1280 const EECharAttrib
* pEndAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1281 if(pEndAttrib
&& pEndAttrib
->nEnd
>= nIndex
)
1283 nIndex
= pEndAttrib
->nEnd
;
1287 case MoveItemFlags::Up
:
1291 case MoveItemFlags::Down
:
1297 //add a new paragraph if there is none yet
1298 if (nPara
>= m_xEditEngine
->GetParagraphCount())
1300 auto nInsPara
= nPara
- 1;
1301 auto nInsPos
= m_xEditEngine
->GetTextLen( nPara
- 1 );
1302 ESelection
aTemp(nInsPara
, nInsPos
, nInsPara
, nInsPos
);
1303 m_xEditEngine
->QuickInsertText("\n", aTemp
);
1305 InsertNewEntryAtPosition( sCurrentItem
, nPara
, nIndex
);
1307 // select the new entry [#i40817]
1308 m_xEditEngine
->GetCharAttribs(nPara
, aAttribList
);
1309 const EECharAttrib
* pAttrib
= FindCharAttrib(nIndex
, aAttribList
);
1311 aEntrySel
= ESelection(nPara
, nIndex
, nPara
, pAttrib
->nEnd
);
1312 m_xEditView
->SetSelection(aEntrySel
);
1314 m_aModifyLink
.Call(*this);
1317 MoveItemFlags
AddressMultiLineEdit::IsCurrentItemMoveable() const
1319 MoveItemFlags nRet
= MoveItemFlags::NONE
;
1320 ESelection aSelection
= m_xEditView
->GetSelection();
1322 std::vector
<EECharAttrib
> aAttribList
;
1323 m_xEditEngine
->GetCharAttribs(aSelection
.nStartPara
, aAttribList
);
1325 const EECharAttrib
* pBeginAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1327 (pBeginAttrib
->nStart
<= aSelection
.nStartPos
1328 && pBeginAttrib
->nEnd
>= aSelection
.nEndPos
))
1330 if (pBeginAttrib
->nStart
)
1331 nRet
|= MoveItemFlags::Left
;
1332 //if there is an entry it can always be move to the right and down
1333 nRet
|= MoveItemFlags::Right
| MoveItemFlags::Down
;
1334 if (aSelection
.nStartPara
> 0)
1335 nRet
|= MoveItemFlags::Up
;
1340 bool AddressMultiLineEdit::HasCurrentItem() const
1342 ESelection aSelection
= m_xEditView
->GetSelection();
1344 std::vector
<EECharAttrib
> aAttribList
;
1345 m_xEditEngine
->GetCharAttribs(aSelection
.nStartPara
, aAttribList
);
1347 const EECharAttrib
* pBeginAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1348 return (pBeginAttrib
&&
1349 (pBeginAttrib
->nStart
<= aSelection
.nStartPos
1350 && pBeginAttrib
->nEnd
>= aSelection
.nEndPos
));
1353 OUString
AddressMultiLineEdit::GetCurrentItem() const
1355 ESelection aSelection
= m_xEditView
->GetSelection();
1357 std::vector
<EECharAttrib
> aAttribList
;
1358 m_xEditEngine
->GetCharAttribs(aSelection
.nStartPara
, aAttribList
);
1360 const EECharAttrib
* pBeginAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1362 (pBeginAttrib
->nStart
<= aSelection
.nStartPos
1363 && pBeginAttrib
->nEnd
>= aSelection
.nEndPos
))
1365 const sal_uInt32 nPara
= aSelection
.nStartPara
;
1366 ESelection
aEntrySel(nPara
, pBeginAttrib
->nStart
, nPara
, pBeginAttrib
->nEnd
);
1367 return m_xEditEngine
->GetText( aEntrySel
);
1372 void AddressMultiLineEdit::SelectCurrentItem()
1374 ESelection aSelection
= m_xEditView
->GetSelection();
1376 std::vector
<EECharAttrib
> aAttribList
;
1377 m_xEditEngine
->GetCharAttribs(aSelection
.nStartPara
, aAttribList
);
1379 const EECharAttrib
* pBeginAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1381 (pBeginAttrib
->nStart
<= aSelection
.nStartPos
1382 && pBeginAttrib
->nEnd
>= aSelection
.nEndPos
))
1384 const sal_uInt32 nPara
= aSelection
.nStartPara
;
1385 ESelection
aEntrySel(nPara
, pBeginAttrib
->nStart
, nPara
, pBeginAttrib
->nEnd
);
1386 m_xEditView
->SetSelection(aEntrySel
);
1391 OUString
AddressMultiLineEdit::GetAddress() const
1394 const sal_uInt32 nParaCount
= m_xEditEngine
->GetParagraphCount();
1395 for(sal_uInt32 nPara
= nParaCount
; nPara
; --nPara
)
1397 const OUString sPara
= comphelper::string::stripEnd(m_xEditEngine
->GetText(nPara
- 1), ' ');
1398 //don't add empty trailing paragraphs
1399 if(!sRet
.isEmpty() || !sPara
.isEmpty())
1401 sRet
= sPara
+ sRet
;
1402 //insert the para break
1410 void AddressMultiLineEdit::UpdateFields()
1412 ESelection aSelection
= m_xEditView
->GetSelection();
1414 //restore the attributes
1415 SetText( GetAddress() );
1417 //reselect the element
1418 m_xEditView
->SetSelection(aSelection
);
1419 m_aSelectionLink
.Call(false);
1422 void AddressMultiLineEdit::EditViewSelectionChange()
1424 WeldEditView::EditViewSelectionChange();
1425 m_aSelectionLink
.Call(true);
1430 // sit between the tree as drag source and the editview as drop target and translate
1431 // the tree dnd data to the simple string the editview wants
1432 class DropTargetListener
: public cppu::WeakImplHelper
< css::datatransfer::dnd::XDropTargetListener
,
1433 css::datatransfer::dnd::XDropTarget
>
1436 css::uno::Reference
<css::datatransfer::dnd::XDropTarget
> m_xRealDropTarget
;
1437 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> m_aListeners
;
1438 SwCustomizeAddressBlockDialog
* m_pParentDialog
;
1441 virtual void SAL_CALL
disposing( const css::lang::EventObject
& ) override
1443 m_xRealDropTarget
.clear();
1444 m_aListeners
.clear();
1447 // XDropTargetListener
1448 virtual void SAL_CALL
drop( const css::datatransfer::dnd::DropTargetDropEvent
& dtde
) override
1450 SolarMutexGuard aGuard
;
1452 auto aReplacement(dtde
);
1454 Point
aMousePos(dtde
.LocationX
, dtde
.LocationY
);
1455 bool bAllowed
= m_pParentDialog
->SetCursorLogicPosition(aMousePos
);
1458 if (weld::TreeView
* pTree
= m_pParentDialog
->get_drag_source())
1460 int nEntry
= pTree
->get_selected_index();
1463 sal_Int32 nUserData
= pTree
->get_id(nEntry
).toInt32();
1464 //special entries can only be once in the address / greeting
1465 if (nUserData
>= 0 || !m_pParentDialog
->HasItem(nUserData
))
1467 rtl::Reference
<TransferDataContainer
> xContainer
= new TransferDataContainer
;
1468 xContainer
->CopyString( "<" + pTree
->get_text(nEntry
) + ">" );
1470 // replace what the treeview is offering with what ImpEditView::drop wants
1471 aReplacement
.Transferable
= xContainer
.get();
1477 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(m_aListeners
);
1478 for (auto const& listener
: aListeners
)
1479 listener
->drop(aReplacement
);
1482 m_pParentDialog
->UpdateFields();
1485 virtual void SAL_CALL
dragEnter( const css::datatransfer::dnd::DropTargetDragEnterEvent
& dtdee
) override
1487 auto aReplacement(dtdee
);
1488 // replace what the treeview is offering with what ImpEditView::dragEnter wants
1489 aReplacement
.SupportedDataFlavors
.realloc(1);
1490 SotExchange::GetFormatDataFlavor(SotClipboardFormatId::STRING
, aReplacement
.SupportedDataFlavors
.getArray()[0]);
1492 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(m_aListeners
);
1493 for (auto const& listener
: aListeners
)
1494 listener
->dragEnter(aReplacement
);
1497 virtual void SAL_CALL
dragExit( const css::datatransfer::dnd::DropTargetEvent
& dte
) override
1499 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(m_aListeners
);
1500 for (auto const& listener
: aListeners
)
1501 listener
->dragExit( dte
);
1504 virtual void SAL_CALL
dragOver( const css::datatransfer::dnd::DropTargetDragEvent
& dtde
) override
1506 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(m_aListeners
);
1507 for (auto const& listener
: aListeners
)
1508 listener
->dragOver( dtde
);
1511 virtual void SAL_CALL
dropActionChanged( const css::datatransfer::dnd::DropTargetDragEvent
& dtde
) override
1513 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(m_aListeners
);
1514 for (auto const& listener
: aListeners
)
1515 listener
->dropActionChanged( dtde
);
1519 virtual void SAL_CALL
addDropTargetListener(const css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>& xListener
) override
1521 m_aListeners
.push_back(xListener
);
1524 virtual void SAL_CALL
removeDropTargetListener(const css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>& xListener
) override
1526 m_aListeners
.erase(std::remove(m_aListeners
.begin(), m_aListeners
.end(), xListener
), m_aListeners
.end());
1529 virtual sal_Bool SAL_CALL
isActive() override
1531 return m_xRealDropTarget
->isActive();
1534 virtual void SAL_CALL
setActive(sal_Bool active
) override
1536 m_xRealDropTarget
->setActive(active
);
1539 virtual sal_Int8 SAL_CALL
getDefaultActions() override
1541 return m_xRealDropTarget
->getDefaultActions();
1544 virtual void SAL_CALL
setDefaultActions(sal_Int8 actions
) override
1546 m_xRealDropTarget
->setDefaultActions(actions
);
1550 DropTargetListener(css::uno::Reference
<css::datatransfer::dnd::XDropTarget
> xRealDropTarget
,
1551 SwCustomizeAddressBlockDialog
* pParentDialog
)
1552 : m_xRealDropTarget(std::move(xRealDropTarget
))
1553 , m_pParentDialog(pParentDialog
)
1559 css::uno::Reference
<css::datatransfer::dnd::XDropTarget
> AddressMultiLineEdit::GetDropTarget()
1561 if (!m_xDropTarget
.is())
1563 auto xRealDropTarget
= GetDrawingArea()->get_drop_target();
1564 rtl::Reference
<DropTargetListener
> pProxy
= new DropTargetListener(xRealDropTarget
, m_pParentDialog
);
1565 xRealDropTarget
->addDropTargetListener(pProxy
);
1566 m_xDropTarget
= pProxy
;
1568 return m_xDropTarget
;
1571 bool AddressMultiLineEdit::SetCursorLogicPosition(const Point
& rPosition
)
1573 Point aMousePos
= EditViewOutputDevice().PixelToLogic(rPosition
);
1574 m_xEditView
->SetCursorLogicPosition(aMousePos
, false, true);
1576 ESelection aSelection
= m_xEditView
->GetSelection();
1577 std::vector
<EECharAttrib
> aAttribList
;
1578 m_xEditEngine
->GetCharAttribs(aSelection
.nStartPara
, aAttribList
);
1579 return FindCharAttrib(aSelection
.nStartPos
, aAttribList
) == nullptr;
1582 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */