1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
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 <vcl/svapp.hxx>
35 #include <vcl/weld.hxx>
36 #include <sfx2/dispatch.hxx>
37 #include <sfx2/viewfrm.hxx>
38 #include <svl/itemset.hxx>
39 #include <editeng/langitem.hxx>
40 #include <osl/diagnose.h>
41 #include <swtypes.hxx>
42 #include <toxmgr.hxx>
43 #include <txttxmrk.hxx>
44 #include <wrtsh.hxx>
45 #include <view.hxx>
46 #include <swundo.hxx>
47 #include <cmdid.h>
48 #include <swmodule.hxx>
49 #include <fldmgr.hxx>
50 #include <fldbas.hxx>
51 #include <strings.hrc>
52 #include <svl/cjkoptions.hxx>
53 #include <comphelper/fileurl.hxx>
54 #include <sfx2/filedlghelper.hxx>
55 #include <ndtxt.hxx>
56 #include <SwRewriter.hxx>
57 #include <doc.hxx>
58 #include <docsh.hxx>
59 
60 #define POS_CONTENT 0
61 #define POS_INDEX   1
62 
63 static sal_Int32  nTypePos = 1; // TOX_INDEX as standard
64 static sal_uInt16 nKey1Pos = USHRT_MAX;
65 
66 static sal_uInt16 nKey2Pos = USHRT_MAX;
67 
68 using namespace com::sun::star;
69 using namespace com::sun::star::i18n;
70 using namespace com::sun::star::lang;
71 using namespace com::sun::star::util;
72 using namespace ::comphelper;
73 
74 namespace
75 {
SplitUrlAndPage(const OUString & rText,OUString & rUrl,int & nPageNumber)76 bool SplitUrlAndPage(const OUString& rText, OUString& rUrl, int& nPageNumber)
77 {
78     uno::Reference<uri::XUriReferenceFactory> xUriReferenceFactory
79         = uri::UriReferenceFactory::create(comphelper::getProcessComponentContext());
80     uno::Reference<uri::XUriReference> xUriRef;
81     try
82     {
83         xUriRef = xUriReferenceFactory->parse(rText);
84     }
85     catch (const uno::Exception& rException)
86     {
87         SAL_WARN("sw.ui", "SplitUrlAndPage: failed to parse url: " << rException.Message);
88         return false;
89     }
90 
91     OUString aPagePrefix("page=");
92     if (!xUriRef->getFragment().startsWith(aPagePrefix))
93     {
94         return false;
95     }
96 
97     nPageNumber = xUriRef->getFragment().copy(aPagePrefix.getLength()).toInt32();
98     xUriRef->clearFragment();
99     rUrl = xUriRef->getUriReference();
100     return true;
101 }
102 
MergeUrlAndPage(const OUString & rUrl,const std::unique_ptr<weld::SpinButton> & xPageSB)103 OUString MergeUrlAndPage(const OUString& rUrl, const std::unique_ptr<weld::SpinButton>& xPageSB)
104 {
105     if (!xPageSB->get_sensitive())
106     {
107         return rUrl;
108     }
109 
110     uno::Reference<uri::XUriReferenceFactory> xUriReferenceFactory
111         = uri::UriReferenceFactory::create(comphelper::getProcessComponentContext());
112     uno::Reference<uri::XUriReference> xUriRef;
113     try
114     {
115         xUriRef = xUriReferenceFactory->parse(rUrl);
116     }
117     catch (const uno::Exception& rException)
118     {
119         SAL_WARN("sw.ui", "MergeUrlAndPage: failed to parse url: " << rException.Message);
120         return rUrl;
121     }
122 
123     OUString aFragment("page=" + OUString::number(xPageSB->get_value()));
124     xUriRef->setFragment(aFragment);
125     return xUriRef->getUriReference();
126 }
127 }
128 
129 // dialog to insert a directory selection
SwIndexMarkPane(const std::shared_ptr<weld::Dialog> & rDialog,weld::Builder & rBuilder,bool bNewDlg,SwWrtShell * pWrtShell)130 SwIndexMarkPane::SwIndexMarkPane(const std::shared_ptr<weld::Dialog>& rDialog, weld::Builder& rBuilder, bool bNewDlg,
131     SwWrtShell* pWrtShell)
132     : m_xDialog(rDialog)
133     , m_bDel(false)
134     , m_bNewMark(bNewDlg)
135     , m_bSelected(false)
136     , m_bPhoneticED0_ChangedByUser(false)
137     , m_bPhoneticED1_ChangedByUser(false)
138     , m_bPhoneticED2_ChangedByUser(false)
139     , m_nLangForPhoneticReading(LANGUAGE_CHINESE_SIMPLIFIED)
140     , m_bIsPhoneticReadingEnabled(false)
141     , m_pSh(pWrtShell)
142     , m_xTypeFT(rBuilder.weld_label("typeft"))
143     , m_xTypeDCB(rBuilder.weld_combo_box("typecb"))
144     , m_xNewBT(rBuilder.weld_button("new"))
145     , m_xEntryED(rBuilder.weld_entry("entryed"))
146     , m_xSyncED(rBuilder.weld_button("sync"))
147     , m_xPhoneticFT0(rBuilder.weld_label("phonetic0ft"))
148     , m_xPhoneticED0(rBuilder.weld_entry("phonetic0ed"))
149     , m_xKey1FT(rBuilder.weld_label("key1ft"))
150     , m_xKey1DCB(rBuilder.weld_combo_box("key1cb"))
151     , m_xPhoneticFT1(rBuilder.weld_label("phonetic1ft"))
152     , m_xPhoneticED1(rBuilder.weld_entry("phonetic1ed"))
153     , m_xKey2FT(rBuilder.weld_label("key2ft"))
154     , m_xKey2DCB(rBuilder.weld_combo_box("key2cb"))
155     , m_xPhoneticFT2(rBuilder.weld_label("phonetic2ft"))
156     , m_xPhoneticED2(rBuilder.weld_entry("phonetic2ed"))
157     , m_xLevelFT(rBuilder.weld_label("levelft"))
158     , m_xLevelNF(rBuilder.weld_spin_button("levelnf"))
159     , m_xMainEntryCB(rBuilder.weld_check_button("mainentrycb"))
160     , m_xApplyToAllCB(rBuilder.weld_check_button("applytoallcb"))
161     , m_xSearchCaseSensitiveCB(rBuilder.weld_check_button("searchcasesensitivecb"))
162     , m_xSearchCaseWordOnlyCB(rBuilder.weld_check_button("searchcasewordonlycb"))
163     , m_xOKBT(bNewDlg ? rBuilder.weld_button("insert") : rBuilder.weld_button("ok"))
164     , m_xCloseBT(rBuilder.weld_button("close"))
165     , m_xDelBT(rBuilder.weld_button("delete"))
166     , m_xPrevSameBT(rBuilder.weld_button("first"))
167     , m_xNextSameBT(rBuilder.weld_button("last"))
168     , m_xPrevBT(rBuilder.weld_button("previous"))
169     , m_xNextBT(rBuilder.weld_button("next"))
170 {
171     m_xSyncED->show();
172 
173     if (SvtCJKOptions().IsCJKFontEnabled())
174     {
175         uno::Reference< uno::XComponentContext > xContext = getProcessComponentContext();
176 
177         m_xExtendedIndexEntrySupplier = i18n::IndexEntrySupplier::create(xContext);
178 
179         m_xPhoneticFT0->show();
180         m_xPhoneticED0->show();
181         m_xPhoneticFT1->show();
182         m_xPhoneticED1->show();
183         m_xPhoneticFT2->show();
184         m_xPhoneticED2->show();
185     }
186 
187     // tdf#129726 there are two help pages for this dialog, one for each mode,
188     // where a widget/dialog appears in both, use -insert/-edit to disambiguate
189     if (m_bNewMark)
190     {
191         m_xDialog->set_title(SwResId(STR_IDXMRK_INSERT));
192         m_xDialog->set_help_id(m_xDialog->get_help_id() + "-insert");
193         m_xTypeDCB->set_help_id(m_xTypeDCB->get_help_id() + "-insert");
194     }
195     else
196     {
197         m_xDialog->set_title(SwResId(STR_IDXMRK_EDIT));
198         m_xDialog->set_help_id(m_xDialog->get_help_id() + "-edit");
199         m_xTypeDCB->set_help_id(m_xTypeDCB->get_help_id() + "-edit");
200     }
201 
202     m_xDelBT->connect_clicked(LINK(this,SwIndexMarkPane,        DelHdl));
203     m_xPrevBT->connect_clicked(LINK(this,SwIndexMarkPane,       PrevHdl));
204     m_xPrevSameBT->connect_clicked(LINK(this,SwIndexMarkPane,   PrevSameHdl));
205     m_xNextBT->connect_clicked(LINK(this,SwIndexMarkPane,       NextHdl));
206     m_xNextSameBT->connect_clicked(LINK(this,SwIndexMarkPane,   NextSameHdl));
207     m_xTypeDCB->connect_changed(LINK(this,SwIndexMarkPane,     ModifyListBoxHdl));
208     m_xKey1DCB->connect_changed(LINK(this,SwIndexMarkPane,      KeyDCBModifyHdl));
209     m_xKey2DCB->connect_changed(LINK(this,SwIndexMarkPane,     KeyDCBModifyHdl));
210     m_xCloseBT->connect_clicked(LINK(this,SwIndexMarkPane,      CloseHdl));
211     m_xEntryED->connect_changed(LINK(this,SwIndexMarkPane,     ModifyEditHdl));
212     m_xNewBT->connect_clicked(LINK(this, SwIndexMarkPane,       NewUserIdxHdl));
213     m_xApplyToAllCB->connect_toggled(LINK(this, SwIndexMarkPane, SearchTypeHdl));
214     m_xPhoneticED0->connect_changed(LINK(this,SwIndexMarkPane, PhoneticEDModifyHdl));
215     m_xPhoneticED1->connect_changed(LINK(this,SwIndexMarkPane, PhoneticEDModifyHdl));
216     m_xPhoneticED2->connect_changed(LINK(this,SwIndexMarkPane, PhoneticEDModifyHdl));
217     m_xSyncED->connect_clicked(LINK(this, SwIndexMarkPane, SyncSelectionHdl));
218 
219     if (m_bNewMark)
220         m_xDelBT->hide();
221     else
222         m_xNewBT->hide();
223     m_xOKBT->show();
224     m_xOKBT->connect_clicked(LINK(this, SwIndexMarkPane, InsertHdl));
225 
226     m_xEntryED->grab_focus();
227 }
228 
229 // Newly initialise controls with the new selection
InitControls()230 void SwIndexMarkPane::InitControls()
231 {
232     assert(m_pSh && m_pTOXMgr && "no shell?");
233     // contents index
234     const SwTOXType* pType = m_pTOXMgr->GetTOXType(TOX_CONTENT);
235     assert(pType && "No directory type !!");
236     OUString sTmpTypeSelection;
237     if (m_xTypeDCB->get_active() != -1)
238         sTmpTypeSelection = m_xTypeDCB->get_active_text();
239     m_xTypeDCB->clear();
240     m_xTypeDCB->append_text(pType->GetTypeName());
241 
242     // keyword index
243     pType = m_pTOXMgr->GetTOXType(TOX_INDEX);
244     assert(pType && "No directory type !!");
245     m_xTypeDCB->append_text(pType->GetTypeName());
246 
247     // user index
248     sal_uInt16 nCount = m_pSh->GetTOXTypeCount(TOX_USER);
249     for (sal_uInt16 i = 0; i < nCount; ++i)
250         m_xTypeDCB->append_text(m_pSh->GetTOXType(TOX_USER, i)->GetTypeName());
251 
252     // read keywords primary
253     {
254         std::vector<OUString> aArr;
255         m_pSh->GetTOIKeys(TOI_PRIMARY, aArr);
256         std::sort(aArr.begin(), aArr.end());
257         auto last = std::unique(aArr.begin(), aArr.end());
258         for (auto it = aArr.begin(); it != last; ++it)
259             m_xKey1DCB->append_text(*it);
260     }
261 
262     // read keywords secondary
263     {
264         std::vector<OUString> aArr;
265         m_pSh->GetTOIKeys( TOI_SECONDARY, aArr );
266         std::sort(aArr.begin(), aArr.end());
267         auto last = std::unique(aArr.begin(), aArr.end());
268         for (auto it = aArr.begin(); it != last; ++it)
269             m_xKey2DCB->append_text(*it);
270     }
271 
272     UpdateLanguageDependenciesForPhoneticReading();
273 
274     // current entry
275     const SwTOXMark* pMark = m_pTOXMgr->GetCurTOXMark();
276     if( pMark && !m_bNewMark)
277     {
278         // Controls-Handling
279 
280         // only if there are more than one
281         // if equal it lands at the same entry
282         m_pSh->SttCursorMove();
283 
284         const SwTOXMark* pMoveMark;
285         bool bShow = false;
286 
287         pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_PRV );
288         if( pMoveMark != pMark )
289         {
290             m_pSh->GotoTOXMark( *pMoveMark, TOX_NXT );
291             bShow = true;
292         }
293         m_xPrevBT->set_sensitive(pMoveMark != pMark);
294         pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_NXT );
295         if( pMoveMark != pMark )
296         {
297             m_pSh->GotoTOXMark( *pMoveMark, TOX_PRV );
298             bShow = true;
299         }
300         m_xNextBT->set_sensitive(pMoveMark != pMark);
301         if( bShow )
302         {
303             m_xPrevBT->show();
304             m_xNextBT->show();
305             bShow = false;
306         }
307 
308         pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_SAME_PRV );
309         if( pMoveMark != pMark )
310         {
311             m_pSh->GotoTOXMark( *pMoveMark, TOX_SAME_NXT );
312             bShow = true;
313         }
314         m_xPrevSameBT->set_sensitive(pMoveMark != pMark);
315         pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_SAME_NXT );
316         if( pMoveMark != pMark )
317         {
318             m_pSh->GotoTOXMark( *pMoveMark, TOX_SAME_PRV );
319             bShow = true;
320         }
321         m_xNextSameBT->set_sensitive(pMoveMark != pMark);
322         if( bShow )
323         {
324             m_xNextSameBT->show();
325             m_xPrevSameBT->show();
326         }
327         m_pSh->EndCursorMove();
328 
329         m_xTypeFT->show();
330 
331         m_xTypeDCB->set_sensitive(false);
332         m_xTypeFT->set_sensitive(false);
333 
334         UpdateDialog();
335     }
336     else
337     {   // display current selection (first element) ????
338         if (m_pSh->GetCursorCnt() < 2)
339         {
340             m_bSelected = !m_pSh->HasSelection();
341             m_aOrgStr = m_pSh->GetView().GetSelectionTextParam(true, false);
342             m_xEntryED->set_text(m_aOrgStr);
343 
344             //to include all equal entries may only be allowed in the body and even there
345             //only when a simple selection exists
346             const FrameTypeFlags nFrameType = m_pSh->GetFrameType(nullptr,true);
347             m_xApplyToAllCB->show();
348             m_xSearchCaseSensitiveCB->show();
349             m_xSearchCaseWordOnlyCB->show();
350             m_xApplyToAllCB->set_sensitive(!m_aOrgStr.isEmpty() &&
351                 !(nFrameType & ( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER | FrameTypeFlags::FLY_ANY )));
352             SearchTypeHdl(*m_xApplyToAllCB);
353         }
354 
355         // index type is default
356         if (!sTmpTypeSelection.isEmpty() && m_xTypeDCB->find_text(sTmpTypeSelection) != -1)
357             m_xTypeDCB->set_active_text(sTmpTypeSelection);
358         else
359             m_xTypeDCB->set_active_text(m_xTypeDCB->get_text(nTypePos));
360         ModifyHdl(*m_xTypeDCB);
361     }
362 }
363 
UpdateLanguageDependenciesForPhoneticReading()364 void    SwIndexMarkPane::UpdateLanguageDependenciesForPhoneticReading()
365 {
366     //no phonetic reading if no global cjk support
367     if( !m_xExtendedIndexEntrySupplier.is() )
368     {
369         m_bIsPhoneticReadingEnabled = false;
370         return;
371     }
372     m_bIsPhoneticReadingEnabled = true;
373 
374     //get the current language
375     if(!m_bNewMark) //if dialog is opened to iterate existing marks
376     {
377         OSL_ENSURE(m_pTOXMgr, "need TOXMgr");
378         if(!m_pTOXMgr)
379             return;
380         SwTOXMark* pMark = m_pTOXMgr->GetCurTOXMark();
381         OSL_ENSURE(pMark, "need current SwTOXMark");
382         if(!pMark)
383             return;
384         SwTextTOXMark* pTextTOXMark = pMark->GetTextTOXMark();
385         OSL_ENSURE(pTextTOXMark, "need current SwTextTOXMark");
386         if(!pTextTOXMark)
387             return;
388         const SwTextNode* pTextNode = pTextTOXMark->GetpTextNd();
389         OSL_ENSURE(pTextNode, "need current SwTextNode");
390         if(!pTextNode)
391             return;
392         sal_Int32 nTextIndex = pTextTOXMark->GetStart();
393         m_nLangForPhoneticReading = pTextNode->GetLang( nTextIndex );
394     }
395     else //if dialog is opened to create a new mark
396     {
397         sal_uInt16 nWhich;
398         switch(m_pSh->GetScriptType())
399         {
400             case SvtScriptType::ASIAN: nWhich = RES_CHRATR_CJK_LANGUAGE; break;
401             case SvtScriptType::COMPLEX:nWhich = RES_CHRATR_CTL_LANGUAGE; break;
402             default:nWhich = RES_CHRATR_LANGUAGE; break;
403         }
404         SfxItemSet aLangSet(m_pSh->GetAttrPool(), {{nWhich, nWhich}});
405         m_pSh->GetCurAttr(aLangSet);
406         m_nLangForPhoneticReading = static_cast<const SvxLanguageItem&>(aLangSet.Get(nWhich)).GetLanguage();
407     }
408 
409 }
410 
GetDefaultPhoneticReading(const OUString & rText)411 OUString SwIndexMarkPane::GetDefaultPhoneticReading( const OUString& rText )
412 {
413     if( !m_bIsPhoneticReadingEnabled )
414         return OUString();
415 
416     return m_xExtendedIndexEntrySupplier->getPhoneticCandidate(rText, LanguageTag::convertToLocale( m_nLangForPhoneticReading ));
417 }
418 
Activate()419 void    SwIndexMarkPane::Activate()
420 {
421     // display current selection (first element) ????
422     if (m_bNewMark)
423     {
424         m_xSyncED->set_sensitive(m_pSh->GetCursorCnt() < 2);
425     }
426 }
427 
IMPL_LINK_NOARG(SwIndexMarkPane,SyncSelectionHdl,weld::Button &,void)428 IMPL_LINK_NOARG(SwIndexMarkPane, SyncSelectionHdl, weld::Button&, void)
429 {
430     m_bSelected = !m_pSh->HasSelection();
431     m_aOrgStr = m_pSh->GetView().GetSelectionTextParam(true, false);
432     m_xEntryED->set_text(m_aOrgStr);
433 
434     //to include all equal entries may only be allowed in the body and even there
435     //only when a simple selection exists
436     const FrameTypeFlags nFrameType = m_pSh->GetFrameType(nullptr,true);
437     m_xApplyToAllCB->show();
438     m_xSearchCaseSensitiveCB->show();
439     m_xSearchCaseWordOnlyCB->show();
440     m_xApplyToAllCB->set_sensitive(!m_aOrgStr.isEmpty() &&
441         !(nFrameType & ( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER | FrameTypeFlags::FLY_ANY )));
442     SearchTypeHdl(*m_xApplyToAllCB);
443     ModifyHdl(*m_xEntryED);
444 }
445 
446 // evaluate Ok-Button
Apply()447 void SwIndexMarkPane::Apply()
448 {
449     InsertUpdate();
450     if(m_bSelected)
451         m_pSh->ResetSelect(nullptr, false);
452 }
453 
454 // apply changes
InsertUpdate()455 void SwIndexMarkPane::InsertUpdate()
456 {
457     m_pSh->StartUndo(m_bDel ? SwUndoId::INDEX_ENTRY_DELETE : SwUndoId::INDEX_ENTRY_INSERT);
458     m_pSh->StartAllAction();
459     SwRewriter aRewriter;
460 
461     if( m_bNewMark )
462     {
463         InsertMark();
464 
465         if ( m_pTOXMgr->GetCurTOXMark())
466             aRewriter.AddRule(UndoArg1,
467                     m_pTOXMgr->GetCurTOXMark()->GetText(m_pSh->GetLayout()));
468     }
469     else if( !m_pSh->HasReadonlySel() )
470     {
471         if ( m_pTOXMgr->GetCurTOXMark())
472             aRewriter.AddRule(UndoArg1,
473                     m_pTOXMgr->GetCurTOXMark()->GetText(m_pSh->GetLayout()));
474 
475         if( m_bDel )
476             m_pTOXMgr->DeleteTOXMark();
477         else if( m_pTOXMgr->GetCurTOXMark() )
478             UpdateMark();
479     }
480 
481     m_pSh->EndAllAction();
482     m_pSh->EndUndo(m_bDel ? SwUndoId::INDEX_ENTRY_DELETE : SwUndoId::INDEX_ENTRY_INSERT);
483 
484     nTypePos = m_xTypeDCB->find_text(m_xTypeDCB->get_active_text());
485     if(nTypePos == -1)
486         nTypePos = 0;
487 
488     nKey1Pos = m_xKey1DCB->find_text(m_xKey1DCB->get_active_text());
489     nKey2Pos = m_xKey2DCB->find_text(m_xKey2DCB->get_active_text());
490 }
491 
492 // insert mark
lcl_SelectSameStrings(SwWrtShell & rSh,bool bWordOnly,bool bCaseSensitive)493 static void lcl_SelectSameStrings(SwWrtShell& rSh, bool bWordOnly, bool bCaseSensitive)
494 {
495     rSh.Push();
496 
497     i18nutil::SearchOptions2 aSearchOpt(
498                         SearchAlgorithms_ABSOLUTE,
499                         ( bWordOnly ? SearchFlags::NORM_WORD_ONLY : 0 ),
500                         rSh.GetSelText(), OUString(),
501                         GetAppLanguageTag().getLocale(),
502                         0, 0, 0,
503                         (bCaseSensitive
504                             ? TransliterationFlags::NONE
505                             : TransliterationFlags::IGNORE_CASE),
506                         SearchAlgorithms2::ABSOLUTE,
507                         '\\' );
508 
509     rSh.ClearMark();
510     bool bCancel;
511 
512     //todo/mba: assuming that notes should not be searched
513     rSh.Find_Text(aSearchOpt, false/*bSearchInNotes*/, SwDocPositions::Start, SwDocPositions::End, bCancel,
514               FindRanges::InSelAll | FindRanges::InBodyOnly );
515 }
516 
InsertMark()517 void SwIndexMarkPane::InsertMark()
518 {
519     auto nPos = m_xTypeDCB->find_text(m_xTypeDCB->get_active_text());
520     TOXTypes eType = nPos == POS_CONTENT ? TOX_CONTENT :
521                         nPos == POS_INDEX ? TOX_INDEX : TOX_USER;
522 
523     SwTOXMarkDescription aDesc(eType);
524 
525     const int nLevel = m_xLevelNF->denormalize(m_xLevelNF->get_value());
526     switch( nPos)
527     {
528         case POS_CONTENT : break;
529         case POS_INDEX:     // keyword index mark
530         {
531             UpdateKeyBoxes();
532             aDesc.SetPrimKey(m_xKey1DCB->get_active_text());
533             aDesc.SetSecKey(m_xKey2DCB->get_active_text());
534             aDesc.SetMainEntry(m_xMainEntryCB->get_active());
535             aDesc.SetPhoneticReadingOfAltStr(m_xPhoneticED0->get_text());
536             aDesc.SetPhoneticReadingOfPrimKey(m_xPhoneticED1->get_text());
537             aDesc.SetPhoneticReadingOfSecKey(m_xPhoneticED2->get_text());
538         }
539         break;
540         default:            // Userdefined index mark
541         {
542             aDesc.SetTOUName(m_xTypeDCB->get_active_text());
543         }
544     }
545     if (m_aOrgStr != m_xEntryED->get_text())
546         aDesc.SetAltStr(m_xEntryED->get_text());
547     bool bApplyAll = m_xApplyToAllCB->get_active();
548     bool bWordOnly = m_xSearchCaseWordOnlyCB->get_active();
549     bool bCaseSensitive = m_xSearchCaseSensitiveCB->get_active();
550 
551     m_pSh->StartAllAction();
552     // all equal strings have to be selected here so that the
553     // entry is applied to all equal strings
554     if(bApplyAll)
555     {
556         lcl_SelectSameStrings(*m_pSh, bWordOnly, bCaseSensitive);
557     }
558     aDesc.SetLevel(nLevel);
559     SwTOXMgr aMgr(m_pSh);
560     aMgr.InsertTOXMark(aDesc);
561     if(bApplyAll)
562         m_pSh->Pop(SwCursorShell::PopMode::DeleteCurrent);
563 
564     m_pSh->EndAllAction();
565 }
566 
567 // update mark
UpdateMark()568 void SwIndexMarkPane::UpdateMark()
569 {
570     OUString  aAltText(m_xEntryED->get_text());
571     OUString* pAltText = m_aOrgStr != m_xEntryED->get_text() ? &aAltText : nullptr;
572     //empty alternative texts are not allowed
573     if(pAltText && pAltText->isEmpty())
574         return;
575 
576     UpdateKeyBoxes();
577 
578     auto nPos = m_xTypeDCB->find_text(m_xTypeDCB->get_active_text());
579     TOXTypes eType = TOX_USER;
580     if(POS_CONTENT == nPos)
581         eType = TOX_CONTENT;
582     else if(POS_INDEX == nPos)
583         eType = TOX_INDEX;
584 
585     SwTOXMarkDescription aDesc(eType);
586     aDesc.SetLevel(m_xLevelNF->get_value());
587     if(pAltText)
588         aDesc.SetAltStr(*pAltText);
589 
590     OUString  aPrim(m_xKey1DCB->get_active_text());
591     if(!aPrim.isEmpty())
592         aDesc.SetPrimKey(aPrim);
593     OUString  aSec(m_xKey2DCB->get_active_text());
594     if(!aSec.isEmpty())
595         aDesc.SetSecKey(aSec);
596 
597     if(eType == TOX_INDEX)
598     {
599         aDesc.SetPhoneticReadingOfAltStr(m_xPhoneticED0->get_text());
600         aDesc.SetPhoneticReadingOfPrimKey(m_xPhoneticED1->get_text());
601         aDesc.SetPhoneticReadingOfSecKey(m_xPhoneticED2->get_text());
602     }
603     aDesc.SetMainEntry(m_xMainEntryCB->get_visible() && m_xMainEntryCB->get_active());
604     m_pTOXMgr->UpdateTOXMark(aDesc);
605 }
606 
607 // insert new keys
UpdateKeyBoxes()608 void SwIndexMarkPane::UpdateKeyBoxes()
609 {
610     OUString aKey(m_xKey1DCB->get_active_text());
611     auto nPos = m_xKey1DCB->find_text(aKey);
612     if(nPos == -1 && !aKey.isEmpty())
613     {   // create new key
614         m_xKey1DCB->append_text(aKey);
615     }
616 
617     aKey = m_xKey2DCB->get_active_text();
618     nPos = m_xKey2DCB->find_text(aKey);
619 
620     if(nPos == -1 && !aKey.isEmpty())
621     {   // create new key
622         m_xKey2DCB->append_text(aKey);
623     }
624 }
625 
626 namespace {
627 
628 class SwNewUserIdxDlg : public weld::GenericDialogController
629 {
630     SwIndexMarkPane* m_pDlg;
631 
632     std::unique_ptr<weld::Button> m_xOKPB;
633     std::unique_ptr<weld::Entry> m_xNameED;
634 
635     DECL_LINK(ModifyHdl, weld::Entry&, void);
636 
637 public:
SwNewUserIdxDlg(SwIndexMarkPane * pPane,weld::Window * pParent)638     explicit SwNewUserIdxDlg(SwIndexMarkPane* pPane, weld::Window* pParent)
639         : GenericDialogController(pParent, "modules/swriter/ui/newuserindexdialog.ui", "NewUserIndexDialog")
640         , m_pDlg(pPane)
641         , m_xOKPB(m_xBuilder->weld_button("ok"))
642         , m_xNameED(m_xBuilder->weld_entry("entry"))
643     {
644         m_xNameED->connect_changed(LINK(this, SwNewUserIdxDlg, ModifyHdl));
645         m_xOKPB->set_sensitive(false);
646         m_xNameED->grab_focus();
647     }
GetName() const648     OUString GetName() const { return m_xNameED->get_text(); }
649 };
650 
651 }
652 
IMPL_LINK(SwNewUserIdxDlg,ModifyHdl,weld::Entry &,rEdit,void)653 IMPL_LINK( SwNewUserIdxDlg, ModifyHdl, weld::Entry&, rEdit, void)
654 {
655     m_xOKPB->set_sensitive(!rEdit.get_text().isEmpty() && !m_pDlg->IsTOXType(rEdit.get_text()));
656 }
657 
IMPL_LINK_NOARG(SwIndexMarkPane,NewUserIdxHdl,weld::Button &,void)658 IMPL_LINK_NOARG(SwIndexMarkPane, NewUserIdxHdl, weld::Button&, void)
659 {
660     SwNewUserIdxDlg aDlg(this, m_xDialog.get());
661     if (aDlg.run() == RET_OK)
662     {
663         OUString sNewName(aDlg.GetName());
664         m_xTypeDCB->append_text(sNewName);
665         m_xTypeDCB->set_active_text(sNewName);
666     }
667 }
668 
IMPL_LINK(SwIndexMarkPane,SearchTypeHdl,weld::Toggleable &,rBox,void)669 IMPL_LINK( SwIndexMarkPane, SearchTypeHdl, weld::Toggleable&, rBox, void)
670 {
671     const bool bEnable = rBox.get_active() && rBox.get_sensitive();
672     m_xSearchCaseWordOnlyCB->set_sensitive(bEnable);
673     m_xSearchCaseSensitiveCB->set_sensitive(bEnable);
674 }
675 
IMPL_LINK(SwIndexMarkPane,InsertHdl,weld::Button &,rButton,void)676 IMPL_LINK(SwIndexMarkPane, InsertHdl, weld::Button&, rButton, void)
677 {
678     Apply();
679     //close the dialog if only one entry is available
680     if(!m_bNewMark && !m_xPrevBT->get_visible() && !m_xNextBT->get_visible())
681         CloseHdl(rButton);
682 }
683 
IMPL_LINK_NOARG(SwIndexMarkPane,CloseHdl,weld::Button &,void)684 IMPL_LINK_NOARG(SwIndexMarkPane, CloseHdl, weld::Button&, void)
685 {
686     if (m_bNewMark)
687     {
688         SfxViewFrame::Current()->GetDispatcher()->Execute(FN_INSERT_IDX_ENTRY_DLG,
689                     SfxCallMode::ASYNCHRON|SfxCallMode::RECORD);
690     }
691     else
692     {
693         m_xDialog->response(RET_CLOSE);
694     }
695 }
696 
697 // select index type only when inserting
IMPL_LINK(SwIndexMarkPane,ModifyListBoxHdl,weld::ComboBox &,rBox,void)698 IMPL_LINK(SwIndexMarkPane, ModifyListBoxHdl, weld::ComboBox&, rBox, void)
699 {
700     ModifyHdl(rBox);
701 }
702 
IMPL_LINK(SwIndexMarkPane,ModifyEditHdl,weld::Entry &,rEdit,void)703 IMPL_LINK(SwIndexMarkPane, ModifyEditHdl, weld::Entry&, rEdit, void)
704 {
705     ModifyHdl(rEdit);
706 }
707 
ModifyHdl(const weld::Widget & rBox)708 void SwIndexMarkPane::ModifyHdl(const weld::Widget& rBox)
709 {
710     if (m_xTypeDCB.get() == &rBox)
711     {
712         // set index type
713         auto nPos = m_xTypeDCB->find_text(m_xTypeDCB->get_active_text());
714         bool bLevelEnable = false,
715              bKeyEnable   = false,
716              bSetKey2     = false,
717              bKey2Enable  = false,
718              bEntryHasText   = false,
719              bKey1HasText    = false,
720              bKey2HasText    = false;
721         if(nPos == POS_INDEX)
722         {
723             if (!m_xEntryED->get_text().isEmpty())
724                 bEntryHasText = true;
725             m_xPhoneticED0->set_text(GetDefaultPhoneticReading(m_xEntryED->get_text()));
726 
727             bKeyEnable = true;
728             m_xKey1DCB->set_active_text(m_xKey1DCB->get_text(nKey1Pos));
729             m_xPhoneticED1->set_text(GetDefaultPhoneticReading(m_xKey1DCB->get_active_text()));
730             if (!m_xKey1DCB->get_active_text().isEmpty())
731             {
732                 bKey1HasText = bSetKey2 = bKey2Enable = true;
733                 m_xKey2DCB->set_active_text(m_xKey2DCB->get_text(nKey2Pos));
734                 m_xPhoneticED2->set_text(GetDefaultPhoneticReading(m_xKey2DCB->get_active_text()));
735                 if(!m_xKey2DCB->get_active_text().isEmpty())
736                     bKey2HasText = true;
737             }
738         }
739         else
740         {
741             bLevelEnable = true;
742             m_xLevelNF->set_max(MAXLEVEL);
743             m_xLevelNF->set_value(m_xLevelNF->normalize(0));
744             bSetKey2 = true;
745         }
746         m_xLevelFT->set_visible(bLevelEnable);
747         m_xLevelNF->set_visible(bLevelEnable);
748         m_xMainEntryCB->set_visible(nPos == POS_INDEX);
749 
750         m_xKey1FT->set_sensitive(bKeyEnable);
751         m_xKey1DCB->set_sensitive(bKeyEnable);
752         if ( bSetKey2 )
753         {
754             m_xKey2DCB->set_sensitive(bKey2Enable);
755             m_xKey2FT->set_sensitive(bKey2Enable);
756         }
757         m_xPhoneticFT0->set_sensitive(bKeyEnable&&bEntryHasText&&m_bIsPhoneticReadingEnabled);
758         m_xPhoneticED0->set_sensitive(bKeyEnable&&bEntryHasText&&m_bIsPhoneticReadingEnabled);
759         m_xPhoneticFT1->set_sensitive(bKeyEnable&&bKey1HasText&&m_bIsPhoneticReadingEnabled);
760         m_xPhoneticED1->set_sensitive(bKeyEnable&&bKey1HasText&&m_bIsPhoneticReadingEnabled);
761         m_xPhoneticFT2->set_sensitive(bKeyEnable&&bKey2HasText&&m_bIsPhoneticReadingEnabled);
762         m_xPhoneticED2->set_sensitive(bKeyEnable&&bKey2HasText&&m_bIsPhoneticReadingEnabled);
763     }
764     else //m_xEntryED  !!m_xEntryED is not a ListBox but an Edit
765     {
766         bool bHasText = !m_xEntryED->get_text().isEmpty();
767         if(!bHasText)
768         {
769             m_xPhoneticED0->set_text(OUString());
770             m_bPhoneticED0_ChangedByUser = false;
771         }
772         else if(!m_bPhoneticED0_ChangedByUser)
773             m_xPhoneticED0->set_text(GetDefaultPhoneticReading(m_xEntryED->get_text()));
774 
775         m_xPhoneticFT0->set_sensitive(bHasText&&m_bIsPhoneticReadingEnabled);
776         m_xPhoneticED0->set_sensitive(bHasText&&m_bIsPhoneticReadingEnabled);
777     }
778     m_xOKBT->set_sensitive(!m_pSh->HasReadonlySel() &&
779         (!m_xEntryED->get_text().isEmpty() || m_pSh->GetCursorCnt(false)));
780 }
781 
IMPL_LINK_NOARG(SwIndexMarkPane,NextHdl,weld::Button &,void)782 IMPL_LINK_NOARG(SwIndexMarkPane, NextHdl, weld::Button&, void)
783 {
784     InsertUpdate();
785     m_pTOXMgr->NextTOXMark();
786     UpdateDialog();
787 }
788 
IMPL_LINK_NOARG(SwIndexMarkPane,NextSameHdl,weld::Button &,void)789 IMPL_LINK_NOARG(SwIndexMarkPane, NextSameHdl, weld::Button&, void)
790 {
791     InsertUpdate();
792     m_pTOXMgr->NextTOXMark(true);
793     UpdateDialog();
794 }
795 
IMPL_LINK_NOARG(SwIndexMarkPane,PrevHdl,weld::Button &,void)796 IMPL_LINK_NOARG(SwIndexMarkPane, PrevHdl, weld::Button&, void)
797 {
798     InsertUpdate();
799     m_pTOXMgr->PrevTOXMark();
800     UpdateDialog();
801 }
802 
IMPL_LINK_NOARG(SwIndexMarkPane,PrevSameHdl,weld::Button &,void)803 IMPL_LINK_NOARG(SwIndexMarkPane, PrevSameHdl, weld::Button&, void)
804 {
805     InsertUpdate();
806     m_pTOXMgr->PrevTOXMark(true);
807     UpdateDialog();
808 }
809 
IMPL_LINK_NOARG(SwIndexMarkPane,DelHdl,weld::Button &,void)810 IMPL_LINK_NOARG(SwIndexMarkPane, DelHdl, weld::Button&, void)
811 {
812     m_bDel = true;
813     InsertUpdate();
814     m_bDel = false;
815 
816     if(m_pTOXMgr->GetCurTOXMark())
817         UpdateDialog();
818     else
819     {
820         CloseHdl(*m_xCloseBT);
821         SfxViewFrame::Current()->GetBindings().Invalidate(FN_EDIT_IDX_ENTRY_DLG);
822     }
823 }
824 
825 // renew dialog view
UpdateDialog()826 void SwIndexMarkPane::UpdateDialog()
827 {
828     OSL_ENSURE(m_pSh && m_pTOXMgr, "no shell?");
829     SwTOXMark* pMark = m_pTOXMgr->GetCurTOXMark();
830     OSL_ENSURE(pMark, "no current marker");
831     if(!pMark)
832         return;
833 
834     SwViewShell::SetCareDialog(m_xDialog);
835 
836     m_aOrgStr = pMark->GetText(m_pSh->GetLayout());
837     m_xEntryED->set_text(m_aOrgStr);
838 
839     // set index type
840     bool bLevelEnable = true,
841          bKeyEnable   = false,
842          bKey2Enable  = false,
843          bEntryHasText  = false,
844          bKey1HasText   = false,
845          bKey2HasText   = false;
846 
847     TOXTypes eCurType = pMark->GetTOXType()->GetType();
848     if(TOX_INDEX == eCurType)
849     {
850         bLevelEnable = false;
851         bKeyEnable = true;
852         bKey1HasText = bKey2Enable = !pMark->GetPrimaryKey().isEmpty();
853         bKey2HasText = !pMark->GetSecondaryKey().isEmpty();
854         bEntryHasText = !pMark->GetText(m_pSh->GetLayout()).isEmpty();
855         m_xKey1DCB->set_entry_text( pMark->GetPrimaryKey() );
856         m_xKey2DCB->set_entry_text( pMark->GetSecondaryKey() );
857         m_xPhoneticED0->set_text( pMark->GetTextReading() );
858         m_xPhoneticED1->set_text( pMark->GetPrimaryKeyReading() );
859         m_xPhoneticED2->set_text( pMark->GetSecondaryKeyReading() );
860         m_xMainEntryCB->set_active(pMark->IsMainEntry());
861     }
862     else if(TOX_CONTENT == eCurType || TOX_USER == eCurType)
863     {
864         m_xLevelNF->set_value(m_xLevelNF->normalize(pMark->GetLevel()));
865     }
866     m_xKey1FT->set_sensitive(bKeyEnable);
867     m_xKey1DCB->set_sensitive(bKeyEnable);
868     m_xLevelNF->set_max(MAXLEVEL);
869     m_xLevelFT->set_visible(bLevelEnable);
870     m_xLevelNF->set_visible(bLevelEnable);
871     m_xMainEntryCB->set_visible(!bLevelEnable);
872     m_xKey2FT->set_sensitive(bKey2Enable);
873     m_xKey2DCB->set_sensitive(bKey2Enable);
874 
875     UpdateLanguageDependenciesForPhoneticReading();
876     m_xPhoneticFT0->set_sensitive(bKeyEnable&&bEntryHasText&&m_bIsPhoneticReadingEnabled);
877     m_xPhoneticED0->set_sensitive(bKeyEnable&&bEntryHasText&&m_bIsPhoneticReadingEnabled);
878     m_xPhoneticFT1->set_sensitive(bKeyEnable&&bKey1HasText&&m_bIsPhoneticReadingEnabled);
879     m_xPhoneticED1->set_sensitive(bKeyEnable&&bKey1HasText&&m_bIsPhoneticReadingEnabled);
880     m_xPhoneticFT2->set_sensitive(bKeyEnable&&bKey2HasText&&m_bIsPhoneticReadingEnabled);
881     m_xPhoneticED2->set_sensitive(bKeyEnable&&bKey2HasText&&m_bIsPhoneticReadingEnabled);
882 
883     // set index type
884     m_xTypeDCB->set_active_text(pMark->GetTOXType()->GetTypeName());
885 
886     // set Next - Prev - Buttons
887     m_pSh->SttCursorMove();
888     if( m_xPrevBT->get_visible() )
889     {
890         const SwTOXMark* pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_PRV );
891         if( pMoveMark != pMark )
892             m_pSh->GotoTOXMark( *pMoveMark, TOX_NXT );
893         m_xPrevBT->set_sensitive( pMoveMark != pMark );
894         pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_NXT );
895         if( pMoveMark != pMark )
896             m_pSh->GotoTOXMark( *pMoveMark, TOX_PRV );
897         m_xNextBT->set_sensitive( pMoveMark != pMark );
898     }
899 
900     if (m_xPrevSameBT->get_visible())
901     {
902         const SwTOXMark* pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_SAME_PRV );
903         if( pMoveMark != pMark )
904             m_pSh->GotoTOXMark( *pMoveMark, TOX_SAME_NXT );
905         m_xPrevSameBT->set_sensitive( pMoveMark != pMark );
906         pMoveMark = &m_pSh->GotoTOXMark( *pMark, TOX_SAME_NXT );
907         if( pMoveMark != pMark )
908             m_pSh->GotoTOXMark( *pMoveMark, TOX_SAME_PRV );
909         m_xNextSameBT->set_sensitive( pMoveMark != pMark );
910     }
911 
912     const bool bEnable = !m_pSh->HasReadonlySel();
913     m_xOKBT->set_sensitive(bEnable);
914     m_xDelBT->set_sensitive(bEnable);
915     m_xEntryED->set_sensitive(bEnable);
916     m_xLevelNF->set_sensitive(bEnable);
917     m_xKey1DCB->set_sensitive(bEnable);
918     m_xKey2DCB->set_sensitive(bEnable);
919 
920     m_pSh->SelectTextAttr( RES_TXTATR_TOXMARK, pMark->GetTextTOXMark() );
921     // we need the point at the start of the attribute
922     m_pSh->SwapPam();
923 
924     m_pSh->EndCursorMove();
925 }
926 
927 // Remind whether the edit boxes for Phonetic reading are changed manually
IMPL_LINK(SwIndexMarkPane,PhoneticEDModifyHdl,weld::Entry &,rEdit,void)928 IMPL_LINK(SwIndexMarkPane, PhoneticEDModifyHdl, weld::Entry&, rEdit, void)
929 {
930     if (m_xPhoneticED0.get() == &rEdit)
931     {
932         m_bPhoneticED0_ChangedByUser = !rEdit.get_text().isEmpty();
933     }
934     else if (m_xPhoneticED1.get() == &rEdit)
935     {
936         m_bPhoneticED1_ChangedByUser = !rEdit.get_text().isEmpty();
937     }
938     else if (m_xPhoneticED2.get() == &rEdit)
939     {
940         m_bPhoneticED2_ChangedByUser = !rEdit.get_text().isEmpty();
941     }
942 }
943 
944 // Enable Disable of the 2nd key
IMPL_LINK(SwIndexMarkPane,KeyDCBModifyHdl,weld::ComboBox &,rBox,void)945 IMPL_LINK( SwIndexMarkPane, KeyDCBModifyHdl, weld::ComboBox&, rBox, void )
946 {
947     if (m_xKey1DCB.get() == &rBox)
948     {
949         bool bEnable = !rBox.get_active_text().isEmpty();
950         if(!bEnable)
951         {
952             m_xKey2DCB->set_entry_text(OUString());
953             m_xPhoneticED1->set_text(OUString());
954             m_xPhoneticED2->set_text(OUString());
955             m_bPhoneticED1_ChangedByUser = false;
956             m_bPhoneticED2_ChangedByUser = false;
957         }
958         else
959         {
960             if (rBox.get_popup_shown())
961             {
962                 //reset bPhoneticED1_ChangedByUser if a completely new string is selected
963                 m_bPhoneticED1_ChangedByUser = false;
964             }
965             if (!m_bPhoneticED1_ChangedByUser)
966                 m_xPhoneticED1->set_text(GetDefaultPhoneticReading(rBox.get_active_text()));
967         }
968         m_xKey2DCB->set_sensitive(bEnable);
969         m_xKey2FT->set_sensitive(bEnable);
970     }
971     else if (m_xKey2DCB.get() == &rBox)
972     {
973         if (rBox.get_active_text().isEmpty())
974         {
975             m_xPhoneticED2->set_text(OUString());
976             m_bPhoneticED2_ChangedByUser = false;
977         }
978         else
979         {
980             if (rBox.get_popup_shown())
981             {
982                 //reset bPhoneticED1_ChangedByUser if a completely new string is selected
983                 m_bPhoneticED2_ChangedByUser = false;
984             }
985             if(!m_bPhoneticED2_ChangedByUser)
986                 m_xPhoneticED2->set_text(GetDefaultPhoneticReading(rBox.get_active_text()));
987         }
988     }
989 
990     bool bKey1HasText = !m_xKey1DCB->get_active_text().isEmpty();
991     bool bKey2HasText = !m_xKey2DCB->get_active_text().isEmpty();
992 
993     m_xPhoneticFT1->set_sensitive(bKey1HasText && m_bIsPhoneticReadingEnabled);
994     m_xPhoneticED1->set_sensitive(bKey1HasText && m_bIsPhoneticReadingEnabled);
995     m_xPhoneticFT2->set_sensitive(bKey2HasText && m_bIsPhoneticReadingEnabled);
996     m_xPhoneticED2->set_sensitive(bKey2HasText && m_bIsPhoneticReadingEnabled);
997 }
998 
~SwIndexMarkPane()999 SwIndexMarkPane::~SwIndexMarkPane()
1000 {
1001 }
1002 
ReInitDlg(SwWrtShell & rWrtShell,SwTOXMark const * pCurTOXMark)1003 void SwIndexMarkPane::ReInitDlg(SwWrtShell& rWrtShell, SwTOXMark const * pCurTOXMark)
1004 {
1005     m_pSh = &rWrtShell;
1006     m_pTOXMgr.reset( new SwTOXMgr(m_pSh) );
1007     if(pCurTOXMark)
1008     {
1009         for(sal_uInt16 i = 0; i < m_pTOXMgr->GetTOXMarkCount(); i++)
1010             if(m_pTOXMgr->GetTOXMark(i) == pCurTOXMark)
1011             {
1012                 m_pTOXMgr->SetCurTOXMark(i);
1013                 break;
1014             }
1015     }
1016     InitControls();
1017 }
1018 
SwIndexMarkFloatDlg(SfxBindings * _pBindings,SfxChildWindow * pChild,weld::Window * pParent,SfxChildWinInfo const * pInfo,bool bNew)1019 SwIndexMarkFloatDlg::SwIndexMarkFloatDlg(SfxBindings* _pBindings,
1020     SfxChildWindow* pChild, weld::Window *pParent,
1021     SfxChildWinInfo const * pInfo, bool bNew)
1022     : SfxModelessDialogController(_pBindings, pChild, pParent,
1023         "modules/swriter/ui/indexentry.ui", "IndexEntryDialog")
1024     , m_aContent(m_xDialog, *m_xBuilder, bNew, ::GetActiveWrtShell())
1025 {
1026     if (SwWrtShell* pWrtShell = ::GetActiveWrtShell())
1027         m_aContent.ReInitDlg(*pWrtShell);
1028     Initialize(pInfo);
1029 }
1030 
Activate()1031 void SwIndexMarkFloatDlg::Activate()
1032 {
1033     SfxModelessDialogController::Activate();
1034     m_aContent.Activate();
1035 }
1036 
ReInitDlg(SwWrtShell & rWrtShell)1037 void SwIndexMarkFloatDlg::ReInitDlg(SwWrtShell& rWrtShell)
1038 {
1039     m_aContent.ReInitDlg( rWrtShell );
1040 }
1041 
SwIndexMarkModalDlg(weld::Window * pParent,SwWrtShell & rSh,SwTOXMark const * pCurTOXMark)1042 SwIndexMarkModalDlg::SwIndexMarkModalDlg(weld::Window *pParent, SwWrtShell& rSh, SwTOXMark const * pCurTOXMark)
1043     : SfxDialogController(pParent, "modules/swriter/ui/indexentry.ui",
1044                           "IndexEntryDialog")
1045     , m_aContent(m_xDialog, *m_xBuilder, false, &rSh)
1046 {
1047     m_aContent.ReInitDlg(rSh, pCurTOXMark);
1048 }
1049 
~SwIndexMarkModalDlg()1050 SwIndexMarkModalDlg::~SwIndexMarkModalDlg()
1051 {
1052     SwViewShell::SetCareDialog(nullptr);
1053 }
1054 
run()1055 short SwIndexMarkModalDlg::run()
1056 {
1057     short nRet = SfxDialogController::run();
1058     if (RET_OK == nRet)
1059         m_aContent.Apply();
1060     return nRet;
1061 }
1062 
1063 namespace {
1064 
1065 class SwCreateAuthEntryDlg_Impl : public weld::GenericDialogController
1066 {
1067     std::vector<std::unique_ptr<weld::Builder>> m_aBuilders;
1068 
1069     Link<weld::Entry&,bool>       aShortNameCheckLink;
1070 
1071     SwWrtShell&     rWrtSh;
1072 
1073     bool            m_bNewEntryMode;
1074     bool            m_bNameAllowed;
1075 
1076     std::vector<std::unique_ptr<weld::Container>> m_aOrigContainers;
1077     std::vector<std::unique_ptr<weld::Label>> m_aFixedTexts;
1078     std::unique_ptr<weld::Box> m_pBoxes[AUTH_FIELD_END];
1079     std::unique_ptr<weld::Entry> pEdits[AUTH_FIELD_END];
1080     std::unique_ptr<weld::Button> m_xOKBT;
1081     std::unique_ptr<weld::Container> m_xBox;
1082     std::unique_ptr<weld::Container> m_xLeft;
1083     std::unique_ptr<weld::Container> m_xRight;
1084     std::unique_ptr<weld::ComboBox> m_xTypeListBox;
1085     std::unique_ptr<weld::ComboBox> m_xIdentifierBox;
1086     std::unique_ptr<weld::Button> m_xBrowseButton;
1087     std::unique_ptr<weld::CheckButton> m_xPageCB;
1088     std::unique_ptr<weld::SpinButton> m_xPageSB;
1089 
1090     DECL_LINK(IdentifierHdl, weld::ComboBox&, void);
1091     DECL_LINK(ShortNameHdl, weld::Entry&, void);
1092     DECL_LINK(EnableHdl, weld::ComboBox&, void);
1093     DECL_LINK(BrowseHdl, weld::Button&, void);
1094     DECL_LINK(PageNumHdl, weld::Toggleable&, void);
1095 
1096 public:
1097     SwCreateAuthEntryDlg_Impl(weld::Window* pParent,
1098                               const OUString pFields[],
1099                               SwWrtShell& rSh,
1100                               bool bNewEntry,
1101                               bool bCreate);
1102 
1103     OUString        GetEntryText(ToxAuthorityField eField) const;
1104 
SetCheckNameHdl(const Link<weld::Entry &,bool> & rLink)1105     void            SetCheckNameHdl(const Link<weld::Entry&,bool>& rLink) {aShortNameCheckLink = rLink;}
1106 
1107 };
1108 
1109 struct TextInfo
1110 {
1111     ToxAuthorityField nToxField;
1112     const char* pHelpId;
1113 };
1114 
1115 }
1116 
1117 const TextInfo aTextInfoArr[] =
1118 {
1119     {AUTH_FIELD_IDENTIFIER,      HID_AUTH_FIELD_IDENTIFIER      },
1120     {AUTH_FIELD_AUTHORITY_TYPE,  HID_AUTH_FIELD_AUTHORITY_TYPE  },
1121     {AUTH_FIELD_AUTHOR,          HID_AUTH_FIELD_AUTHOR          },
1122     {AUTH_FIELD_TITLE,           HID_AUTH_FIELD_TITLE           },
1123     {AUTH_FIELD_YEAR,            HID_AUTH_FIELD_YEAR            },
1124     {AUTH_FIELD_PUBLISHER,       HID_AUTH_FIELD_PUBLISHER       },
1125     {AUTH_FIELD_ADDRESS,         HID_AUTH_FIELD_ADDRESS         },
1126     {AUTH_FIELD_ISBN,            HID_AUTH_FIELD_ISBN            },
1127     {AUTH_FIELD_CHAPTER,         HID_AUTH_FIELD_CHAPTER         },
1128     {AUTH_FIELD_PAGES,           HID_AUTH_FIELD_PAGES           },
1129     {AUTH_FIELD_EDITOR,          HID_AUTH_FIELD_EDITOR          },
1130     {AUTH_FIELD_EDITION,         HID_AUTH_FIELD_EDITION         },
1131     {AUTH_FIELD_BOOKTITLE,       HID_AUTH_FIELD_BOOKTITLE       },
1132     {AUTH_FIELD_VOLUME,          HID_AUTH_FIELD_VOLUME          },
1133     {AUTH_FIELD_HOWPUBLISHED,    HID_AUTH_FIELD_HOWPUBLISHED    },
1134     {AUTH_FIELD_ORGANIZATIONS,   HID_AUTH_FIELD_ORGANIZATIONS   },
1135     {AUTH_FIELD_INSTITUTION,     HID_AUTH_FIELD_INSTITUTION     },
1136     {AUTH_FIELD_SCHOOL,          HID_AUTH_FIELD_SCHOOL          },
1137     {AUTH_FIELD_REPORT_TYPE,     HID_AUTH_FIELD_REPORT_TYPE     },
1138     {AUTH_FIELD_MONTH,           HID_AUTH_FIELD_MONTH           },
1139     {AUTH_FIELD_JOURNAL,         HID_AUTH_FIELD_JOURNAL         },
1140     {AUTH_FIELD_NUMBER,          HID_AUTH_FIELD_NUMBER          },
1141     {AUTH_FIELD_SERIES,          HID_AUTH_FIELD_SERIES          },
1142     {AUTH_FIELD_ANNOTE,          HID_AUTH_FIELD_ANNOTE          },
1143     {AUTH_FIELD_NOTE,            HID_AUTH_FIELD_NOTE            },
1144     {AUTH_FIELD_URL,             HID_AUTH_FIELD_URL             },
1145     {AUTH_FIELD_CUSTOM1,         HID_AUTH_FIELD_CUSTOM1         },
1146     {AUTH_FIELD_CUSTOM2,         HID_AUTH_FIELD_CUSTOM2         },
1147     {AUTH_FIELD_CUSTOM3,         HID_AUTH_FIELD_CUSTOM3         },
1148     {AUTH_FIELD_CUSTOM4,         HID_AUTH_FIELD_CUSTOM4         },
1149     {AUTH_FIELD_CUSTOM5,         HID_AUTH_FIELD_CUSTOM5         }
1150 };
1151 
lcl_FindColumnEntry(const uno::Sequence<beans::PropertyValue> & rFields,std::u16string_view rColumnTitle)1152 static OUString lcl_FindColumnEntry(const uno::Sequence<beans::PropertyValue>& rFields, std::u16string_view rColumnTitle)
1153 {
1154     for(const auto& rField : rFields)
1155     {
1156         OUString sRet;
1157         if(rField.Name == rColumnTitle &&
1158             (rField.Value >>= sRet))
1159         {
1160             return sRet;
1161         }
1162     }
1163     return OUString();
1164 }
1165 
1166 bool SwAuthorMarkPane::bIsFromComponent = true;
1167 
SwAuthorMarkPane(weld::DialogController & rDialog,weld::Builder & rBuilder,bool bNewDlg)1168 SwAuthorMarkPane::SwAuthorMarkPane(weld::DialogController &rDialog, weld::Builder& rBuilder, bool bNewDlg)
1169     : m_rDialog(rDialog)
1170     , bNewEntry(bNewDlg)
1171     , bBibAccessInitialized(false)
1172     , pSh(nullptr)
1173     , m_xFromComponentRB(rBuilder.weld_radio_button("frombibliography"))
1174     , m_xFromDocContentRB(rBuilder.weld_radio_button("fromdocument"))
1175     , m_xAuthorFI(rBuilder.weld_label("author"))
1176     , m_xTitleFI(rBuilder.weld_label("title"))
1177     , m_xEntryED(rBuilder.weld_entry("entryed"))
1178     , m_xEntryLB(rBuilder.weld_combo_box("entrylb"))
1179     , m_xActionBT(rBuilder.weld_button(bNewEntry ? OString("insert") : OString("modify")))
1180     , m_xCloseBT(rBuilder.weld_button("close"))
1181     , m_xCreateEntryPB(rBuilder.weld_button("new"))
1182     , m_xEditEntryPB(rBuilder.weld_button("edit"))
1183 {
1184     m_xActionBT->show();
1185     m_xFromComponentRB->set_visible(bNewEntry);
1186     m_xFromDocContentRB->set_visible(bNewEntry);
1187     m_xFromComponentRB->set_active(bIsFromComponent);
1188     m_xFromDocContentRB->set_active(!bIsFromComponent);
1189 
1190     m_xActionBT->connect_clicked(LINK(this,SwAuthorMarkPane, InsertHdl));
1191     m_xCloseBT->connect_clicked(LINK(this,SwAuthorMarkPane, CloseHdl));
1192     m_xCreateEntryPB->connect_clicked(LINK(this,SwAuthorMarkPane, CreateEntryHdl));
1193     m_xEditEntryPB->connect_clicked(LINK(this,SwAuthorMarkPane, CreateEntryHdl));
1194     m_xFromComponentRB->connect_toggled(LINK(this,SwAuthorMarkPane, ChangeSourceHdl));
1195     m_xFromDocContentRB->connect_toggled(LINK(this,SwAuthorMarkPane, ChangeSourceHdl));
1196     m_xEntryED->connect_changed(LINK(this,SwAuthorMarkPane, EditModifyHdl));
1197 
1198     m_rDialog.set_title(SwResId(
1199                     bNewEntry ? STR_AUTHMRK_INSERT : STR_AUTHMRK_EDIT));
1200 
1201     m_xEntryED->set_visible(!bNewEntry);
1202     m_xEntryLB->set_visible(bNewEntry);
1203     if (bNewEntry)
1204     {
1205         m_xEntryLB->connect_changed(LINK(this, SwAuthorMarkPane, CompEntryHdl));
1206     }
1207 }
1208 
ReInitDlg(SwWrtShell & rWrtShell)1209 void SwAuthorMarkPane::ReInitDlg(SwWrtShell& rWrtShell)
1210 {
1211     pSh = &rWrtShell;
1212     InitControls();
1213 }
1214 
IMPL_LINK_NOARG(SwAuthorMarkPane,CloseHdl,weld::Button &,void)1215 IMPL_LINK_NOARG(SwAuthorMarkPane, CloseHdl, weld::Button&, void)
1216 {
1217     if(bNewEntry)
1218     {
1219         SfxViewFrame::Current()->GetDispatcher()->Execute(FN_INSERT_AUTH_ENTRY_DLG,
1220                     SfxCallMode::ASYNCHRON|SfxCallMode::RECORD);
1221     }
1222     else
1223     {
1224         m_rDialog.response(RET_CANCEL);
1225     }
1226 }
1227 
IMPL_LINK(SwAuthorMarkPane,CompEntryHdl,weld::ComboBox &,rBox,void)1228 IMPL_LINK( SwAuthorMarkPane, CompEntryHdl, weld::ComboBox&, rBox, void)
1229 {
1230     const OUString sEntry(rBox.get_active_text());
1231     if(bIsFromComponent)
1232     {
1233         if(xBibAccess.is() && !sEntry.isEmpty())
1234         {
1235             if(xBibAccess->hasByName(sEntry))
1236             {
1237                 uno::Any aEntry(xBibAccess->getByName(sEntry));
1238                 uno::Sequence<beans::PropertyValue> aFieldProps;
1239                 if(aEntry >>= aFieldProps)
1240                 {
1241                     auto nSize = std::min(static_cast<sal_Int32>(AUTH_FIELD_END), aFieldProps.getLength());
1242                     for(sal_Int32 i = 0; i < nSize; i++)
1243                     {
1244                         m_sFields[i] = lcl_FindColumnEntry(aFieldProps, m_sColumnTitles[i]);
1245                     }
1246                 }
1247             }
1248         }
1249     }
1250     else
1251     {
1252         if(!sEntry.isEmpty())
1253         {
1254             const SwAuthorityFieldType* pFType = static_cast<const SwAuthorityFieldType*>(
1255                                         pSh->GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
1256             const SwAuthEntry*  pEntry = pFType ? pFType->GetEntryByIdentifier(sEntry) : nullptr;
1257             for(int i = 0; i < AUTH_FIELD_END; i++)
1258                 m_sFields[i] = pEntry ?
1259                             pEntry->GetAuthorField(static_cast<ToxAuthorityField>(i)) : OUString();
1260         }
1261     }
1262     if (rBox.get_active_text().isEmpty())
1263     {
1264         for(OUString & s : m_sFields)
1265             s.clear();
1266     }
1267     m_xAuthorFI->set_label(m_sFields[AUTH_FIELD_AUTHOR]);
1268     m_xTitleFI->set_label(m_sFields[AUTH_FIELD_TITLE]);
1269 }
1270 
IMPL_LINK_NOARG(SwAuthorMarkPane,InsertHdl,weld::Button &,void)1271 IMPL_LINK_NOARG(SwAuthorMarkPane, InsertHdl, weld::Button&, void)
1272 {
1273     //insert or update the SwAuthorityField...
1274     if(pSh)
1275     {
1276         bool bDifferent = false;
1277         OSL_ENSURE(!m_sFields[AUTH_FIELD_IDENTIFIER].isEmpty() , "No Id is set!");
1278         OSL_ENSURE(!m_sFields[AUTH_FIELD_AUTHORITY_TYPE].isEmpty() , "No authority type is set!");
1279         //check if the entry already exists with different content
1280         const SwAuthorityFieldType* pFType = static_cast<const SwAuthorityFieldType*>(
1281                                         pSh->GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
1282         const SwAuthEntry*  pEntry = pFType ?
1283                 pFType->GetEntryByIdentifier( m_sFields[AUTH_FIELD_IDENTIFIER])
1284                 : nullptr;
1285         if(pEntry)
1286         {
1287             for(int i = 0; i < AUTH_FIELD_END && !bDifferent; i++)
1288                 bDifferent |= m_sFields[i] != pEntry->GetAuthorField(static_cast<ToxAuthorityField>(i));
1289             if(bDifferent)
1290             {
1291                 std::unique_ptr<weld::MessageDialog> xQuery(Application::CreateMessageDialog(m_rDialog.getDialog(),
1292                                                             VclMessageType::Question, VclButtonsType::YesNo,
1293                                                             SwResId(STR_QUERY_CHANGE_AUTH_ENTRY)));
1294                 if (RET_YES != xQuery->run())
1295                     return;
1296             }
1297         }
1298 
1299         SwFieldMgr aMgr(pSh);
1300         OUStringBuffer sFields;
1301         for(OUString & s : m_sFields)
1302         {
1303             sFields.append(s).append(TOX_STYLE_DELIMITER);
1304         }
1305         if(bNewEntry)
1306         {
1307             if(bDifferent)
1308             {
1309                 rtl::Reference<SwAuthEntry> xNewData(new SwAuthEntry);
1310                 for(int i = 0; i < AUTH_FIELD_END; i++)
1311                     xNewData->SetAuthorField(static_cast<ToxAuthorityField>(i), m_sFields[i]);
1312                 pSh->ChangeAuthorityData(xNewData.get());
1313             }
1314             SwInsertField_Data aData(SwFieldTypesEnum::Authority, 0, sFields.makeStringAndClear(), OUString(), 0 );
1315             aMgr.InsertField( aData );
1316         }
1317         else if(aMgr.GetCurField())
1318         {
1319             aMgr.UpdateCurField(0, sFields.makeStringAndClear(), OUString());
1320         }
1321     }
1322     if(!bNewEntry)
1323         CloseHdl(*m_xCloseBT);
1324 }
1325 
IMPL_LINK(SwAuthorMarkPane,CreateEntryHdl,weld::Button &,rButton,void)1326 IMPL_LINK(SwAuthorMarkPane, CreateEntryHdl, weld::Button&, rButton, void)
1327 {
1328     bool bCreate = &rButton == m_xCreateEntryPB.get();
1329     OUString sOldId = m_sCreatedEntry[0];
1330     for(int i = 0; i < AUTH_FIELD_END; i++)
1331         m_sCreatedEntry[i] = bCreate ? OUString() : m_sFields[i];
1332     SwCreateAuthEntryDlg_Impl aDlg(m_rDialog.getDialog(),
1333                 bCreate ? m_sCreatedEntry : m_sFields,
1334                 *pSh, bNewEntry, bCreate);
1335     if(bNewEntry)
1336     {
1337         aDlg.SetCheckNameHdl(LINK(this, SwAuthorMarkPane, IsEntryAllowedHdl));
1338     }
1339     if(RET_OK != aDlg.run())
1340         return;
1341 
1342     if(bCreate && !sOldId.isEmpty())
1343     {
1344         m_xEntryLB->remove_text(sOldId);
1345     }
1346     for(int i = 0; i < AUTH_FIELD_END; i++)
1347     {
1348         m_sFields[i] = aDlg.GetEntryText(static_cast<ToxAuthorityField>(i));
1349         m_sCreatedEntry[i] = m_sFields[i];
1350     }
1351     if(bNewEntry && !m_xFromDocContentRB->get_active())
1352     {
1353         m_xFromDocContentRB->set_active(true);
1354         ChangeSourceHdl(*m_xFromDocContentRB);
1355     }
1356     if(bCreate)
1357     {
1358         OSL_ENSURE(m_xEntryLB->find_text(m_sFields[AUTH_FIELD_IDENTIFIER]) == -1,
1359                     "entry exists!");
1360         m_xEntryLB->append_text(m_sFields[AUTH_FIELD_IDENTIFIER]);
1361         m_xEntryLB->set_active_text(m_sFields[AUTH_FIELD_IDENTIFIER]);
1362     }
1363     m_xEntryED->set_text(m_sFields[AUTH_FIELD_IDENTIFIER]);
1364     m_xAuthorFI->set_label(m_sFields[AUTH_FIELD_AUTHOR]);
1365     m_xTitleFI->set_label(m_sFields[AUTH_FIELD_TITLE]);
1366     m_xActionBT->set_sensitive(true);
1367 
1368     if (!bNewEntry)
1369     {
1370         // When in edit mode, automatically apply the changed entry to update the field in the doc
1371         // model.
1372         InsertHdl(*m_xActionBT);
1373     }
1374 }
1375 
IMPL_LINK_NOARG(SwAuthorMarkPane,ChangeSourceHdl,weld::Toggleable &,void)1376 IMPL_LINK_NOARG(SwAuthorMarkPane, ChangeSourceHdl, weld::Toggleable&, void)
1377 {
1378     bool bFromComp = m_xFromComponentRB->get_active();
1379     bIsFromComponent = bFromComp;
1380     m_xCreateEntryPB->set_sensitive(!bIsFromComponent);
1381     m_xEntryLB->clear();
1382     if(bIsFromComponent)
1383     {
1384         if(!bBibAccessInitialized)
1385         {
1386             uno::Reference< uno::XComponentContext > xContext = getProcessComponentContext();
1387             xBibAccess = frame::Bibliography::create( xContext );
1388             uno::Reference< beans::XPropertySet >  xPropSet(xBibAccess, uno::UNO_QUERY);
1389             OUString uPropName("BibliographyDataFieldNames");
1390             if(xPropSet.is() && xPropSet->getPropertySetInfo()->hasPropertyByName(uPropName))
1391             {
1392                 uno::Any aNames = xPropSet->getPropertyValue(uPropName);
1393                 uno::Sequence<beans::PropertyValue> aSeq;
1394                 if( aNames >>= aSeq)
1395                 {
1396                     for(const beans::PropertyValue& rProp : std::as_const(aSeq))
1397                     {
1398                         sal_Int16 nField = 0;
1399                         rProp.Value >>= nField;
1400                         if(nField >= 0 && nField < AUTH_FIELD_END)
1401                             m_sColumnTitles[nField] = rProp.Name;
1402                     }
1403                 }
1404             }
1405             bBibAccessInitialized = true;
1406         }
1407         if(xBibAccess.is())
1408         {
1409             const uno::Sequence<OUString> aIdentifiers = xBibAccess->getElementNames();
1410             for(const OUString& rName : aIdentifiers)
1411                 m_xEntryLB->append_text(rName);
1412         }
1413     }
1414     else
1415     {
1416         const SwAuthorityFieldType* pFType = static_cast<const SwAuthorityFieldType*>(
1417                                     pSh->GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
1418         if(pFType)
1419         {
1420             std::vector<OUString> aIds;
1421             pFType->GetAllEntryIdentifiers( aIds );
1422             for(const OUString & i : aIds)
1423                 m_xEntryLB->append_text(i);
1424         }
1425         if(!m_sCreatedEntry[AUTH_FIELD_IDENTIFIER].isEmpty())
1426             m_xEntryLB->append_text(m_sCreatedEntry[AUTH_FIELD_IDENTIFIER]);
1427     }
1428     m_xEntryLB->set_active(0);
1429     CompEntryHdl(*m_xEntryLB);
1430 }
1431 
IMPL_LINK(SwAuthorMarkPane,EditModifyHdl,weld::Entry &,rEdit,void)1432 IMPL_LINK(SwAuthorMarkPane, EditModifyHdl, weld::Entry&, rEdit, void)
1433 {
1434     Link<weld::Entry&,bool> aAllowed = LINK(this, SwAuthorMarkPane, IsEditAllowedHdl);
1435     bool bResult = aAllowed.Call(rEdit);
1436     m_xActionBT->set_sensitive(bResult);
1437     if(bResult)
1438     {
1439         OUString sEntry(rEdit.get_text());
1440         m_sFields[AUTH_FIELD_IDENTIFIER] = sEntry;
1441         m_sCreatedEntry[AUTH_FIELD_IDENTIFIER] = sEntry;
1442     }
1443 };
1444 
IMPL_LINK(SwAuthorMarkPane,IsEntryAllowedHdl,weld::Entry &,rEdit,bool)1445 IMPL_LINK(SwAuthorMarkPane, IsEntryAllowedHdl, weld::Entry&, rEdit, bool)
1446 {
1447     OUString sEntry = rEdit.get_text();
1448     bool bAllowed = false;
1449     if(!sEntry.isEmpty())
1450     {
1451         if (m_xEntryLB->find_text(sEntry) != -1)
1452             return false;
1453         else if(bIsFromComponent)
1454         {
1455             const SwAuthorityFieldType* pFType = static_cast<const SwAuthorityFieldType*>(
1456                                         pSh->GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
1457             bAllowed = !pFType || !pFType->GetEntryByIdentifier(sEntry);
1458         }
1459         else
1460         {
1461             bAllowed = !xBibAccess.is() || !xBibAccess->hasByName(sEntry);
1462         }
1463     }
1464     return bAllowed;
1465 }
1466 
IMPL_LINK(SwAuthorMarkPane,IsEditAllowedHdl,weld::Entry &,rEdit,bool)1467 IMPL_LINK(SwAuthorMarkPane, IsEditAllowedHdl, weld::Entry&, rEdit, bool)
1468 {
1469     OUString sEntry = rEdit.get_text();
1470     bool bAllowed = false;
1471     if(!sEntry.isEmpty())
1472     {
1473         if (m_xEntryLB->find_text(sEntry) != -1)
1474             return false;
1475         else if(bIsFromComponent)
1476         {
1477             const SwAuthorityFieldType* pFType = static_cast<const SwAuthorityFieldType*>(
1478                                         pSh->GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
1479             bAllowed = !pFType || !pFType->GetEntryByIdentifier(sEntry);
1480         }
1481         else
1482         {
1483             bAllowed = !xBibAccess.is() || !xBibAccess->hasByName(sEntry);
1484         }
1485     }
1486     return bAllowed;
1487 }
1488 
InitControls()1489 void SwAuthorMarkPane::InitControls()
1490 {
1491     OSL_ENSURE(pSh, "no shell?");
1492     SwField* pField = pSh->GetCurField();
1493     OSL_ENSURE(bNewEntry || pField, "no current marker");
1494     if(bNewEntry)
1495     {
1496         ChangeSourceHdl(m_xFromComponentRB->get_active() ? *m_xFromComponentRB : *m_xFromDocContentRB);
1497         m_xCreateEntryPB->set_sensitive(!m_xFromComponentRB->get_active());
1498         if(!m_xFromComponentRB->get_active() && !m_sCreatedEntry[0].isEmpty())
1499             for(int i = 0; i < AUTH_FIELD_END; i++)
1500                 m_sFields[i] = m_sCreatedEntry[i];
1501     }
1502     if(bNewEntry || !pField || pField->GetTyp()->Which() != SwFieldIds::TableOfAuthorities)
1503         return;
1504 
1505     const SwAuthEntry* pEntry = static_cast<SwAuthorityField*>(pField)->GetAuthEntry();
1506 
1507     OSL_ENSURE(pEntry, "No authority entry found");
1508     if(!pEntry)
1509         return;
1510     for(int i = 0; i < AUTH_FIELD_END; i++)
1511         m_sFields[i] = pEntry->GetAuthorField(static_cast<ToxAuthorityField>(i));
1512 
1513     m_xEntryED->set_text(pEntry->GetAuthorField(AUTH_FIELD_IDENTIFIER));
1514     m_xAuthorFI->set_label(pEntry->GetAuthorField(AUTH_FIELD_AUTHOR));
1515     m_xTitleFI->set_label(pEntry->GetAuthorField(AUTH_FIELD_TITLE));
1516 }
1517 
Activate()1518 void SwAuthorMarkPane::Activate()
1519 {
1520     m_xActionBT->set_sensitive(!pSh->HasReadonlySel());
1521 }
1522 
1523 namespace
1524 {
1525     const char* STR_AUTH_FIELD_ARY[] =
1526     {
1527         STR_AUTH_FIELD_IDENTIFIER,
1528         STR_AUTH_FIELD_AUTHORITY_TYPE,
1529         STR_AUTH_FIELD_ADDRESS,
1530         STR_AUTH_FIELD_ANNOTE,
1531         STR_AUTH_FIELD_AUTHOR,
1532         STR_AUTH_FIELD_BOOKTITLE,
1533         STR_AUTH_FIELD_CHAPTER,
1534         STR_AUTH_FIELD_EDITION,
1535         STR_AUTH_FIELD_EDITOR,
1536         STR_AUTH_FIELD_HOWPUBLISHED,
1537         STR_AUTH_FIELD_INSTITUTION,
1538         STR_AUTH_FIELD_JOURNAL,
1539         STR_AUTH_FIELD_MONTH,
1540         STR_AUTH_FIELD_NOTE,
1541         STR_AUTH_FIELD_NUMBER,
1542         STR_AUTH_FIELD_ORGANIZATIONS,
1543         STR_AUTH_FIELD_PAGES,
1544         STR_AUTH_FIELD_PUBLISHER,
1545         STR_AUTH_FIELD_SCHOOL,
1546         STR_AUTH_FIELD_SERIES,
1547         STR_AUTH_FIELD_TITLE,
1548         STR_AUTH_FIELD_TYPE,
1549         STR_AUTH_FIELD_VOLUME,
1550         STR_AUTH_FIELD_YEAR,
1551         STR_AUTH_FIELD_URL,
1552         STR_AUTH_FIELD_CUSTOM1,
1553         STR_AUTH_FIELD_CUSTOM2,
1554         STR_AUTH_FIELD_CUSTOM3,
1555         STR_AUTH_FIELD_CUSTOM4,
1556         STR_AUTH_FIELD_CUSTOM5,
1557         STR_AUTH_FIELD_ISBN
1558     };
1559 }
1560 
SwCreateAuthEntryDlg_Impl(weld::Window * pParent,const OUString pFields[],SwWrtShell & rSh,bool bNewEntry,bool bCreate)1561 SwCreateAuthEntryDlg_Impl::SwCreateAuthEntryDlg_Impl(weld::Window* pParent,
1562         const OUString pFields[],
1563         SwWrtShell& rSh,
1564         bool bNewEntry,
1565         bool bCreate)
1566     : GenericDialogController(pParent, "modules/swriter/ui/createauthorentry.ui", "CreateAuthorEntryDialog")
1567     , rWrtSh(rSh)
1568     , m_bNewEntryMode(bNewEntry)
1569     , m_bNameAllowed(true)
1570     , m_xOKBT(m_xBuilder->weld_button("ok"))
1571     , m_xBox(m_xBuilder->weld_container("box"))
1572     , m_xLeft(m_xBuilder->weld_container("leftgrid"))
1573     , m_xRight(m_xBuilder->weld_container("rightgrid"))
1574 {
1575     bool bLeft = true;
1576     sal_Int32 nLeftRow(0), nRightRow(0);
1577     for(int nIndex = 0; nIndex < AUTH_FIELD_END; nIndex++)
1578     {
1579         //m_xBox parent just to have some parent during setup, added contents are not directly visible under m_xBox
1580         m_aBuilders.emplace_back(Application::CreateBuilder(m_xBox.get(), "modules/swriter/ui/bibliofragment.ui"));
1581         const TextInfo aCurInfo = aTextInfoArr[nIndex];
1582 
1583         m_aOrigContainers.emplace_back(m_aBuilders.back()->weld_container("biblioentry"));
1584         m_aFixedTexts.emplace_back(m_aBuilders.back()->weld_label("label"));
1585         if (bLeft)
1586             m_aOrigContainers.back()->move(m_aFixedTexts.back().get(), m_xLeft.get());
1587         else
1588             m_aOrigContainers.back()->move(m_aFixedTexts.back().get(), m_xRight.get());
1589         m_aFixedTexts.back()->set_grid_left_attach(0);
1590         m_aFixedTexts.back()->set_grid_top_attach(bLeft ? nLeftRow : nRightRow);
1591         m_aFixedTexts.back()->set_label(SwResId(STR_AUTH_FIELD_ARY[aCurInfo.nToxField]));
1592         m_aFixedTexts.back()->show();
1593         if( AUTH_FIELD_AUTHORITY_TYPE == aCurInfo.nToxField )
1594         {
1595             m_xTypeListBox = m_aBuilders.back()->weld_combo_box("listbox");
1596             if (bLeft)
1597                 m_aOrigContainers.back()->move(m_xTypeListBox.get(), m_xLeft.get());
1598             else
1599                 m_aOrigContainers.back()->move(m_xTypeListBox.get(), m_xRight.get());
1600 
1601             for (int j = 0; j < AUTH_TYPE_END; j++)
1602             {
1603                 m_xTypeListBox->append_text(
1604                     SwAuthorityFieldType::GetAuthTypeName(static_cast<ToxAuthorityType>(j)));
1605             }
1606             if(!pFields[aCurInfo.nToxField].isEmpty())
1607             {
1608                 m_xTypeListBox->set_active(pFields[aCurInfo.nToxField].toInt32());
1609             }
1610             m_xTypeListBox->set_grid_left_attach(1);
1611             m_xTypeListBox->set_grid_top_attach(bLeft ? nLeftRow : nRightRow);
1612             m_xTypeListBox->set_hexpand(true);
1613             m_xTypeListBox->show();
1614             m_xTypeListBox->connect_changed(LINK(this, SwCreateAuthEntryDlg_Impl, EnableHdl));
1615             m_xTypeListBox->set_help_id(aCurInfo.pHelpId);
1616             m_aFixedTexts.back()->set_mnemonic_widget(m_xTypeListBox.get());
1617         }
1618         else if(AUTH_FIELD_IDENTIFIER == aCurInfo.nToxField && !m_bNewEntryMode)
1619         {
1620             m_xIdentifierBox = m_aBuilders.back()->weld_combo_box("combobox");
1621             if (bLeft)
1622                 m_aOrigContainers.back()->move(m_xIdentifierBox.get(), m_xLeft.get());
1623             else
1624                 m_aOrigContainers.back()->move(m_xIdentifierBox.get(), m_xRight.get());
1625 
1626             m_xIdentifierBox->connect_changed(LINK(this,
1627                                     SwCreateAuthEntryDlg_Impl, IdentifierHdl));
1628 
1629             const SwAuthorityFieldType* pFType = static_cast<const SwAuthorityFieldType*>(
1630                                         rSh.GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
1631             if(pFType)
1632             {
1633                 std::vector<OUString> aIds;
1634                 pFType->GetAllEntryIdentifiers( aIds );
1635                 for (const OUString& a : aIds)
1636                     m_xIdentifierBox->append_text(a);
1637             }
1638             m_xIdentifierBox->set_entry_text(pFields[aCurInfo.nToxField]);
1639             m_xIdentifierBox->set_grid_left_attach(1);
1640             m_xIdentifierBox->set_grid_top_attach(bLeft ? nLeftRow : nRightRow);
1641             m_xIdentifierBox->set_hexpand(true);
1642             m_xIdentifierBox->show();
1643             m_xIdentifierBox->set_help_id(aCurInfo.pHelpId);
1644             m_aFixedTexts.back()->set_mnemonic_widget(m_xIdentifierBox.get());
1645         }
1646         else
1647         {
1648             m_pBoxes[nIndex] = m_aBuilders.back()->weld_box("vbox");
1649             pEdits[nIndex] = m_aBuilders.back()->weld_entry("entry");
1650             if (bLeft)
1651                 m_aOrigContainers.back()->move(m_pBoxes[nIndex].get(), m_xLeft.get());
1652             else
1653                 m_aOrigContainers.back()->move(m_pBoxes[nIndex].get(), m_xRight.get());
1654 
1655             m_pBoxes[nIndex]->set_grid_left_attach(1);
1656             m_pBoxes[nIndex]->set_grid_top_attach(bLeft ? nLeftRow : nRightRow);
1657             m_pBoxes[nIndex]->set_hexpand(true);
1658             if (aCurInfo.nToxField == AUTH_FIELD_URL)
1659             {
1660                 m_xBrowseButton = m_aBuilders.back()->weld_button("browse");
1661                 m_xBrowseButton->connect_clicked(LINK(this, SwCreateAuthEntryDlg_Impl, BrowseHdl));
1662                 m_xPageCB = m_aBuilders.back()->weld_check_button("pagecb");
1663                 // Distinguish different instances of this for ui-testing.
1664                 m_xPageCB->set_buildable_name(m_xPageCB->get_buildable_name() + "-visible");
1665                 m_xPageSB = m_aBuilders.back()->weld_spin_button("pagesb");
1666             }
1667 
1668             // Now that both pEdits[nIndex] and m_xPageSB is initialized, set their values.
1669             OUString aText = pFields[aCurInfo.nToxField];
1670             if (aCurInfo.nToxField != AUTH_FIELD_URL)
1671             {
1672                 pEdits[nIndex]->set_text(aText);
1673             }
1674             else
1675             {
1676                 OUString aUrl;
1677                 int nPageNumber;
1678                 if (SplitUrlAndPage(aText, aUrl, nPageNumber))
1679                 {
1680                     pEdits[nIndex]->set_text(aUrl);
1681                     m_xPageCB->set_active(true);
1682                     m_xPageSB->set_sensitive(true);
1683                     m_xPageSB->set_value(nPageNumber);
1684                 }
1685                 else
1686                 {
1687                     pEdits[nIndex]->set_text(aText);
1688                 }
1689             }
1690             pEdits[nIndex]->show();
1691             pEdits[nIndex]->set_help_id(aCurInfo.pHelpId);
1692 
1693             if(AUTH_FIELD_IDENTIFIER == aCurInfo.nToxField)
1694             {
1695                 pEdits[nIndex]->connect_changed(LINK(this, SwCreateAuthEntryDlg_Impl, ShortNameHdl));
1696                 m_bNameAllowed = !pFields[nIndex].isEmpty();
1697                 if(!bCreate)
1698                 {
1699                     m_aFixedTexts.back()->set_sensitive(false);
1700                     pEdits[nIndex]->set_sensitive(false);
1701                 }
1702             }
1703             else if (aCurInfo.nToxField == AUTH_FIELD_URL)
1704             {
1705                 if (comphelper::isFileUrl(pFields[aCurInfo.nToxField]))
1706                 {
1707                     m_xBrowseButton->show();
1708                 }
1709                 m_xPageCB->show();
1710                 m_xPageCB->connect_toggled(LINK(this, SwCreateAuthEntryDlg_Impl, PageNumHdl));
1711                 m_xPageSB->show();
1712             }
1713 
1714             m_aFixedTexts.back()->set_mnemonic_widget(pEdits[nIndex].get());
1715         }
1716         if(bLeft)
1717             ++nLeftRow;
1718         else
1719             ++nRightRow;
1720         bLeft = !bLeft;
1721     }
1722     EnableHdl(*m_xTypeListBox);
1723 }
1724 
GetEntryText(ToxAuthorityField eField) const1725 OUString  SwCreateAuthEntryDlg_Impl::GetEntryText(ToxAuthorityField eField) const
1726 {
1727     if( AUTH_FIELD_AUTHORITY_TYPE == eField )
1728     {
1729         OSL_ENSURE(m_xTypeListBox, "No ListBox");
1730         return OUString::number(m_xTypeListBox->get_active());
1731     }
1732 
1733     if( AUTH_FIELD_IDENTIFIER == eField && !m_bNewEntryMode)
1734     {
1735         OSL_ENSURE(m_xIdentifierBox, "No ComboBox");
1736         return m_xIdentifierBox->get_active_text();
1737     }
1738 
1739     for(int nIndex = 0; nIndex < AUTH_FIELD_END; nIndex++)
1740     {
1741         const TextInfo aCurInfo = aTextInfoArr[nIndex];
1742         if(aCurInfo.nToxField == eField)
1743         {
1744             if (aCurInfo.nToxField != AUTH_FIELD_URL)
1745             {
1746                 return pEdits[nIndex]->get_text();
1747             }
1748             else
1749             {
1750                 return MergeUrlAndPage(pEdits[nIndex]->get_text(), m_xPageSB);
1751             }
1752         }
1753     }
1754 
1755     return OUString();
1756 }
1757 
IMPL_LINK(SwCreateAuthEntryDlg_Impl,IdentifierHdl,weld::ComboBox &,rBox,void)1758 IMPL_LINK(SwCreateAuthEntryDlg_Impl, IdentifierHdl, weld::ComboBox&, rBox, void)
1759 {
1760     const SwAuthorityFieldType* pFType = static_cast<const SwAuthorityFieldType*>(
1761                                 rWrtSh.GetFieldType(SwFieldIds::TableOfAuthorities, OUString()));
1762     if(!pFType)
1763         return;
1764 
1765     const SwAuthEntry* pEntry = pFType->GetEntryByIdentifier(
1766                                                     rBox.get_active_text());
1767     if(!pEntry)
1768         return;
1769 
1770     for(int i = 0; i < AUTH_FIELD_END; i++)
1771     {
1772         const TextInfo aCurInfo = aTextInfoArr[i];
1773         if(AUTH_FIELD_IDENTIFIER == aCurInfo.nToxField)
1774             continue;
1775         if(AUTH_FIELD_AUTHORITY_TYPE == aCurInfo.nToxField)
1776             m_xTypeListBox->set_active_text(
1777                         pEntry->GetAuthorField(aCurInfo.nToxField));
1778         else
1779             pEdits[i]->set_text(
1780                         pEntry->GetAuthorField(aCurInfo.nToxField));
1781     }
1782 }
1783 
IMPL_LINK(SwCreateAuthEntryDlg_Impl,ShortNameHdl,weld::Entry &,rEdit,void)1784 IMPL_LINK(SwCreateAuthEntryDlg_Impl, ShortNameHdl, weld::Entry&, rEdit, void)
1785 {
1786     if (aShortNameCheckLink.IsSet())
1787     {
1788         bool bEnable = aShortNameCheckLink.Call(rEdit);
1789         m_bNameAllowed |= bEnable;
1790         m_xOKBT->set_sensitive(m_xTypeListBox->get_active() != -1 && bEnable);
1791     }
1792 }
1793 
IMPL_LINK(SwCreateAuthEntryDlg_Impl,EnableHdl,weld::ComboBox &,rBox,void)1794 IMPL_LINK(SwCreateAuthEntryDlg_Impl, EnableHdl, weld::ComboBox&, rBox, void)
1795 {
1796     m_xOKBT->set_sensitive(m_bNameAllowed && rBox.get_active() != -1);
1797     m_xBrowseButton->show();
1798 };
1799 
IMPL_LINK_NOARG(SwCreateAuthEntryDlg_Impl,BrowseHdl,weld::Button &,void)1800 IMPL_LINK_NOARG(SwCreateAuthEntryDlg_Impl, BrowseHdl, weld::Button&, void)
1801 {
1802     sfx2::FileDialogHelper aFileDlg(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
1803                                     FileDialogFlags::NONE, getDialog());
1804     OUString aPath = GetEntryText(AUTH_FIELD_URL);
1805     if (!aPath.isEmpty())
1806     {
1807         aFileDlg.SetDisplayDirectory(aPath);
1808     }
1809 
1810     if (aFileDlg.Execute() != ERRCODE_NONE)
1811     {
1812         return;
1813     }
1814 
1815     aPath = aFileDlg.GetPath();
1816 
1817     for (int nIndex = 0; nIndex < AUTH_FIELD_END; nIndex++)
1818     {
1819         const TextInfo& rCurInfo = aTextInfoArr[nIndex];
1820         if (rCurInfo.nToxField == AUTH_FIELD_URL)
1821         {
1822             pEdits[nIndex]->set_text(aPath);
1823             break;
1824         }
1825     }
1826 };
1827 
IMPL_LINK_NOARG(SwCreateAuthEntryDlg_Impl,PageNumHdl,weld::Toggleable &,void)1828 IMPL_LINK_NOARG(SwCreateAuthEntryDlg_Impl, PageNumHdl, weld::Toggleable&, void)
1829 {
1830     if (m_xPageCB->get_active())
1831     {
1832         m_xPageSB->set_sensitive(true);
1833         m_xPageSB->set_value(1);
1834     }
1835     else
1836     {
1837         m_xPageSB->set_sensitive(false);
1838     }
1839 }
1840 
SwAuthMarkFloatDlg(SfxBindings * _pBindings,SfxChildWindow * pChild,weld::Window * pParent,SfxChildWinInfo const * pInfo,bool bNew)1841 SwAuthMarkFloatDlg::SwAuthMarkFloatDlg(SfxBindings* _pBindings,
1842                                        SfxChildWindow* pChild,
1843                                        weld::Window *pParent,
1844                                        SfxChildWinInfo const * pInfo,
1845                                        bool bNew)
1846     : SfxModelessDialogController(_pBindings, pChild, pParent,
1847         "modules/swriter/ui/bibliographyentry.ui", "BibliographyEntryDialog")
1848     , m_aContent(*this, *m_xBuilder, bNew)
1849 {
1850     Initialize(pInfo);
1851     if (SwWrtShell* pWrtShell = ::GetActiveWrtShell())
1852         m_aContent.ReInitDlg(*pWrtShell);
1853 }
1854 
Activate()1855 void SwAuthMarkFloatDlg::Activate()
1856 {
1857     SfxModelessDialogController::Activate();
1858     m_aContent.Activate();
1859 }
1860 
ReInitDlg(SwWrtShell & rWrtShell)1861 void SwAuthMarkFloatDlg::ReInitDlg(SwWrtShell& rWrtShell)
1862 {
1863     m_aContent.ReInitDlg( rWrtShell );
1864 }
1865 
SwAuthMarkModalDlg(weld::Window * pParent,SwWrtShell & rSh)1866 SwAuthMarkModalDlg::SwAuthMarkModalDlg(weld::Window *pParent, SwWrtShell& rSh)
1867     : SfxDialogController(pParent, "modules/swriter/ui/bibliographyentry.ui",
1868                           "BibliographyEntryDialog")
1869     , m_aContent(*this, *m_xBuilder, false)
1870 {
1871     m_aContent.ReInitDlg(rSh);
1872 }
1873 
run()1874 short SwAuthMarkModalDlg::run()
1875 {
1876     short ret = SfxDialogController::run();
1877     if (ret == RET_OK)
1878         Apply();
1879     return ret;
1880 }
1881 
Apply()1882 void SwAuthMarkModalDlg::Apply()
1883 {
1884     m_aContent.InsertHdl(*m_aContent.m_xActionBT);
1885 }
1886 
1887 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1888