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 <hintids.hxx>
22 #include <o3tl/any.hxx>
23 #include <vcl/event.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/transfer.hxx>
26 #include <vcl/weld.hxx>
27 #include <svl/stritem.hxx>
28 #include <svl/macitem.hxx>
29 #include <unotools/pathoptions.hxx>
30 #include <sfx2/request.hxx>
31 #include <sfx2/fcontnr.hxx>
32 #include <sfx2/docfilt.hxx>
33 #include <osl/diagnose.h>
35 #include <svx/svxdlg.hxx>
36 #include <editeng/acorrcfg.hxx>
37 #include <sfx2/viewfrm.hxx>
38 #include <unotools.hxx>
39 #include <comphelper/processfactory.hxx>
40 #include <ucbhelper/content.hxx>
41 #include <com/sun/star/text/AutoTextContainer.hpp>
42 #include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
43 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
44 #include <svl/urihelper.hxx>
45 #include <unotools/charclass.hxx>
46 #include <swtypes.hxx>
49 #include <glossary.hxx>
50 #include <gloshdl.hxx>
51 #include <glosbib.hxx>
53 #include <glosdoc.hxx>
54 #include <macassgn.hxx>
56 #include <shellio.hxx>
59 #include <sfx2/filedlghelper.hxx>
63 #include <strings.hrc>
64 #include <iodetect.hxx>
66 #include <officecfg/Office/Writer.hxx>
68 using namespace ::com::sun::star
;
69 using namespace ::com::sun::star::lang
;
70 using namespace ::com::sun::star::uno
;
71 using namespace ::com::sun::star::text
;
72 using namespace ::com::sun::star::ucb
;
73 using namespace ::com::sun::star::ui::dialogs
;
74 using namespace ::ucbhelper
;
75 using namespace ::sfx2
;
77 static OUString
lcl_GetValidShortCut( const OUString
& rName
)
79 const sal_Int32 nSz
= rName
.getLength();
85 while( rName
[nStart
-1]==' ' && nStart
< nSz
)
88 OUStringBuffer
aBuf(OUString::number(rName
[nStart
-1]));
90 for( ; nStart
< nSz
; ++nStart
)
92 if( rName
[nStart
-1]==' ' && rName
[nStart
]!=' ')
93 aBuf
.append(rName
[nStart
]);
95 return aBuf
.makeStringAndClear();
109 // dialog for new block name
110 class SwNewGlosNameDlg
: public weld::GenericDialogController
112 TextFilter m_aNoSpaceFilter
;
113 SwGlossaryDlg
* m_pParent
;
115 std::unique_ptr
<weld::Entry
> m_xNewName
;
116 std::unique_ptr
<weld::Entry
> m_xNewShort
;
117 std::unique_ptr
<weld::Button
> m_xOk
;
118 std::unique_ptr
<weld::Entry
> m_xOldName
;
119 std::unique_ptr
<weld::Entry
> m_xOldShort
;
122 DECL_LINK(Modify
, weld::Entry
&, void);
123 DECL_LINK(Rename
, weld::Button
&, void);
124 DECL_LINK(TextFilterHdl
, OUString
&, bool);
127 SwNewGlosNameDlg(SwGlossaryDlg
* pParent
,
128 const OUString
& rOldName
,
129 const OUString
& rOldShort
);
131 OUString
GetNewName() const { return m_xNewName
->get_text(); }
132 OUString
GetNewShort() const { return m_xNewShort
->get_text(); }
135 IMPL_LINK(SwNewGlosNameDlg
, TextFilterHdl
, OUString
&, rTest
, bool)
137 rTest
= m_aNoSpaceFilter
.filter(rTest
);
141 SwNewGlosNameDlg::SwNewGlosNameDlg(SwGlossaryDlg
* pParent
, const OUString
& rOldName
, const OUString
& rOldShort
)
142 : GenericDialogController(pParent
->getDialog(), "modules/swriter/ui/renameautotextdialog.ui", "RenameAutoTextDialog")
144 , m_xNewName(m_xBuilder
->weld_entry("newname"))
145 , m_xNewShort(m_xBuilder
->weld_entry("newsc"))
146 , m_xOk(m_xBuilder
->weld_button("ok"))
147 , m_xOldName(m_xBuilder
->weld_entry("oldname"))
148 , m_xOldShort(m_xBuilder
->weld_entry("oldsc"))
150 m_xNewShort
->connect_insert_text(LINK(this, SwNewGlosNameDlg
, TextFilterHdl
));
152 m_xOldName
->set_text(rOldName
);
153 m_xOldShort
->set_text(rOldShort
);
154 m_xNewName
->connect_changed(LINK(this, SwNewGlosNameDlg
, Modify
));
155 m_xNewShort
->connect_changed(LINK(this, SwNewGlosNameDlg
, Modify
));
156 m_xOk
->connect_clicked(LINK(this, SwNewGlosNameDlg
, Rename
));
157 m_xNewName
->grab_focus();
160 // query / set currently set group
161 OUString
SwGlossaryDlg::GetCurrGroup()
163 if( !::GetCurrGlosGroup().isEmpty() )
164 return ::GetCurrGlosGroup();
165 return SwGlossaries::GetDefName();
168 void SwGlossaryDlg::SetActGroup(const OUString
&rGrp
)
170 ::SetCurrGlosGroup(rGrp
);
173 IMPL_LINK(SwGlossaryDlg
, TextFilterHdl
, OUString
&, rTest
, bool)
175 rTest
= m_aNoSpaceFilter
.filter(rTest
);
179 class SwGlossaryDropTarget
: public DropTargetHelper
182 weld::TreeView
& m_rTreeView
;
183 SwGlossaryHdl
* m_pGlosHdl
;
185 virtual sal_Int8
AcceptDrop(const AcceptDropEvent
& rEvt
) override
187 weld::TreeView
* pSource
= m_rTreeView
.get_drag_source();
188 if (!pSource
|| pSource
!= &m_rTreeView
)
189 return DND_ACTION_NONE
;
191 std::unique_ptr
<weld::TreeIter
> xSelected(pSource
->make_iterator());
192 bool bSelected
= pSource
->get_selected(xSelected
.get());
194 return DND_ACTION_NONE
;
196 while (pSource
->get_iter_depth(*xSelected
))
197 (void)pSource
->iter_parent(*xSelected
);
199 GroupUserData
* pSrcRootData
= weld::fromId
<GroupUserData
*>(pSource
->get_id(*xSelected
));
200 GroupUserData
* pDestRootData
= nullptr;
202 std::unique_ptr
<weld::TreeIter
> xDestEntry(m_rTreeView
.make_iterator());
203 bool bEntry
= m_rTreeView
.get_dest_row_at_pos(rEvt
.maPosPixel
, xDestEntry
.get(), true);
206 while (m_rTreeView
.get_iter_depth(*xDestEntry
))
207 (void)m_rTreeView
.iter_parent(*xDestEntry
);
208 pDestRootData
= weld::fromId
<GroupUserData
*>(m_rTreeView
.get_id(*xDestEntry
));
210 if (pDestRootData
== pSrcRootData
)
211 return DND_ACTION_NONE
;
212 sal_uInt8 nRet
= DND_ACTION_COPY
;
213 const bool bCheckForMove
= rEvt
.mnAction
& DND_ACTION_MOVE
;
214 if (bCheckForMove
&& !pSrcRootData
->bReadonly
)
215 nRet
|= DND_ACTION_MOVE
;
219 virtual sal_Int8
ExecuteDrop(const ExecuteDropEvent
& rEvt
) override
221 weld::TreeView
* pSource
= m_rTreeView
.get_drag_source();
223 return DND_ACTION_NONE
;
225 std::unique_ptr
<weld::TreeIter
> xDestEntry(m_rTreeView
.make_iterator());
226 bool bEntry
= m_rTreeView
.get_dest_row_at_pos(rEvt
.maPosPixel
, xDestEntry
.get(), true);
228 return DND_ACTION_NONE
;
230 std::unique_ptr
<weld::TreeIter
> xSelected(pSource
->make_iterator());
231 bool bSelected
= pSource
->get_selected(xSelected
.get());
233 return DND_ACTION_NONE
;
235 std::unique_ptr
<weld::TreeIter
> xSrcParent(pSource
->make_iterator(xSelected
.get()));
236 while (pSource
->get_iter_depth(*xSrcParent
))
237 (void)pSource
->iter_parent(*xSrcParent
);
239 std::unique_ptr
<weld::TreeIter
> xDestParent(pSource
->make_iterator(xDestEntry
.get()));
240 while (pSource
->get_iter_depth(*xDestParent
))
241 (void)pSource
->iter_parent(*xDestParent
);
243 GroupUserData
* pSrcParent
= weld::fromId
<GroupUserData
*>(pSource
->get_id(*xSrcParent
));
244 GroupUserData
* pDestParent
= weld::fromId
<GroupUserData
*>(m_rTreeView
.get_id(*xDestParent
));
246 if (pDestParent
!= pSrcParent
)
248 weld::WaitObject
aBusy(&m_rTreeView
);
250 OUString sSourceGroup
= pSrcParent
->sGroupName
251 + OUStringChar(GLOS_DELIM
)
252 + OUString::number(pSrcParent
->nPathIdx
);
254 m_pGlosHdl
->SetCurGroup(sSourceGroup
);
255 OUString
sTitle(pSource
->get_text(*xSelected
));
256 OUString
sShortName(pSource
->get_id(*xSelected
));
258 OUString sDestName
= pDestParent
->sGroupName
259 + OUStringChar(GLOS_DELIM
)
260 + OUString::number(pDestParent
->nPathIdx
);
262 bool bIsMove
= rEvt
.mnAction
& DND_ACTION_MOVE
;
264 const bool bRet
= m_pGlosHdl
->CopyOrMove(sSourceGroup
, sShortName
,
265 sDestName
, sTitle
, bIsMove
);
269 m_rTreeView
.insert(xDestParent
.get(), -1, &sTitle
, &sShortName
,
270 nullptr, nullptr, false, nullptr);
273 pSource
->remove(*xSelected
);
278 return DND_ACTION_NONE
;
282 SwGlossaryDropTarget(weld::TreeView
& rTreeView
, SwGlossaryHdl
* pGlosHdl
)
283 : DropTargetHelper(rTreeView
.get_drop_target())
284 , m_rTreeView(rTreeView
)
285 , m_pGlosHdl(pGlosHdl
)
290 SwGlossaryDlg::SwGlossaryDlg(const SfxViewFrame
& rViewFrame
,
291 SwGlossaryHdl
* pGlosHdl
, SwWrtShell
*pWrtShell
)
292 : SfxDialogController(rViewFrame
.GetFrameWeld(), "modules/swriter/ui/autotext.ui", "AutoTextDialog")
293 , m_sReadonlyPath(SwResId(STR_READONLY_PATH
))
294 , m_pGlossaryHdl(pGlosHdl
)
296 , m_bSelection(pWrtShell
->IsSelection())
299 , m_bIsDocReadOnly(false)
300 , m_pShell(pWrtShell
)
301 , m_xInsertTipCB(m_xBuilder
->weld_check_button("inserttip"))
302 , m_xNameED(m_xBuilder
->weld_entry("name"))
303 , m_xShortNameLbl(m_xBuilder
->weld_label("shortnameft"))
304 , m_xShortNameEdit(m_xBuilder
->weld_entry("shortname"))
305 , m_xCategoryBox(m_xBuilder
->weld_tree_view("category"))
306 , m_xFileRelCB(m_xBuilder
->weld_check_button("relfile"))
307 , m_xNetRelCB(m_xBuilder
->weld_check_button("relnet"))
308 , m_xInsertBtn(m_xBuilder
->weld_button("ok"))
309 , m_xEditBtn(m_xBuilder
->weld_menu_button("autotext"))
310 , m_xBibBtn(m_xBuilder
->weld_button("categories"))
311 , m_xPathBtn(m_xBuilder
->weld_button("path"))
313 m_xCategoryBox
->set_size_request(m_xCategoryBox
->get_approximate_digit_width() * 52,
314 m_xCategoryBox
->get_height_rows(12));
316 Link
<SwOneExampleFrame
&,void> aLink(LINK(this, SwGlossaryDlg
, PreviewLoadedHdl
));
317 m_xExampleFrame
.reset(new SwOneExampleFrame(EX_SHOW_ONLINE_LAYOUT
, &aLink
));
318 m_xExampleFrameWin
.reset(new weld::CustomWeld(*m_xBuilder
, "example", *m_xExampleFrame
));
319 Size aSize
= m_xExampleFrame
->GetDrawingArea()->get_ref_device().LogicToPixel(
320 Size(82, 124), MapMode(MapUnit::MapAppFont
));
321 m_xExampleFrame
->set_size_request(aSize
.Width(), aSize
.Height());
323 m_xShortNameEdit
->connect_insert_text(LINK(this, SwGlossaryDlg
, TextFilterHdl
));
325 m_xEditBtn
->connect_toggled(LINK(this, SwGlossaryDlg
, EnableHdl
));
326 m_xEditBtn
->connect_selected(LINK(this, SwGlossaryDlg
, MenuHdl
));
327 m_xPathBtn
->connect_clicked(LINK(this, SwGlossaryDlg
, PathHdl
));
329 m_xNameED
->connect_changed(LINK(this,SwGlossaryDlg
,NameModify
));
330 m_xShortNameEdit
->connect_changed(LINK(this,SwGlossaryDlg
,NameModify
));
332 m_xCategoryBox
->connect_row_activated(LINK(this, SwGlossaryDlg
, NameDoubleClick
));
333 m_xCategoryBox
->connect_changed(LINK(this, SwGlossaryDlg
, GrpSelect
));
334 m_xCategoryBox
->connect_key_press(LINK(this, SwGlossaryDlg
, KeyInputHdl
));
336 m_xDropTarget
.reset(new SwGlossaryDropTarget(*m_xCategoryBox
, pGlosHdl
));
337 rtl::Reference
<TransferDataContainer
> xHelper(new TransferDataContainer
);
338 m_xCategoryBox
->enable_drag_source(xHelper
, DND_ACTION_COPYMOVE
);
340 m_xBibBtn
->connect_clicked(LINK(this,SwGlossaryDlg
,BibHdl
));
342 m_xInsertBtn
->connect_clicked(LINK(this,SwGlossaryDlg
,InsertHdl
));
346 m_bIsDocReadOnly
= m_pShell
->GetView().GetDocShell()->IsReadOnly() ||
347 m_pShell
->HasReadonlySel();
348 if( m_bIsDocReadOnly
)
349 m_xInsertBtn
->set_sensitive(false);
350 m_xNameED
->grab_focus();
351 m_xCategoryBox
->make_sorted();
352 m_xCategoryBox
->set_sort_order(true);
357 SwGlossaryDlg::~SwGlossaryDlg()
364 OUString
getCurrentGlossary()
366 const OUString sTemp
{ ::GetCurrGlosGroup() };
368 // the zeroth path is not being recorded!
369 if (o3tl::starts_with(o3tl::getToken(sTemp
, 1, GLOS_DELIM
), u
"0"))
370 return sTemp
.getToken(0, GLOS_DELIM
);
378 IMPL_LINK(SwGlossaryDlg
, GrpSelect
, weld::TreeView
&, rBox
, void)
380 std::unique_ptr
<weld::TreeIter
> xEntry
= rBox
.make_iterator();
381 if (!rBox
.get_selected(xEntry
.get()))
384 std::unique_ptr
<weld::TreeIter
> xParent
= rBox
.make_iterator(xEntry
.get());
385 weld::TreeIter
* pParent
;
386 if (rBox
.get_iter_depth(*xParent
))
388 rBox
.iter_parent(*xParent
);
389 pParent
= xParent
.get();
392 pParent
= xEntry
.get();
393 GroupUserData
* pGroupData
= weld::fromId
<GroupUserData
*>(rBox
.get_id(*pParent
));
394 ::SetCurrGlosGroup(pGroupData
->sGroupName
395 + OUStringChar(GLOS_DELIM
)
396 + OUString::number(pGroupData
->nPathIdx
));
397 m_pGlossaryHdl
->SetCurGroup(::GetCurrGlosGroup());
398 // set current text block
399 m_bReadOnly
= m_pGlossaryHdl
->IsReadOnly();
400 EnableShortName( !m_bReadOnly
);
401 m_xEditBtn
->set_sensitive(!m_bReadOnly
);
402 m_bIsOld
= m_pGlossaryHdl
->IsOld();
403 if( pParent
!= xEntry
.get())
405 OUString
aName(rBox
.get_text(*xEntry
));
406 m_xNameED
->set_text(aName
);
407 m_xShortNameEdit
->set_text(rBox
.get_id(*xEntry
));
408 m_xInsertBtn
->set_sensitive( !m_bIsDocReadOnly
);
409 ShowAutoText(::GetCurrGlosGroup(), m_xShortNameEdit
->get_text());
412 ShowAutoText("", "");
414 NameModify(*m_xShortNameEdit
);
415 if (SfxRequest::HasMacroRecorder(m_pShell
->GetView().GetViewFrame()))
417 SfxRequest
aReq(m_pShell
->GetView().GetViewFrame(), FN_SET_ACT_GLOSSARY
);
418 aReq
.AppendItem(SfxStringItem(FN_SET_ACT_GLOSSARY
, getCurrentGlossary()));
423 short SwGlossaryDlg::run()
425 short nRet
= SfxDialogController::run();
431 void SwGlossaryDlg::Apply()
433 const OUString
aGlosName(m_xShortNameEdit
->get_text());
434 if (!aGlosName
.isEmpty())
436 m_pGlossaryHdl
->InsertGlossary(aGlosName
);
438 if (SfxRequest::HasMacroRecorder(m_pShell
->GetView().GetViewFrame()))
440 SfxRequest
aReq(m_pShell
->GetView().GetViewFrame(), FN_INSERT_GLOSSARY
);
441 aReq
.AppendItem(SfxStringItem(FN_INSERT_GLOSSARY
, getCurrentGlossary()));
442 aReq
.AppendItem(SfxStringItem(FN_PARAM_1
, aGlosName
));
447 void SwGlossaryDlg::EnableShortName(bool bOn
)
449 m_xShortNameLbl
->set_sensitive(bOn
);
450 m_xShortNameEdit
->set_sensitive(bOn
);
453 // does the title exist in the selected group?
454 std::unique_ptr
<weld::TreeIter
> SwGlossaryDlg::DoesBlockExist(std::u16string_view rBlock
,
455 std::u16string_view rShort
)
457 // look for possible entry in TreeListBox
458 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xCategoryBox
->make_iterator();
459 if (m_xCategoryBox
->get_selected(xEntry
.get()))
461 if (m_xCategoryBox
->get_iter_depth(*xEntry
))
462 m_xCategoryBox
->iter_parent(*xEntry
);
463 if (!m_xCategoryBox
->iter_children(*xEntry
))
467 if (rBlock
== m_xCategoryBox
->get_text(*xEntry
) &&
469 rShort
== m_xCategoryBox
->get_id(*xEntry
))
475 while (m_xCategoryBox
->iter_next_sibling(*xEntry
));
480 IMPL_LINK(SwGlossaryDlg
, NameModify
, weld::Entry
&, rEdit
, void)
482 const OUString
aName(m_xNameED
->get_text());
483 bool bNameED
= &rEdit
== m_xNameED
.get();
484 if( aName
.isEmpty() )
487 m_xShortNameEdit
->set_text(aName
);
488 m_xInsertBtn
->set_sensitive(false);
491 const bool bNotFound
= !DoesBlockExist(aName
, bNameED
? OUString() : rEdit
.get_text());
494 // did the text get in to the Listbox in the Edit with a click?
497 m_xShortNameEdit
->set_text( lcl_GetValidShortCut( aName
) );
502 m_xShortNameEdit
->set_text(m_pGlossaryHdl
->GetGlossaryShortName(aName
));
503 EnableShortName(!m_bReadOnly
);
505 m_xInsertBtn
->set_sensitive(!bNotFound
&& !m_bIsDocReadOnly
);
512 m_xInsertBtn
->set_sensitive(!m_bIsDocReadOnly
);
517 IMPL_LINK( SwGlossaryDlg
, NameDoubleClick
, weld::TreeView
&, rBox
, bool )
519 std::unique_ptr
<weld::TreeIter
> xEntry
= rBox
.make_iterator();
520 if (rBox
.get_selected(xEntry
.get()) && rBox
.get_iter_depth(*xEntry
) && !m_bIsDocReadOnly
)
521 m_xDialog
->response(RET_OK
);
525 IMPL_LINK_NOARG( SwGlossaryDlg
, EnableHdl
, weld::Toggleable
&, void )
527 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xCategoryBox
->make_iterator();
528 bool bEntry
= m_xCategoryBox
->get_selected(xEntry
.get());
530 const OUString
aEditText(m_xNameED
->get_text());
531 const bool bHasEntry
= !aEditText
.isEmpty() && !m_xShortNameEdit
->get_text().isEmpty();
532 const bool bExists
= nullptr != DoesBlockExist(aEditText
, m_xShortNameEdit
->get_text());
533 const bool bIsGroup
= bEntry
&& !m_xCategoryBox
->get_iter_depth(*xEntry
);
534 m_xEditBtn
->set_item_visible("new", m_bSelection
&& bHasEntry
&& !bExists
);
535 m_xEditBtn
->set_item_visible("newtext", m_bSelection
&& bHasEntry
&& !bExists
);
536 m_xEditBtn
->set_item_visible("copy", bExists
&& !bIsGroup
);
537 m_xEditBtn
->set_item_visible("replace", m_bSelection
&& bExists
&& !bIsGroup
&& !m_bIsOld
);
538 m_xEditBtn
->set_item_visible("replacetext", m_bSelection
&& bExists
&& !bIsGroup
&& !m_bIsOld
);
539 m_xEditBtn
->set_item_visible("edit", bExists
&& !bIsGroup
);
540 m_xEditBtn
->set_item_visible("rename", bExists
&& !bIsGroup
);
541 m_xEditBtn
->set_item_visible("delete", bExists
&& !bIsGroup
);
542 m_xEditBtn
->set_item_visible("macro", bExists
&& !bIsGroup
&& !m_bIsOld
&&
543 !m_pGlossaryHdl
->IsReadOnly() );
544 m_xEditBtn
->set_item_visible("import", bIsGroup
&& !m_bIsOld
&& !m_pGlossaryHdl
->IsReadOnly() );
547 IMPL_LINK(SwGlossaryDlg
, MenuHdl
, const OUString
&, rItemIdent
, void)
549 if (rItemIdent
== "edit")
551 std::unique_ptr
<SwTextBlocks
> pGroup
= ::GetGlossaries()->GetGroupDoc ( GetCurrGrpName () );
553 m_xDialog
->response(RET_EDIT
);
555 else if (rItemIdent
== "replace")
557 m_pGlossaryHdl
->NewGlossary(m_xNameED
->get_text(),
558 m_xShortNameEdit
->get_text());
560 else if (rItemIdent
== "replacetext")
562 m_pGlossaryHdl
->NewGlossary(m_xNameED
->get_text(),
563 m_xShortNameEdit
->get_text(),
566 else if (rItemIdent
== "new" || rItemIdent
== "newtext")
568 bool bNoAttr
= rItemIdent
== "newtext";
570 const OUString
aStr(m_xNameED
->get_text());
571 const OUString
aShortName(m_xShortNameEdit
->get_text());
572 if(m_pGlossaryHdl
->HasShortName(aShortName
))
574 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(m_xDialog
.get(),
575 VclMessageType::Info
, VclButtonsType::Ok
,
576 SwResId(STR_DOUBLE_SHORTNAME
)));
578 m_xShortNameEdit
->select_region(0, -1);
579 m_xShortNameEdit
->grab_focus();
581 if(m_pGlossaryHdl
->NewGlossary(aStr
, aShortName
, false, bNoAttr
))
583 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xCategoryBox
->make_iterator();
584 if (!m_xCategoryBox
->get_selected(xEntry
.get()))
586 else if (m_xCategoryBox
->get_iter_depth(*xEntry
))
587 m_xCategoryBox
->iter_parent(*xEntry
);
588 m_xCategoryBox
->insert(xEntry
.get(), -1, &aStr
, &aShortName
,
589 nullptr, nullptr, false, nullptr);
591 m_xNameED
->set_text(aStr
);
592 m_xShortNameEdit
->set_text(aShortName
);
593 NameModify(*m_xNameED
); // for toggling the buttons
595 if (SfxRequest::HasMacroRecorder(m_pShell
->GetView().GetViewFrame()))
597 SfxRequest
aReq(m_pShell
->GetView().GetViewFrame(), FN_NEW_GLOSSARY
);
598 aReq
.AppendItem(SfxStringItem(FN_NEW_GLOSSARY
, getCurrentGlossary()));
599 aReq
.AppendItem(SfxStringItem(FN_PARAM_1
, aShortName
));
600 aReq
.AppendItem(SfxStringItem(FN_PARAM_2
, aStr
));
605 else if (rItemIdent
== "copy")
607 m_pGlossaryHdl
->CopyToClipboard(*m_pShell
, m_xShortNameEdit
->get_text());
609 else if (rItemIdent
== "rename")
611 m_xShortNameEdit
->set_text(m_pGlossaryHdl
->GetGlossaryShortName(m_xNameED
->get_text()));
612 SwNewGlosNameDlg
aNewNameDlg(this, m_xNameED
->get_text(), m_xShortNameEdit
->get_text());
613 if (aNewNameDlg
.run() == RET_OK
&& m_pGlossaryHdl
->Rename(m_xShortNameEdit
->get_text(),
614 aNewNameDlg
.GetNewShort(),
615 aNewNameDlg
.GetNewName()))
617 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xCategoryBox
->make_iterator();
618 if (m_xCategoryBox
->get_selected(xEntry
.get()))
620 std::unique_ptr
<weld::TreeIter
> xOldEntry
= m_xCategoryBox
->make_iterator(xEntry
.get());
621 if (m_xCategoryBox
->get_iter_depth(*xEntry
))
622 m_xCategoryBox
->iter_parent(*xEntry
);
624 std::unique_ptr
<weld::TreeIter
> xNewEntry
= m_xCategoryBox
->make_iterator();
625 OUString
sId(aNewNameDlg
.GetNewShort());
626 OUString
sName(aNewNameDlg
.GetNewName());
628 m_xCategoryBox
->insert(xEntry
.get(), -1, &sName
, &sId
,
629 nullptr, nullptr, false, xNewEntry
.get());
631 m_xCategoryBox
->remove(*xOldEntry
);
632 m_xCategoryBox
->select(*xNewEntry
);
633 m_xCategoryBox
->scroll_to_row(*xNewEntry
);
636 GrpSelect(*m_xCategoryBox
);
638 else if (rItemIdent
== "delete")
642 else if (rItemIdent
== "macro")
644 SfxItemSetFixed
<RES_FRMMACRO
, RES_FRMMACRO
, SID_EVENTCONFIG
, SID_EVENTCONFIG
> aSet( m_pShell
->GetAttrPool() );
646 SvxMacro
aStart(OUString(), OUString(), STARBASIC
);
647 SvxMacro
aEnd(OUString(), OUString(), STARBASIC
);
648 m_pGlossaryHdl
->GetMacros(m_xShortNameEdit
->get_text(), aStart
, aEnd
);
650 SvxMacroItem
aItem(RES_FRMMACRO
);
651 if( aStart
.HasMacro() )
652 aItem
.SetMacro( SvMacroItemId::SwStartInsGlossary
, aStart
);
653 if( aEnd
.HasMacro() )
654 aItem
.SetMacro( SvMacroItemId::SwEndInsGlossary
, aEnd
);
657 aSet
.Put( SwMacroAssignDlg::AddEvents( MACASSGN_AUTOTEXT
) );
659 const SvxMacroItem
* pMacroItem
;
660 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
661 ScopedVclPtr
<SfxAbstractDialog
> pMacroDlg(pFact
->CreateEventConfigDialog(m_xDialog
.get(), aSet
,
662 m_pShell
->GetView().GetViewFrame().GetFrame().GetFrameInterface() ));
663 if ( pMacroDlg
&& pMacroDlg
->Execute() == RET_OK
&&
664 (pMacroItem
= pMacroDlg
->GetOutputItemSet()->GetItemIfSet( RES_FRMMACRO
, false )) )
666 const SvxMacroTableDtor
& rTable
= pMacroItem
->GetMacroTable();
667 m_pGlossaryHdl
->SetMacros( m_xShortNameEdit
->get_text(),
668 rTable
.Get( SvMacroItemId::SwStartInsGlossary
),
669 rTable
.Get( SvMacroItemId::SwEndInsGlossary
) );
672 else if (rItemIdent
== "import")
674 // call the FileOpenDialog do find WinWord - Files with templates
675 FileDialogHelper
aDlgHelper(TemplateDescription::FILEOPEN_SIMPLE
,
676 FileDialogFlags::NONE
, m_xDialog
.get());
677 aDlgHelper
.SetContext(FileDialogHelper::WriterImportAutotext
);
678 uno::Reference
< XFilePicker3
> xFP
= aDlgHelper
.GetFilePicker();
680 SfxFilterMatcher
aMatcher( SwDocShell::Factory().GetFactoryName() );
681 SfxFilterMatcherIter
aIter( aMatcher
);
682 std::shared_ptr
<const SfxFilter
> pFilter
= aIter
.First();
685 if( pFilter
->GetUserData() == FILTER_WW8
)
687 xFP
->appendFilter( pFilter
->GetUIName(),
688 pFilter
->GetWildcard().getGlob() );
689 xFP
->setCurrentFilter( pFilter
->GetUIName() ) ;
691 else if( pFilter
->GetUserData() == FILTER_DOCX
)
693 xFP
->appendFilter( pFilter
->GetUIName(),
694 pFilter
->GetWildcard().getGlob() );
695 xFP
->setCurrentFilter( pFilter
->GetUIName() ) ;
698 pFilter
= aIter
.Next();
701 if( aDlgHelper
.Execute() == ERRCODE_NONE
)
703 if( m_pGlossaryHdl
->ImportGlossaries( xFP
->getSelectedFiles().getConstArray()[0] ))
707 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(m_xDialog
.get(),
708 VclMessageType::Info
, VclButtonsType::Ok
,
709 SwResId(STR_NO_GLOSSARIES
)));
716 // dialog manage regions
717 IMPL_LINK_NOARG(SwGlossaryDlg
, BibHdl
, weld::Button
&, void)
719 SwGlossaries
* pGloss
= ::GetGlossaries();
720 if( pGloss
->IsGlosPathErr() )
724 //check if at least one glossary path is write enabled
725 SvtPathOptions aPathOpt
;
726 const OUString
& sGlosPath( aPathOpt
.GetAutoTextPath() );
727 bool bIsWritable
= false;
728 sal_Int32 nIdx
{sGlosPath
.isEmpty() ? -1 : 0};
731 const OUString sPath
= URIHelper::SmartRel2Abs(
732 INetURLObject(), sGlosPath
.getToken(0, ';', nIdx
),
733 URIHelper::GetMaybeFileHdl());
736 Content
aTestContent( sPath
,
737 uno::Reference
< XCommandEnvironment
>(),
738 comphelper::getProcessComponentContext() );
739 Any aAny
= aTestContent
.getPropertyValue( "IsReadOnly" );
742 bIsWritable
= !*o3tl::doAccess
<bool>(aAny
);
745 catch (const Exception
&)
754 SwGlossaryGroupDlg
aDlg(m_xDialog
.get(), pGloss
->GetPathArray(), m_pGlossaryHdl
);
755 if (aDlg
.run() == RET_OK
)
758 //if new groups were created - select one of them
759 const OUString sNewGroup
= aDlg
.GetCreatedGroupName();
761 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xCategoryBox
->make_iterator();
762 bool bEntry
= m_xCategoryBox
->get_iter_first(*xEntry
);
764 while (!sNewGroup
.isEmpty() && bEntry
)
766 if (!m_xCategoryBox
->get_iter_depth(*xEntry
))
768 GroupUserData
* pGroupData
= weld::fromId
<GroupUserData
*>(m_xCategoryBox
->get_id(*xEntry
));
769 const OUString sGroup
= pGroupData
->sGroupName
770 + OUStringChar(GLOS_DELIM
)
771 + OUString::number(pGroupData
->nPathIdx
);
772 if(sGroup
== sNewGroup
)
774 m_xCategoryBox
->select(*xEntry
);
775 m_xCategoryBox
->scroll_to_row(*xEntry
);
776 GrpSelect(*m_xCategoryBox
);
780 bEntry
= m_xCategoryBox
->iter_next(*xEntry
);
787 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(m_xDialog
.get(),
788 VclMessageType::Question
, VclButtonsType::YesNo
,
790 if (RET_YES
== xBox
->run())
791 PathHdl(*m_xPathBtn
);
796 // initialisation; from Ctor and after editing regions
797 void SwGlossaryDlg::Init()
799 m_xCategoryBox
->freeze();
800 m_xCategoryBox
->clear();
801 m_xGroupData
.clear();
802 m_xCategoryBox
->make_unsorted();
804 // display text block regions
805 const size_t nCnt
= m_pGlossaryHdl
->GetGroupCnt();
806 std::unique_ptr
<weld::TreeIter
> xSelEntry
;
807 const OUString
sSelStr(::GetCurrGlosGroup().getToken(0, GLOS_DELIM
));
808 const sal_Int32 nSelPath
= o3tl::toInt32(o3tl::getToken(::GetCurrGlosGroup(), 1, GLOS_DELIM
));
809 // #i66304# - "My AutoText" comes from mytexts.bau, but should be translated
810 static const OUStringLiteral
sMyAutoTextEnglish(u
"My AutoText");
811 const OUString
sMyAutoTextTranslated(SwResId(STR_MY_AUTOTEXT
));
812 for(size_t nId
= 0; nId
< nCnt
; ++nId
)
815 OUString
sGroupName(m_pGlossaryHdl
->GetGroupName(nId
, &sTitle
));
816 if(sGroupName
.isEmpty())
819 const OUString sName
{ sGroupName
.getToken( 0, GLOS_DELIM
, nIdx
) };
822 if(sTitle
== sMyAutoTextEnglish
)
823 sTitle
= sMyAutoTextTranslated
;
825 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xCategoryBox
->make_iterator();
826 m_xCategoryBox
->append(xEntry
.get());
827 m_xCategoryBox
->set_text(*xEntry
, sTitle
, 0);
828 const sal_Int32 nPath
= o3tl::toInt32(o3tl::getToken(sGroupName
, 0, GLOS_DELIM
, nIdx
));
830 GroupUserData
* pData
= new GroupUserData
;
831 pData
->sGroupName
= sName
;
832 pData
->nPathIdx
= static_cast< sal_uInt16
>(nPath
);
833 pData
->bReadonly
= m_pGlossaryHdl
->IsReadOnly(&sGroupName
);
834 m_xGroupData
.emplace_back(pData
);
836 m_xCategoryBox
->set_id(*xEntry
, weld::toId(pData
));
837 if (sSelStr
== pData
->sGroupName
&& nSelPath
== nPath
)
838 xSelEntry
= m_xCategoryBox
->make_iterator(xEntry
.get());
840 // fill entries for the groups
842 m_pGlossaryHdl
->SetCurGroup(sGroupName
, false, true);
843 const sal_uInt16 nCount
= m_pGlossaryHdl
->GetGlossaryCnt();
844 for(sal_uInt16 i
= 0; i
< nCount
; ++i
)
846 OUString sEntryName
= m_pGlossaryHdl
->GetGlossaryName(i
);
847 OUString sId
= m_pGlossaryHdl
->GetGlossaryShortName(i
);
848 m_xCategoryBox
->insert(xEntry
.get(), -1, &sEntryName
, &sId
,
849 nullptr, nullptr, false, nullptr);
853 // set current group and display text blocks
856 //find a non-readonly group
857 std::unique_ptr
<weld::TreeIter
> xSearch
= m_xCategoryBox
->make_iterator();
858 if (m_xCategoryBox
->get_iter_first(*xSearch
))
862 if (!m_xCategoryBox
->get_iter_depth(*xSearch
))
864 GroupUserData
* pData
= weld::fromId
<GroupUserData
*>(m_xCategoryBox
->get_id(*xSearch
));
865 if (!pData
->bReadonly
)
867 xSelEntry
= std::move(xSearch
);
872 while (m_xCategoryBox
->iter_next(*xSearch
));
876 xSelEntry
= std::move(xSearch
);
877 if (!xSelEntry
|| !m_xCategoryBox
->get_iter_first(*xSelEntry
))
882 m_xCategoryBox
->thaw();
883 m_xCategoryBox
->make_sorted();
887 m_xCategoryBox
->expand_row(*xSelEntry
);
888 m_xCategoryBox
->select(*xSelEntry
);
889 m_xCategoryBox
->scroll_to_row(*xSelEntry
);
890 GrpSelect(*m_xCategoryBox
);
893 const SvxAutoCorrCfg
& rCfg
= SvxAutoCorrCfg::Get();
894 m_xFileRelCB
->set_active( rCfg
.IsSaveRelFile() );
895 m_xFileRelCB
->connect_toggled(LINK(this, SwGlossaryDlg
, CheckBoxHdl
));
896 m_xNetRelCB
->set_active( rCfg
.IsSaveRelNet() );
897 m_xNetRelCB
->connect_toggled(LINK(this, SwGlossaryDlg
, CheckBoxHdl
));
898 m_xInsertTipCB
->set_active( rCfg
.IsAutoTextTip() );
899 m_xInsertTipCB
->set_sensitive(!officecfg::Office::Writer::AutoFunction::Text::ShowToolTip::isReadOnly());
900 m_xInsertTipCB
->connect_toggled(LINK(this, SwGlossaryDlg
, CheckBoxHdl
));
902 // tdf#124088 - propose autotext and shortcut name based on selected text
903 if (m_pShell
->HasSelection())
906 m_pShell
->GetSelectedText(aSelText
, ParaBreakType::ToBlank
);
908 aSelText
= aSelText
.trim();
909 if (aSelText
.getLength() > 25)
911 aSelText
= aSelText
.copy(0, 25);
912 if (const sal_Int32 nBlankIndex
= aSelText
.lastIndexOf(' '); nBlankIndex
!= -1)
913 aSelText
= aSelText
.copy(0, nBlankIndex
);
916 m_xNameED
->set_text(aSelText
);
917 m_xNameED
->select_region(0, -1);
918 m_xShortNameEdit
->set_text(lcl_GetValidShortCut(aSelText
));
922 // KeyInput for ShortName - Edits without Spaces
923 IMPL_LINK( SwNewGlosNameDlg
, Modify
, weld::Entry
&, rBox
, void )
925 OUString
aName(m_xNewName
->get_text());
926 SwGlossaryDlg
* pDlg
= m_pParent
;
927 if (&rBox
== m_xNewName
.get())
928 m_xNewShort
->set_text(lcl_GetValidShortCut(aName
));
930 bool bEnable
= !aName
.isEmpty() && !m_xNewShort
->get_text().isEmpty() &&
931 (!pDlg
->DoesBlockExist(aName
, m_xNewShort
->get_text())
932 || aName
== m_xOldName
->get_text());
933 m_xOk
->set_sensitive(bEnable
);
936 IMPL_LINK_NOARG(SwNewGlosNameDlg
, Rename
, weld::Button
&, void)
938 SwGlossaryDlg
* pDlg
= m_pParent
;
939 OUString sNew
= GetAppCharClass().uppercase(m_xNewShort
->get_text());
940 if (pDlg
->m_pGlossaryHdl
->HasShortName(m_xNewShort
->get_text())
941 && sNew
!= m_xOldShort
->get_text())
943 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(m_xDialog
.get(),
944 VclMessageType::Info
, VclButtonsType::Ok
,
945 SwResId(STR_DOUBLE_SHORTNAME
)));
947 m_xNewShort
->grab_focus();
950 m_xDialog
->response(RET_OK
);
953 IMPL_LINK(SwGlossaryDlg
, CheckBoxHdl
, weld::Toggleable
&, rBox
, void)
955 SvxAutoCorrCfg
& rCfg
= SvxAutoCorrCfg::Get();
956 bool bCheck
= rBox
.get_active();
957 if (&rBox
== m_xInsertTipCB
.get())
958 rCfg
.SetAutoTextTip(bCheck
);
959 else if (&rBox
== m_xFileRelCB
.get())
960 rCfg
.SetSaveRelFile(bCheck
);
962 rCfg
.SetSaveRelNet(bCheck
);
966 IMPL_LINK(SwGlossaryDlg
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
968 if (rKEvt
.GetKeyCode().GetCode() == KEY_DELETE
)
976 OUString
SwGlossaryDlg::GetCurrGrpName() const
978 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xCategoryBox
->make_iterator();
979 if (m_xCategoryBox
->get_selected(xEntry
.get()))
981 if (m_xCategoryBox
->get_iter_depth(*xEntry
))
982 m_xCategoryBox
->iter_parent(*xEntry
);
983 GroupUserData
* pGroupData
= weld::fromId
<GroupUserData
*>(m_xCategoryBox
->get_id(*xEntry
));
984 return pGroupData
->sGroupName
+ OUStringChar(GLOS_DELIM
) + OUString::number(pGroupData
->nPathIdx
);
989 IMPL_LINK_NOARG( SwGlossaryDlg
, PathHdl
, weld::Button
&, void )
991 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
992 ScopedVclPtr
<AbstractSvxMultiPathDialog
> pDlg(pFact
->CreateSvxPathSelectDialog(m_xDialog
.get()));
993 SvtPathOptions aPathOpt
;
994 const OUString
sGlosPath( aPathOpt
.GetAutoTextPath() );
995 pDlg
->SetPath(sGlosPath
);
996 if(RET_OK
== pDlg
->Execute())
998 const OUString
sTmp(pDlg
->GetPath());
999 if(sTmp
!= sGlosPath
)
1001 aPathOpt
.SetAutoTextPath( sTmp
);
1002 ::GetGlossaries()->UpdateGlosPath( true );
1008 IMPL_LINK_NOARG(SwGlossaryDlg
, InsertHdl
, weld::Button
&, void)
1010 m_xDialog
->response(RET_OK
);
1013 void SwGlossaryDlg::ShowPreview()
1015 ShowAutoText(::GetCurrGlosGroup(), m_xShortNameEdit
->get_text());
1018 IMPL_LINK_NOARG(SwGlossaryDlg
, PreviewLoadedHdl
, SwOneExampleFrame
&, void)
1020 ResumeShowAutoText();
1023 void SwGlossaryDlg::ShowAutoText(const OUString
& rGroup
, const OUString
& rShortName
)
1025 if (m_xExampleFrameWin
->get_visible())
1027 SetResumeData(rGroup
, rShortName
);
1028 //try to make an Undo()
1029 m_xExampleFrame
->ClearDocument();
1033 void SwGlossaryDlg::ResumeShowAutoText()
1036 OUString sShortName
;
1037 if(GetResumeData(sGroup
, sShortName
) && m_xExampleFrameWin
->get_visible())
1039 if(!m_xAutoText
.is())
1041 //now the AutoText ListBoxes have to be filled
1042 m_xAutoText
= text::AutoTextContainer::create( comphelper::getProcessComponentContext() );
1045 uno::Reference
< XTextCursor
> & xCursor
= m_xExampleFrame
->GetTextCursor();
1048 if (!sShortName
.isEmpty())
1050 uno::Any aGroup
= m_xAutoText
->getByName(sGroup
);
1051 uno::Reference
< XAutoTextGroup
> xGroup
;
1052 if((aGroup
>>= xGroup
) && xGroup
->hasByName(sShortName
))
1054 uno::Any
aEntry(xGroup
->getByName(sShortName
));
1055 uno::Reference
< XAutoTextEntry
> xEntry
;
1057 xEntry
->applyTo(xCursor
);
1065 void SwGlossaryDlg::DeleteEntry()
1067 bool bEntry
= m_xCategoryBox
->get_selected(nullptr);
1069 const OUString
aTitle(m_xNameED
->get_text());
1070 const OUString
aShortName(m_xShortNameEdit
->get_text());
1072 std::unique_ptr
<weld::TreeIter
> xParent
;
1073 std::unique_ptr
<weld::TreeIter
> xChild
= DoesBlockExist(aTitle
, aShortName
);
1074 if (xChild
&& m_xCategoryBox
->get_iter_depth(*xChild
))
1076 xParent
= m_xCategoryBox
->make_iterator(xChild
.get());
1077 m_xCategoryBox
->iter_parent(*xParent
);
1080 const bool bExists
= nullptr != xChild
;
1081 const bool bIsGroup
= bEntry
&& !xParent
;
1083 std::unique_ptr
<weld::MessageDialog
> xQuery(Application::CreateMessageDialog(m_xDialog
.get(),
1084 VclMessageType::Question
, VclButtonsType::YesNo
,
1085 SwResId(STR_QUERY_DELETE
)));
1086 if (bExists
&& !bIsGroup
&& RET_YES
== xQuery
->run())
1088 if (!aTitle
.isEmpty() && m_pGlossaryHdl
->DelGlossary(aShortName
))
1090 OSL_ENSURE(xChild
, "entry not found!");
1091 m_xCategoryBox
->select(*xParent
);
1092 m_xCategoryBox
->remove(*xChild
);
1093 m_xNameED
->set_text(OUString());
1094 NameModify(*m_xNameED
);
1099 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */