android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / ui / misc / glossary.cxx
blob12145f1e74edf58f2432f0d56f829a02d95e3d72
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
47 #include <wrtsh.hxx>
48 #include <view.hxx>
49 #include <glossary.hxx>
50 #include <gloshdl.hxx>
51 #include <glosbib.hxx>
52 #include <initui.hxx>
53 #include <glosdoc.hxx>
54 #include <macassgn.hxx>
55 #include <docsh.hxx>
56 #include <shellio.hxx>
58 #include <cmdid.h>
59 #include <sfx2/filedlghelper.hxx>
61 #include <memory>
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();
81 if ( 0 == nSz )
82 return rName;
84 sal_Int32 nStart = 1;
85 while( rName[nStart-1]==' ' && nStart < nSz )
86 nStart++;
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();
98 struct GroupUserData
100 OUString sGroupName;
101 sal_uInt16 nPathIdx;
102 bool bReadonly;
104 GroupUserData()
105 : nPathIdx(0),
106 bReadonly(false) {}
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;
121 protected:
122 DECL_LINK(Modify, weld::Entry&, void);
123 DECL_LINK(Rename, weld::Button&, void);
124 DECL_LINK(TextFilterHdl, OUString&, bool);
126 public:
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);
138 return true;
141 SwNewGlosNameDlg::SwNewGlosNameDlg(SwGlossaryDlg* pParent, const OUString& rOldName, const OUString& rOldShort)
142 : GenericDialogController(pParent->getDialog(), "modules/swriter/ui/renameautotextdialog.ui", "RenameAutoTextDialog")
143 , m_pParent(pParent)
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);
176 return true;
179 class SwGlossaryDropTarget : public DropTargetHelper
181 private:
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());
193 if (!bSelected)
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);
204 if (bEntry)
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;
216 return nRet;
219 virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt) override
221 weld::TreeView* pSource = m_rTreeView.get_drag_source();
222 if (!pSource)
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);
227 if (!bEntry)
228 return DND_ACTION_NONE;
230 std::unique_ptr<weld::TreeIter> xSelected(pSource->make_iterator());
231 bool bSelected = pSource->get_selected(xSelected.get());
232 if (!bSelected)
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);
267 if(bRet)
269 m_rTreeView.insert(xDestParent.get(), -1, &sTitle, &sShortName,
270 nullptr, nullptr, false, nullptr);
271 if (bIsMove)
273 pSource->remove(*xSelected);
278 return DND_ACTION_NONE;
281 public:
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)
295 , m_bResume(false)
296 , m_bSelection(pWrtShell->IsSelection())
297 , m_bReadOnly(false)
298 , m_bIsOld(false)
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));
344 ShowPreview();
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);
354 Init();
357 SwGlossaryDlg::~SwGlossaryDlg()
361 namespace
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);
372 return sTemp;
377 // select new group
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()))
382 return;
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();
391 else
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());
411 else
412 ShowAutoText("", "");
413 // update controls
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()));
419 aReq.Done();
423 short SwGlossaryDlg::run()
425 short nRet = SfxDialogController::run();
426 if (nRet == RET_OK)
427 Apply();
428 return nRet;
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));
443 aReq.Done();
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))
464 return nullptr;
467 if (rBlock == m_xCategoryBox->get_text(*xEntry) &&
468 (rShort.empty() ||
469 rShort == m_xCategoryBox->get_id(*xEntry))
472 return xEntry;
475 while (m_xCategoryBox->iter_next_sibling(*xEntry));
477 return nullptr;
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() )
486 if(bNameED)
487 m_xShortNameEdit->set_text(aName);
488 m_xInsertBtn->set_sensitive(false);
489 return;
491 const bool bNotFound = !DoesBlockExist(aName, bNameED ? OUString() : rEdit.get_text());
492 if(bNameED)
494 // did the text get in to the Listbox in the Edit with a click?
495 if(bNotFound)
497 m_xShortNameEdit->set_text( lcl_GetValidShortCut( aName ) );
498 EnableShortName();
500 else
502 m_xShortNameEdit->set_text(m_pGlossaryHdl->GetGlossaryShortName(aName));
503 EnableShortName(!m_bReadOnly);
505 m_xInsertBtn->set_sensitive(!bNotFound && !m_bIsDocReadOnly);
507 else
509 //ShortNameEdit
510 if(!bNotFound)
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);
522 return true;
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 () );
552 pGroup.reset();
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(),
564 false, true);
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)));
577 xInfoBox->run();
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()))
585 xEntry.reset();
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));
601 aReq.Done();
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")
640 DeleteEntry();
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 );
656 aSet.Put( aItem );
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();
683 while ( pFilter )
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] ))
704 Init();
705 else
707 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
708 VclMessageType::Info, VclButtonsType::Ok,
709 SwResId(STR_NO_GLOSSARIES)));
710 xInfoBox->run();
716 // dialog manage regions
717 IMPL_LINK_NOARG(SwGlossaryDlg, BibHdl, weld::Button&, void)
719 SwGlossaries* pGloss = ::GetGlossaries();
720 if( pGloss->IsGlosPathErr() )
721 pGloss->ShowError();
722 else
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};
729 while (nIdx>=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" );
740 if(aAny.hasValue())
742 bIsWritable = !*o3tl::doAccess<bool>(aAny);
745 catch (const Exception&)
748 if(bIsWritable)
749 break;
751 if(bIsWritable)
754 SwGlossaryGroupDlg aDlg(m_xDialog.get(), pGloss->GetPathArray(), m_pGlossaryHdl);
755 if (aDlg.run() == RET_OK)
757 Init();
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);
777 break;
780 bEntry = m_xCategoryBox->iter_next(*xEntry);
785 else
787 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
788 VclMessageType::Question, VclButtonsType::YesNo,
789 m_sReadonlyPath));
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 )
814 OUString sTitle;
815 OUString sGroupName(m_pGlossaryHdl->GetGroupName(nId, &sTitle));
816 if(sGroupName.isEmpty())
817 continue;
818 sal_Int32 nIdx{ 0 };
819 const OUString sName{ sGroupName.getToken( 0, GLOS_DELIM, nIdx ) };
820 if(sTitle.isEmpty())
821 sTitle = sName;
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
854 if (!xSelEntry)
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);
868 break;
872 while (m_xCategoryBox->iter_next(*xSearch));
874 if (!xSelEntry)
876 xSelEntry = std::move(xSearch);
877 if (!xSelEntry || !m_xCategoryBox->get_iter_first(*xSelEntry))
878 xSelEntry.reset();
882 m_xCategoryBox->thaw();
883 m_xCategoryBox->make_sorted();
885 if (xSelEntry)
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())
905 OUString aSelText;
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)));
946 xBox->run();
947 m_xNewShort->grab_focus();
949 else
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);
961 else
962 rCfg.SetSaveRelNet(bCheck);
963 rCfg.Commit();
966 IMPL_LINK(SwGlossaryDlg, KeyInputHdl, const KeyEvent&, rKEvt, bool)
968 if (rKEvt.GetKeyCode().GetCode() == KEY_DELETE)
970 DeleteEntry();
971 return true;
973 return false;
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);
986 return OUString();
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 );
1003 Init();
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()
1035 OUString sGroup;
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();
1046 if(xCursor.is())
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;
1056 aEntry >>= xEntry;
1057 xEntry->applyTo(xCursor);
1062 m_bResume = false;
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: */