docthemes: Save themes def. to a file when added to ColorSets
[LibreOffice.git] / sw / source / ui / index / swuiidxmrk.cxx
blob58a0f1f6562160a92b756e8f034d102514370c2f
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 <swuiidxmrk.hxx>
21 #include <hintids.hxx>
22 #include <helpids.h>
23 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
24 #include <comphelper/processfactory.hxx>
25 #include <com/sun/star/beans/PropertyValue.hpp>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <com/sun/star/frame/Bibliography.hpp>
28 #include <com/sun/star/i18n/IndexEntrySupplier.hpp>
29 #include <com/sun/star/util/SearchAlgorithms2.hpp>
30 #include <com/sun/star/util/SearchFlags.hpp>
31 #include <com/sun/star/uri/UriReferenceFactory.hpp>
32 #include <rtl/ustrbuf.hxx>
33 #include <i18nutil/searchopt.hxx>
34 #include <utility>
35 #include <vcl/svapp.hxx>
36 #include <vcl/weld.hxx>
37 #include <sfx2/dispatch.hxx>
38 #include <sfx2/viewfrm.hxx>
39 #include <svl/itemset.hxx>
40 #include <editeng/langitem.hxx>
41 #include <osl/diagnose.h>
42 #include <o3tl/string_view.hxx>
43 #include <swtypes.hxx>
44 #include <toxmgr.hxx>
45 #include <txttxmrk.hxx>
46 #include <wrtsh.hxx>
47 #include <view.hxx>
48 #include <swundo.hxx>
49 #include <cmdid.h>
50 #include <swmodule.hxx>
51 #include <fldmgr.hxx>
52 #include <fldbas.hxx>
53 #include <strings.hrc>
54 #include <svl/cjkoptions.hxx>
55 #include <sfx2/filedlghelper.hxx>
56 #include <ndtxt.hxx>
57 #include <SwRewriter.hxx>
58 #include <doc.hxx>
59 #include <docsh.hxx>
61 #define POS_CONTENT 0
62 #define POS_INDEX 1
64 static sal_Int32 nTypePos = 1; // TOX_INDEX as standard
65 static sal_uInt16 nKey1Pos = USHRT_MAX;
67 static sal_uInt16 nKey2Pos = USHRT_MAX;
69 using namespace com::sun::star;
70 using namespace com::sun::star::i18n;
71 using namespace com::sun::star::lang;
72 using namespace com::sun::star::util;
73 using namespace ::comphelper;
75 namespace
77 bool SplitUrlAndPage(const OUString& rText, OUString& rUrl, int& nPageNumber)
79 uno::Reference<uri::XUriReferenceFactory> xUriReferenceFactory
80 = uri::UriReferenceFactory::create(comphelper::getProcessComponentContext());
81 uno::Reference<uri::XUriReference> xUriRef;
82 try
84 xUriRef = xUriReferenceFactory->parse(rText);
86 catch (const uno::Exception& rException)
88 SAL_WARN("sw.ui", "SplitUrlAndPage: failed to parse url: " << rException.Message);
89 return false;
92 OUString aPagePrefix(u"page="_ustr);
93 if (!xUriRef->getFragment().startsWith(aPagePrefix))
95 return false;
98 nPageNumber = o3tl::toInt32(xUriRef->getFragment().subView(aPagePrefix.getLength()));
99 xUriRef->clearFragment();
100 rUrl = xUriRef->getUriReference();
101 return true;
104 OUString MergeUrlAndPage(const OUString& rUrl, const std::unique_ptr<weld::SpinButton>& xPageSB)
106 if (!xPageSB->get_sensitive())
108 return rUrl;
111 uno::Reference<uri::XUriReferenceFactory> xUriReferenceFactory
112 = uri::UriReferenceFactory::create(comphelper::getProcessComponentContext());
113 uno::Reference<uri::XUriReference> xUriRef;
116 xUriRef = xUriReferenceFactory->parse(rUrl);
118 catch (const uno::Exception& rException)
120 SAL_WARN("sw.ui", "MergeUrlAndPage: failed to parse url: " << rException.Message);
121 return rUrl;
124 OUString aFragment("page=" + OUString::number(xPageSB->get_value()));
125 xUriRef->setFragment(aFragment);
126 return xUriRef->getUriReference();
130 // dialog to insert a directory selection
131 SwIndexMarkPane::SwIndexMarkPane(std::shared_ptr<weld::Dialog> xDialog, weld::Builder& rBuilder, bool bNewDlg,
132 SwWrtShell* pWrtShell)
133 : m_xDialog(std::move(xDialog))
134 , m_bDel(false)
135 , m_bNewMark(bNewDlg)
136 , m_bSelected(false)
137 , m_bPhoneticED0_ChangedByUser(false)
138 , m_bPhoneticED1_ChangedByUser(false)
139 , m_bPhoneticED2_ChangedByUser(false)
140 , m_nLangForPhoneticReading(LANGUAGE_CHINESE_SIMPLIFIED)
141 , m_bIsPhoneticReadingEnabled(false)
142 , m_pSh(pWrtShell)
143 , m_xTypeFT(rBuilder.weld_label(u"typeft"_ustr))
144 , m_xTypeDCB(rBuilder.weld_combo_box(u"typecb"_ustr))
145 , m_xNewBT(rBuilder.weld_button(u"new"_ustr))
146 , m_xEntryED(rBuilder.weld_entry(u"entryed"_ustr))
147 , m_xSyncED(rBuilder.weld_button(u"sync"_ustr))
148 , m_xPhoneticFT0(rBuilder.weld_label(u"phonetic0ft"_ustr))
149 , m_xPhoneticED0(rBuilder.weld_entry(u"phonetic0ed"_ustr))
150 , m_xKey1FT(rBuilder.weld_label(u"key1ft"_ustr))
151 , m_xKey1DCB(rBuilder.weld_combo_box(u"key1cb"_ustr))
152 , m_xPhoneticFT1(rBuilder.weld_label(u"phonetic1ft"_ustr))
153 , m_xPhoneticED1(rBuilder.weld_entry(u"phonetic1ed"_ustr))
154 , m_xKey2FT(rBuilder.weld_label(u"key2ft"_ustr))
155 , m_xKey2DCB(rBuilder.weld_combo_box(u"key2cb"_ustr))
156 , m_xPhoneticFT2(rBuilder.weld_label(u"phonetic2ft"_ustr))
157 , m_xPhoneticED2(rBuilder.weld_entry(u"phonetic2ed"_ustr))
158 , m_xLevelFT(rBuilder.weld_label(u"levelft"_ustr))
159 , m_xLevelNF(rBuilder.weld_spin_button(u"levelnf"_ustr))
160 , m_xMainEntryCB(rBuilder.weld_check_button(u"mainentrycb"_ustr))
161 , m_xApplyToAllCB(rBuilder.weld_check_button(u"applytoallcb"_ustr))
162 , m_xSearchCaseSensitiveCB(rBuilder.weld_check_button(u"searchcasesensitivecb"_ustr))
163 , m_xSearchCaseWordOnlyCB(rBuilder.weld_check_button(u"searchcasewordonlycb"_ustr))
164 , m_xOKBT(bNewDlg ? rBuilder.weld_button(u"insert"_ustr) : rBuilder.weld_button(u"ok"_ustr))
165 , m_xCloseBT(rBuilder.weld_button(u"close"_ustr))
166 , m_xDelBT(rBuilder.weld_button(u"delete"_ustr))
167 , m_xPrevSameBT(rBuilder.weld_button(u"first"_ustr))
168 , m_xNextSameBT(rBuilder.weld_button(u"last"_ustr))
169 , m_xPrevBT(rBuilder.weld_button(u"previous"_ustr))
170 , m_xNextBT(rBuilder.weld_button(u"next"_ustr))
171 , m_xForSelectedEntry(rBuilder.weld_label(u"selectedentrytitle"_ustr))
173 m_xSyncED->show();
175 if (SvtCJKOptions::IsCJKFontEnabled())
177 const uno::Reference< uno::XComponentContext >& xContext = getProcessComponentContext();
179 m_xExtendedIndexEntrySupplier = i18n::IndexEntrySupplier::create(xContext);
181 m_xPhoneticFT0->show();
182 m_xPhoneticED0->show();
183 m_xPhoneticFT1->show();
184 m_xPhoneticED1->show();
185 m_xPhoneticFT2->show();
186 m_xPhoneticED2->show();
189 // tdf#129726 there are two help pages for this dialog, one for each mode,
190 // where a widget/dialog appears in both, use -insert/-edit to disambiguate
191 if (m_bNewMark)
193 m_xDialog->set_title(SwResId(STR_IDXMRK_INSERT));
194 m_xDialog->set_help_id(m_xDialog->get_help_id() + "-insert");
195 m_xTypeDCB->set_help_id(m_xTypeDCB->get_help_id() + "-insert");
197 else
199 m_xDialog->set_title(SwResId(STR_IDXMRK_EDIT));
200 m_xDialog->set_help_id(m_xDialog->get_help_id() + "-edit");
201 m_xTypeDCB->set_help_id(m_xTypeDCB->get_help_id() + "-edit");
204 m_xDelBT->connect_clicked(LINK(this,SwIndexMarkPane, DelHdl));
205 m_xPrevBT->connect_clicked(LINK(this,SwIndexMarkPane, PrevHdl));
206 m_xPrevSameBT->connect_clicked(LINK(this,SwIndexMarkPane, PrevSameHdl));
207 m_xNextBT->connect_clicked(LINK(this,SwIndexMarkPane, NextHdl));
208 m_xNextSameBT->connect_clicked(LINK(this,SwIndexMarkPane, NextSameHdl));
209 m_xTypeDCB->connect_changed(LINK(this,SwIndexMarkPane, ModifyListBoxHdl));
210 m_xKey1DCB->connect_changed(LINK(this,SwIndexMarkPane, KeyDCBModifyHdl));
211 m_xKey2DCB->connect_changed(LINK(this,SwIndexMarkPane, KeyDCBModifyHdl));
212 m_xCloseBT->connect_clicked(LINK(this,SwIndexMarkPane, CloseHdl));
213 m_xEntryED->connect_changed(LINK(this,SwIndexMarkPane, ModifyEditHdl));
214 m_xNewBT->connect_clicked(LINK(this, SwIndexMarkPane, NewUserIdxHdl));
215 m_xApplyToAllCB->connect_toggled(LINK(this, SwIndexMarkPane, SearchTypeHdl));
216 m_xPhoneticED0->connect_changed(LINK(this,SwIndexMarkPane, PhoneticEDModifyHdl));
217 m_xPhoneticED1->connect_changed(LINK(this,SwIndexMarkPane, PhoneticEDModifyHdl));
218 m_xPhoneticED2->connect_changed(LINK(this,SwIndexMarkPane, PhoneticEDModifyHdl));
219 m_xSyncED->connect_clicked(LINK(this, SwIndexMarkPane, SyncSelectionHdl));
221 if (m_bNewMark)
222 m_xDelBT->hide();
223 else
224 m_xNewBT->hide();
225 m_xOKBT->show();
226 m_xOKBT->connect_clicked(LINK(this, SwIndexMarkPane, InsertHdl));
228 m_xEntryED->grab_focus();
231 // Newly initialise controls with the new selection
232 void SwIndexMarkPane::InitControls()
234 assert(m_pSh && m_pTOXMgr && "no shell?");
235 // contents index
236 const SwTOXType* pType = m_pTOXMgr->GetTOXType(TOX_CONTENT);
237 assert(pType && "No directory type !!");
238 OUString sTmpTypeSelection;
239 if (m_xTypeDCB->get_active() != -1)
240 sTmpTypeSelection = m_xTypeDCB->get_active_text();
241 m_xTypeDCB->clear();
242 m_xTypeDCB->append_text(pType->GetTypeName());
244 // keyword index
245 pType = m_pTOXMgr->GetTOXType(TOX_INDEX);
246 assert(pType && "No directory type !!");
247 m_xTypeDCB->append_text(pType->GetTypeName());
249 // user index
250 sal_uInt16 nCount = m_pSh->GetTOXTypeCount(TOX_USER);
251 for (sal_uInt16 i = 0; i < nCount; ++i)
252 m_xTypeDCB->append_text(m_pSh->GetTOXType(TOX_USER, i)->GetTypeName());
254 // read keywords primary
256 std::vector<OUString> aArr;
257 m_pSh->GetTOIKeys(TOI_PRIMARY, aArr);
258 std::sort(aArr.begin(), aArr.end());
259 auto last = std::unique(aArr.begin(), aArr.end());
260 for (auto it = aArr.begin(); it != last; ++it)
261 m_xKey1DCB->append_text(*it);
264 // read keywords secondary
266 std::vector<OUString> aArr;
267 m_pSh->GetTOIKeys( TOI_SECONDARY, aArr );
268 std::sort(aArr.begin(), aArr.end());
269 auto last = std::unique(aArr.begin(), aArr.end());
270 for (auto it = aArr.begin(); it != last; ++it)
271 m_xKey2DCB->append_text(*it);
274 UpdateLanguageDependenciesForPhoneticReading();
276 // current entry
277 const SwTOXMark* pMark = m_pTOXMgr->GetCurTOXMark();
278 if( pMark && !m_bNewMark)
280 // Controls-Handling
282 // only if there are more than one
283 // if equal it lands at the same entry
284 m_pSh->SttCursorMove();
286 const SwTOXMark* pMoveMark;
287 bool bShow = false;
289 pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_PRV );
290 // tdf#158783 ptr compare OK for SwTOXMark (more below)
291 if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
293 m_pSh->GotoTOXMark( *pMoveMark, TOX_NXT );
294 bShow = true;
296 m_xPrevBT->set_sensitive(!areSfxPoolItemPtrsEqual(pMoveMark, pMark));
297 pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_NXT );
298 if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
300 m_pSh->GotoTOXMark( *pMoveMark, TOX_PRV );
301 bShow = true;
303 m_xNextBT->set_sensitive(!areSfxPoolItemPtrsEqual(pMoveMark, pMark));
304 if( bShow )
306 m_xPrevBT->show();
307 m_xNextBT->show();
308 bShow = false;
311 pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_SAME_PRV );
312 if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
314 m_pSh->GotoTOXMark( *pMoveMark, TOX_SAME_NXT );
315 bShow = true;
317 m_xPrevSameBT->set_sensitive(!areSfxPoolItemPtrsEqual(pMoveMark, pMark));
318 pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_SAME_NXT );
319 if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
321 m_pSh->GotoTOXMark( *pMoveMark, TOX_SAME_PRV );
322 bShow = true;
324 m_xNextSameBT->set_sensitive(!areSfxPoolItemPtrsEqual(pMoveMark, pMark));
325 if( bShow )
327 m_xNextSameBT->show();
328 m_xPrevSameBT->show();
330 m_pSh->EndCursorMove();
332 m_xTypeFT->show();
334 m_xTypeDCB->set_sensitive(false);
335 m_xTypeFT->set_sensitive(false);
337 UpdateDialog();
339 else
340 { // display current selection (first element) ????
341 if (m_pSh->GetCursorCnt() < 2)
343 m_bSelected = !m_pSh->HasSelection();
344 m_aOrgStr = m_pSh->GetView().GetSelectionTextParam(true, false);
345 m_xEntryED->set_text(m_aOrgStr);
347 //to include all equal entries may only be allowed in the body and even there
348 //only when a simple selection exists
349 const FrameTypeFlags nFrameType = m_pSh->GetFrameType(nullptr,true);
350 m_xForSelectedEntry->show();
351 m_xApplyToAllCB->show();
352 m_xSearchCaseSensitiveCB->show();
353 m_xSearchCaseWordOnlyCB->show();
354 m_xApplyToAllCB->set_sensitive(!m_aOrgStr.isEmpty() &&
355 !(nFrameType & ( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER | FrameTypeFlags::FLY_ANY )));
356 SearchTypeHdl(*m_xApplyToAllCB);
359 // index type is default
360 if (!sTmpTypeSelection.isEmpty() && m_xTypeDCB->find_text(sTmpTypeSelection) != -1)
361 m_xTypeDCB->set_active_text(sTmpTypeSelection);
362 else
363 m_xTypeDCB->set_active_text(m_xTypeDCB->get_text(nTypePos));
364 ModifyHdl(*m_xTypeDCB);
368 void SwIndexMarkPane::UpdateLanguageDependenciesForPhoneticReading()
370 //no phonetic reading if no global cjk support
371 if( !m_xExtendedIndexEntrySupplier.is() )
373 m_bIsPhoneticReadingEnabled = false;
374 return;
376 m_bIsPhoneticReadingEnabled = true;
378 //get the current language
379 if(!m_bNewMark) //if dialog is opened to iterate existing marks
381 OSL_ENSURE(m_pTOXMgr, "need TOXMgr");
382 if(!m_pTOXMgr)
383 return;
384 SwTOXMark* pMark = m_pTOXMgr->GetCurTOXMark();
385 OSL_ENSURE(pMark, "need current SwTOXMark");
386 if(!pMark)
387 return;
388 SwTextTOXMark* pTextTOXMark = pMark->GetTextTOXMark();
389 OSL_ENSURE(pTextTOXMark, "need current SwTextTOXMark");
390 if(!pTextTOXMark)
391 return;
392 const SwTextNode* pTextNode = pTextTOXMark->GetpTextNd();
393 OSL_ENSURE(pTextNode, "need current SwTextNode");
394 if(!pTextNode)
395 return;
396 sal_Int32 nTextIndex = pTextTOXMark->GetStart();
397 m_nLangForPhoneticReading = pTextNode->GetLang( nTextIndex );
399 else //if dialog is opened to create a new mark
401 sal_uInt16 nWhich;
402 switch(m_pSh->GetScriptType())
404 case SvtScriptType::ASIAN: nWhich = RES_CHRATR_CJK_LANGUAGE; break;
405 case SvtScriptType::COMPLEX:nWhich = RES_CHRATR_CTL_LANGUAGE; break;
406 default:nWhich = RES_CHRATR_LANGUAGE; break;
408 SfxItemSet aLangSet(m_pSh->GetAttrPool(), nWhich, nWhich);
409 m_pSh->GetCurAttr(aLangSet);
410 m_nLangForPhoneticReading = static_cast<const SvxLanguageItem&>(aLangSet.Get(nWhich)).GetLanguage();
415 OUString SwIndexMarkPane::GetDefaultPhoneticReading( const OUString& rText )
417 if( !m_bIsPhoneticReadingEnabled )
418 return OUString();
420 return m_xExtendedIndexEntrySupplier->getPhoneticCandidate(rText, LanguageTag::convertToLocale( m_nLangForPhoneticReading ));
423 void SwIndexMarkPane::Activate()
425 // display current selection (first element) ????
426 if (m_bNewMark)
428 m_xSyncED->set_sensitive(m_pSh->GetCursorCnt() < 2);
432 IMPL_LINK_NOARG(SwIndexMarkPane, SyncSelectionHdl, weld::Button&, void)
434 m_bSelected = !m_pSh->HasSelection();
435 m_aOrgStr = m_pSh->GetView().GetSelectionTextParam(true, false);
436 m_xEntryED->set_text(m_aOrgStr);
438 //to include all equal entries may only be allowed in the body and even there
439 //only when a simple selection exists
440 const FrameTypeFlags nFrameType = m_pSh->GetFrameType(nullptr,true);
441 m_xApplyToAllCB->show();
442 m_xSearchCaseSensitiveCB->show();
443 m_xSearchCaseWordOnlyCB->show();
444 m_xDialog->resize_to_request();
445 m_xApplyToAllCB->set_sensitive(!m_aOrgStr.isEmpty() &&
446 !(nFrameType & ( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER | FrameTypeFlags::FLY_ANY )));
447 SearchTypeHdl(*m_xApplyToAllCB);
448 ModifyHdl(*m_xEntryED);
451 // evaluate Ok-Button
452 void SwIndexMarkPane::Apply()
454 InsertUpdate();
455 if(m_bSelected)
456 m_pSh->ResetSelect(nullptr, false, ScrollSizeMode::ScrollSizeDefault);
459 // apply changes
460 void SwIndexMarkPane::InsertUpdate()
462 m_pSh->StartUndo(m_bDel ? SwUndoId::INDEX_ENTRY_DELETE : SwUndoId::INDEX_ENTRY_INSERT);
463 m_pSh->StartAllAction();
464 SwRewriter aRewriter;
466 if( m_bNewMark )
468 InsertMark();
470 if ( m_pTOXMgr->GetCurTOXMark())
471 aRewriter.AddRule(UndoArg1,
472 m_pTOXMgr->GetCurTOXMark()->GetText(m_pSh->GetLayout()));
474 else if( !m_pSh->HasReadonlySel() )
476 if ( m_pTOXMgr->GetCurTOXMark())
477 aRewriter.AddRule(UndoArg1,
478 m_pTOXMgr->GetCurTOXMark()->GetText(m_pSh->GetLayout()));
480 if( m_bDel )
481 m_pTOXMgr->DeleteTOXMark();
482 else if( m_pTOXMgr->GetCurTOXMark() )
483 UpdateMark();
486 m_pSh->EndAllAction();
487 m_pSh->EndUndo(m_bDel ? SwUndoId::INDEX_ENTRY_DELETE : SwUndoId::INDEX_ENTRY_INSERT);
489 nTypePos = m_xTypeDCB->find_text(m_xTypeDCB->get_active_text());
490 if(nTypePos == -1)
491 nTypePos = 0;
493 nKey1Pos = m_xKey1DCB->find_text(m_xKey1DCB->get_active_text());
494 nKey2Pos = m_xKey2DCB->find_text(m_xKey2DCB->get_active_text());
497 // insert mark
498 static void lcl_SelectSameStrings(SwWrtShell& rSh, bool bWordOnly, bool bCaseSensitive)
500 rSh.Push();
502 i18nutil::SearchOptions2 aSearchOpt(
503 ( bWordOnly ? SearchFlags::NORM_WORD_ONLY : 0 ),
504 rSh.GetSelText(), OUString(),
505 GetAppLanguageTag().getLocale(),
506 0, 0, 0,
507 (bCaseSensitive
508 ? TransliterationFlags::NONE
509 : TransliterationFlags::IGNORE_CASE),
510 SearchAlgorithms2::ABSOLUTE,
511 '\\' );
513 rSh.ClearMark();
514 bool bCancel;
516 //todo/mba: assuming that notes should not be searched
517 rSh.Find_Text(aSearchOpt, false/*bSearchInNotes*/, SwDocPositions::Start, SwDocPositions::End, bCancel,
518 FindRanges::InSelAll | FindRanges::InBodyOnly );
521 void SwIndexMarkPane::InsertMark()
523 auto nPos = m_xTypeDCB->find_text(m_xTypeDCB->get_active_text());
524 TOXTypes eType = nPos == POS_CONTENT ? TOX_CONTENT :
525 nPos == POS_INDEX ? TOX_INDEX : TOX_USER;
527 SwTOXMarkDescription aDesc(eType);
529 const auto nLevel = m_xLevelNF->denormalize(m_xLevelNF->get_value());
530 switch( nPos)
532 case POS_CONTENT : break;
533 case POS_INDEX: // keyword index mark
535 UpdateKeyBoxes();
536 aDesc.SetPrimKey(m_xKey1DCB->get_active_text());
537 aDesc.SetSecKey(m_xKey2DCB->get_active_text());
538 aDesc.SetMainEntry(m_xMainEntryCB->get_active());
539 aDesc.SetPhoneticReadingOfAltStr(m_xPhoneticED0->get_text());
540 aDesc.SetPhoneticReadingOfPrimKey(m_xPhoneticED1->get_text());
541 aDesc.SetPhoneticReadingOfSecKey(m_xPhoneticED2->get_text());
543 break;
544 default: // Userdefined index mark
546 aDesc.SetTOUName(m_xTypeDCB->get_active_text());
549 if (m_aOrgStr != m_xEntryED->get_text())
550 aDesc.SetAltStr(m_xEntryED->get_text());
551 bool bApplyAll = m_xApplyToAllCB->get_active();
552 bool bWordOnly = m_xSearchCaseWordOnlyCB->get_active();
553 bool bCaseSensitive = m_xSearchCaseSensitiveCB->get_active();
555 m_pSh->StartAllAction();
556 // all equal strings have to be selected here so that the
557 // entry is applied to all equal strings
558 if(bApplyAll)
560 lcl_SelectSameStrings(*m_pSh, bWordOnly, bCaseSensitive);
562 aDesc.SetLevel(nLevel);
563 SwTOXMgr aMgr(m_pSh);
564 aMgr.InsertTOXMark(aDesc);
565 if(bApplyAll)
566 m_pSh->Pop(SwCursorShell::PopMode::DeleteCurrent);
568 m_pSh->EndAllAction();
571 // update mark
572 void SwIndexMarkPane::UpdateMark()
574 OUString aAltText(m_xEntryED->get_text());
575 OUString* pAltText = m_aOrgStr != m_xEntryED->get_text() ? &aAltText : nullptr;
576 //empty alternative texts are not allowed
577 if(pAltText && pAltText->isEmpty())
578 return;
580 UpdateKeyBoxes();
582 auto nPos = m_xTypeDCB->find_text(m_xTypeDCB->get_active_text());
583 TOXTypes eType = TOX_USER;
584 if(POS_CONTENT == nPos)
585 eType = TOX_CONTENT;
586 else if(POS_INDEX == nPos)
587 eType = TOX_INDEX;
589 SwTOXMarkDescription aDesc(eType);
590 aDesc.SetLevel(m_xLevelNF->get_value());
591 if(pAltText)
592 aDesc.SetAltStr(*pAltText);
594 OUString aPrim(m_xKey1DCB->get_active_text());
595 if(!aPrim.isEmpty())
596 aDesc.SetPrimKey(aPrim);
597 OUString aSec(m_xKey2DCB->get_active_text());
598 if(!aSec.isEmpty())
599 aDesc.SetSecKey(aSec);
601 if(eType == TOX_INDEX)
603 aDesc.SetPhoneticReadingOfAltStr(m_xPhoneticED0->get_text());
604 aDesc.SetPhoneticReadingOfPrimKey(m_xPhoneticED1->get_text());
605 aDesc.SetPhoneticReadingOfSecKey(m_xPhoneticED2->get_text());
607 aDesc.SetMainEntry(m_xMainEntryCB->get_visible() && m_xMainEntryCB->get_active());
608 m_pTOXMgr->UpdateTOXMark(aDesc);
611 // insert new keys
612 void SwIndexMarkPane::UpdateKeyBoxes()
614 OUString aKey(m_xKey1DCB->get_active_text());
615 auto nPos = m_xKey1DCB->find_text(aKey);
616 if(nPos == -1 && !aKey.isEmpty())
617 { // create new key
618 m_xKey1DCB->append_text(aKey);
621 aKey = m_xKey2DCB->get_active_text();
622 nPos = m_xKey2DCB->find_text(aKey);
624 if(nPos == -1 && !aKey.isEmpty())
625 { // create new key
626 m_xKey2DCB->append_text(aKey);
630 namespace {
632 class SwNewUserIdxDlg : public weld::GenericDialogController
634 SwIndexMarkPane* m_pDlg;
636 std::unique_ptr<weld::Button> m_xOKPB;
637 std::unique_ptr<weld::Entry> m_xNameED;
639 DECL_LINK(ModifyHdl, weld::Entry&, void);
641 public:
642 explicit SwNewUserIdxDlg(SwIndexMarkPane* pPane, weld::Window* pParent)
643 : GenericDialogController(pParent, u"modules/swriter/ui/newuserindexdialog.ui"_ustr, u"NewUserIndexDialog"_ustr)
644 , m_pDlg(pPane)
645 , m_xOKPB(m_xBuilder->weld_button(u"ok"_ustr))
646 , m_xNameED(m_xBuilder->weld_entry(u"entry"_ustr))
648 m_xNameED->connect_changed(LINK(this, SwNewUserIdxDlg, ModifyHdl));
649 m_xOKPB->set_sensitive(false);
650 m_xNameED->grab_focus();
652 OUString GetName() const { return m_xNameED->get_text(); }
657 IMPL_LINK( SwNewUserIdxDlg, ModifyHdl, weld::Entry&, rEdit, void)
659 m_xOKPB->set_sensitive(!rEdit.get_text().isEmpty() && !m_pDlg->IsTOXType(rEdit.get_text()));
662 IMPL_LINK_NOARG(SwIndexMarkPane, NewUserIdxHdl, weld::Button&, void)
664 SwNewUserIdxDlg aDlg(this, m_xDialog.get());
665 if (aDlg.run() == RET_OK)
667 OUString sNewName(aDlg.GetName());
668 m_xTypeDCB->append_text(sNewName);
669 m_xTypeDCB->set_active_text(sNewName);
673 IMPL_LINK( SwIndexMarkPane, SearchTypeHdl, weld::Toggleable&, rBox, void)
675 const bool bEnable = rBox.get_active() && rBox.get_sensitive();
676 m_xSearchCaseWordOnlyCB->set_sensitive(bEnable);
677 m_xSearchCaseSensitiveCB->set_sensitive(bEnable);
680 IMPL_LINK(SwIndexMarkPane, InsertHdl, weld::Button&, rButton, void)
682 Apply();
683 //close the dialog if only one entry is available
684 if(!m_bNewMark && !m_xPrevBT->get_visible() && !m_xNextBT->get_visible())
685 CloseHdl(rButton);
688 IMPL_LINK_NOARG(SwIndexMarkPane, CloseHdl, weld::Button&, void)
690 if (m_bNewMark)
692 if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
694 pViewFrm->GetDispatcher()->Execute(FN_INSERT_IDX_ENTRY_DLG,
695 SfxCallMode::ASYNCHRON|SfxCallMode::RECORD);
698 else
700 m_xDialog->response(RET_CLOSE);
704 // select index type only when inserting
705 IMPL_LINK(SwIndexMarkPane, ModifyListBoxHdl, weld::ComboBox&, rBox, void)
707 ModifyHdl(rBox);
710 IMPL_LINK(SwIndexMarkPane, ModifyEditHdl, weld::Entry&, rEdit, void)
712 ModifyHdl(rEdit);
715 void SwIndexMarkPane::ModifyHdl(const weld::Widget& rBox)
717 if (m_xTypeDCB.get() == &rBox)
719 // set index type
720 auto nPos = m_xTypeDCB->find_text(m_xTypeDCB->get_active_text());
721 bool bLevelEnable = false,
722 bKeyEnable = false,
723 bSetKey2 = false,
724 bKey2Enable = false,
725 bEntryHasText = false,
726 bKey1HasText = false,
727 bKey2HasText = false;
728 if(nPos == POS_INDEX)
730 if (!m_xEntryED->get_text().isEmpty())
731 bEntryHasText = true;
732 m_xPhoneticED0->set_text(GetDefaultPhoneticReading(m_xEntryED->get_text()));
734 bKeyEnable = true;
735 m_xKey1DCB->set_active_text(m_xKey1DCB->get_text(nKey1Pos));
736 m_xPhoneticED1->set_text(GetDefaultPhoneticReading(m_xKey1DCB->get_active_text()));
737 if (!m_xKey1DCB->get_active_text().isEmpty())
739 bKey1HasText = bSetKey2 = bKey2Enable = true;
740 m_xKey2DCB->set_active_text(m_xKey2DCB->get_text(nKey2Pos));
741 m_xPhoneticED2->set_text(GetDefaultPhoneticReading(m_xKey2DCB->get_active_text()));
742 if(!m_xKey2DCB->get_active_text().isEmpty())
743 bKey2HasText = true;
746 else
748 bLevelEnable = true;
749 m_xLevelNF->set_max(MAXLEVEL);
750 m_xLevelNF->set_value(m_xLevelNF->normalize(0));
751 bSetKey2 = true;
753 m_xLevelFT->set_visible(bLevelEnable);
754 m_xLevelNF->set_visible(bLevelEnable);
755 m_xMainEntryCB->set_visible(nPos == POS_INDEX);
757 m_xKey1FT->set_sensitive(bKeyEnable);
758 m_xKey1DCB->set_sensitive(bKeyEnable);
759 if ( bSetKey2 )
761 m_xKey2DCB->set_sensitive(bKey2Enable);
762 m_xKey2FT->set_sensitive(bKey2Enable);
764 m_xPhoneticFT0->set_sensitive(bKeyEnable&&bEntryHasText&&m_bIsPhoneticReadingEnabled);
765 m_xPhoneticED0->set_sensitive(bKeyEnable&&bEntryHasText&&m_bIsPhoneticReadingEnabled);
766 m_xPhoneticFT1->set_sensitive(bKeyEnable&&bKey1HasText&&m_bIsPhoneticReadingEnabled);
767 m_xPhoneticED1->set_sensitive(bKeyEnable&&bKey1HasText&&m_bIsPhoneticReadingEnabled);
768 m_xPhoneticFT2->set_sensitive(bKeyEnable&&bKey2HasText&&m_bIsPhoneticReadingEnabled);
769 m_xPhoneticED2->set_sensitive(bKeyEnable&&bKey2HasText&&m_bIsPhoneticReadingEnabled);
771 else //m_xEntryED !!m_xEntryED is not a ListBox but an Edit
773 bool bHasText = !m_xEntryED->get_text().isEmpty();
774 if(!bHasText)
776 m_xPhoneticED0->set_text(OUString());
777 m_bPhoneticED0_ChangedByUser = false;
779 else if(!m_bPhoneticED0_ChangedByUser)
780 m_xPhoneticED0->set_text(GetDefaultPhoneticReading(m_xEntryED->get_text()));
782 m_xPhoneticFT0->set_sensitive(bHasText&&m_bIsPhoneticReadingEnabled);
783 m_xPhoneticED0->set_sensitive(bHasText&&m_bIsPhoneticReadingEnabled);
785 m_xOKBT->set_sensitive(!m_pSh->HasReadonlySel() &&
786 (!m_xEntryED->get_text().isEmpty() || m_pSh->GetCursorCnt(false)));
789 IMPL_LINK_NOARG(SwIndexMarkPane, NextHdl, weld::Button&, void)
791 InsertUpdate();
792 m_pTOXMgr->NextTOXMark();
793 UpdateDialog();
796 IMPL_LINK_NOARG(SwIndexMarkPane, NextSameHdl, weld::Button&, void)
798 InsertUpdate();
799 m_pTOXMgr->NextTOXMark(true);
800 UpdateDialog();
803 IMPL_LINK_NOARG(SwIndexMarkPane, PrevHdl, weld::Button&, void)
805 InsertUpdate();
806 m_pTOXMgr->PrevTOXMark();
807 UpdateDialog();
810 IMPL_LINK_NOARG(SwIndexMarkPane, PrevSameHdl, weld::Button&, void)
812 InsertUpdate();
813 m_pTOXMgr->PrevTOXMark(true);
814 UpdateDialog();
817 IMPL_LINK_NOARG(SwIndexMarkPane, DelHdl, weld::Button&, void)
819 m_bDel = true;
820 InsertUpdate();
821 m_bDel = false;
823 if(m_pTOXMgr->GetCurTOXMark())
824 UpdateDialog();
825 else
827 CloseHdl(*m_xCloseBT);
828 if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
829 pViewFrm->GetBindings().Invalidate(FN_EDIT_IDX_ENTRY_DLG);
833 // renew dialog view
834 void SwIndexMarkPane::UpdateDialog()
836 assert(m_pTOXMgr && "no tox manager?");
837 SwTOXMark* pMark = m_pTOXMgr->GetCurTOXMark();
838 OSL_ENSURE(pMark, "no current marker");
839 if(!pMark)
840 return;
842 assert(m_pSh && "no shell?");
843 SwViewShell::SetCareDialog(m_xDialog);
845 m_aOrgStr = pMark->GetText(m_pSh->GetLayout());
846 m_xEntryED->set_text(m_aOrgStr);
848 // set index type
849 bool bLevelEnable = true,
850 bKeyEnable = false,
851 bKey2Enable = false,
852 bEntryHasText = false,
853 bKey1HasText = false,
854 bKey2HasText = false;
856 TOXTypes eCurType = pMark->GetTOXType()->GetType();
857 if(TOX_INDEX == eCurType)
859 bLevelEnable = false;
860 bKeyEnable = true;
861 bKey1HasText = bKey2Enable = !pMark->GetPrimaryKey().isEmpty();
862 bKey2HasText = !pMark->GetSecondaryKey().isEmpty();
863 bEntryHasText = !pMark->GetText(m_pSh->GetLayout()).isEmpty();
864 m_xKey1DCB->set_entry_text( pMark->GetPrimaryKey() );
865 m_xKey2DCB->set_entry_text( pMark->GetSecondaryKey() );
866 m_xPhoneticED0->set_text( pMark->GetTextReading() );
867 m_xPhoneticED1->set_text( pMark->GetPrimaryKeyReading() );
868 m_xPhoneticED2->set_text( pMark->GetSecondaryKeyReading() );
869 m_xMainEntryCB->set_active(pMark->IsMainEntry());
871 else if(TOX_CONTENT == eCurType || TOX_USER == eCurType)
873 m_xLevelNF->set_value(m_xLevelNF->normalize(pMark->GetLevel()));
875 m_xKey1FT->set_sensitive(bKeyEnable);
876 m_xKey1DCB->set_sensitive(bKeyEnable);
877 m_xLevelNF->set_max(MAXLEVEL);
878 m_xLevelFT->set_visible(bLevelEnable);
879 m_xLevelNF->set_visible(bLevelEnable);
880 m_xMainEntryCB->set_visible(!bLevelEnable);
881 m_xKey2FT->set_sensitive(bKey2Enable);
882 m_xKey2DCB->set_sensitive(bKey2Enable);
884 UpdateLanguageDependenciesForPhoneticReading();
885 m_xPhoneticFT0->set_sensitive(bKeyEnable&&bEntryHasText&&m_bIsPhoneticReadingEnabled);
886 m_xPhoneticED0->set_sensitive(bKeyEnable&&bEntryHasText&&m_bIsPhoneticReadingEnabled);
887 m_xPhoneticFT1->set_sensitive(bKeyEnable&&bKey1HasText&&m_bIsPhoneticReadingEnabled);
888 m_xPhoneticED1->set_sensitive(bKeyEnable&&bKey1HasText&&m_bIsPhoneticReadingEnabled);
889 m_xPhoneticFT2->set_sensitive(bKeyEnable&&bKey2HasText&&m_bIsPhoneticReadingEnabled);
890 m_xPhoneticED2->set_sensitive(bKeyEnable&&bKey2HasText&&m_bIsPhoneticReadingEnabled);
892 // set index type
893 m_xTypeDCB->set_active_text(pMark->GetTOXType()->GetTypeName());
895 // set Next - Prev - Buttons
896 m_pSh->SttCursorMove();
897 if( m_xPrevBT->get_visible() )
899 const SwTOXMark* pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_PRV );
900 // tdf#158783 ptr compare OK for SwTOXMark (more below)
901 if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
902 m_pSh->GotoTOXMark( *pMoveMark, TOX_NXT );
903 m_xPrevBT->set_sensitive( !areSfxPoolItemPtrsEqual(pMoveMark, pMark) );
904 pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_NXT );
905 if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
906 m_pSh->GotoTOXMark( *pMoveMark, TOX_PRV );
907 m_xNextBT->set_sensitive( !areSfxPoolItemPtrsEqual(pMoveMark, pMark) );
910 if (m_xPrevSameBT->get_visible())
912 const SwTOXMark* pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_SAME_PRV );
913 if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
914 m_pSh->GotoTOXMark( *pMoveMark, TOX_SAME_NXT );
915 m_xPrevSameBT->set_sensitive( !areSfxPoolItemPtrsEqual(pMoveMark, pMark) );
916 pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_SAME_NXT );
917 if (!areSfxPoolItemPtrsEqual( pMoveMark, pMark ))
918 m_pSh->GotoTOXMark( *pMoveMark, TOX_SAME_PRV );
919 m_xNextSameBT->set_sensitive( !areSfxPoolItemPtrsEqual(pMoveMark, pMark) );
922 const bool bEnable = !m_pSh->HasReadonlySel();
923 m_xOKBT->set_sensitive(bEnable);
924 m_xDelBT->set_sensitive(bEnable);
925 m_xEntryED->set_sensitive(bEnable);
926 m_xLevelNF->set_sensitive(bEnable);
927 m_xKey1DCB->set_sensitive(bEnable);
928 m_xKey2DCB->set_sensitive(bEnable);
930 assert(pMark->GetTextTOXMark()->GetTextNode() == m_pSh->GetCursor_()->GetPoint()->GetNode());
931 m_pSh->SelectTextAttr( RES_TXTATR_TOXMARK, pMark->GetTextTOXMark() );
932 // we need the point at the start of the attribute
933 m_pSh->SwapPam();
935 m_pSh->EndCursorMove();
938 // Remind whether the edit boxes for Phonetic reading are changed manually
939 IMPL_LINK(SwIndexMarkPane, PhoneticEDModifyHdl, weld::Entry&, rEdit, void)
941 if (m_xPhoneticED0.get() == &rEdit)
943 m_bPhoneticED0_ChangedByUser = !rEdit.get_text().isEmpty();
945 else if (m_xPhoneticED1.get() == &rEdit)
947 m_bPhoneticED1_ChangedByUser = !rEdit.get_text().isEmpty();
949 else if (m_xPhoneticED2.get() == &rEdit)
951 m_bPhoneticED2_ChangedByUser = !rEdit.get_text().isEmpty();
955 // Enable Disable of the 2nd key
956 IMPL_LINK( SwIndexMarkPane, KeyDCBModifyHdl, weld::ComboBox&, rBox, void )
958 if (m_xKey1DCB.get() == &rBox)
960 bool bEnable = !rBox.get_active_text().isEmpty();
961 if(!bEnable)
963 m_xKey2DCB->set_entry_text(OUString());
964 m_xPhoneticED1->set_text(OUString());
965 m_xPhoneticED2->set_text(OUString());
966 m_bPhoneticED1_ChangedByUser = false;
967 m_bPhoneticED2_ChangedByUser = false;
969 else
971 if (rBox.get_popup_shown())
973 //reset bPhoneticED1_ChangedByUser if a completely new string is selected
974 m_bPhoneticED1_ChangedByUser = false;
976 if (!m_bPhoneticED1_ChangedByUser)
977 m_xPhoneticED1->set_text(GetDefaultPhoneticReading(rBox.get_active_text()));
979 m_xKey2DCB->set_sensitive(bEnable);
980 m_xKey2FT->set_sensitive(bEnable);
982 else if (m_xKey2DCB.get() == &rBox)
984 if (rBox.get_active_text().isEmpty())
986 m_xPhoneticED2->set_text(OUString());
987 m_bPhoneticED2_ChangedByUser = false;
989 else
991 if (rBox.get_popup_shown())
993 //reset bPhoneticED1_ChangedByUser if a completely new string is selected
994 m_bPhoneticED2_ChangedByUser = false;
996 if(!m_bPhoneticED2_ChangedByUser)
997 m_xPhoneticED2->set_text(GetDefaultPhoneticReading(rBox.get_active_text()));
1001 bool bKey1HasText = !m_xKey1DCB->get_active_text().isEmpty();
1002 bool bKey2HasText = !m_xKey2DCB->get_active_text().isEmpty();
1004 m_xPhoneticFT1->set_sensitive(bKey1HasText && m_bIsPhoneticReadingEnabled);
1005 m_xPhoneticED1->set_sensitive(bKey1HasText && m_bIsPhoneticReadingEnabled);
1006 m_xPhoneticFT2->set_sensitive(bKey2HasText && m_bIsPhoneticReadingEnabled);
1007 m_xPhoneticED2->set_sensitive(bKey2HasText && m_bIsPhoneticReadingEnabled);
1010 SwIndexMarkPane::~SwIndexMarkPane()
1014 void SwIndexMarkPane::ReInitDlg(SwWrtShell& rWrtShell, SwTOXMark const * pCurTOXMark)
1016 m_pSh = &rWrtShell;
1017 m_pTOXMgr.reset( new SwTOXMgr(m_pSh) );
1018 if(pCurTOXMark)
1020 for(sal_uInt16 i = 0; i < m_pTOXMgr->GetTOXMarkCount(); i++)
1021 // tdf#158783 ptr compare OK for SwTOXMark (more below)
1022 if (areSfxPoolItemPtrsEqual(m_pTOXMgr->GetTOXMark(i), pCurTOXMark))
1024 m_pTOXMgr->SetCurTOXMark(i);
1025 break;
1028 InitControls();
1031 SwIndexMarkFloatDlg::SwIndexMarkFloatDlg(SfxBindings* _pBindings,
1032 SfxChildWindow* pChild, weld::Window *pParent,
1033 SfxChildWinInfo const * pInfo, bool bNew)
1034 : SfxModelessDialogController(_pBindings, pChild, pParent,
1035 u"modules/swriter/ui/indexentry.ui"_ustr, u"IndexEntryDialog"_ustr)
1036 , m_aContent(m_xDialog, *m_xBuilder, bNew, ::GetActiveWrtShell())
1038 if (SwWrtShell* pWrtShell = ::GetActiveWrtShell())
1039 m_aContent.ReInitDlg(*pWrtShell);
1040 Initialize(pInfo);
1043 void SwIndexMarkFloatDlg::Activate()
1045 SfxModelessDialogController::Activate();
1046 m_aContent.Activate();
1049 void SwIndexMarkFloatDlg::ReInitDlg(SwWrtShell& rWrtShell)
1051 m_aContent.ReInitDlg( rWrtShell );
1054 SwIndexMarkModalDlg::SwIndexMarkModalDlg(weld::Window *pParent, SwWrtShell& rSh, SwTOXMark const * pCurTOXMark)
1055 : SfxDialogController(pParent, u"modules/swriter/ui/indexentry.ui"_ustr,
1056 u"IndexEntryDialog"_ustr)
1057 , m_aContent(m_xDialog, *m_xBuilder, false, &rSh)
1059 m_aContent.ReInitDlg(rSh, pCurTOXMark);
1062 SwIndexMarkModalDlg::~SwIndexMarkModalDlg()
1064 SwViewShell::SetCareDialog(nullptr);
1067 short SwIndexMarkModalDlg::run()
1069 short nRet = SfxDialogController::run();
1070 if (RET_OK == nRet)
1071 m_aContent.Apply();
1072 return nRet;
1075 namespace {
1077 class SwCreateAuthEntryDlg_Impl : public weld::GenericDialogController
1079 std::vector<std::unique_ptr<weld::Builder>> m_aBuilders;
1081 Link<weld::Entry&,bool> m_aShortNameCheckLink;
1083 SwWrtShell& m_rWrtSh;
1085 bool m_bNewEntryMode;
1086 bool m_bNameAllowed;
1088 std::vector<std::unique_ptr<weld::Grid>> m_aOrigContainers;
1089 std::vector<std::unique_ptr<weld::Label>> m_aFixedTexts;
1090 std::unique_ptr<weld::Box> m_pBoxes[AUTH_FIELD_END];
1091 std::unique_ptr<weld::Entry> m_pEdits[AUTH_FIELD_END];
1092 std::unique_ptr<weld::Button> m_xOKBT;
1093 std::unique_ptr<weld::Container> m_xBox;
1094 std::unique_ptr<weld::Grid> m_xLeft;
1095 std::unique_ptr<weld::Grid> m_xRight;
1096 std::unique_ptr<weld::ComboBox> m_xTypeListBox;
1097 std::unique_ptr<weld::ComboBox> m_xIdentifierBox;
1098 std::unique_ptr<weld::Button> m_xLocalBrowseButton;
1099 std::unique_ptr<weld::CheckButton> m_xLocalPageCB;
1100 std::unique_ptr<weld::SpinButton> m_xLocalPageSB;
1101 std::unique_ptr<weld::ComboBox> m_xTargetTypeListBox;
1102 weld::Entry* m_pTargetURLField;
1104 DECL_LINK(IdentifierHdl, weld::ComboBox&, void);
1105 DECL_LINK(ShortNameHdl, weld::Entry&, void);
1106 DECL_LINK(EnableHdl, weld::ComboBox&, void);
1107 DECL_LINK(BrowseHdl, weld::Button&, void);
1108 DECL_LINK(PageNumHdl, weld::Toggleable&, void);
1109 DECL_LINK(TargetTypeHdl, weld::ComboBox&, void);
1111 void SetFields(const OUString pFields[], bool bNewEntry, bool bSetIdentifier);
1113 public:
1114 SwCreateAuthEntryDlg_Impl(weld::Window* pParent,
1115 const OUString pFields[],
1116 SwWrtShell& rSh,
1117 bool bNewEntry,
1118 bool bCreate);
1120 OUString GetEntryText(ToxAuthorityField eField) const;
1122 void SetCheckNameHdl(const Link<weld::Entry&,bool>& rLink) {m_aShortNameCheckLink = rLink;}
1126 struct TextInfo
1128 ToxAuthorityField nToxField;
1129 const OUString pHelpId;
1134 const TextInfo aTextInfoArr[] =
1136 {AUTH_FIELD_IDENTIFIER, HID_AUTH_FIELD_IDENTIFIER },
1137 {AUTH_FIELD_AUTHORITY_TYPE, HID_AUTH_FIELD_AUTHORITY_TYPE },
1138 {AUTH_FIELD_AUTHOR, HID_AUTH_FIELD_AUTHOR },
1139 {AUTH_FIELD_TITLE, HID_AUTH_FIELD_TITLE },
1140 {AUTH_FIELD_YEAR, HID_AUTH_FIELD_YEAR },
1141 {AUTH_FIELD_PUBLISHER, HID_AUTH_FIELD_PUBLISHER },
1142 {AUTH_FIELD_ADDRESS, HID_AUTH_FIELD_ADDRESS },
1143 {AUTH_FIELD_ISBN, HID_AUTH_FIELD_ISBN },
1144 {AUTH_FIELD_CHAPTER, HID_AUTH_FIELD_CHAPTER },
1145 {AUTH_FIELD_PAGES, HID_AUTH_FIELD_PAGES },
1146 {AUTH_FIELD_EDITOR, HID_AUTH_FIELD_EDITOR },
1147 {AUTH_FIELD_EDITION, HID_AUTH_FIELD_EDITION },
1148 {AUTH_FIELD_BOOKTITLE, HID_AUTH_FIELD_BOOKTITLE },
1149 {AUTH_FIELD_VOLUME, HID_AUTH_FIELD_VOLUME },
1150 {AUTH_FIELD_HOWPUBLISHED, HID_AUTH_FIELD_HOWPUBLISHED },
1151 {AUTH_FIELD_ORGANIZATIONS, HID_AUTH_FIELD_ORGANIZATIONS },
1152 {AUTH_FIELD_INSTITUTION, HID_AUTH_FIELD_INSTITUTION },
1153 {AUTH_FIELD_SCHOOL, HID_AUTH_FIELD_SCHOOL },
1154 {AUTH_FIELD_REPORT_TYPE, HID_AUTH_FIELD_REPORT_TYPE },
1155 {AUTH_FIELD_MONTH, HID_AUTH_FIELD_MONTH },
1156 {AUTH_FIELD_JOURNAL, HID_AUTH_FIELD_JOURNAL },
1157 {AUTH_FIELD_NUMBER, HID_AUTH_FIELD_NUMBER },
1158 {AUTH_FIELD_SERIES, HID_AUTH_FIELD_SERIES },
1159 {AUTH_FIELD_ANNOTE, HID_AUTH_FIELD_ANNOTE },
1160 {AUTH_FIELD_NOTE, HID_AUTH_FIELD_NOTE },
1161 {AUTH_FIELD_URL, HID_AUTH_FIELD_URL },
1162 {AUTH_FIELD_TARGET_TYPE, HID_AUTH_FIELD_TARGET_TYPE },
1163 {AUTH_FIELD_TARGET_URL, HID_AUTH_FIELD_TARGET_URL },
1164 {AUTH_FIELD_LOCAL_URL, HID_AUTH_FIELD_LOCAL_URL },
1165 {AUTH_FIELD_CUSTOM1, HID_AUTH_FIELD_CUSTOM1 },
1166 {AUTH_FIELD_CUSTOM2, HID_AUTH_FIELD_CUSTOM2 },
1167 {AUTH_FIELD_CUSTOM3, HID_AUTH_FIELD_CUSTOM3 },
1168 {AUTH_FIELD_CUSTOM4, HID_AUTH_FIELD_CUSTOM4 },
1169 {AUTH_FIELD_CUSTOM5, HID_AUTH_FIELD_CUSTOM5 }
1172 static OUString lcl_FindColumnEntry(const uno::Sequence<beans::PropertyValue>& rFields, std::u16string_view rColumnTitle)
1174 for(const auto& rField : rFields)
1176 OUString sRet;
1177 if(rField.Name == rColumnTitle &&
1178 (rField.Value >>= sRet))
1180 return sRet;
1183 return OUString();
1186 bool SwAuthorMarkPane::s_bIsFromComponent = true;
1188 SwAuthorMarkPane::SwAuthorMarkPane(weld::DialogController &rDialog, weld::Builder& rBuilder, bool bNewDlg)
1189 : m_rDialog(rDialog)
1190 , m_bNewEntry(bNewDlg)
1191 , m_bBibAccessInitialized(false)
1192 , m_pSh(nullptr)
1193 , m_xFromComponentRB(rBuilder.weld_radio_button(u"frombibliography"_ustr))
1194 , m_xFromDocContentRB(rBuilder.weld_radio_button(u"fromdocument"_ustr))
1195 , m_xAuthorFI(rBuilder.weld_label(u"author"_ustr))
1196 , m_xTitleFI(rBuilder.weld_label(u"title"_ustr))
1197 , m_xEntryED(rBuilder.weld_entry(u"entryed"_ustr))
1198 , m_xEntryLB(rBuilder.weld_combo_box(u"entrylb"_ustr))
1199 , m_xActionBT(rBuilder.weld_button(m_bNewEntry ? u"insert"_ustr : u"modify"_ustr))
1200 , m_xCloseBT(rBuilder.weld_button(u"close"_ustr))
1201 , m_xCreateEntryPB(rBuilder.weld_button(u"new"_ustr))
1202 , m_xEditEntryPB(rBuilder.weld_button(u"edit"_ustr))
1204 m_xActionBT->show();
1205 m_xFromComponentRB->set_visible(m_bNewEntry);
1206 m_xFromDocContentRB->set_visible(m_bNewEntry);
1207 m_xFromComponentRB->set_active(s_bIsFromComponent);
1208 m_xFromDocContentRB->set_active(!s_bIsFromComponent);
1210 m_xActionBT->connect_clicked(LINK(this,SwAuthorMarkPane, InsertHdl));
1211 m_xCloseBT->connect_clicked(LINK(this,SwAuthorMarkPane, CloseHdl));
1212 m_xCreateEntryPB->connect_clicked(LINK(this,SwAuthorMarkPane, CreateEntryHdl));
1213 m_xEditEntryPB->connect_clicked(LINK(this,SwAuthorMarkPane, CreateEntryHdl));
1214 m_xFromComponentRB->connect_toggled(LINK(this,SwAuthorMarkPane, ChangeSourceHdl));
1215 m_xFromDocContentRB->connect_toggled(LINK(this,SwAuthorMarkPane, ChangeSourceHdl));
1216 m_xEntryED->connect_changed(LINK(this,SwAuthorMarkPane, EditModifyHdl));
1218 m_rDialog.set_title(SwResId(
1219 m_bNewEntry ? STR_AUTHMRK_INSERT : STR_AUTHMRK_EDIT));
1221 m_xEntryED->set_visible(!m_bNewEntry);
1222 m_xEntryLB->set_visible(m_bNewEntry);
1223 // tdf#90641 - sort bibliography entries by identifier
1224 m_xEntryLB->make_sorted();
1225 if (m_bNewEntry)
1227 m_xEntryLB->connect_changed(LINK(this, SwAuthorMarkPane, CompEntryHdl));
1231 void SwAuthorMarkPane::ReInitDlg(SwWrtShell& rWrtShell)
1233 m_pSh = &rWrtShell;
1234 InitControls();
1237 IMPL_LINK_NOARG(SwAuthorMarkPane, CloseHdl, weld::Button&, void)
1239 if(m_bNewEntry)
1241 if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
1243 pViewFrm->GetDispatcher()->Execute(FN_INSERT_AUTH_ENTRY_DLG,
1244 SfxCallMode::ASYNCHRON|SfxCallMode::RECORD);
1247 else
1249 m_rDialog.response(RET_CANCEL);
1253 IMPL_LINK( SwAuthorMarkPane, CompEntryHdl, weld::ComboBox&, rBox, void)
1255 const OUString sEntry(rBox.get_active_text());
1256 if(s_bIsFromComponent)
1258 if(m_xBibAccess.is() && !sEntry.isEmpty())
1260 if(m_xBibAccess->hasByName(sEntry))
1262 uno::Any aEntry(m_xBibAccess->getByName(sEntry));
1263 uno::Sequence<beans::PropertyValue> aFieldProps;
1264 if(aEntry >>= aFieldProps)
1266 auto nSize = std::min(static_cast<sal_Int32>(AUTH_FIELD_END), aFieldProps.getLength());
1267 for(sal_Int32 i = 0; i < nSize; i++)
1269 m_sFields[i] = lcl_FindColumnEntry(aFieldProps, m_sColumnTitles[i]);
1275 else
1277 if(!sEntry.isEmpty())
1279 const SwAuthorityFieldType* pFType = static_cast<const SwAuthorityFieldType*>(
1280 m_pSh->GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
1281 const SwAuthEntry* pEntry = pFType ? pFType->GetEntryByIdentifier(sEntry) : nullptr;
1282 for(int i = 0; i < AUTH_FIELD_END; i++)
1283 m_sFields[i] = pEntry ?
1284 pEntry->GetAuthorField(static_cast<ToxAuthorityField>(i)) : OUString();
1287 if (rBox.get_active_text().isEmpty())
1289 for(OUString & s : m_sFields)
1290 s.clear();
1292 m_xAuthorFI->set_label(m_sFields[AUTH_FIELD_AUTHOR]);
1293 m_xTitleFI->set_label(m_sFields[AUTH_FIELD_TITLE]);
1296 IMPL_LINK_NOARG(SwAuthorMarkPane, InsertHdl, weld::Button&, void)
1298 //insert or update the SwAuthorityField...
1299 if(m_pSh)
1301 bool bDifferent = false;
1302 OSL_ENSURE(!m_sFields[AUTH_FIELD_IDENTIFIER].isEmpty() , "No Id is set!");
1303 OSL_ENSURE(!m_sFields[AUTH_FIELD_AUTHORITY_TYPE].isEmpty() , "No authority type is set!");
1304 //check if the entry already exists with different content
1305 const SwAuthorityFieldType* pFType = static_cast<const SwAuthorityFieldType*>(
1306 m_pSh->GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
1307 const SwAuthEntry* pEntry = pFType ?
1308 pFType->GetEntryByIdentifier( m_sFields[AUTH_FIELD_IDENTIFIER])
1309 : nullptr;
1310 if(pEntry)
1312 for(int i = 0; i < AUTH_FIELD_END && !bDifferent; i++)
1313 bDifferent |= m_sFields[i] != pEntry->GetAuthorField(static_cast<ToxAuthorityField>(i));
1314 if(bDifferent)
1316 std::unique_ptr<weld::MessageDialog> xQuery(Application::CreateMessageDialog(m_rDialog.getDialog(),
1317 VclMessageType::Question, VclButtonsType::YesNo,
1318 SwResId(STR_QUERY_CHANGE_AUTH_ENTRY)));
1319 if (RET_YES != xQuery->run())
1320 return;
1324 SwFieldMgr aMgr(m_pSh);
1325 OUStringBuffer sFields;
1326 for(OUString & s : m_sFields)
1328 sFields.append(s + OUStringChar(TOX_STYLE_DELIMITER));
1330 if(m_bNewEntry)
1332 if(bDifferent)
1334 rtl::Reference<SwAuthEntry> xNewData(new SwAuthEntry);
1335 for(int i = 0; i < AUTH_FIELD_END; i++)
1336 xNewData->SetAuthorField(static_cast<ToxAuthorityField>(i), m_sFields[i]);
1337 m_pSh->ChangeAuthorityData(xNewData.get());
1339 SwInsertField_Data aData(SwFieldTypesEnum::Authority, 0, sFields.makeStringAndClear(), OUString(), 0 );
1340 aMgr.InsertField( aData );
1342 else if(aMgr.GetCurField())
1344 aMgr.UpdateCurField(0, sFields.makeStringAndClear(), OUString());
1347 if(!m_bNewEntry)
1348 CloseHdl(*m_xCloseBT);
1351 IMPL_LINK(SwAuthorMarkPane, CreateEntryHdl, weld::Button&, rButton, void)
1353 bool bCreate = &rButton == m_xCreateEntryPB.get();
1354 OUString sOldId = m_sCreatedEntry[0];
1355 for(int i = 0; i < AUTH_FIELD_END; i++)
1356 m_sCreatedEntry[i] = bCreate ? OUString() : m_sFields[i];
1357 SwCreateAuthEntryDlg_Impl aDlg(m_rDialog.getDialog(),
1358 bCreate ? m_sCreatedEntry : m_sFields,
1359 *m_pSh, m_bNewEntry, bCreate);
1360 if(m_bNewEntry)
1362 aDlg.SetCheckNameHdl(LINK(this, SwAuthorMarkPane, IsEntryAllowedHdl));
1364 if(RET_OK != aDlg.run())
1365 return;
1367 if(bCreate && !sOldId.isEmpty())
1369 m_xEntryLB->remove_text(sOldId);
1371 for(int i = 0; i < AUTH_FIELD_END; i++)
1373 m_sFields[i] = aDlg.GetEntryText(static_cast<ToxAuthorityField>(i));
1374 m_sCreatedEntry[i] = m_sFields[i];
1376 if(m_bNewEntry && !m_xFromDocContentRB->get_active())
1378 m_xFromDocContentRB->set_active(true);
1379 ChangeSourceHdl(*m_xFromDocContentRB);
1381 if(bCreate)
1383 OSL_ENSURE(m_xEntryLB->find_text(m_sFields[AUTH_FIELD_IDENTIFIER]) == -1,
1384 "entry exists!");
1385 m_xEntryLB->append_text(m_sFields[AUTH_FIELD_IDENTIFIER]);
1386 m_xEntryLB->set_active_text(m_sFields[AUTH_FIELD_IDENTIFIER]);
1388 m_xEntryED->set_text(m_sFields[AUTH_FIELD_IDENTIFIER]);
1389 m_xAuthorFI->set_label(m_sFields[AUTH_FIELD_AUTHOR]);
1390 m_xTitleFI->set_label(m_sFields[AUTH_FIELD_TITLE]);
1391 m_xActionBT->set_sensitive(true);
1393 if (!m_bNewEntry)
1395 // When in edit mode, automatically apply the changed entry to update the field in the doc
1396 // model.
1397 InsertHdl(*m_xActionBT);
1401 IMPL_LINK_NOARG(SwAuthorMarkPane, ChangeSourceHdl, weld::Toggleable&, void)
1403 bool bFromComp = m_xFromComponentRB->get_active();
1404 s_bIsFromComponent = bFromComp;
1405 m_xCreateEntryPB->set_sensitive(!s_bIsFromComponent);
1406 m_xEntryLB->clear();
1407 if(s_bIsFromComponent)
1409 if(!m_bBibAccessInitialized)
1411 const uno::Reference< uno::XComponentContext >& xContext = getProcessComponentContext();
1412 m_xBibAccess = frame::Bibliography::create( xContext );
1413 uno::Reference< beans::XPropertySet > xPropSet(m_xBibAccess, uno::UNO_QUERY);
1414 OUString uPropName(u"BibliographyDataFieldNames"_ustr);
1415 if(xPropSet.is() && xPropSet->getPropertySetInfo()->hasPropertyByName(uPropName))
1417 uno::Any aNames = xPropSet->getPropertyValue(uPropName);
1418 uno::Sequence<beans::PropertyValue> aSeq;
1419 if( aNames >>= aSeq)
1421 for (const beans::PropertyValue& rProp : aSeq)
1423 sal_Int16 nField = 0;
1424 rProp.Value >>= nField;
1425 if(nField >= 0 && nField < AUTH_FIELD_END)
1426 m_sColumnTitles[nField] = rProp.Name;
1430 m_bBibAccessInitialized = true;
1432 if(m_xBibAccess.is())
1434 const uno::Sequence<OUString> aIdentifiers = m_xBibAccess->getElementNames();
1435 for(const OUString& rName : aIdentifiers)
1436 m_xEntryLB->append_text(rName);
1439 else
1441 const SwAuthorityFieldType* pFType = static_cast<const SwAuthorityFieldType*>(
1442 m_pSh->GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
1443 if(pFType)
1445 std::vector<OUString> aIds;
1446 pFType->GetAllEntryIdentifiers( aIds );
1447 for(const OUString & i : aIds)
1448 m_xEntryLB->append_text(i);
1450 if(!m_sCreatedEntry[AUTH_FIELD_IDENTIFIER].isEmpty())
1451 m_xEntryLB->append_text(m_sCreatedEntry[AUTH_FIELD_IDENTIFIER]);
1453 m_xEntryLB->set_active(0);
1454 CompEntryHdl(*m_xEntryLB);
1457 IMPL_LINK(SwAuthorMarkPane, EditModifyHdl, weld::Entry&, rEdit, void)
1459 Link<weld::Entry&,bool> aAllowed = LINK(this, SwAuthorMarkPane, IsEditAllowedHdl);
1460 bool bResult = aAllowed.Call(rEdit);
1461 m_xActionBT->set_sensitive(bResult);
1462 if(bResult)
1464 OUString sEntry(rEdit.get_text());
1465 m_sFields[AUTH_FIELD_IDENTIFIER] = sEntry;
1466 m_sCreatedEntry[AUTH_FIELD_IDENTIFIER] = sEntry;
1470 IMPL_LINK(SwAuthorMarkPane, IsEntryAllowedHdl, weld::Entry&, rEdit, bool)
1472 OUString sEntry = rEdit.get_text();
1473 bool bAllowed = false;
1474 if(!sEntry.isEmpty())
1476 if (m_xEntryLB->find_text(sEntry) != -1)
1477 return false;
1478 else if(s_bIsFromComponent)
1480 const SwAuthorityFieldType* pFType = static_cast<const SwAuthorityFieldType*>(
1481 m_pSh->GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
1482 bAllowed = !pFType || !pFType->GetEntryByIdentifier(sEntry);
1484 else
1486 bAllowed = !m_xBibAccess.is() || !m_xBibAccess->hasByName(sEntry);
1489 return bAllowed;
1492 IMPL_LINK(SwAuthorMarkPane, IsEditAllowedHdl, weld::Entry&, rEdit, bool)
1494 OUString sEntry = rEdit.get_text();
1495 bool bAllowed = false;
1496 if(!sEntry.isEmpty())
1498 if (m_xEntryLB->find_text(sEntry) != -1)
1499 return false;
1500 else if(s_bIsFromComponent)
1502 const SwAuthorityFieldType* pFType = static_cast<const SwAuthorityFieldType*>(
1503 m_pSh->GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
1504 bAllowed = !pFType || !pFType->GetEntryByIdentifier(sEntry);
1506 else
1508 bAllowed = !m_xBibAccess.is() || !m_xBibAccess->hasByName(sEntry);
1511 return bAllowed;
1514 void SwAuthorMarkPane::InitControls()
1516 assert(m_pSh && "no shell?");
1517 SwField* pField = m_pSh->GetCurField();
1518 OSL_ENSURE(m_bNewEntry || pField, "no current marker");
1519 if(m_bNewEntry)
1521 ChangeSourceHdl(m_xFromComponentRB->get_active() ? *m_xFromComponentRB : *m_xFromDocContentRB);
1522 m_xCreateEntryPB->set_sensitive(!m_xFromComponentRB->get_active());
1523 if(!m_xFromComponentRB->get_active() && !m_sCreatedEntry[0].isEmpty())
1524 for(int i = 0; i < AUTH_FIELD_END; i++)
1525 m_sFields[i] = m_sCreatedEntry[i];
1527 if(m_bNewEntry || !pField || pField->GetTyp()->Which() != SwFieldIds::TableOfAuthorities)
1528 return;
1530 const SwAuthEntry* pEntry = static_cast<SwAuthorityField*>(pField)->GetAuthEntry();
1532 OSL_ENSURE(pEntry, "No authority entry found");
1533 if(!pEntry)
1534 return;
1535 for(int i = 0; i < AUTH_FIELD_END; i++)
1536 m_sFields[i] = pEntry->GetAuthorField(static_cast<ToxAuthorityField>(i));
1538 m_xEntryED->set_text(pEntry->GetAuthorField(AUTH_FIELD_IDENTIFIER));
1539 m_xAuthorFI->set_label(pEntry->GetAuthorField(AUTH_FIELD_AUTHOR));
1540 m_xTitleFI->set_label(pEntry->GetAuthorField(AUTH_FIELD_TITLE));
1543 void SwAuthorMarkPane::Activate()
1545 m_xActionBT->set_sensitive(!m_pSh->HasReadonlySel());
1548 namespace
1550 const TranslateId STR_AUTH_FIELD_ARY[] =
1552 STR_AUTH_FIELD_IDENTIFIER,
1553 STR_AUTH_FIELD_AUTHORITY_TYPE,
1554 STR_AUTH_FIELD_ADDRESS,
1555 STR_AUTH_FIELD_ANNOTE,
1556 STR_AUTH_FIELD_AUTHOR,
1557 STR_AUTH_FIELD_BOOKTITLE,
1558 STR_AUTH_FIELD_CHAPTER,
1559 STR_AUTH_FIELD_EDITION,
1560 STR_AUTH_FIELD_EDITOR,
1561 STR_AUTH_FIELD_HOWPUBLISHED,
1562 STR_AUTH_FIELD_INSTITUTION,
1563 STR_AUTH_FIELD_JOURNAL,
1564 STR_AUTH_FIELD_MONTH,
1565 STR_AUTH_FIELD_NOTE,
1566 STR_AUTH_FIELD_NUMBER,
1567 STR_AUTH_FIELD_ORGANIZATIONS,
1568 STR_AUTH_FIELD_PAGES,
1569 STR_AUTH_FIELD_PUBLISHER,
1570 STR_AUTH_FIELD_SCHOOL,
1571 STR_AUTH_FIELD_SERIES,
1572 STR_AUTH_FIELD_TITLE,
1573 STR_AUTH_FIELD_TYPE,
1574 STR_AUTH_FIELD_VOLUME,
1575 STR_AUTH_FIELD_YEAR,
1576 STR_AUTH_FIELD_URL,
1577 STR_AUTH_FIELD_CUSTOM1,
1578 STR_AUTH_FIELD_CUSTOM2,
1579 STR_AUTH_FIELD_CUSTOM3,
1580 STR_AUTH_FIELD_CUSTOM4,
1581 STR_AUTH_FIELD_CUSTOM5,
1582 STR_AUTH_FIELD_ISBN,
1583 STR_AUTH_FIELD_LOCAL_URL,
1584 STR_AUTH_FIELD_TARGET_TYPE,
1585 STR_AUTH_FIELD_TARGET_URL,
1589 SwCreateAuthEntryDlg_Impl::SwCreateAuthEntryDlg_Impl(weld::Window* pParent,
1590 const OUString pFields[],
1591 SwWrtShell& rSh,
1592 bool bNewEntry,
1593 bool bCreate)
1594 : GenericDialogController(pParent, u"modules/swriter/ui/createauthorentry.ui"_ustr, u"CreateAuthorEntryDialog"_ustr)
1595 , m_rWrtSh(rSh)
1596 , m_bNewEntryMode(bNewEntry)
1597 , m_bNameAllowed(true)
1598 , m_xOKBT(m_xBuilder->weld_button(u"ok"_ustr))
1599 , m_xBox(m_xBuilder->weld_container(u"box"_ustr))
1600 , m_xLeft(m_xBuilder->weld_grid(u"leftgrid"_ustr))
1601 , m_xRight(m_xBuilder->weld_grid(u"rightgrid"_ustr))
1602 , m_pTargetURLField(nullptr)
1604 bool bLeft = true;
1605 sal_Int32 nLeftRow(0), nRightRow(0);
1606 for(int nIndex = 0; nIndex < AUTH_FIELD_END; nIndex++)
1608 //m_xBox parent just to have some parent during setup, added contents are not directly visible under m_xBox
1609 m_aBuilders.emplace_back(Application::CreateBuilder(m_xBox.get(), u"modules/swriter/ui/bibliofragment.ui"_ustr));
1610 const TextInfo aCurInfo = aTextInfoArr[nIndex];
1612 m_aOrigContainers.emplace_back(m_aBuilders.back()->weld_grid(u"biblioentry"_ustr));
1613 m_aFixedTexts.emplace_back(m_aBuilders.back()->weld_label(u"label"_ustr));
1615 weld::Grid* pTargetGrid = bLeft ? m_xLeft.get() : m_xRight.get();
1616 m_aOrigContainers.back()->move(m_aFixedTexts.back().get(), pTargetGrid);
1617 pTargetGrid->set_child_left_attach(*m_aFixedTexts.back(), 0);
1618 pTargetGrid->set_child_top_attach(*m_aFixedTexts.back(), bLeft ? nLeftRow : nRightRow);
1620 m_aFixedTexts.back()->set_label(SwResId(STR_AUTH_FIELD_ARY[aCurInfo.nToxField]));
1621 m_aFixedTexts.back()->show();
1622 if( AUTH_FIELD_AUTHORITY_TYPE == aCurInfo.nToxField )
1624 m_xTypeListBox = m_aBuilders.back()->weld_combo_box(u"listbox"_ustr);
1625 m_aOrigContainers.back()->move(m_xTypeListBox.get(), pTargetGrid);
1627 for (int j = 0; j < AUTH_TYPE_END; j++)
1629 m_xTypeListBox->append_text(
1630 SwAuthorityFieldType::GetAuthTypeName(static_cast<ToxAuthorityType>(j)));
1633 pTargetGrid->set_child_left_attach(*m_xTypeListBox, 1);
1634 pTargetGrid->set_child_top_attach(*m_xTypeListBox, bLeft ? nLeftRow : nRightRow);
1635 m_xTypeListBox->set_hexpand(true);
1636 m_xTypeListBox->show();
1637 m_xTypeListBox->connect_changed(LINK(this, SwCreateAuthEntryDlg_Impl, EnableHdl));
1638 m_xTypeListBox->set_help_id(aCurInfo.pHelpId);
1639 m_aFixedTexts.back()->set_mnemonic_widget(m_xTypeListBox.get());
1641 else if(AUTH_FIELD_IDENTIFIER == aCurInfo.nToxField && !m_bNewEntryMode)
1643 m_xIdentifierBox = m_aBuilders.back()->weld_combo_box(u"combobox"_ustr);
1644 m_aOrigContainers.back()->move(m_xIdentifierBox.get(), pTargetGrid);
1646 m_xIdentifierBox->connect_changed(LINK(this,
1647 SwCreateAuthEntryDlg_Impl, IdentifierHdl));
1649 const SwAuthorityFieldType* pFType = static_cast<const SwAuthorityFieldType*>(
1650 rSh.GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
1651 if(pFType)
1653 std::vector<OUString> aIds;
1654 pFType->GetAllEntryIdentifiers( aIds );
1655 for (const OUString& a : aIds)
1656 m_xIdentifierBox->append_text(a);
1659 pTargetGrid->set_child_left_attach(*m_xIdentifierBox, 1);
1660 pTargetGrid->set_child_top_attach(*m_xIdentifierBox, bLeft ? nLeftRow : nRightRow);
1661 m_xIdentifierBox->set_hexpand(true);
1662 m_xIdentifierBox->show();
1663 m_xIdentifierBox->set_help_id(aCurInfo.pHelpId);
1664 m_aFixedTexts.back()->set_mnemonic_widget(m_xIdentifierBox.get());
1666 else if (AUTH_FIELD_TARGET_TYPE == aCurInfo.nToxField)
1668 m_xTargetTypeListBox = m_aBuilders.back()->weld_combo_box(u"listbox-target-type"_ustr);
1669 m_aOrigContainers.back()->move(m_xTargetTypeListBox.get(), pTargetGrid);
1671 pTargetGrid->set_child_left_attach(*m_xTargetTypeListBox, 1);
1672 pTargetGrid->set_child_top_attach(*m_xTargetTypeListBox, bLeft ? nLeftRow : nRightRow);
1673 m_xTargetTypeListBox->set_hexpand(true);
1674 m_xTargetTypeListBox->show();
1675 m_xTargetTypeListBox->connect_changed(LINK(this, SwCreateAuthEntryDlg_Impl, TargetTypeHdl));
1676 m_xTargetTypeListBox->set_help_id(aCurInfo.pHelpId);
1677 m_aFixedTexts.back()->set_mnemonic_widget(m_xTargetTypeListBox.get());
1679 else
1681 m_pBoxes[nIndex] = m_aBuilders.back()->weld_box(u"vbox"_ustr);
1682 m_pEdits[nIndex] = m_aBuilders.back()->weld_entry(u"entry"_ustr);
1684 m_aOrigContainers.back()->move(m_pBoxes[nIndex].get(), pTargetGrid);
1685 pTargetGrid->set_child_left_attach(*m_pBoxes[nIndex], 1);
1686 pTargetGrid->set_child_top_attach(*m_pBoxes[nIndex], bLeft ? nLeftRow : nRightRow);
1687 m_pBoxes[nIndex]->set_hexpand(true);
1688 if (aCurInfo.nToxField == AUTH_FIELD_LOCAL_URL)
1690 m_xLocalBrowseButton = m_aBuilders.back()->weld_button(u"browse"_ustr);
1691 m_xLocalBrowseButton->connect_clicked(
1692 LINK(this, SwCreateAuthEntryDlg_Impl, BrowseHdl));
1693 m_xLocalPageCB = m_aBuilders.back()->weld_check_button(u"pagecb"_ustr);
1694 // Distinguish different instances of this for ui-testing.
1695 m_xLocalPageCB->set_buildable_name(m_xLocalPageCB->get_buildable_name()
1696 + "-local-visible");
1697 m_xLocalPageSB = m_aBuilders.back()->weld_spin_button(u"pagesb"_ustr);
1699 m_pEdits[nIndex]->show();
1700 m_pEdits[nIndex]->set_help_id(aCurInfo.pHelpId);
1702 if(AUTH_FIELD_IDENTIFIER == aCurInfo.nToxField)
1704 m_pEdits[nIndex]->connect_changed(LINK(this, SwCreateAuthEntryDlg_Impl, ShortNameHdl));
1705 m_bNameAllowed = !pFields[nIndex].isEmpty();
1706 if(!bCreate)
1708 m_aFixedTexts.back()->set_sensitive(false);
1709 m_pEdits[nIndex]->set_sensitive(false);
1712 else if (aCurInfo.nToxField == AUTH_FIELD_LOCAL_URL)
1714 m_xLocalPageCB->show();
1715 m_xLocalPageCB->connect_toggled(LINK(this, SwCreateAuthEntryDlg_Impl, PageNumHdl));
1716 m_xLocalPageSB->show();
1719 m_aFixedTexts.back()->set_mnemonic_widget(m_pEdits[nIndex].get());
1721 if(bLeft)
1722 ++nLeftRow;
1723 else
1724 ++nRightRow;
1725 bLeft = !bLeft;
1727 SetFields(pFields, bNewEntry, !bNewEntry);
1728 assert(m_xTypeListBox && "this will exist after the loop");
1729 EnableHdl(*m_xTypeListBox);
1732 void SwCreateAuthEntryDlg_Impl::SetFields(const OUString pFields[], bool bNewEntry, bool bSetIdentifier) {
1733 for (int nIndex = 0; nIndex < AUTH_FIELD_END; ++nIndex)
1735 switch (const TextInfo aCurInfo = aTextInfoArr[nIndex]; aCurInfo.nToxField)
1737 case AUTH_FIELD_IDENTIFIER:
1738 if (!bNewEntry && bSetIdentifier)
1740 assert(m_xIdentifierBox);
1741 m_xIdentifierBox->set_entry_text(pFields[aCurInfo.nToxField]);
1743 break;
1744 case AUTH_FIELD_AUTHORITY_TYPE:
1745 if (!pFields[aCurInfo.nToxField].isEmpty())
1747 m_xTypeListBox->set_active(pFields[aCurInfo.nToxField].toInt32());
1749 else
1751 m_xTypeListBox->clear();
1753 break;
1754 case AUTH_FIELD_TARGET_TYPE:
1755 assert(m_xTargetTypeListBox && "No TargetType ListBox");
1756 if (!pFields[aCurInfo.nToxField].isEmpty())
1758 m_xTargetTypeListBox->set_active(pFields[aCurInfo.nToxField].toInt32());
1760 else
1762 // For new entries, set value to "BibliographyTableRow", for legacy ones set it to "UseDisplayURL"
1763 m_xTargetTypeListBox->set_active(bNewEntry ? SwAuthorityField::TargetType::BibliographyTableRow : SwAuthorityField::TargetType::UseDisplayURL);
1765 break;
1766 default:
1767 if (AUTH_FIELD_TARGET_URL == aCurInfo.nToxField)
1769 m_pTargetURLField = m_pEdits[nIndex].get();
1770 assert(m_xTargetTypeListBox);
1771 m_pTargetURLField->set_sensitive(
1772 m_xTargetTypeListBox->get_active() == SwAuthorityField::TargetType::UseTargetURL);
1775 OUString aText = pFields[aCurInfo.nToxField], aUrl;
1776 if (int nPageNumber; AUTH_FIELD_LOCAL_URL == aCurInfo.nToxField && SplitUrlAndPage(aText, aUrl, nPageNumber))
1778 assert(m_xLocalPageCB && m_xLocalPageSB);
1779 m_pEdits[nIndex]->set_text(aUrl);
1780 m_xLocalPageCB->set_active(true);
1781 m_xLocalPageSB->set_sensitive(true);
1782 m_xLocalPageSB->set_value(nPageNumber);
1784 else
1786 m_pEdits[nIndex]->set_text(aText);
1792 OUString SwCreateAuthEntryDlg_Impl::GetEntryText(ToxAuthorityField eField) const
1794 if( AUTH_FIELD_AUTHORITY_TYPE == eField )
1796 assert(m_xTypeListBox && "No ListBox");
1797 return OUString::number(m_xTypeListBox->get_active());
1800 if( AUTH_FIELD_IDENTIFIER == eField && !m_bNewEntryMode)
1802 assert(m_xIdentifierBox && "No ComboBox");
1803 return m_xIdentifierBox->get_active_text();
1806 if (AUTH_FIELD_TARGET_TYPE == eField)
1808 assert(m_xTargetTypeListBox && "No TargetType ListBox");
1809 return OUString::number(m_xTargetTypeListBox->get_active());
1812 for(int nIndex = 0; nIndex < AUTH_FIELD_END; nIndex++)
1814 const TextInfo aCurInfo = aTextInfoArr[nIndex];
1815 if(aCurInfo.nToxField == eField)
1817 if (aCurInfo.nToxField == AUTH_FIELD_LOCAL_URL)
1819 return MergeUrlAndPage(m_pEdits[nIndex]->get_text(), m_xLocalPageSB);
1821 else
1823 return m_pEdits[nIndex]->get_text();
1828 return OUString();
1831 IMPL_LINK(SwCreateAuthEntryDlg_Impl, IdentifierHdl, weld::ComboBox&, rBox, void)
1833 const SwAuthorityFieldType* pFType = static_cast<const SwAuthorityFieldType*>(
1834 m_rWrtSh.GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
1835 if(!pFType)
1836 return;
1838 const SwAuthEntry* pEntry = pFType->GetEntryByIdentifier(
1839 rBox.get_active_text());
1840 if(!pEntry)
1841 return;
1843 OUString sFields[AUTH_FIELD_END];
1844 for(int ii = 0; ii < AUTH_FIELD_END; ++ii)
1845 sFields[ii] = pEntry->GetAuthorField(ToxAuthorityField(ii));
1846 SetFields(sFields, false, false);
1849 IMPL_LINK(SwCreateAuthEntryDlg_Impl, ShortNameHdl, weld::Entry&, rEdit, void)
1851 if (m_aShortNameCheckLink.IsSet())
1853 bool bEnable = m_aShortNameCheckLink.Call(rEdit);
1854 m_bNameAllowed |= bEnable;
1855 m_xOKBT->set_sensitive(m_xTypeListBox->get_active() != -1 && bEnable);
1859 IMPL_LINK(SwCreateAuthEntryDlg_Impl, EnableHdl, weld::ComboBox&, rBox, void)
1861 m_xOKBT->set_sensitive(m_bNameAllowed && rBox.get_active() != -1);
1862 m_xLocalBrowseButton->show();
1865 IMPL_LINK(SwCreateAuthEntryDlg_Impl, TargetTypeHdl, weld::ComboBox&, rBox, void)
1867 assert(m_pTargetURLField);
1868 m_pTargetURLField->set_sensitive(rBox.get_active() == SwAuthorityField::TargetType::UseTargetURL);
1871 IMPL_LINK(SwCreateAuthEntryDlg_Impl, BrowseHdl, weld::Button&, rButton, void)
1873 sfx2::FileDialogHelper aFileDlg(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
1874 FileDialogFlags::NONE, getDialog());
1875 OUString aPath;
1876 if (&rButton == m_xLocalBrowseButton.get())
1878 aPath = GetEntryText(AUTH_FIELD_LOCAL_URL);
1880 if (!aPath.isEmpty())
1882 aFileDlg.SetDisplayDirectory(aPath);
1884 else
1886 if (SwDocShell* pShell = m_rWrtSh.GetDoc()->GetDocShell())
1888 OUString aBaseURL = pShell->getDocumentBaseURL();
1889 if (!aBaseURL.isEmpty())
1891 aFileDlg.SetDisplayDirectory(aBaseURL);
1896 if (aFileDlg.Execute() != ERRCODE_NONE)
1898 return;
1901 aPath = aFileDlg.GetPath();
1903 for (int nIndex = 0; nIndex < AUTH_FIELD_END; nIndex++)
1905 const TextInfo& rCurInfo = aTextInfoArr[nIndex];
1906 if (rCurInfo.nToxField == AUTH_FIELD_LOCAL_URL && &rButton == m_xLocalBrowseButton.get())
1908 m_pEdits[nIndex]->set_text(aPath);
1909 break;
1914 IMPL_LINK(SwCreateAuthEntryDlg_Impl, PageNumHdl, weld::Toggleable&, rPageCB, void)
1916 if (rPageCB.get_active())
1918 m_xLocalPageSB->set_sensitive(true);
1919 m_xLocalPageSB->set_value(1);
1921 else
1923 m_xLocalPageSB->set_sensitive(false);
1927 SwAuthMarkFloatDlg::SwAuthMarkFloatDlg(SfxBindings* _pBindings,
1928 SfxChildWindow* pChild,
1929 weld::Window *pParent,
1930 SfxChildWinInfo const * pInfo,
1931 bool bNew)
1932 : SfxModelessDialogController(_pBindings, pChild, pParent,
1933 u"modules/swriter/ui/bibliographyentry.ui"_ustr, u"BibliographyEntryDialog"_ustr)
1934 , m_aContent(*this, *m_xBuilder, bNew)
1936 Initialize(pInfo);
1937 if (SwWrtShell* pWrtShell = ::GetActiveWrtShell())
1938 m_aContent.ReInitDlg(*pWrtShell);
1941 void SwAuthMarkFloatDlg::Activate()
1943 SfxModelessDialogController::Activate();
1944 m_aContent.Activate();
1947 void SwAuthMarkFloatDlg::ReInitDlg(SwWrtShell& rWrtShell)
1949 m_aContent.ReInitDlg( rWrtShell );
1952 SwAuthMarkModalDlg::SwAuthMarkModalDlg(weld::Window *pParent, SwWrtShell& rSh)
1953 : SfxDialogController(pParent, u"modules/swriter/ui/bibliographyentry.ui"_ustr,
1954 u"BibliographyEntryDialog"_ustr)
1955 , m_aContent(*this, *m_xBuilder, false)
1957 m_aContent.ReInitDlg(rSh);
1960 short SwAuthMarkModalDlg::run()
1962 short ret = SfxDialogController::run();
1963 if (ret == RET_OK)
1964 Apply();
1965 return ret;
1968 void SwAuthMarkModalDlg::Apply()
1970 m_aContent.InsertHdl(*m_aContent.m_xActionBT);
1973 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */