/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::text; using namespace ::com::sun::star::ucb; using namespace ::com::sun::star::ui::dialogs; using namespace ::ucbhelper; using namespace ::sfx2; static OUString lcl_GetValidShortCut( const OUString& rName ) { const sal_Int32 nSz = rName.getLength(); if ( 0 == nSz ) return rName; sal_Int32 nStart = 1; while( rName[nStart-1]==' ' && nStart < nSz ) nStart++; OUStringBuffer aBuf; aBuf.append(rName[nStart-1]); for( ; nStart < nSz; ++nStart ) { if( rName[nStart-1]==' ' && rName[nStart]!=' ') aBuf.append(rName[nStart]); } return aBuf.makeStringAndClear(); } struct GroupUserData { OUString sGroupName; sal_uInt16 nPathIdx; bool bReadonly; GroupUserData() : nPathIdx(0), bReadonly(false) {} }; // dialog for new block name class SwNewGlosNameDlg : public weld::GenericDialogController { TextFilter m_aNoSpaceFilter; SwGlossaryDlg* m_pParent; std::unique_ptr m_xNewName; std::unique_ptr m_xNewShort; std::unique_ptr m_xOk; std::unique_ptr m_xOldName; std::unique_ptr m_xOldShort; protected: DECL_LINK(Modify, weld::Entry&, void); DECL_LINK(Rename, weld::Button&, void); DECL_LINK(TextFilterHdl, OUString&, bool); public: SwNewGlosNameDlg(SwGlossaryDlg* pParent, const OUString& rOldName, const OUString& rOldShort); OUString GetNewName() const { return m_xNewName->get_text(); } OUString GetNewShort() const { return m_xNewShort->get_text(); } }; IMPL_LINK(SwNewGlosNameDlg, TextFilterHdl, OUString&, rTest, bool) { rTest = m_aNoSpaceFilter.filter(rTest); return true; } SwNewGlosNameDlg::SwNewGlosNameDlg(SwGlossaryDlg* pParent, const OUString& rOldName, const OUString& rOldShort) : GenericDialogController(pParent->getDialog(), "modules/swriter/ui/renameautotextdialog.ui", "RenameAutoTextDialog") , m_pParent(pParent) , m_xNewName(m_xBuilder->weld_entry("newname")) , m_xNewShort(m_xBuilder->weld_entry("newsc")) , m_xOk(m_xBuilder->weld_button("ok")) , m_xOldName(m_xBuilder->weld_entry("oldname")) , m_xOldShort(m_xBuilder->weld_entry("oldsc")) { m_xNewShort->connect_insert_text(LINK(this, SwNewGlosNameDlg, TextFilterHdl)); m_xOldName->set_text(rOldName); m_xOldShort->set_text(rOldShort); m_xNewName->connect_changed(LINK(this, SwNewGlosNameDlg, Modify )); m_xNewShort->connect_changed(LINK(this, SwNewGlosNameDlg, Modify )); m_xOk->connect_clicked(LINK(this, SwNewGlosNameDlg, Rename )); m_xNewName->grab_focus(); } // query / set currently set group OUString SwGlossaryDlg::GetCurrGroup() { if( !::GetCurrGlosGroup().isEmpty() ) return ::GetCurrGlosGroup(); return SwGlossaries::GetDefName(); } void SwGlossaryDlg::SetActGroup(const OUString &rGrp) { ::SetCurrGlosGroup(rGrp); } IMPL_LINK(SwGlossaryDlg, TextFilterHdl, OUString&, rTest, bool) { rTest = m_aNoSpaceFilter.filter(rTest); return true; } class SwGlossaryDropTarget : public DropTargetHelper { private: weld::TreeView& m_rTreeView; SwGlossaryHdl* m_pGlosHdl; virtual sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt) override { weld::TreeView* pSource = m_rTreeView.get_drag_source(); if (!pSource || pSource != &m_rTreeView) return DND_ACTION_NONE; std::unique_ptr xSelected(pSource->make_iterator()); bool bSelected = pSource->get_selected(xSelected.get()); if (!bSelected) return DND_ACTION_NONE; while (pSource->get_iter_depth(*xSelected)) (void)pSource->iter_parent(*xSelected); GroupUserData* pSrcRootData = weld::fromId(pSource->get_id(*xSelected)); GroupUserData* pDestRootData = nullptr; std::unique_ptr xDestEntry(m_rTreeView.make_iterator()); bool bEntry = m_rTreeView.get_dest_row_at_pos(rEvt.maPosPixel, xDestEntry.get(), true); if (bEntry) { while (m_rTreeView.get_iter_depth(*xDestEntry)) (void)m_rTreeView.iter_parent(*xDestEntry); pDestRootData = weld::fromId(m_rTreeView.get_id(*xDestEntry)); } if (pDestRootData == pSrcRootData) return DND_ACTION_NONE; sal_uInt8 nRet = DND_ACTION_COPY; const bool bCheckForMove = rEvt.mnAction & DND_ACTION_MOVE; if (bCheckForMove && !pSrcRootData->bReadonly) nRet |= DND_ACTION_MOVE; return nRet; } virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt) override { weld::TreeView* pSource = m_rTreeView.get_drag_source(); if (!pSource) return DND_ACTION_NONE; std::unique_ptr xDestEntry(m_rTreeView.make_iterator()); bool bEntry = m_rTreeView.get_dest_row_at_pos(rEvt.maPosPixel, xDestEntry.get(), true); if (!bEntry) return DND_ACTION_NONE; std::unique_ptr xSelected(pSource->make_iterator()); bool bSelected = pSource->get_selected(xSelected.get()); if (!bSelected) return DND_ACTION_NONE; std::unique_ptr xSrcParent(pSource->make_iterator(xSelected.get())); while (pSource->get_iter_depth(*xSrcParent)) (void)pSource->iter_parent(*xSrcParent); std::unique_ptr xDestParent(pSource->make_iterator(xDestEntry.get())); while (pSource->get_iter_depth(*xDestParent)) (void)pSource->iter_parent(*xDestParent); GroupUserData* pSrcParent = weld::fromId(pSource->get_id(*xSrcParent)); GroupUserData* pDestParent = weld::fromId(m_rTreeView.get_id(*xDestParent)); if (pDestParent != pSrcParent) { weld::WaitObject aBusy(&m_rTreeView); OUString sSourceGroup = pSrcParent->sGroupName + OUStringChar(GLOS_DELIM) + OUString::number(pSrcParent->nPathIdx); m_pGlosHdl->SetCurGroup(sSourceGroup); OUString sTitle(pSource->get_text(*xSelected)); OUString sShortName(pSource->get_id(*xSelected)); OUString sDestName = pDestParent->sGroupName + OUStringChar(GLOS_DELIM) + OUString::number(pDestParent->nPathIdx); bool bIsMove = rEvt.mnAction & DND_ACTION_MOVE; const bool bRet = m_pGlosHdl->CopyOrMove(sSourceGroup, sShortName, sDestName, sTitle, bIsMove); if(bRet) { m_rTreeView.insert(xDestParent.get(), -1, &sTitle, &sShortName, nullptr, nullptr, false, nullptr); if (bIsMove) { pSource->remove(*xSelected); } } } return DND_ACTION_NONE; } public: SwGlossaryDropTarget(weld::TreeView& rTreeView, SwGlossaryHdl* pGlosHdl) : DropTargetHelper(rTreeView.get_drop_target()) , m_rTreeView(rTreeView) , m_pGlosHdl(pGlosHdl) { } }; SwGlossaryDlg::SwGlossaryDlg(const SfxViewFrame& rViewFrame, SwGlossaryHdl * pGlosHdl, SwWrtShell *pWrtShell) : SfxDialogController(rViewFrame.GetFrameWeld(), "modules/swriter/ui/autotext.ui", "AutoTextDialog") , m_sReadonlyPath(SwResId(STR_READONLY_PATH)) , m_pGlossaryHdl(pGlosHdl) , m_bResume(false) , m_bSelection(pWrtShell->IsSelection()) , m_bReadOnly(false) , m_bIsOld(false) , m_bIsDocReadOnly(false) , m_pShell(pWrtShell) , m_xInsertTipCB(m_xBuilder->weld_check_button("inserttip")) , m_xNameED(m_xBuilder->weld_entry("name")) , m_xShortNameLbl(m_xBuilder->weld_label("shortnameft")) , m_xShortNameEdit(m_xBuilder->weld_entry("shortname")) , m_xCategoryBox(m_xBuilder->weld_tree_view("category")) , m_xFileRelCB(m_xBuilder->weld_check_button("relfile")) , m_xNetRelCB(m_xBuilder->weld_check_button("relnet")) , m_xInsertBtn(m_xBuilder->weld_button("ok")) , m_xEditBtn(m_xBuilder->weld_menu_button("autotext")) , m_xBibBtn(m_xBuilder->weld_button("categories")) , m_xPathBtn(m_xBuilder->weld_button("path")) { m_xCategoryBox->set_size_request(m_xCategoryBox->get_approximate_digit_width() * 52, m_xCategoryBox->get_height_rows(12)); Link aLink(LINK(this, SwGlossaryDlg, PreviewLoadedHdl)); m_xExampleFrame.reset(new SwOneExampleFrame(EX_SHOW_ONLINE_LAYOUT, &aLink)); m_xExampleFrameWin.reset(new weld::CustomWeld(*m_xBuilder, "example", *m_xExampleFrame)); Size aSize = m_xExampleFrame->GetDrawingArea()->get_ref_device().LogicToPixel( Size(82, 124), MapMode(MapUnit::MapAppFont)); m_xExampleFrame->set_size_request(aSize.Width(), aSize.Height()); m_xShortNameEdit->connect_insert_text(LINK(this, SwGlossaryDlg, TextFilterHdl)); m_xEditBtn->connect_toggled(LINK(this, SwGlossaryDlg, EnableHdl)); m_xEditBtn->connect_selected(LINK(this, SwGlossaryDlg, MenuHdl)); m_xPathBtn->connect_clicked(LINK(this, SwGlossaryDlg, PathHdl)); m_xNameED->connect_changed(LINK(this,SwGlossaryDlg,NameModify)); m_xShortNameEdit->connect_changed(LINK(this,SwGlossaryDlg,NameModify)); m_xCategoryBox->connect_row_activated(LINK(this, SwGlossaryDlg, NameDoubleClick)); m_xCategoryBox->connect_changed(LINK(this, SwGlossaryDlg, GrpSelect)); m_xCategoryBox->connect_key_press(LINK(this, SwGlossaryDlg, KeyInputHdl)); m_xDropTarget.reset(new SwGlossaryDropTarget(*m_xCategoryBox, pGlosHdl)); rtl::Reference xHelper(new TransferDataContainer); m_xCategoryBox->enable_drag_source(xHelper, DND_ACTION_COPYMOVE); m_xBibBtn->connect_clicked(LINK(this,SwGlossaryDlg,BibHdl)); m_xInsertBtn->connect_clicked(LINK(this,SwGlossaryDlg,InsertHdl)); ShowPreview(); m_bIsDocReadOnly = m_pShell->GetView().GetDocShell()->IsReadOnly() || m_pShell->HasReadonlySel(); if( m_bIsDocReadOnly ) m_xInsertBtn->set_sensitive(false); m_xNameED->grab_focus(); m_xCategoryBox->make_sorted(); m_xCategoryBox->set_sort_order(true); Init(); } SwGlossaryDlg::~SwGlossaryDlg() { } namespace { OUString getCurrentGlossary() { const OUString sTemp{ ::GetCurrGlosGroup() }; // the zeroth path is not being recorded! if (o3tl::starts_with(o3tl::getToken(sTemp, 1, GLOS_DELIM), u"0")) return sTemp.getToken(0, GLOS_DELIM); return sTemp; } } // select new group IMPL_LINK(SwGlossaryDlg, GrpSelect, weld::TreeView&, rBox, void) { std::unique_ptr xEntry = rBox.make_iterator(); if (!rBox.get_selected(xEntry.get())) return; std::unique_ptr xParent = rBox.make_iterator(xEntry.get()); weld::TreeIter* pParent; if (rBox.get_iter_depth(*xParent)) { rBox.iter_parent(*xParent); pParent = xParent.get(); } else pParent = xEntry.get(); GroupUserData* pGroupData = weld::fromId(rBox.get_id(*pParent)); ::SetCurrGlosGroup(pGroupData->sGroupName + OUStringChar(GLOS_DELIM) + OUString::number(pGroupData->nPathIdx)); m_pGlossaryHdl->SetCurGroup(::GetCurrGlosGroup()); // set current text block m_bReadOnly = m_pGlossaryHdl->IsReadOnly(); EnableShortName( !m_bReadOnly ); m_xEditBtn->set_sensitive(!m_bReadOnly); m_bIsOld = m_pGlossaryHdl->IsOld(); if( pParent != xEntry.get()) { OUString aName(rBox.get_text(*xEntry)); m_xNameED->set_text(aName); m_xShortNameEdit->set_text(rBox.get_id(*xEntry)); m_xInsertBtn->set_sensitive( !m_bIsDocReadOnly); ShowAutoText(::GetCurrGlosGroup(), m_xShortNameEdit->get_text()); } else ShowAutoText("", ""); // update controls NameModify(*m_xShortNameEdit); if (SfxRequest::HasMacroRecorder(m_pShell->GetView().GetViewFrame())) { SfxRequest aReq(m_pShell->GetView().GetViewFrame(), FN_SET_ACT_GLOSSARY); aReq.AppendItem(SfxStringItem(FN_SET_ACT_GLOSSARY, getCurrentGlossary())); aReq.Done(); } } short SwGlossaryDlg::run() { short nRet = SfxDialogController::run(); if (nRet == RET_OK) Apply(); return nRet; } void SwGlossaryDlg::Apply() { const OUString aGlosName(m_xShortNameEdit->get_text()); if (!aGlosName.isEmpty()) { m_pGlossaryHdl->InsertGlossary(aGlosName); } if (SfxRequest::HasMacroRecorder(m_pShell->GetView().GetViewFrame())) { SfxRequest aReq(m_pShell->GetView().GetViewFrame(), FN_INSERT_GLOSSARY); aReq.AppendItem(SfxStringItem(FN_INSERT_GLOSSARY, getCurrentGlossary())); aReq.AppendItem(SfxStringItem(FN_PARAM_1, aGlosName)); aReq.Done(); } } void SwGlossaryDlg::EnableShortName(bool bOn) { m_xShortNameLbl->set_sensitive(bOn); m_xShortNameEdit->set_sensitive(bOn); } // does the title exist in the selected group? std::unique_ptr SwGlossaryDlg::DoesBlockExist(std::u16string_view rBlock, std::u16string_view rShort) { // look for possible entry in TreeListBox std::unique_ptr xEntry = m_xCategoryBox->make_iterator(); if (m_xCategoryBox->get_selected(xEntry.get())) { if (m_xCategoryBox->get_iter_depth(*xEntry)) m_xCategoryBox->iter_parent(*xEntry); if (!m_xCategoryBox->iter_children(*xEntry)) return nullptr; do { if (rBlock == m_xCategoryBox->get_text(*xEntry) && (rShort.empty() || rShort == m_xCategoryBox->get_id(*xEntry)) ) { return xEntry; } } while (m_xCategoryBox->iter_next_sibling(*xEntry)); } return nullptr; } IMPL_LINK(SwGlossaryDlg, NameModify, weld::Entry&, rEdit, void) { const OUString aName(m_xNameED->get_text()); bool bNameED = &rEdit == m_xNameED.get(); if( aName.isEmpty() ) { if(bNameED) m_xShortNameEdit->set_text(aName); m_xInsertBtn->set_sensitive(false); return; } const bool bNotFound = !DoesBlockExist(aName, bNameED ? OUString() : rEdit.get_text()); if(bNameED) { // did the text get in to the Listbox in the Edit with a click? if(bNotFound) { m_xShortNameEdit->set_text( lcl_GetValidShortCut( aName ) ); EnableShortName(); } else { m_xShortNameEdit->set_text(m_pGlossaryHdl->GetGlossaryShortName(aName)); EnableShortName(!m_bReadOnly); } m_xInsertBtn->set_sensitive(!bNotFound && !m_bIsDocReadOnly); } else { //ShortNameEdit if(!bNotFound) { m_xInsertBtn->set_sensitive(!m_bIsDocReadOnly); } } } IMPL_LINK( SwGlossaryDlg, NameDoubleClick, weld::TreeView&, rBox, bool ) { std::unique_ptr xEntry = rBox.make_iterator(); if (rBox.get_selected(xEntry.get()) && rBox.get_iter_depth(*xEntry) && !m_bIsDocReadOnly) m_xDialog->response(RET_OK); return true; } IMPL_LINK_NOARG( SwGlossaryDlg, EnableHdl, weld::Toggleable&, void ) { std::unique_ptr xEntry = m_xCategoryBox->make_iterator(); bool bEntry = m_xCategoryBox->get_selected(xEntry.get()); const OUString aEditText(m_xNameED->get_text()); const bool bHasEntry = !aEditText.isEmpty() && !m_xShortNameEdit->get_text().isEmpty(); const bool bExists = nullptr != DoesBlockExist(aEditText, m_xShortNameEdit->get_text()); const bool bIsGroup = bEntry && !m_xCategoryBox->get_iter_depth(*xEntry); m_xEditBtn->set_item_visible("new", m_bSelection && bHasEntry && !bExists); m_xEditBtn->set_item_visible("newtext", m_bSelection && bHasEntry && !bExists); m_xEditBtn->set_item_visible("copy", bExists && !bIsGroup); m_xEditBtn->set_item_visible("replace", m_bSelection && bExists && !bIsGroup && !m_bIsOld ); m_xEditBtn->set_item_visible("replacetext", m_bSelection && bExists && !bIsGroup && !m_bIsOld ); m_xEditBtn->set_item_visible("edit", bExists && !bIsGroup ); m_xEditBtn->set_item_visible("rename", bExists && !bIsGroup ); m_xEditBtn->set_item_visible("delete", bExists && !bIsGroup ); m_xEditBtn->set_item_visible("macro", bExists && !bIsGroup && !m_bIsOld && !m_pGlossaryHdl->IsReadOnly() ); m_xEditBtn->set_item_visible("import", bIsGroup && !m_bIsOld && !m_pGlossaryHdl->IsReadOnly() ); } IMPL_LINK(SwGlossaryDlg, MenuHdl, const OString&, rItemIdent, void) { if (rItemIdent == "edit") { std::unique_ptr pGroup = ::GetGlossaries()->GetGroupDoc ( GetCurrGrpName () ); pGroup.reset(); m_xDialog->response(RET_EDIT); } else if (rItemIdent == "replace") { m_pGlossaryHdl->NewGlossary(m_xNameED->get_text(), m_xShortNameEdit->get_text()); } else if (rItemIdent == "replacetext") { m_pGlossaryHdl->NewGlossary(m_xNameED->get_text(), m_xShortNameEdit->get_text(), false, true); } else if (rItemIdent == "new" || rItemIdent == "newtext") { bool bNoAttr = rItemIdent == "newtext"; const OUString aStr(m_xNameED->get_text()); const OUString aShortName(m_xShortNameEdit->get_text()); if(m_pGlossaryHdl->HasShortName(aShortName)) { std::unique_ptr xInfoBox(Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Info, VclButtonsType::Ok, SwResId(STR_DOUBLE_SHORTNAME))); xInfoBox->run(); m_xShortNameEdit->select_region(0, -1); m_xShortNameEdit->grab_focus(); } if(m_pGlossaryHdl->NewGlossary(aStr, aShortName, false, bNoAttr )) { std::unique_ptr xEntry = m_xCategoryBox->make_iterator(); if (!m_xCategoryBox->get_selected(xEntry.get())) xEntry.reset(); else if (m_xCategoryBox->get_iter_depth(*xEntry)) m_xCategoryBox->iter_parent(*xEntry); m_xCategoryBox->insert(xEntry.get(), -1, &aStr, &aShortName, nullptr, nullptr, false, nullptr); m_xNameED->set_text(aStr); m_xShortNameEdit->set_text(aShortName); NameModify(*m_xNameED); // for toggling the buttons if (SfxRequest::HasMacroRecorder(m_pShell->GetView().GetViewFrame())) { SfxRequest aReq(m_pShell->GetView().GetViewFrame(), FN_NEW_GLOSSARY); aReq.AppendItem(SfxStringItem(FN_NEW_GLOSSARY, getCurrentGlossary())); aReq.AppendItem(SfxStringItem(FN_PARAM_1, aShortName)); aReq.AppendItem(SfxStringItem(FN_PARAM_2, aStr)); aReq.Done(); } } } else if (rItemIdent == "copy") { m_pGlossaryHdl->CopyToClipboard(*m_pShell, m_xShortNameEdit->get_text()); } else if (rItemIdent == "rename") { m_xShortNameEdit->set_text(m_pGlossaryHdl->GetGlossaryShortName(m_xNameED->get_text())); SwNewGlosNameDlg aNewNameDlg(this, m_xNameED->get_text(), m_xShortNameEdit->get_text()); if (aNewNameDlg.run() == RET_OK && m_pGlossaryHdl->Rename(m_xShortNameEdit->get_text(), aNewNameDlg.GetNewShort(), aNewNameDlg.GetNewName())) { std::unique_ptr xEntry = m_xCategoryBox->make_iterator(); if (m_xCategoryBox->get_selected(xEntry.get())) { std::unique_ptr xOldEntry = m_xCategoryBox->make_iterator(xEntry.get()); if (m_xCategoryBox->get_iter_depth(*xEntry)) m_xCategoryBox->iter_parent(*xEntry); std::unique_ptr xNewEntry = m_xCategoryBox->make_iterator(); OUString sId(aNewNameDlg.GetNewShort()); OUString sName(aNewNameDlg.GetNewName()); m_xCategoryBox->insert(xEntry.get(), -1, &sName, &sId, nullptr, nullptr, false, xNewEntry.get()); m_xCategoryBox->remove(*xOldEntry); m_xCategoryBox->select(*xNewEntry); m_xCategoryBox->scroll_to_row(*xNewEntry); } } GrpSelect(*m_xCategoryBox); } else if (rItemIdent == "delete") { DeleteEntry(); } else if (rItemIdent == "macro") { SfxItemSetFixed aSet( m_pShell->GetAttrPool() ); SvxMacro aStart(OUString(), OUString(), STARBASIC); SvxMacro aEnd(OUString(), OUString(), STARBASIC); m_pGlossaryHdl->GetMacros(m_xShortNameEdit->get_text(), aStart, aEnd ); SvxMacroItem aItem(RES_FRMMACRO); if( aStart.HasMacro() ) aItem.SetMacro( SvMacroItemId::SwStartInsGlossary, aStart ); if( aEnd.HasMacro() ) aItem.SetMacro( SvMacroItemId::SwEndInsGlossary, aEnd ); aSet.Put( aItem ); aSet.Put( SwMacroAssignDlg::AddEvents( MACASSGN_AUTOTEXT ) ); const SvxMacroItem* pMacroItem; SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); ScopedVclPtr pMacroDlg(pFact->CreateEventConfigDialog(m_xDialog.get(), aSet, m_pShell->GetView().GetViewFrame().GetFrame().GetFrameInterface() )); if ( pMacroDlg && pMacroDlg->Execute() == RET_OK && (pMacroItem = pMacroDlg->GetOutputItemSet()->GetItemIfSet( RES_FRMMACRO, false )) ) { const SvxMacroTableDtor& rTable = pMacroItem->GetMacroTable(); m_pGlossaryHdl->SetMacros( m_xShortNameEdit->get_text(), rTable.Get( SvMacroItemId::SwStartInsGlossary ), rTable.Get( SvMacroItemId::SwEndInsGlossary ) ); } } else if (rItemIdent == "import") { // call the FileOpenDialog do find WinWord - Files with templates FileDialogHelper aDlgHelper(TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, m_xDialog.get()); aDlgHelper.SetContext(FileDialogHelper::WriterImportAutotext); uno::Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker(); SfxFilterMatcher aMatcher( SwDocShell::Factory().GetFactoryName() ); SfxFilterMatcherIter aIter( aMatcher ); std::shared_ptr pFilter = aIter.First(); while ( pFilter ) { if( pFilter->GetUserData() == FILTER_WW8 ) { xFP->appendFilter( pFilter->GetUIName(), pFilter->GetWildcard().getGlob() ); xFP->setCurrentFilter( pFilter->GetUIName() ) ; } else if( pFilter->GetUserData() == FILTER_DOCX ) { xFP->appendFilter( pFilter->GetUIName(), pFilter->GetWildcard().getGlob() ); xFP->setCurrentFilter( pFilter->GetUIName() ) ; } pFilter = aIter.Next(); } if( aDlgHelper.Execute() == ERRCODE_NONE ) { if( m_pGlossaryHdl->ImportGlossaries( xFP->getSelectedFiles().getConstArray()[0] )) Init(); else { std::unique_ptr xInfoBox(Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Info, VclButtonsType::Ok, SwResId(STR_NO_GLOSSARIES))); xInfoBox->run(); } } } } // dialog manage regions IMPL_LINK_NOARG(SwGlossaryDlg, BibHdl, weld::Button&, void) { SwGlossaries* pGloss = ::GetGlossaries(); if( pGloss->IsGlosPathErr() ) pGloss->ShowError(); else { //check if at least one glossary path is write enabled SvtPathOptions aPathOpt; const OUString& sGlosPath( aPathOpt.GetAutoTextPath() ); bool bIsWritable = false; sal_Int32 nIdx {sGlosPath.isEmpty() ? -1 : 0}; while (nIdx>=0) { const OUString sPath = URIHelper::SmartRel2Abs( INetURLObject(), sGlosPath.getToken(0, ';', nIdx), URIHelper::GetMaybeFileHdl()); try { Content aTestContent( sPath, uno::Reference< XCommandEnvironment >(), comphelper::getProcessComponentContext() ); Any aAny = aTestContent.getPropertyValue( "IsReadOnly" ); if(aAny.hasValue()) { bIsWritable = !*o3tl::doAccess(aAny); } } catch (const Exception&) { } if(bIsWritable) break; } if(bIsWritable) { SwGlossaryGroupDlg aDlg(m_xDialog.get(), pGloss->GetPathArray(), m_pGlossaryHdl); if (aDlg.run() == RET_OK) { Init(); //if new groups were created - select one of them const OUString sNewGroup = aDlg.GetCreatedGroupName(); std::unique_ptr xEntry = m_xCategoryBox->make_iterator(); bool bEntry = m_xCategoryBox->get_iter_first(*xEntry); while (!sNewGroup.isEmpty() && bEntry) { if (!m_xCategoryBox->get_iter_depth(*xEntry)) { GroupUserData* pGroupData = weld::fromId(m_xCategoryBox->get_id(*xEntry)); const OUString sGroup = pGroupData->sGroupName + OUStringChar(GLOS_DELIM) + OUString::number(pGroupData->nPathIdx); if(sGroup == sNewGroup) { m_xCategoryBox->select(*xEntry); m_xCategoryBox->scroll_to_row(*xEntry); GrpSelect(*m_xCategoryBox); break; } } bEntry = m_xCategoryBox->iter_next(*xEntry); } } } else { std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Question, VclButtonsType::YesNo, m_sReadonlyPath)); if (RET_YES == xBox->run()) PathHdl(*m_xPathBtn); } } } // initialisation; from Ctor and after editing regions void SwGlossaryDlg::Init() { m_xCategoryBox->freeze(); m_xCategoryBox->clear(); m_xGroupData.clear(); m_xCategoryBox->make_unsorted(); // display text block regions const size_t nCnt = m_pGlossaryHdl->GetGroupCnt(); std::unique_ptr xSelEntry; const OUString sSelStr(::GetCurrGlosGroup().getToken(0, GLOS_DELIM)); const sal_Int32 nSelPath = o3tl::toInt32(o3tl::getToken(::GetCurrGlosGroup(), 1, GLOS_DELIM)); // #i66304# - "My AutoText" comes from mytexts.bau, but should be translated static const OUStringLiteral sMyAutoTextEnglish(u"My AutoText"); const OUString sMyAutoTextTranslated(SwResId(STR_MY_AUTOTEXT)); for(size_t nId = 0; nId < nCnt; ++nId ) { OUString sTitle; OUString sGroupName(m_pGlossaryHdl->GetGroupName(nId, &sTitle)); if(sGroupName.isEmpty()) continue; sal_Int32 nIdx{ 0 }; const OUString sName{ sGroupName.getToken( 0, GLOS_DELIM, nIdx ) }; if(sTitle.isEmpty()) sTitle = sName; if(sTitle == sMyAutoTextEnglish) sTitle = sMyAutoTextTranslated; std::unique_ptr xEntry = m_xCategoryBox->make_iterator(); m_xCategoryBox->append(xEntry.get()); m_xCategoryBox->set_text(*xEntry, sTitle, 0); const sal_Int32 nPath = o3tl::toInt32(o3tl::getToken(sGroupName, 0, GLOS_DELIM, nIdx )); GroupUserData* pData = new GroupUserData; pData->sGroupName = sName; pData->nPathIdx = static_cast< sal_uInt16 >(nPath); pData->bReadonly = m_pGlossaryHdl->IsReadOnly(&sGroupName); m_xGroupData.emplace_back(pData); m_xCategoryBox->set_id(*xEntry, weld::toId(pData)); if (sSelStr == pData->sGroupName && nSelPath == nPath) xSelEntry = m_xCategoryBox->make_iterator(xEntry.get()); // fill entries for the groups { m_pGlossaryHdl->SetCurGroup(sGroupName, false, true); const sal_uInt16 nCount = m_pGlossaryHdl->GetGlossaryCnt(); for(sal_uInt16 i = 0; i < nCount; ++i) { OUString sEntryName = m_pGlossaryHdl->GetGlossaryName(i); OUString sId = m_pGlossaryHdl->GetGlossaryShortName(i); m_xCategoryBox->insert(xEntry.get(), -1, &sEntryName, &sId, nullptr, nullptr, false, nullptr); } } } // set current group and display text blocks if (!xSelEntry) { //find a non-readonly group std::unique_ptr xSearch = m_xCategoryBox->make_iterator(); if (m_xCategoryBox->get_iter_first(*xSearch)) { do { if (!m_xCategoryBox->get_iter_depth(*xSearch)) { GroupUserData* pData = weld::fromId(m_xCategoryBox->get_id(*xSearch)); if (!pData->bReadonly) { xSelEntry = std::move(xSearch); break; } } } while (m_xCategoryBox->iter_next(*xSearch)); } if (!xSelEntry) { xSelEntry = std::move(xSearch); if (!xSelEntry || !m_xCategoryBox->get_iter_first(*xSelEntry)) xSelEntry.reset(); } } m_xCategoryBox->thaw(); m_xCategoryBox->make_sorted(); if (xSelEntry) { m_xCategoryBox->expand_row(*xSelEntry); m_xCategoryBox->select(*xSelEntry); m_xCategoryBox->scroll_to_row(*xSelEntry); GrpSelect(*m_xCategoryBox); } const SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); m_xFileRelCB->set_active( rCfg.IsSaveRelFile() ); m_xFileRelCB->connect_toggled(LINK(this, SwGlossaryDlg, CheckBoxHdl)); m_xNetRelCB->set_active( rCfg.IsSaveRelNet() ); m_xNetRelCB->connect_toggled(LINK(this, SwGlossaryDlg, CheckBoxHdl)); m_xInsertTipCB->set_active( rCfg.IsAutoTextTip() ); m_xInsertTipCB->set_sensitive(!officecfg::Office::Writer::AutoFunction::Text::ShowToolTip::isReadOnly()); m_xInsertTipCB->connect_toggled(LINK(this, SwGlossaryDlg, CheckBoxHdl)); // tdf#124088 - propose autotext and shortcut name based on selected text if (m_pShell->HasSelection()) { OUString aSelText; m_pShell->GetSelectedText(aSelText, ParaBreakType::ToBlank); aSelText = aSelText.trim(); if (aSelText.getLength() > 25) { aSelText = aSelText.copy(0, 25); if (const sal_Int32 nBlankIndex = aSelText.lastIndexOf(' '); nBlankIndex != -1) aSelText = aSelText.copy(0, nBlankIndex); } m_xNameED->set_text(aSelText); m_xNameED->select_region(0, -1); m_xShortNameEdit->set_text(lcl_GetValidShortCut(aSelText)); } } // KeyInput for ShortName - Edits without Spaces IMPL_LINK( SwNewGlosNameDlg, Modify, weld::Entry&, rBox, void ) { OUString aName(m_xNewName->get_text()); SwGlossaryDlg* pDlg = m_pParent; if (&rBox == m_xNewName.get()) m_xNewShort->set_text(lcl_GetValidShortCut(aName)); bool bEnable = !aName.isEmpty() && !m_xNewShort->get_text().isEmpty() && (!pDlg->DoesBlockExist(aName, m_xNewShort->get_text()) || aName == m_xOldName->get_text()); m_xOk->set_sensitive(bEnable); } IMPL_LINK_NOARG(SwNewGlosNameDlg, Rename, weld::Button&, void) { SwGlossaryDlg* pDlg = m_pParent; OUString sNew = GetAppCharClass().uppercase(m_xNewShort->get_text()); if (pDlg->m_pGlossaryHdl->HasShortName(m_xNewShort->get_text()) && sNew != m_xOldShort->get_text()) { std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Info, VclButtonsType::Ok, SwResId(STR_DOUBLE_SHORTNAME))); xBox->run(); m_xNewShort->grab_focus(); } else m_xDialog->response(RET_OK); } IMPL_LINK(SwGlossaryDlg, CheckBoxHdl, weld::Toggleable&, rBox, void) { SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); bool bCheck = rBox.get_active(); if (&rBox == m_xInsertTipCB.get()) rCfg.SetAutoTextTip(bCheck); else if (&rBox == m_xFileRelCB.get()) rCfg.SetSaveRelFile(bCheck); else rCfg.SetSaveRelNet(bCheck); rCfg.Commit(); } IMPL_LINK(SwGlossaryDlg, KeyInputHdl, const KeyEvent&, rKEvt, bool) { if (rKEvt.GetKeyCode().GetCode() == KEY_DELETE) { DeleteEntry(); return true; } return false; } OUString SwGlossaryDlg::GetCurrGrpName() const { std::unique_ptr xEntry = m_xCategoryBox->make_iterator(); if (m_xCategoryBox->get_selected(xEntry.get())) { if (m_xCategoryBox->get_iter_depth(*xEntry)) m_xCategoryBox->iter_parent(*xEntry); GroupUserData* pGroupData = weld::fromId(m_xCategoryBox->get_id(*xEntry)); return pGroupData->sGroupName + OUStringChar(GLOS_DELIM) + OUString::number(pGroupData->nPathIdx); } return OUString(); } IMPL_LINK_NOARG( SwGlossaryDlg, PathHdl, weld::Button&, void ) { SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); ScopedVclPtr pDlg(pFact->CreateSvxPathSelectDialog(m_xDialog.get())); SvtPathOptions aPathOpt; const OUString sGlosPath( aPathOpt.GetAutoTextPath() ); pDlg->SetPath(sGlosPath); if(RET_OK == pDlg->Execute()) { const OUString sTmp(pDlg->GetPath()); if(sTmp != sGlosPath) { aPathOpt.SetAutoTextPath( sTmp ); ::GetGlossaries()->UpdateGlosPath( true ); Init(); } } } IMPL_LINK_NOARG(SwGlossaryDlg, InsertHdl, weld::Button&, void) { m_xDialog->response(RET_OK); } void SwGlossaryDlg::ShowPreview() { ShowAutoText(::GetCurrGlosGroup(), m_xShortNameEdit->get_text()); }; IMPL_LINK_NOARG(SwGlossaryDlg, PreviewLoadedHdl, SwOneExampleFrame&, void) { ResumeShowAutoText(); } void SwGlossaryDlg::ShowAutoText(const OUString& rGroup, const OUString& rShortName) { if (m_xExampleFrameWin->get_visible()) { SetResumeData(rGroup, rShortName); //try to make an Undo() m_xExampleFrame->ClearDocument(); } } void SwGlossaryDlg::ResumeShowAutoText() { OUString sGroup; OUString sShortName; if(GetResumeData(sGroup, sShortName) && m_xExampleFrameWin->get_visible()) { if(!m_xAutoText.is()) { //now the AutoText ListBoxes have to be filled m_xAutoText = text::AutoTextContainer::create( comphelper::getProcessComponentContext() ); } uno::Reference< XTextCursor > & xCursor = m_xExampleFrame->GetTextCursor(); if(xCursor.is()) { if (!sShortName.isEmpty()) { uno::Any aGroup = m_xAutoText->getByName(sGroup); uno::Reference< XAutoTextGroup > xGroup; if((aGroup >>= xGroup) && xGroup->hasByName(sShortName)) { uno::Any aEntry(xGroup->getByName(sShortName)); uno::Reference< XAutoTextEntry > xEntry; aEntry >>= xEntry; xEntry->applyTo(xCursor); } } } } m_bResume = false; } void SwGlossaryDlg::DeleteEntry() { bool bEntry = m_xCategoryBox->get_selected(nullptr); const OUString aTitle(m_xNameED->get_text()); const OUString aShortName(m_xShortNameEdit->get_text()); std::unique_ptr xParent; std::unique_ptr xChild = DoesBlockExist(aTitle, aShortName); if (xChild && m_xCategoryBox->get_iter_depth(*xChild)) { xParent = m_xCategoryBox->make_iterator(xChild.get()); m_xCategoryBox->iter_parent(*xParent); } const bool bExists = nullptr != xChild; const bool bIsGroup = bEntry && !xParent; std::unique_ptr xQuery(Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Question, VclButtonsType::YesNo, SwResId(STR_QUERY_DELETE))); if (bExists && !bIsGroup && RET_YES == xQuery->run()) { if (!aTitle.isEmpty() && m_pGlossaryHdl->DelGlossary(aShortName)) { OSL_ENSURE(xChild, "entry not found!"); m_xCategoryBox->select(*xParent); m_xCategoryBox->remove(*xChild); m_xNameED->set_text(OUString()); NameModify(*m_xNameED); } } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */