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>
28 #include <vcl/event.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/weld.hxx>
31 #include <vcl/transfer.hxx>
32 #include <mmconfigitem.hxx>
33 #include <com/sun/star/container/XNameAccess.hpp>
34 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
35 #include <com/sun/star/sdbc/SQLException.hpp>
36 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
37 #include <com/sun/star/sdb/XColumn.hpp>
38 #include <comphelper/sequence.hxx>
39 #include <comphelper/string.hxx>
40 #include <tools/diagnose_ex.h>
43 #include <strings.hrc>
44 #include <mmaddressblockpage.hrc>
48 using namespace ::com::sun::star
;
49 using namespace ::com::sun::star::container
;
50 using namespace ::com::sun::star::sdb
;
51 using namespace ::com::sun::star::sdbc
;
52 using namespace ::com::sun::star::sdbcx
;
54 SwMailMergeAddressBlockPage::SwMailMergeAddressBlockPage(weld::Container
* pPage
, SwMailMergeWizard
* pWizard
)
55 : vcl::OWizardPage(pPage
, pWizard
, "modules/swriter/ui/mmaddressblockpage.ui", "MMAddressBlockPage")
57 , m_xAddressListPB(m_xBuilder
->weld_button("addresslist"))
58 , m_xCurrentAddressFI(m_xBuilder
->weld_label("currentaddress"))
59 , m_xStep2(m_xBuilder
->weld_container("step2"))
60 , m_xStep3(m_xBuilder
->weld_container("step3"))
61 , m_xStep4(m_xBuilder
->weld_container("step4"))
62 , m_xSettingsFI(m_xBuilder
->weld_label("settingsft"))
63 , m_xAddressCB(m_xBuilder
->weld_check_button("address"))
64 , m_xSettingsPB(m_xBuilder
->weld_button("settings"))
65 , m_xHideEmptyParagraphsCB(m_xBuilder
->weld_check_button("hideempty"))
66 , m_xAssignPB(m_xBuilder
->weld_button("assign"))
67 , m_xDocumentIndexFI(m_xBuilder
->weld_label("documentindex"))
68 , m_xPrevSetIB(m_xBuilder
->weld_button("prev"))
69 , m_xNextSetIB(m_xBuilder
->weld_button("next"))
70 , m_xDifferentlist(m_xBuilder
->weld_button("differentlist"))
71 , m_xSettings(new SwAddressPreview(m_xBuilder
->weld_scrolled_window("settingspreviewwin", true)))
72 , m_xPreview(new SwAddressPreview(m_xBuilder
->weld_scrolled_window("addresspreviewwin", true)))
73 , m_xSettingsWIN(new weld::CustomWeld(*m_xBuilder
, "settingspreview", *m_xSettings
))
74 , m_xPreviewWIN(new weld::CustomWeld(*m_xBuilder
, "addresspreview", *m_xPreview
))
76 m_xSettingsWIN
->set_size_request(m_xDifferentlist
->get_approximate_digit_width() * 40,
77 m_xDifferentlist
->get_text_height() * 6);
78 m_xPreviewWIN
->set_size_request(m_xDifferentlist
->get_approximate_digit_width() * 44,
79 m_xDifferentlist
->get_text_height() * 6);
80 m_sChangeAddress
= m_xDifferentlist
->get_label();
81 m_sDocument
= m_xDocumentIndexFI
->get_label();
83 m_sCurrentAddress
= m_xCurrentAddressFI
->get_label();
84 m_xAddressListPB
->connect_clicked(LINK(this, SwMailMergeAddressBlockPage
, AddressListHdl_Impl
));
85 m_xSettingsPB
->connect_clicked(LINK(this, SwMailMergeAddressBlockPage
, SettingsHdl_Impl
));
86 m_xAssignPB
->connect_clicked(LINK(this, SwMailMergeAddressBlockPage
, AssignHdl_Impl
));
87 m_xAddressCB
->connect_toggled(LINK(this, SwMailMergeAddressBlockPage
, AddressBlockHdl_Impl
));
88 m_xSettings
->SetSelectHdl(LINK(this, SwMailMergeAddressBlockPage
, AddressBlockSelectHdl_Impl
));
89 m_xHideEmptyParagraphsCB
->connect_toggled(LINK(this, SwMailMergeAddressBlockPage
, HideParagraphsHdl_Impl
));
91 Link
<weld::Button
&,void> aLink
= LINK(this, SwMailMergeAddressBlockPage
, InsertDataHdl_Impl
);
92 m_xPrevSetIB
->connect_clicked(aLink
);
93 m_xNextSetIB
->connect_clicked(aLink
);
95 // lock in preferred size including current address line
96 Size
aSize1(m_xContainer
->get_preferred_size());
98 OUString sOrigLabel
= m_xAddressListPB
->get_label();
99 m_xAddressListPB
->set_label(m_sChangeAddress
);
100 Size
aSize2(m_xContainer
->get_preferred_size());
101 m_xAddressListPB
->set_label(sOrigLabel
);
103 m_xCurrentAddressFI
->hide();
105 m_xContainer
->set_size_request(std::max(aSize1
.Width(), aSize2
.Width()),
106 std::max(aSize1
.Height(), aSize2
.Height()));
109 SwMailMergeAddressBlockPage::~SwMailMergeAddressBlockPage()
111 m_xPreviewWIN
.reset();
112 m_xSettingsWIN
.reset();
117 bool SwMailMergeAddressBlockPage::canAdvance() const
119 return m_pWizard
->GetConfigItem().GetResultSet().is();
122 void SwMailMergeAddressBlockPage::Activate()
124 SwMailMergeConfigItem
& rConfigItem
= m_pWizard
->GetConfigItem();
125 bool bIsLetter
= rConfigItem
.IsOutputToLetter();
127 //no address block is created for e-Mail
128 m_xStep2
->set_visible(bIsLetter
);
129 m_xStep3
->set_visible(bIsLetter
);
130 m_xStep4
->set_visible(bIsLetter
);
135 m_xHideEmptyParagraphsCB
->set_active( rConfigItem
.IsHideEmptyParagraphs() );
136 m_xDocumentIndexFI
->set_label(m_sDocument
.replaceFirst("%1", "1"));
138 m_xSettings
->Clear();
139 const uno::Sequence
< OUString
> aBlocks
=
140 m_pWizard
->GetConfigItem().GetAddressBlocks();
141 for(const auto& rAddress
: aBlocks
)
142 m_xSettings
->AddAddress(rAddress
);
143 m_xSettings
->SelectAddress(static_cast<sal_uInt16
>(rConfigItem
.GetCurrentAddressBlockIndex()));
144 m_xAddressCB
->set_active(rConfigItem
.IsAddressBlock());
145 AddressBlockHdl_Impl(*m_xAddressCB
);
146 m_xSettings
->SetLayout(1, 2);
147 InsertDataHdl(nullptr);
150 bool SwMailMergeAddressBlockPage::commitPage( ::vcl::WizardTypes::CommitPageReason _eReason
)
152 return ::vcl::WizardTypes::eTravelForward
!= _eReason
|| m_pWizard
->GetConfigItem().GetResultSet().is();
155 IMPL_LINK_NOARG(SwMailMergeAddressBlockPage
, AddressListHdl_Impl
, weld::Button
&, void)
159 SwAddressListDialog
aAddrDialog(this);
160 if (RET_OK
== aAddrDialog
.run())
162 SwMailMergeConfigItem
& rConfigItem
= m_pWizard
->GetConfigItem();
163 rConfigItem
.SetCurrentConnection(
164 aAddrDialog
.GetSource(),
165 aAddrDialog
.GetConnection(),
166 aAddrDialog
.GetColumnsSupplier(),
167 aAddrDialog
.GetDBData());
168 OUString sFilter
= aAddrDialog
.GetFilter();
169 rConfigItem
.SetFilter( sFilter
);
170 InsertDataHdl(nullptr);
171 GetWizard()->UpdateRoadmap();
172 GetWizard()->enableButtons(WizardButtonFlags::NEXT
, GetWizard()->isStateEnabled(MM_GREETINGSPAGE
));
175 catch (const uno::Exception
& e
)
177 TOOLS_WARN_EXCEPTION("sw", "");
178 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(m_pWizard
->getDialog(),
179 VclMessageType::Warning
, VclButtonsType::Ok
, e
.Message
));
184 IMPL_LINK_NOARG(SwMailMergeAddressBlockPage
, SettingsHdl_Impl
, weld::Button
&, void)
186 SwSelectAddressBlockDialog
aDlg(m_pWizard
->getDialog(), m_pWizard
->GetConfigItem());
187 SwMailMergeConfigItem
& rConfig
= m_pWizard
->GetConfigItem();
188 aDlg
.SetAddressBlocks(rConfig
.GetAddressBlocks(), m_xSettings
->GetSelectedAddress());
189 aDlg
.SetSettings(rConfig
.IsIncludeCountry(), rConfig
.GetExcludeCountry());
190 if (aDlg
.run() == RET_OK
)
192 //the dialog provides the selected address at the first position!
193 const uno::Sequence
< OUString
> aBlocks
= aDlg
.GetAddressBlocks();
194 rConfig
.SetAddressBlocks(aBlocks
);
195 m_xSettings
->Clear();
196 for(const auto& rAddress
: aBlocks
)
197 m_xSettings
->AddAddress(rAddress
);
198 m_xSettings
->SelectAddress(0);
199 m_xSettings
->Invalidate(); // #i40408
200 rConfig
.SetCountrySettings(aDlg
.IsIncludeCountry(), aDlg
.GetCountry());
201 InsertDataHdl(nullptr);
203 GetWizard()->UpdateRoadmap();
204 GetWizard()->enableButtons(WizardButtonFlags::NEXT
, GetWizard()->isStateEnabled(MM_GREETINGSPAGE
));
207 IMPL_LINK_NOARG(SwMailMergeAddressBlockPage
, AssignHdl_Impl
, weld::Button
&, void)
209 SwMailMergeConfigItem
& rConfigItem
= m_pWizard
->GetConfigItem();
210 const sal_uInt16 nSel
= m_xSettings
->GetSelectedAddress();
211 const uno::Sequence
< OUString
> aBlocks
= rConfigItem
.GetAddressBlocks();
212 SwAssignFieldsDialog
aDlg(m_pWizard
->getDialog(), m_pWizard
->GetConfigItem(), aBlocks
[nSel
], true);
213 if(RET_OK
== aDlg
.run())
216 InsertDataHdl(nullptr);
217 GetWizard()->UpdateRoadmap();
218 GetWizard()->enableButtons(WizardButtonFlags::NEXT
, GetWizard()->isStateEnabled(MM_GREETINGSPAGE
));
222 void SwMailMergeAddressBlockPage::EnableAddressBlock(bool bAll
, bool bSelective
)
224 m_xSettingsFI
->set_sensitive(bAll
);
225 m_xAddressCB
->set_sensitive(bAll
);
227 m_xHideEmptyParagraphsCB
->set_sensitive(bSelective
);
228 m_xSettingsWIN
->set_sensitive(bSelective
);
229 m_xSettingsPB
->set_sensitive(bSelective
);
230 m_xStep3
->set_sensitive(bSelective
);
231 m_xStep4
->set_sensitive(bSelective
);
234 IMPL_LINK(SwMailMergeAddressBlockPage
, AddressBlockHdl_Impl
, weld::ToggleButton
&, rBox
, void)
236 EnableAddressBlock(rBox
.get_sensitive(), rBox
.get_active());
237 SwMailMergeConfigItem
& rConfigItem
= m_pWizard
->GetConfigItem();
238 rConfigItem
.SetAddressBlock(m_xAddressCB
->get_active());
239 m_pWizard
->UpdateRoadmap();
240 GetWizard()->enableButtons(WizardButtonFlags::NEXT
, GetWizard()->isStateEnabled(MM_GREETINGSPAGE
));
243 IMPL_LINK_NOARG(SwMailMergeAddressBlockPage
, AddressBlockSelectHdl_Impl
, LinkParamNone
*, void)
245 const sal_uInt16 nSel
= m_xSettings
->GetSelectedAddress();
246 const uno::Sequence
< OUString
> aBlocks
=
247 m_pWizard
->GetConfigItem().GetAddressBlocks();
248 m_xPreview
->SetAddress(SwAddressPreview::FillData(aBlocks
[nSel
],
249 m_pWizard
->GetConfigItem()));
250 m_pWizard
->GetConfigItem().SetCurrentAddressBlockIndex( nSel
);
251 GetWizard()->UpdateRoadmap();
252 GetWizard()->enableButtons(WizardButtonFlags::NEXT
, GetWizard()->isStateEnabled(MM_GREETINGSPAGE
));
255 IMPL_LINK(SwMailMergeAddressBlockPage
, HideParagraphsHdl_Impl
, weld::ToggleButton
&, rBox
, void)
257 SwMailMergeConfigItem
& rConfigItem
= m_pWizard
->GetConfigItem();
258 rConfigItem
.SetHideEmptyParagraphs(rBox
.get_active());
261 void SwMailMergeAddressBlockPage::InsertDataHdl(const weld::Button
* pButton
)
263 //if no pButton is given, the first set has to be pre-set
264 SwMailMergeConfigItem
& rConfig
= m_pWizard
->GetConfigItem();
265 std::unique_ptr
<weld::WaitObject
> xWaitObj(new weld::WaitObject(m_pWizard
->getDialog()));
268 rConfig
.GetResultSet();
272 bool bNext
= pButton
== m_xNextSetIB
.get();
273 sal_Int32 nPos
= rConfig
.GetResultSetPosition();
274 rConfig
.MoveResultSet( bNext
? ++nPos
: --nPos
);
277 sal_Int32 nPos
= rConfig
.GetResultSetPosition();
286 //if output type is letter
287 if (m_xSettings
->IsVisible())
289 //Fill data into preview
290 const sal_uInt16 nSel
= m_xSettings
->GetSelectedAddress();
291 const uno::Sequence
< OUString
> aBlocks
=
292 m_pWizard
->GetConfigItem().GetAddressBlocks();
293 m_xPreview
->SetAddress(SwAddressPreview::FillData(aBlocks
[nSel
], rConfig
));
296 m_xPrevSetIB
->set_sensitive(bEnable
);
297 m_xDocumentIndexFI
->set_label(m_sDocument
.replaceFirst("%1", OUString::number(nPos
)));
299 GetWizard()->enableButtons(WizardButtonFlags::NEXT
, GetWizard()->isStateEnabled(MM_GREETINGSPAGE
));
300 bool bHasResultSet
= rConfig
.GetResultSet().is();
301 m_xCurrentAddressFI
->set_visible(bHasResultSet
);
304 m_xCurrentAddressFI
->set_label(m_sCurrentAddress
.replaceFirst("%1", rConfig
.GetCurrentDBData().sDataSource
));
305 m_xAddressListPB
->set_label(m_sChangeAddress
);
307 EnableAddressBlock(bHasResultSet
, m_xAddressCB
->get_active());
310 IMPL_LINK(SwMailMergeAddressBlockPage
, InsertDataHdl_Impl
, weld::Button
&, rButton
, void)
312 InsertDataHdl(&rButton
);
315 SwSelectAddressBlockDialog::SwSelectAddressBlockDialog(weld::Window
* pParent
, SwMailMergeConfigItem
& rConfig
)
316 : SfxDialogController(pParent
, "modules/swriter/ui/selectblockdialog.ui", "SelectBlockDialog")
318 , m_xPreview(new SwAddressPreview(m_xBuilder
->weld_scrolled_window("previewwin", true)))
319 , m_xNewPB(m_xBuilder
->weld_button("new"))
320 , m_xCustomizePB(m_xBuilder
->weld_button("edit"))
321 , m_xDeletePB(m_xBuilder
->weld_button("delete"))
322 , m_xNeverRB(m_xBuilder
->weld_radio_button("never"))
323 , m_xAlwaysRB(m_xBuilder
->weld_radio_button("always"))
324 , m_xDependentRB(m_xBuilder
->weld_radio_button("dependent"))
325 , m_xCountryED(m_xBuilder
->weld_entry("country"))
326 , m_xPreviewWin(new weld::CustomWeld(*m_xBuilder
, "preview", *m_xPreview
))
328 m_xPreviewWin
->set_size_request(m_xCountryED
->get_approximate_digit_width() * 45,
329 m_xCountryED
->get_text_height() * 12);
331 Link
<weld::Button
&,void> aCustomizeHdl
= LINK(this, SwSelectAddressBlockDialog
, NewCustomizeHdl_Impl
);
332 m_xNewPB
->connect_clicked(aCustomizeHdl
);
333 m_xCustomizePB
->connect_clicked(aCustomizeHdl
);
335 m_xDeletePB
->connect_clicked(LINK(this, SwSelectAddressBlockDialog
, DeleteHdl_Impl
));
337 Link
<weld::ToggleButton
&,void> aLk
= LINK(this, SwSelectAddressBlockDialog
, IncludeHdl_Impl
);
338 m_xNeverRB
->connect_toggled(aLk
);
339 m_xAlwaysRB
->connect_toggled(aLk
);
340 m_xDependentRB
->connect_toggled(aLk
);
341 m_xPreview
->SetLayout(2, 2);
342 m_xPreview
->EnableScrollBar();
345 SwSelectAddressBlockDialog::~SwSelectAddressBlockDialog()
349 void SwSelectAddressBlockDialog::SetAddressBlocks(const uno::Sequence
< OUString
>& rBlocks
,
350 sal_uInt16 nSelectedAddress
)
352 m_aAddressBlocks
= rBlocks
;
353 for (const auto& rAddressBlock
: std::as_const(m_aAddressBlocks
))
354 m_xPreview
->AddAddress(rAddressBlock
);
355 m_xPreview
->SelectAddress(nSelectedAddress
);
358 // return the address blocks and put the selected one to the first position
359 const uno::Sequence
< OUString
>& SwSelectAddressBlockDialog::GetAddressBlocks()
361 //put the selected block to the first position
362 const sal_Int32 nSelect
= static_cast<sal_Int32
>(m_xPreview
->GetSelectedAddress());
365 uno::Sequence
< OUString
>aTemp
= m_aAddressBlocks
;
366 aTemp
[0] = m_aAddressBlocks
[nSelect
];
367 std::copy(m_aAddressBlocks
.begin(), std::next(m_aAddressBlocks
.begin(), nSelect
), std::next(aTemp
.begin()));
368 std::copy(std::next(m_aAddressBlocks
.begin(), nSelect
+ 1), m_aAddressBlocks
.end(), std::next(aTemp
.begin(), nSelect
+ 1));
369 m_aAddressBlocks
= aTemp
;
371 return m_aAddressBlocks
;
374 void SwSelectAddressBlockDialog::SetSettings(
375 bool bIsCountry
, const OUString
& rCountry
)
377 weld::RadioButton
*pActive
= m_xNeverRB
.get();
380 pActive
= !rCountry
.isEmpty() ? m_xDependentRB
.get() : m_xAlwaysRB
.get();
381 m_xCountryED
->set_text(rCountry
);
383 pActive
->set_active(true);
384 IncludeHdl_Impl(*pActive
);
385 m_xDeletePB
->set_sensitive(m_aAddressBlocks
.getLength() > 1);
388 OUString
SwSelectAddressBlockDialog::GetCountry() const
390 if (m_xDependentRB
->get_active())
391 return m_xCountryED
->get_text();
395 IMPL_LINK(SwSelectAddressBlockDialog
, DeleteHdl_Impl
, weld::Button
&, rButton
, void)
397 if (m_aAddressBlocks
.getLength())
399 const sal_Int32 nSelected
= static_cast<sal_Int32
>(m_xPreview
->GetSelectedAddress());
400 comphelper::removeElementAt(m_aAddressBlocks
, nSelected
);
401 if (m_aAddressBlocks
.getLength() <= 1)
402 rButton
.set_sensitive(false);
403 m_xPreview
->RemoveSelectedAddress();
407 IMPL_LINK(SwSelectAddressBlockDialog
, NewCustomizeHdl_Impl
, weld::Button
&, rButton
, void)
409 bool bCustomize
= &rButton
== m_xCustomizePB
.get();
410 SwCustomizeAddressBlockDialog::DialogType nType
= bCustomize
?
411 SwCustomizeAddressBlockDialog::ADDRESSBLOCK_EDIT
:
412 SwCustomizeAddressBlockDialog::ADDRESSBLOCK_NEW
;
413 std::unique_ptr
<SwCustomizeAddressBlockDialog
> xDlg(new SwCustomizeAddressBlockDialog(&rButton
,
417 xDlg
->SetAddress(m_aAddressBlocks
[m_xPreview
->GetSelectedAddress()]);
419 if (RET_OK
!= xDlg
->run())
422 const OUString sNew
= xDlg
->GetAddress();
425 m_xPreview
->ReplaceSelectedAddress(sNew
);
426 m_aAddressBlocks
[m_xPreview
->GetSelectedAddress()] = sNew
;
430 m_xPreview
->AddAddress(sNew
);
431 m_aAddressBlocks
.realloc(m_aAddressBlocks
.getLength() + 1);
432 const sal_Int32 nSelect
= m_aAddressBlocks
.getLength() - 1;
433 m_aAddressBlocks
[nSelect
] = sNew
;
434 m_xPreview
->SelectAddress(static_cast<sal_uInt16
>(nSelect
));
436 m_xDeletePB
->set_sensitive(m_aAddressBlocks
.getLength() > 1);
439 IMPL_LINK_NOARG(SwSelectAddressBlockDialog
, IncludeHdl_Impl
, weld::ToggleButton
&, void)
441 m_xCountryED
->set_sensitive(m_xDependentRB
->get_active());
444 #define USER_DATA_SALUTATION -1
445 #define USER_DATA_PUNCTUATION -2
446 #define USER_DATA_TEXT -3
447 #define USER_DATA_NONE -4
449 IMPL_LINK(SwCustomizeAddressBlockDialog
, TextFilterHdl
, OUString
&, rTest
, bool)
451 rTest
= m_aTextFilter
.filter(rTest
);
455 SwCustomizeAddressBlockDialog::SwCustomizeAddressBlockDialog(
456 weld::Widget
* pParent
, SwMailMergeConfigItem
& rConfig
, DialogType eType
)
457 : SfxDialogController(pParent
, "modules/swriter/ui/addressblockdialog.ui",
458 "AddressBlockDialog")
459 , m_aTextFilter("<>")
460 , m_rConfigItem(rConfig
)
462 , m_xAddressElementsFT(m_xBuilder
->weld_label("addressesft"))
463 , m_xAddressElementsLB(m_xBuilder
->weld_tree_view("addresses"))
464 , m_xInsertFieldIB(m_xBuilder
->weld_button("toaddr"))
465 , m_xRemoveFieldIB(m_xBuilder
->weld_button("fromaddr"))
466 , m_xDragFT(m_xBuilder
->weld_label("addressdestft"))
467 , m_xUpIB(m_xBuilder
->weld_button("up"))
468 , m_xLeftIB(m_xBuilder
->weld_button("left"))
469 , m_xRightIB(m_xBuilder
->weld_button("right"))
470 , m_xDownIB(m_xBuilder
->weld_button("down"))
471 , m_xFieldFT(m_xBuilder
->weld_label("customft"))
472 , m_xFieldCB(m_xBuilder
->weld_combo_box("custom"))
473 , m_xOK(m_xBuilder
->weld_button("ok"))
474 , m_xPreview(new SwAddressPreview(m_xBuilder
->weld_scrolled_window("previewwin", true)))
475 , m_xPreviewWIN(new weld::CustomWeld(*m_xBuilder
, "addrpreview", *m_xPreview
))
476 , m_xDragED(new AddressMultiLineEdit(this))
477 , m_xDragWIN(new weld::CustomWeld(*m_xBuilder
, "addressdest", *m_xDragED
))
479 m_aSelectionChangedIdle
.SetInvokeHandler( LINK( this, SwCustomizeAddressBlockDialog
, SelectionChangedIdleHdl
) );
481 Size
aSize(m_xDragED
->GetDrawingArea()->get_size_request());
482 m_xPreview
->set_size_request(aSize
.Width(), aSize
.Height());
484 m_xFieldCB
->connect_entry_insert_text(LINK(this, SwCustomizeAddressBlockDialog
, TextFilterHdl
));
485 m_xAddressElementsLB
->set_size_request(-1, m_xAddressElementsLB
->get_height_rows(16));
487 if( eType
>= GREETING_FEMALE
)
491 m_xAddressElementsLB
->append(OUString::number(USER_DATA_SALUTATION
), SwResId(ST_SALUTATION
));
492 m_xAddressElementsLB
->append(OUString::number(USER_DATA_PUNCTUATION
), SwResId(ST_PUNCTUATION
));
493 m_xAddressElementsLB
->append(OUString::number(USER_DATA_TEXT
), SwResId(ST_TEXT
));
494 for (size_t i
= 0; i
< SAL_N_ELEMENTS(RA_SALUTATION
); ++i
)
495 m_aSalutations
.push_back(SwResId(RA_SALUTATION
[i
]));
496 for (size_t i
= 0; i
< SAL_N_ELEMENTS(RA_PUNCTUATION
); ++i
)
497 m_aPunctuations
.push_back(SwResId(RA_PUNCTUATION
[i
]));
498 m_xDragED
->SetText(" ");
499 m_xDialog
->set_title(SwResId(eType
== GREETING_MALE
? ST_TITLE_MALE
: ST_TITLE_FEMALE
));
500 m_xAddressElementsFT
->set_label(SwResId(ST_SALUTATIONELEMENTS
));
501 m_xInsertFieldIB
->set_tooltip_text(SwResId(ST_INSERTSALUTATIONFIELD
));
502 m_xRemoveFieldIB
->set_tooltip_text(SwResId(ST_REMOVESALUTATIONFIELD
));
503 m_xDragFT
->set_label(SwResId(ST_DRAGSALUTATION
));
507 if (eType
== ADDRESSBLOCK_EDIT
)
508 m_xDialog
->set_title(SwResId(ST_TITLE_EDIT
));
509 m_xDragED
->SetText("\n\n\n\n\n");
510 /* Set custom HIDs for swriter/01/mm_newaddblo.xhp */
511 m_xAddressElementsLB
->set_help_id( HID_MM_ADDBLOCK_ELEMENTS
);
512 m_xInsertFieldIB
->set_help_id( HID_MM_ADDBLOCK_INSERT
);
513 m_xRemoveFieldIB
->set_help_id( HID_MM_ADDBLOCK_REMOVE
);
514 m_xDragWIN
->set_help_id( HID_MM_ADDBLOCK_DRAG
);
515 m_xPreviewWIN
->set_help_id( HID_MM_ADDBLOCK_PREVIEW
);
516 m_xRightIB
->set_help_id( HID_MM_ADDBLOCK_MOVEBUTTONS
);
517 m_xLeftIB
->set_help_id( HID_MM_ADDBLOCK_MOVEBUTTONS
);
518 m_xDownIB
->set_help_id( HID_MM_ADDBLOCK_MOVEBUTTONS
);
519 m_xUpIB
->set_help_id( HID_MM_ADDBLOCK_MOVEBUTTONS
);
522 const std::vector
<std::pair
<OUString
, int>>& rHeaders
= m_rConfigItem
.GetDefaultAddressHeaders();
523 for (size_t i
= 0; i
< rHeaders
.size(); ++i
)
524 m_xAddressElementsLB
->append(OUString::number(i
), rHeaders
[i
].first
);
525 m_xOK
->connect_clicked(LINK(this, SwCustomizeAddressBlockDialog
, OKHdl_Impl
));
526 m_xAddressElementsLB
->connect_changed(LINK(this, SwCustomizeAddressBlockDialog
, ListBoxSelectHdl_Impl
));
527 if (m_xAddressElementsLB
->n_children())
528 m_xAddressElementsLB
->select(0);
529 m_xDragED
->SetModifyHdl(LINK(this, SwCustomizeAddressBlockDialog
, EditModifyHdl_Impl
));
530 m_xDragED
->SetSelectionChangedHdl( LINK( this, SwCustomizeAddressBlockDialog
, SelectionChangedHdl_Impl
));
531 m_xFieldCB
->connect_changed(LINK(this, SwCustomizeAddressBlockDialog
, FieldChangeComboBoxHdl_Impl
));
532 Link
<weld::Button
&,void> aImgButtonHdl
= LINK(this, SwCustomizeAddressBlockDialog
, ImageButtonHdl_Impl
);
533 m_xInsertFieldIB
->connect_clicked(aImgButtonHdl
);
534 m_xRemoveFieldIB
->connect_clicked(aImgButtonHdl
);
535 m_xUpIB
->connect_clicked(aImgButtonHdl
);
536 m_xLeftIB
->connect_clicked(aImgButtonHdl
);
537 m_xRightIB
->connect_clicked(aImgButtonHdl
);
538 m_xDownIB
->connect_clicked(aImgButtonHdl
);
539 UpdateImageButtons_Impl();
542 bool SwCustomizeAddressBlockDialog::SetCursorLogicPosition(const Point
& rPosition
)
544 return m_xDragED
->SetCursorLogicPosition(rPosition
);
547 void SwCustomizeAddressBlockDialog::UpdateFields()
549 m_xDragED
->UpdateFields();
552 SwCustomizeAddressBlockDialog::~SwCustomizeAddressBlockDialog()
554 m_xDragED
->EndDropTarget();
557 IMPL_LINK_NOARG(SwCustomizeAddressBlockDialog
, OKHdl_Impl
, weld::Button
&, void)
559 m_xDialog
->response(RET_OK
);
562 IMPL_LINK(SwCustomizeAddressBlockDialog
, ListBoxSelectHdl_Impl
, weld::TreeView
&, rBox
, void)
564 sal_Int32 nUserData
= rBox
.get_selected_id().toInt32();
565 // Check if the selected entry is already in the address and then forbid inserting
566 m_xInsertFieldIB
->set_sensitive(nUserData
>= 0 || !HasItem(nUserData
));
569 IMPL_LINK_NOARG(SwCustomizeAddressBlockDialog
, EditModifyHdl_Impl
, AddressMultiLineEdit
&, void)
571 m_xPreview
->SetAddress(SwAddressPreview::FillData(GetAddress(), m_rConfigItem
));
572 UpdateImageButtons_Impl();
575 IMPL_LINK(SwCustomizeAddressBlockDialog
, ImageButtonHdl_Impl
, weld::Button
&, rButton
, void)
577 if (m_xInsertFieldIB
.get() == &rButton
)
579 int nEntry
= m_xAddressElementsLB
->get_selected_index();
582 m_xDragED
->InsertNewEntry("<" + m_xAddressElementsLB
->get_text(nEntry
) + ">");
585 else if (m_xRemoveFieldIB
.get() == &rButton
)
587 m_xDragED
->RemoveCurrentEntry();
591 MoveItemFlags nMove
= MoveItemFlags::Down
;
592 if (m_xUpIB
.get() == &rButton
)
593 nMove
= MoveItemFlags::Up
;
594 else if (m_xLeftIB
.get() == &rButton
)
595 nMove
= MoveItemFlags::Left
;
596 else if (m_xRightIB
.get() == &rButton
)
597 nMove
= MoveItemFlags::Right
;
598 m_xDragED
->MoveCurrentItem(nMove
);
600 UpdateImageButtons_Impl();
603 sal_Int32
SwCustomizeAddressBlockDialog::GetSelectedItem_Impl() const
605 sal_Int32 nRet
= USER_DATA_NONE
;
606 const OUString sSelected
= m_xDragED
->GetCurrentItem();
607 if(!sSelected
.isEmpty())
609 for (int i
= 0, nEntryCount
= m_xAddressElementsLB
->n_children(); i
< nEntryCount
; ++i
)
611 const OUString sEntry
= m_xAddressElementsLB
->get_text(i
);
612 if( sEntry
== sSelected
.subView( 1, sSelected
.getLength() - 2 ) )
614 nRet
= m_xAddressElementsLB
->get_id(i
).toInt32();
622 bool SwCustomizeAddressBlockDialog::HasItem(sal_Int32 nUserData
)
624 //get the entry from the ListBox
626 for (int i
= 0, nEntryCount
= m_xAddressElementsLB
->n_children(); i
< nEntryCount
; ++i
)
628 if (m_xAddressElementsLB
->get_id(i
).toInt32() == nUserData
)
630 sEntry
= m_xAddressElementsLB
->get_text(i
);
634 //search for this entry in the content
635 return m_xDragED
->GetText().indexOf(OUString("<" + sEntry
+ ">")) >= 0;
638 IMPL_LINK_NOARG(SwCustomizeAddressBlockDialog
, SelectionChangedIdleHdl
, Timer
*, void)
640 // called in case the selection of the edit field changes.
641 // determine selection - if it's one of the editable fields then
642 // enable the related ComboBox and fill it
644 // don't trigger outself again
645 m_xDragED
->SetSelectionChangedHdl(Link
<bool, void>());
647 sal_Int32 nSelected
= GetSelectedItem_Impl();
648 if (USER_DATA_NONE
!= nSelected
)
649 m_xDragED
->SelectCurrentItem();
651 if(m_xFieldCB
->get_visible() && (USER_DATA_NONE
!= nSelected
) && (nSelected
< 0))
653 //search in ListBox if it's one of the first entries
655 std::vector
<OUString
>* pVector
= nullptr;
657 case USER_DATA_SALUTATION
:
658 sSelect
= m_sCurrentSalutation
;
659 pVector
= &m_aSalutations
;
661 case USER_DATA_PUNCTUATION
:
662 sSelect
= m_sCurrentPunctuation
;
663 pVector
= &m_aPunctuations
;
666 sSelect
= m_sCurrentText
;
671 for (const auto& rItem
: *pVector
)
672 m_xFieldCB
->append_text(rItem
);
674 m_xFieldCB
->set_entry_text(sSelect
);
675 m_xFieldCB
->set_sensitive(true);
676 m_xFieldFT
->set_sensitive(true);
680 m_xFieldCB
->set_sensitive(false);
681 m_xFieldFT
->set_sensitive(false);
684 UpdateImageButtons_Impl();
685 m_xDragED
->SetSelectionChangedHdl( LINK( this, SwCustomizeAddressBlockDialog
, SelectionChangedHdl_Impl
));
688 IMPL_LINK(SwCustomizeAddressBlockDialog
, SelectionChangedHdl_Impl
, bool, bIdle
, void)
691 m_aSelectionChangedIdle
.Start();
694 m_aSelectionChangedIdle
.Stop();
695 SelectionChangedIdleHdl(nullptr);
699 IMPL_LINK_NOARG(SwCustomizeAddressBlockDialog
, FieldChangeComboBoxHdl_Impl
, weld::ComboBox
&, void)
701 //changing the field content changes the related members, too
702 sal_Int32 nSelected
= GetSelectedItem_Impl();
703 const OUString sContent
= m_xFieldCB
->get_active_text();
705 case USER_DATA_SALUTATION
:
706 m_sCurrentSalutation
= sContent
;
708 case USER_DATA_PUNCTUATION
:
709 m_sCurrentPunctuation
= sContent
;
712 m_sCurrentText
= sContent
;
715 UpdateImageButtons_Impl();
716 m_xPreview
->SetAddress(GetAddress());
717 EditModifyHdl_Impl(*m_xDragED
);
720 void SwCustomizeAddressBlockDialog::UpdateImageButtons_Impl()
722 MoveItemFlags nMove
= m_xDragED
->IsCurrentItemMoveable();
723 m_xUpIB
->set_sensitive( bool(nMove
& MoveItemFlags::Up
) );
724 m_xLeftIB
->set_sensitive( bool(nMove
& MoveItemFlags::Left
) );
725 m_xRightIB
->set_sensitive( bool(nMove
& MoveItemFlags::Right
) );
726 m_xDownIB
->set_sensitive( bool(nMove
& MoveItemFlags::Down
) );
727 m_xRemoveFieldIB
->set_sensitive(m_xDragED
->HasCurrentItem());
728 int nEntry
= m_xAddressElementsLB
->get_selected_index();
729 m_xInsertFieldIB
->set_sensitive( nEntry
!= -1 &&
730 (m_xAddressElementsLB
->get_id(nEntry
).toInt32() >= 0 || !m_xFieldCB
->get_active_text().isEmpty()));
733 void SwCustomizeAddressBlockDialog::SetAddress(const OUString
& rAddress
)
735 m_xDragED
->SetText(rAddress
);
736 UpdateImageButtons_Impl();
737 EditModifyHdl_Impl(*m_xDragED
);
740 OUString
SwCustomizeAddressBlockDialog::GetAddress() const
742 OUString
sAddress(m_xDragED
->GetAddress());
743 //remove placeholders by the actual content
744 if (m_xFieldFT
->get_visible())
746 for (int i
= 0, nEntryCount
= m_xAddressElementsLB
->n_children(); i
< nEntryCount
; ++i
)
748 const OUString sEntry
= "<" + m_xAddressElementsLB
->get_text(i
) + ">";
749 sal_Int32 nUserData
= m_xAddressElementsLB
->get_id(i
).toInt32();
752 case USER_DATA_SALUTATION
:
753 sAddress
= sAddress
.replaceFirst(sEntry
, m_sCurrentSalutation
);
755 case USER_DATA_PUNCTUATION
:
756 sAddress
= sAddress
.replaceFirst(sEntry
, m_sCurrentPunctuation
);
759 sAddress
= sAddress
.replaceFirst(sEntry
, m_sCurrentText
);
769 struct SwAssignFragment
771 std::unique_ptr
<weld::Builder
> m_xBuilder
;
772 std::unique_ptr
<weld::Label
> m_xLabel
;
773 std::unique_ptr
<weld::ComboBox
> m_xComboBox
;
774 std::unique_ptr
<weld::Label
> m_xPreview
;
776 SwAssignFragment(weld::Container
* pGrid
, int nLine
)
777 : m_xBuilder(Application::CreateBuilder(pGrid
, "modules/swriter/ui/assignfragment.ui"))
778 , m_xLabel(m_xBuilder
->weld_label("label"))
779 , m_xComboBox(m_xBuilder
->weld_combo_box("combobox"))
780 , m_xPreview(m_xBuilder
->weld_label("preview"))
782 m_xLabel
->set_grid_left_attach(0);
783 m_xLabel
->set_grid_top_attach(nLine
);
785 m_xComboBox
->set_grid_left_attach(1);
786 m_xComboBox
->set_grid_top_attach(nLine
);
788 m_xPreview
->set_grid_left_attach(2);
789 m_xPreview
->set_grid_top_attach(nLine
);
795 class SwAssignFieldsControl
797 friend class SwAssignFieldsDialog
;
798 std::unique_ptr
<weld::ScrolledWindow
> m_xVScroll
;
799 std::unique_ptr
<weld::Container
> m_xGrid
;
801 std::vector
<SwAssignFragment
> m_aFields
;
803 SwMailMergeConfigItem
* m_rConfigItem
;
805 Link
<LinkParamNone
*,void> m_aModifyHdl
;
807 DECL_LINK(MatchHdl_Impl
, weld::ComboBox
&, void);
808 DECL_LINK(GotFocusHdl_Impl
, weld::Widget
&, void);
810 void MakeVisible(const tools::Rectangle
& rRect
);
812 SwAssignFieldsControl(std::unique_ptr
<weld::ScrolledWindow
> xWindow
,
813 std::unique_ptr
<weld::Container
> xGrid
);
815 void Init(SwAssignFieldsDialog
* pDialog
, SwMailMergeConfigItem
& rConfigItem
);
816 void SetModifyHdl(const Link
<LinkParamNone
*,void>& rModifyHdl
)
818 m_aModifyHdl
= rModifyHdl
;
819 m_aModifyHdl
.Call(nullptr);
823 SwAssignFieldsControl::SwAssignFieldsControl(std::unique_ptr
<weld::ScrolledWindow
> xWindow
,
824 std::unique_ptr
<weld::Container
> xGrid
)
825 : m_xVScroll(std::move(xWindow
))
826 , m_xGrid(std::move(xGrid
))
827 , m_rConfigItem(nullptr)
831 void SwAssignFieldsControl::Init(SwAssignFieldsDialog
* pDialog
, SwMailMergeConfigItem
& rConfigItem
)
833 m_rConfigItem
= &rConfigItem
;
835 //get the name of the default headers
836 const std::vector
<std::pair
<OUString
, int>>& rHeaders
= rConfigItem
.GetDefaultAddressHeaders();
837 //get the actual data
838 uno::Reference
< XColumnsSupplier
> xColsSupp( rConfigItem
.GetResultSet(), uno::UNO_QUERY
);
839 //get the name of the actual columns
840 uno::Reference
<XNameAccess
> xColAccess
= xColsSupp
.is() ? xColsSupp
->getColumns() : nullptr;
841 uno::Sequence
< OUString
> aFields
;
843 aFields
= xColAccess
->getElementNames();
845 //get the current assignment list
846 //each position in this sequence matches the position in the header array rHeaders
847 //if no assignment is available an empty sequence will be returned
848 uno::Sequence
< OUString
> aAssignments
= rConfigItem
.GetColumnAssignment( rConfigItem
.GetCurrentDBData() );
849 Link
<weld::ComboBox
&,void> aMatchHdl
= LINK(this, SwAssignFieldsControl
, MatchHdl_Impl
);
850 Link
<weld::Widget
&,void> aFocusHdl
= LINK(this, SwAssignFieldsControl
, GotFocusHdl_Impl
);
852 int nLabelWidth(0), nComboBoxWidth(0), nPreviewWidth(0);
855 for (size_t i
= 0; i
< rHeaders
.size(); ++i
)
857 m_aFields
.emplace_back(m_xGrid
.get(), i
);
859 const OUString rHeader
= rHeaders
[i
].first
;
860 weld::ComboBox
& rNewLB
= *m_aFields
.back().m_xComboBox
;
861 rNewLB
.append_text(SwResId(SW_STR_NONE
));
862 rNewLB
.set_active(0);
864 for (const OUString
& rField
: std::as_const(aFields
))
865 rNewLB
.append_text(rField
);
867 //if there is an assignment
868 if(o3tl::make_unsigned(aAssignments
.getLength()) > i
&& !aAssignments
[i
].isEmpty())
869 rNewLB
.set_active_text(aAssignments
[i
]);
870 else //otherwise the current column name may match one of the db columns
871 rNewLB
.set_active_text(rHeader
);
873 weld::Label
& rNewText
= *m_aFields
.back().m_xLabel
;
874 rNewText
.set_label("<" + rHeader
+ ">");
876 weld::Label
& rNewPreview
= *m_aFields
.back().m_xPreview
;
877 //then the preview can be filled accordingly
878 if (xColAccess
.is() && rNewLB
.get_active() > 0 &&
879 xColAccess
->hasByName(rNewLB
.get_active_text()))
881 uno::Any aCol
= xColAccess
->getByName(rNewLB
.get_active_text());
882 uno::Reference
< XColumn
> xColumn
;
888 rNewPreview
.set_label(xColumn
->getString());
890 catch (const SQLException
&)
898 auto nLineHeight
= m_xGrid
->get_preferred_size().Height();
899 m_xVScroll
->set_size_request(m_xVScroll
->get_approximate_digit_width() * 65,
901 nComboBoxWidth
= rNewLB
.get_preferred_size().Width();
904 nLabelWidth
= std::max
<int>(nLabelWidth
, rNewText
.get_preferred_size().Width());
905 nPreviewWidth
= std::max
<int>(nPreviewWidth
, rNewPreview
.get_preferred_size().Width());
907 rNewLB
.connect_changed(aMatchHdl
);
908 rNewLB
.connect_focus_in(aFocusHdl
);
913 pDialog
->ConnectSizeGroups(nLabelWidth
, nComboBoxWidth
, nPreviewWidth
);
916 void SwAssignFieldsControl::MakeVisible(const tools::Rectangle
& rRect
)
918 //determine range of visible positions
919 auto nMinVisiblePos
= m_xVScroll
->vadjustment_get_value();
920 auto nMaxVisiblePos
= nMinVisiblePos
+ m_xVScroll
->vadjustment_get_page_size();
921 if (rRect
.Top() < nMinVisiblePos
|| rRect
.Bottom() > nMaxVisiblePos
)
922 m_xVScroll
->vadjustment_set_value(rRect
.Top());
925 IMPL_LINK(SwAssignFieldsControl
, MatchHdl_Impl
, weld::ComboBox
&, rBox
, void)
927 const OUString sColumn
= rBox
.get_active_text();
928 uno::Reference
< XColumnsSupplier
> xColsSupp( m_rConfigItem
->GetResultSet(), uno::UNO_QUERY
);
929 uno::Reference
<XNameAccess
> xColAccess
= xColsSupp
.is() ? xColsSupp
->getColumns() : nullptr;
931 if(xColAccess
.is() && xColAccess
->hasByName(sColumn
))
933 uno::Any aCol
= xColAccess
->getByName(sColumn
);
934 uno::Reference
< XColumn
> xColumn
;
940 sPreview
= xColumn
->getString();
942 catch (const sdbc::SQLException
&)
947 auto aLBIter
= std::find_if(m_aFields
.begin(), m_aFields
.end(), [&rBox
](const SwAssignFragment
& rFragment
){
948 return &rBox
== rFragment
.m_xComboBox
.get(); });
949 if (aLBIter
!= m_aFields
.end())
951 auto nIndex
= static_cast<sal_Int32
>(std::distance(m_aFields
.begin(), aLBIter
));
952 m_aFields
[nIndex
].m_xPreview
->set_label(sPreview
);
954 m_aModifyHdl
.Call(nullptr);
957 IMPL_LINK(SwAssignFieldsControl
, GotFocusHdl_Impl
, weld::Widget
&, rBox
, void)
959 int x
, y
, width
, height
;
960 rBox
.get_extents_relative_to(*m_xGrid
, x
, y
, width
, height
);
961 // the container has a border of 3 in the .ui
962 tools::Rectangle
aRect(Point(x
- 3, y
- 3), Size(width
+ 6, height
+ 6));
966 SwAssignFieldsDialog::SwAssignFieldsDialog(
967 weld::Window
* pParent
, SwMailMergeConfigItem
& rConfigItem
,
968 const OUString
& rPreview
,
969 bool bIsAddressBlock
)
970 : SfxDialogController(pParent
, "modules/swriter/ui/assignfieldsdialog.ui", "AssignFieldsDialog")
971 , m_sNone(SwResId(SW_STR_NONE
))
972 , m_rPreviewString(rPreview
)
973 , m_rConfigItem(rConfigItem
)
974 , m_xPreview(new SwAddressPreview(m_xBuilder
->weld_scrolled_window("previewwin", true)))
975 , m_xMatchingFI(m_xBuilder
->weld_label("MATCHING_LABEL"))
976 , m_xAddressTitle(m_xBuilder
->weld_label("addresselem"))
977 , m_xMatchTitle(m_xBuilder
->weld_label("matchelem"))
978 , m_xPreviewTitle(m_xBuilder
->weld_label("previewelem"))
979 , m_xPreviewFI(m_xBuilder
->weld_label("PREVIEW_LABEL"))
980 , m_xOK(m_xBuilder
->weld_button("ok"))
981 , m_xPreviewWin(new weld::CustomWeld(*m_xBuilder
, "PREVIEW", *m_xPreview
))
982 , m_xFieldsControl(new SwAssignFieldsControl(m_xBuilder
->weld_scrolled_window("scroll"),
983 m_xBuilder
->weld_container("FIELDS")))
985 m_xPreviewWin
->set_size_request(m_xMatchingFI
->get_approximate_digit_width() * 45,
986 m_xMatchingFI
->get_text_height() * 5);
987 m_xFieldsControl
->Init(this, rConfigItem
);
989 const OUString
sMatchesTo( SwResId(ST_MATCHESTO
) );
990 if (!bIsAddressBlock
)
992 m_xPreviewFI
->set_label(SwResId(ST_SALUTATIONPREVIEW
));
993 m_xMatchingFI
->set_label(SwResId(ST_SALUTATIONMATCHING
));
994 m_xAddressTitle
->set_label(SwResId(ST_SALUTATIONELEMENT
));
997 m_xFieldsControl
->SetModifyHdl(LINK(this, SwAssignFieldsDialog
, AssignmentModifyHdl_Impl
));
998 m_xMatchingFI
->set_label(m_xMatchingFI
->get_label().replaceAll("%1", sMatchesTo
));
999 m_xOK
->connect_clicked(LINK(this, SwAssignFieldsDialog
, OkHdl_Impl
));
1002 SwAssignFieldsDialog::~SwAssignFieldsDialog()
1006 uno::Sequence
< OUString
> SwAssignFieldsDialog::CreateAssignments()
1008 uno::Sequence
< OUString
> aAssignments(
1009 m_rConfigItem
.GetDefaultAddressHeaders().size());
1010 OUString
* pAssignments
= aAssignments
.getArray();
1011 sal_Int32 nIndex
= 0;
1012 for (const auto& rLBItem
: m_xFieldsControl
->m_aFields
)
1014 const OUString sSelect
= rLBItem
.m_xComboBox
->get_active_text();
1015 pAssignments
[nIndex
] = (m_sNone
!= sSelect
) ? sSelect
: OUString();
1018 return aAssignments
;
1021 IMPL_LINK_NOARG(SwAssignFieldsDialog
, OkHdl_Impl
, weld::Button
&, void)
1023 m_rConfigItem
.SetColumnAssignment(
1024 m_rConfigItem
.GetCurrentDBData(),
1025 CreateAssignments() );
1026 m_xDialog
->response(RET_OK
);
1029 IMPL_LINK_NOARG(SwAssignFieldsDialog
, AssignmentModifyHdl_Impl
, LinkParamNone
*, void)
1031 uno::Sequence
< OUString
> aAssignments
= CreateAssignments();
1032 const OUString sPreview
= SwAddressPreview::FillData(
1033 m_rPreviewString
, m_rConfigItem
, &aAssignments
);
1034 m_xPreview
->SetAddress(sPreview
);
1037 void SwAssignFieldsDialog::ConnectSizeGroups(int nLabelWidth
, int nComboBoxWidth
, int nPreviewWidth
)
1039 m_xAddressTitle
->set_size_request(nLabelWidth
, -1);
1040 m_xMatchTitle
->set_size_request(nComboBoxWidth
, -1);
1041 m_xPreviewTitle
->set_size_request(nPreviewWidth
, -1);
1046 const EECharAttrib
* FindCharAttrib(int nStartPosition
, std::vector
<EECharAttrib
>& rAttribList
)
1048 for (auto it
= rAttribList
.rbegin(); it
!= rAttribList
.rend(); ++it
)
1050 const auto& rTextAtr
= *it
;
1051 if (rTextAtr
.pAttr
->Which() != EE_CHAR_GRABBAG
)
1053 if (rTextAtr
.nStart
<= nStartPosition
&& rTextAtr
.nEnd
>= nStartPosition
)
1063 AddressMultiLineEdit::AddressMultiLineEdit(SwCustomizeAddressBlockDialog
*pParent
)
1064 : m_pParentDialog(pParent
)
1068 void AddressMultiLineEdit::EndDropTarget()
1070 if (m_xDropTarget
.is())
1072 auto xRealDropTarget
= GetDrawingArea()->get_drop_target();
1073 uno::Reference
<css::datatransfer::dnd::XDropTargetListener
> xListener(m_xDropTarget
, uno::UNO_QUERY
);
1074 xRealDropTarget
->removeDropTargetListener(xListener
);
1075 m_xDropTarget
.clear();
1079 AddressMultiLineEdit::~AddressMultiLineEdit()
1081 assert(!m_xDropTarget
.is());
1084 void AddressMultiLineEdit::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
1086 Size
aSize(pDrawingArea
->get_ref_device().LogicToPixel(Size(160, 60), MapMode(MapUnit::MapAppFont
)));
1087 pDrawingArea
->set_size_request(aSize
.Width(), aSize
.Height());
1088 WeldEditView::SetDrawingArea(pDrawingArea
);
1091 bool AddressMultiLineEdit::KeyInput(const KeyEvent
& rKEvt
)
1093 if (rKEvt
.GetKeyCode().GetCode() == KEY_ESCAPE
)
1094 return false; // we want default esc behaviour
1095 if (rKEvt
.GetCharCode())
1096 return true; // handled
1097 return WeldEditView::KeyInput(rKEvt
);
1100 bool AddressMultiLineEdit::MouseButtonDown(const MouseEvent
& rMEvt
)
1102 if (rMEvt
.GetClicks() >= 2)
1103 return true; // handled
1104 return WeldEditView::MouseButtonDown(rMEvt
);
1107 OUString
AddressMultiLineEdit::GetText() const
1109 return m_xEditEngine
->GetText();
1112 void AddressMultiLineEdit::SetText( const OUString
& rStr
)
1114 m_xEditEngine
->SetText(rStr
);
1115 //set attributes to all address tokens
1117 sal_Int32
nSequence(0);
1118 SfxGrabBagItem
aProtectAttr(EE_CHAR_GRABBAG
);
1119 const sal_uInt32 nParaCount
= m_xEditEngine
->GetParagraphCount();
1120 for(sal_uInt32 nPara
= 0; nPara
< nParaCount
; ++nPara
)
1122 sal_Int32 nIndex
= 0;
1123 const OUString sPara
= m_xEditEngine
->GetText( nPara
);
1124 if (!sPara
.isEmpty() && !sPara
.endsWith(" "))
1126 ESelection
aPaM(nPara
, sPara
.getLength(), nPara
, sPara
.getLength());
1127 m_xEditEngine
->QuickInsertText(" ", aPaM
);
1131 const sal_Int32 nStart
= sPara
.indexOf( '<', nIndex
);
1134 const sal_Int32 nEnd
= sPara
.indexOf( '>', nStart
);
1138 SfxItemSet
aSet(m_xEditEngine
->GetEmptyItemSet());
1139 // make each one different, so they are not collapsed together
1141 aProtectAttr
.GetGrabBag()["Index"] <<= nSequence
++;
1142 aSet
.Put(aProtectAttr
);
1143 m_xEditEngine
->QuickSetAttribs(aSet
, ESelection(nPara
, nStart
, nPara
, nEnd
+ 1));
1147 // add two empty paragraphs at the end
1148 if(m_pParentDialog
->m_eType
== SwCustomizeAddressBlockDialog::ADDRESSBLOCK_NEW
||
1149 m_pParentDialog
->m_eType
== SwCustomizeAddressBlockDialog::ADDRESSBLOCK_EDIT
)
1151 sal_Int32 nLastLen
= m_xEditEngine
->GetText(nParaCount
- 1).getLength();
1154 int nPara
= nParaCount
? nParaCount
- 1 : 0;
1155 ESelection
aPaM(nPara
, nLastLen
, nPara
, nLastLen
);
1156 m_xEditEngine
->QuickInsertText("\n \n ", aPaM
);
1160 m_xEditView
->SetSelection(ESelection(0, 0, 0, 0));
1163 // Insert the new entry in front of the entry at the beginning of the selection
1164 void AddressMultiLineEdit::InsertNewEntry( const OUString
& rStr
)
1166 // insert new entry after current selected one.
1167 ESelection aSelection
= m_xEditView
->GetSelection();
1168 const sal_uInt32 nPara
= aSelection
.nStartPara
;
1170 std::vector
<EECharAttrib
> aAttribList
;
1171 m_xEditEngine
->GetCharAttribs(nPara
, aAttribList
);
1173 sal_Int32 nIndex
= aSelection
.nEndPara
;
1174 const EECharAttrib
* pAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1175 if(nullptr != pAttrib
)
1176 nIndex
= pAttrib
->nEnd
;
1177 InsertNewEntryAtPosition( rStr
, nPara
, nIndex
);
1179 // select the new entry
1180 m_xEditEngine
->GetCharAttribs(nPara
, aAttribList
);
1181 pAttrib
= FindCharAttrib(nIndex
, aAttribList
);
1182 const sal_Int32 nEnd
= pAttrib
? pAttrib
->nEnd
: nIndex
;
1183 ESelection
aEntrySel(nPara
, nIndex
, nPara
, nEnd
);
1184 m_xEditView
->SetSelection(aEntrySel
);
1186 m_aModifyLink
.Call(*this);
1189 void AddressMultiLineEdit::InsertNewEntryAtPosition( const OUString
& rStr
, sal_uLong nPara
, sal_uInt16 nIndex
)
1191 ESelection
aInsertPos(nPara
, nIndex
, nPara
, nIndex
);
1192 m_xEditEngine
->QuickInsertText(rStr
, aInsertPos
);
1194 //restore the attributes
1195 SetText( GetAddress() );
1197 //select the newly inserted/moved element
1198 m_xEditView
->SetSelection(aInsertPos
);
1199 m_aSelectionLink
.Call(false);
1202 void AddressMultiLineEdit::RemoveCurrentEntry()
1204 ESelection aSelection
= m_xEditView
->GetSelection();
1206 std::vector
<EECharAttrib
> aAttribList
;
1207 m_xEditEngine
->GetCharAttribs(aSelection
.nStartPara
, aAttribList
);
1209 const EECharAttrib
* pBeginAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1211 (pBeginAttrib
->nStart
<= aSelection
.nStartPos
1212 && pBeginAttrib
->nEnd
>= aSelection
.nEndPos
))
1214 const sal_uInt32 nPara
= aSelection
.nStartPara
;
1215 ESelection
aEntrySel(nPara
, pBeginAttrib
->nStart
, nPara
, pBeginAttrib
->nEnd
);
1216 m_xEditEngine
->QuickInsertText(OUString(), aEntrySel
);
1217 //restore the attributes
1218 SetText( GetAddress() );
1219 m_aModifyLink
.Call(*this);
1223 void AddressMultiLineEdit::MoveCurrentItem(MoveItemFlags nMove
)
1225 ESelection aSelection
= m_xEditView
->GetSelection();
1227 std::vector
<EECharAttrib
> aAttribList
;
1228 m_xEditEngine
->GetCharAttribs(aSelection
.nStartPara
, aAttribList
);
1230 const EECharAttrib
* pBeginAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1232 pBeginAttrib
->nStart
> aSelection
.nStartPos
||
1233 pBeginAttrib
->nEnd
< aSelection
.nEndPos
)
1236 //current item has been found
1237 sal_Int32 nPara
= aSelection
.nStartPara
;
1238 sal_Int32 nIndex
= pBeginAttrib
->nStart
;
1239 ESelection
aEntrySel(nPara
, pBeginAttrib
->nStart
, nPara
, pBeginAttrib
->nEnd
);
1240 const OUString sCurrentItem
= m_xEditEngine
->GetText(aEntrySel
);
1241 m_xEditEngine
->RemoveAttribs(aEntrySel
, false, EE_CHAR_GRABBAG
);
1242 m_xEditEngine
->QuickInsertText(OUString(), aEntrySel
);
1243 m_xEditEngine
->GetCharAttribs(nPara
, aAttribList
);
1246 case MoveItemFlags::Left
:
1249 //go left to find a predecessor or simple text
1251 const OUString sPara
= m_xEditEngine
->GetText( nPara
);
1252 sal_Int32 nSearchIndex
= sPara
.lastIndexOf( '>', nIndex
+1 );
1253 if( nSearchIndex
!= -1 && nSearchIndex
== nIndex
)
1255 nSearchIndex
= sPara
.lastIndexOf( '<', nIndex
);
1256 if( nSearchIndex
!= -1 )
1257 nIndex
= nSearchIndex
;
1261 case MoveItemFlags::Right
:
1263 //go right to find a successor or simple text
1265 const EECharAttrib
* pEndAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1266 if(pEndAttrib
&& pEndAttrib
->nEnd
>= nIndex
)
1268 nIndex
= pEndAttrib
->nEnd
;
1272 case MoveItemFlags::Up
:
1276 case MoveItemFlags::Down
:
1282 //add a new paragraph if there is none yet
1283 if (nPara
>= m_xEditEngine
->GetParagraphCount())
1285 auto nInsPara
= nPara
- 1;
1286 auto nInsPos
= m_xEditEngine
->GetTextLen( nPara
- 1 );
1287 ESelection
aTemp(nInsPara
, nInsPos
, nInsPara
, nInsPos
);
1288 m_xEditEngine
->QuickInsertText("\n", aTemp
);
1290 InsertNewEntryAtPosition( sCurrentItem
, nPara
, nIndex
);
1292 // select the new entry [#i40817]
1293 m_xEditEngine
->GetCharAttribs(nPara
, aAttribList
);
1294 const EECharAttrib
* pAttrib
= FindCharAttrib(nIndex
, aAttribList
);
1296 aEntrySel
= ESelection(nPara
, nIndex
, nPara
, pAttrib
->nEnd
);
1297 m_xEditView
->SetSelection(aEntrySel
);
1299 m_aModifyLink
.Call(*this);
1302 MoveItemFlags
AddressMultiLineEdit::IsCurrentItemMoveable() const
1304 MoveItemFlags nRet
= MoveItemFlags::NONE
;
1305 ESelection aSelection
= m_xEditView
->GetSelection();
1307 std::vector
<EECharAttrib
> aAttribList
;
1308 m_xEditEngine
->GetCharAttribs(aSelection
.nStartPara
, aAttribList
);
1310 const EECharAttrib
* pBeginAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1312 (pBeginAttrib
->nStart
<= aSelection
.nStartPos
1313 && pBeginAttrib
->nEnd
>= aSelection
.nEndPos
))
1315 if (pBeginAttrib
->nStart
)
1316 nRet
|= MoveItemFlags::Left
;
1317 //if there is an entry it can always be move to the right and down
1318 nRet
|= MoveItemFlags::Right
| MoveItemFlags::Down
;
1319 if (aSelection
.nStartPara
> 0)
1320 nRet
|= MoveItemFlags::Up
;
1325 bool AddressMultiLineEdit::HasCurrentItem() const
1327 ESelection aSelection
= m_xEditView
->GetSelection();
1329 std::vector
<EECharAttrib
> aAttribList
;
1330 m_xEditEngine
->GetCharAttribs(aSelection
.nStartPara
, aAttribList
);
1332 const EECharAttrib
* pBeginAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1333 return (pBeginAttrib
&&
1334 (pBeginAttrib
->nStart
<= aSelection
.nStartPos
1335 && pBeginAttrib
->nEnd
>= aSelection
.nEndPos
));
1338 OUString
AddressMultiLineEdit::GetCurrentItem() const
1340 ESelection aSelection
= m_xEditView
->GetSelection();
1342 std::vector
<EECharAttrib
> aAttribList
;
1343 m_xEditEngine
->GetCharAttribs(aSelection
.nStartPara
, aAttribList
);
1345 const EECharAttrib
* pBeginAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1347 (pBeginAttrib
->nStart
<= aSelection
.nStartPos
1348 && pBeginAttrib
->nEnd
>= aSelection
.nEndPos
))
1350 const sal_uInt32 nPara
= aSelection
.nStartPara
;
1351 ESelection
aEntrySel(nPara
, pBeginAttrib
->nStart
, nPara
, pBeginAttrib
->nEnd
);
1352 return m_xEditEngine
->GetText( aEntrySel
);
1357 void AddressMultiLineEdit::SelectCurrentItem()
1359 ESelection aSelection
= m_xEditView
->GetSelection();
1361 std::vector
<EECharAttrib
> aAttribList
;
1362 m_xEditEngine
->GetCharAttribs(aSelection
.nStartPara
, aAttribList
);
1364 const EECharAttrib
* pBeginAttrib
= FindCharAttrib(aSelection
.nStartPos
, aAttribList
);
1366 (pBeginAttrib
->nStart
<= aSelection
.nStartPos
1367 && pBeginAttrib
->nEnd
>= aSelection
.nEndPos
))
1369 const sal_uInt32 nPara
= aSelection
.nStartPara
;
1370 ESelection
aEntrySel(nPara
, pBeginAttrib
->nStart
, nPara
, pBeginAttrib
->nEnd
);
1371 m_xEditView
->SetSelection(aEntrySel
);
1376 OUString
AddressMultiLineEdit::GetAddress() const
1379 const sal_uInt32 nParaCount
= m_xEditEngine
->GetParagraphCount();
1380 for(sal_uInt32 nPara
= nParaCount
; nPara
; --nPara
)
1382 const OUString sPara
= comphelper::string::stripEnd(m_xEditEngine
->GetText(nPara
- 1), ' ');
1383 //don't add empty trailing paragraphs
1384 if(!sRet
.isEmpty() || !sPara
.isEmpty())
1386 sRet
= sPara
+ sRet
;
1387 //insert the para break
1395 void AddressMultiLineEdit::UpdateFields()
1397 ESelection aSelection
= m_xEditView
->GetSelection();
1399 //restore the attributes
1400 SetText( GetAddress() );
1402 //reselect the element
1403 m_xEditView
->SetSelection(aSelection
);
1404 m_aSelectionLink
.Call(false);
1407 void AddressMultiLineEdit::EditViewSelectionChange()
1409 WeldEditView::EditViewSelectionChange();
1410 m_aSelectionLink
.Call(true);
1415 // sit between the tree as drag source and the editview as drop target and translate
1416 // the tree dnd data to the simple string the editview wants
1417 class DropTargetListener
: public cppu::WeakImplHelper
< css::datatransfer::dnd::XDropTargetListener
,
1418 css::datatransfer::dnd::XDropTarget
>
1421 css::uno::Reference
<css::datatransfer::dnd::XDropTarget
> m_xRealDropTarget
;
1422 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> m_aListeners
;
1423 SwCustomizeAddressBlockDialog
* m_pParentDialog
;
1426 virtual void SAL_CALL
disposing( const css::lang::EventObject
& ) override
1428 m_xRealDropTarget
.clear();
1429 m_aListeners
.clear();
1432 // XDropTargetListener
1433 virtual void SAL_CALL
drop( const css::datatransfer::dnd::DropTargetDropEvent
& dtde
) override
1435 SolarMutexGuard aGuard
;
1437 auto aReplacement(dtde
);
1439 Point
aMousePos(dtde
.LocationX
, dtde
.LocationY
);
1440 bool bAllowed
= m_pParentDialog
->SetCursorLogicPosition(aMousePos
);
1443 if (weld::TreeView
* pTree
= m_pParentDialog
->get_drag_source())
1445 int nEntry
= pTree
->get_selected_index();
1448 sal_Int32 nUserData
= pTree
->get_id(nEntry
).toInt32();
1449 //special entries can only be once in the address / greeting
1450 if (nUserData
>= 0 || !m_pParentDialog
->HasItem(nUserData
))
1452 rtl::Reference
<TransferDataContainer
> xContainer
= new TransferDataContainer
;
1453 xContainer
->CopyString( "<" + pTree
->get_text(nEntry
) + ">" );
1455 // replace what the treeview is offering with what ImpEditView::drop wants
1456 aReplacement
.Transferable
= xContainer
.get();
1462 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(m_aListeners
);
1463 for (auto const& listener
: aListeners
)
1464 listener
->drop(aReplacement
);
1467 m_pParentDialog
->UpdateFields();
1470 virtual void SAL_CALL
dragEnter( const css::datatransfer::dnd::DropTargetDragEnterEvent
& dtdee
) override
1472 auto aReplacement(dtdee
);
1473 // replace what the treeview is offering with what ImpEditView::dragEnter wants
1474 aReplacement
.SupportedDataFlavors
.realloc(1);
1475 SotExchange::GetFormatDataFlavor(SotClipboardFormatId::STRING
, aReplacement
.SupportedDataFlavors
[0]);
1477 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(m_aListeners
);
1478 for (auto const& listener
: aListeners
)
1479 listener
->dragEnter(aReplacement
);
1482 virtual void SAL_CALL
dragExit( const css::datatransfer::dnd::DropTargetEvent
& dte
) override
1484 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(m_aListeners
);
1485 for (auto const& listener
: aListeners
)
1486 listener
->dragExit( dte
);
1489 virtual void SAL_CALL
dragOver( const css::datatransfer::dnd::DropTargetDragEvent
& dtde
) override
1491 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(m_aListeners
);
1492 for (auto const& listener
: aListeners
)
1493 listener
->dragOver( dtde
);
1496 virtual void SAL_CALL
dropActionChanged( const css::datatransfer::dnd::DropTargetDragEvent
& dtde
) override
1498 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> aListeners(m_aListeners
);
1499 for (auto const& listener
: aListeners
)
1500 listener
->dropActionChanged( dtde
);
1504 virtual void SAL_CALL
addDropTargetListener(const css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>& xListener
) override
1506 m_aListeners
.push_back(xListener
);
1509 virtual void SAL_CALL
removeDropTargetListener(const css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>& xListener
) override
1511 m_aListeners
.erase(std::remove(m_aListeners
.begin(), m_aListeners
.end(), xListener
), m_aListeners
.end());
1514 virtual sal_Bool SAL_CALL
isActive() override
1516 return m_xRealDropTarget
->isActive();
1519 virtual void SAL_CALL
setActive(sal_Bool active
) override
1521 m_xRealDropTarget
->setActive(active
);
1524 virtual sal_Int8 SAL_CALL
getDefaultActions() override
1526 return m_xRealDropTarget
->getDefaultActions();
1529 virtual void SAL_CALL
setDefaultActions(sal_Int8 actions
) override
1531 m_xRealDropTarget
->setDefaultActions(actions
);
1535 DropTargetListener(css::uno::Reference
<css::datatransfer::dnd::XDropTarget
> xRealDropTarget
,
1536 SwCustomizeAddressBlockDialog
* pParentDialog
)
1537 : m_xRealDropTarget(xRealDropTarget
)
1538 , m_pParentDialog(pParentDialog
)
1544 css::uno::Reference
<css::datatransfer::dnd::XDropTarget
> AddressMultiLineEdit::GetDropTarget()
1546 if (!m_xDropTarget
.is())
1548 auto xRealDropTarget
= GetDrawingArea()->get_drop_target();
1549 DropTargetListener
* pProxy
= new DropTargetListener(xRealDropTarget
, m_pParentDialog
);
1550 uno::Reference
<css::datatransfer::dnd::XDropTargetListener
> xListener(pProxy
);
1551 xRealDropTarget
->addDropTargetListener(xListener
);
1552 m_xDropTarget
= uno::Reference
<css::datatransfer::dnd::XDropTarget
>(pProxy
);
1554 return m_xDropTarget
;
1557 bool AddressMultiLineEdit::SetCursorLogicPosition(const Point
& rPosition
)
1559 Point aMousePos
= EditViewOutputDevice().PixelToLogic(rPosition
);
1560 m_xEditView
->SetCursorLogicPosition(aMousePos
, false, true);
1562 ESelection aSelection
= m_xEditView
->GetSelection();
1563 std::vector
<EECharAttrib
> aAttribList
;
1564 m_xEditEngine
->GetCharAttribs(aSelection
.nStartPara
, aAttribList
);
1565 return FindCharAttrib(aSelection
.nStartPos
, aAttribList
) == nullptr;
1568 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */