diff options
Diffstat (limited to '')
-rw-r--r-- | sw/source/ui/fldui/DateFormFieldDialog.cxx | 126 | ||||
-rw-r--r-- | sw/source/ui/fldui/DropDownFieldDialog.cxx | 142 | ||||
-rw-r--r-- | sw/source/ui/fldui/DropDownFormFieldDialog.cxx | 200 | ||||
-rw-r--r-- | sw/source/ui/fldui/changedb.cxx | 258 | ||||
-rw-r--r-- | sw/source/ui/fldui/flddb.cxx | 541 | ||||
-rw-r--r-- | sw/source/ui/fldui/flddb.hxx | 83 | ||||
-rw-r--r-- | sw/source/ui/fldui/flddinf.cxx | 483 | ||||
-rw-r--r-- | sw/source/ui/fldui/flddinf.hxx | 68 | ||||
-rw-r--r-- | sw/source/ui/fldui/flddok.cxx | 641 | ||||
-rw-r--r-- | sw/source/ui/fldui/flddok.hxx | 72 | ||||
-rw-r--r-- | sw/source/ui/fldui/fldedt.cxx | 336 | ||||
-rw-r--r-- | sw/source/ui/fldui/fldfunc.cxx | 614 | ||||
-rw-r--r-- | sw/source/ui/fldui/fldfunc.hxx | 95 | ||||
-rw-r--r-- | sw/source/ui/fldui/fldpage.cxx | 348 | ||||
-rw-r--r-- | sw/source/ui/fldui/fldpage.hxx | 89 | ||||
-rw-r--r-- | sw/source/ui/fldui/fldref.cxx | 1154 | ||||
-rw-r--r-- | sw/source/ui/fldui/fldref.hxx | 93 | ||||
-rw-r--r-- | sw/source/ui/fldui/fldtdlg.cxx | 307 | ||||
-rw-r--r-- | sw/source/ui/fldui/fldvar.cxx | 1250 | ||||
-rw-r--r-- | sw/source/ui/fldui/fldvar.hxx | 84 | ||||
-rw-r--r-- | sw/source/ui/fldui/inpdlg.cxx | 176 | ||||
-rw-r--r-- | sw/source/ui/fldui/javaedit.cxx | 253 |
22 files changed, 7413 insertions, 0 deletions
diff --git a/sw/source/ui/fldui/DateFormFieldDialog.cxx b/sw/source/ui/fldui/DateFormFieldDialog.cxx new file mode 100644 index 000000000..24461c47d --- /dev/null +++ b/sw/source/ui/fldui/DateFormFieldDialog.cxx @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <DateFormFieldDialog.hxx> +#include <IMark.hxx> +#include <xmloff/odffields.hxx> +#include <svl/numformat.hxx> +#include <svl/zforlist.hxx> +#include <svl/zformat.hxx> +#include <doc.hxx> + +namespace sw +{ +DateFormFieldDialog::DateFormFieldDialog(weld::Widget* pParent, + sw::mark::IDateFieldmark* pDateField, SwDoc& rDoc) + : GenericDialogController(pParent, "modules/swriter/ui/dateformfielddialog.ui", + "DateFormFieldDialog") + , m_pDateField(pDateField) + , m_pNumberFormatter(rDoc.GetNumberFormatter()) + , m_xFormatLB(new SwNumFormatTreeView(m_xBuilder->weld_tree_view("date_formats_treeview"))) +{ + m_xFormatLB->SetFormatType(SvNumFormatType::DATE); + m_xFormatLB->SetAutomaticLanguage(true); + m_xFormatLB->SetShowLanguageControl(true); + m_xFormatLB->SetOneArea(true); + + // Set a default height + weld::TreeView& rTreeView = dynamic_cast<weld::TreeView&>(m_xFormatLB->get_widget()); + rTreeView.set_size_request(rTreeView.get_preferred_size().Width(), + rTreeView.get_height_rows(10)); + InitControls(); +} + +DateFormFieldDialog::~DateFormFieldDialog() {} + +void DateFormFieldDialog::Apply() +{ + if (m_pDateField == nullptr) + return; + + // Try to find out the current date value and replace the content + // with the right formatted date string + sw::mark::IFieldmark::parameter_map_t* pParameters = m_pDateField->GetParameters(); + const SvNumberformat* pFormat = m_pNumberFormatter->GetEntry(m_xFormatLB->GetFormat()); + + // Get date value first + std::pair<bool, double> aResult = m_pDateField->GetCurrentDate(); + + // Then set the date format + (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= pFormat->GetFormatstring(); + (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] + <<= LanguageTag(pFormat->GetLanguage()).getBcp47(); + + // Update current date + if (aResult.first) + { + m_pDateField->SetCurrentDate(aResult.second); + } + else + { + (*pParameters)[ODF_FORMDATE_CURRENTDATE] <<= OUString(); + } +} + +void DateFormFieldDialog::InitControls() +{ + if (m_pDateField == nullptr) + return; + + sw::mark::IFieldmark::parameter_map_t* pParameters = m_pDateField->GetParameters(); + + OUString sFormatString; + auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT); + if (pResult != pParameters->end()) + { + pResult->second >>= sFormatString; + } + + OUString sLang; + pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE); + if (pResult != pParameters->end()) + { + pResult->second >>= sLang; + } + + if (sFormatString.isEmpty() || sLang.isEmpty()) + return; + + LanguageType aLangType = LanguageTag(sLang).getLanguageType(); + sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(sFormatString, aLangType); + if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) + { + sal_Int32 nCheckPos = 0; + SvNumFormatType nType; + m_pNumberFormatter->PutEntry(sFormatString, nCheckPos, nType, nFormat, + LanguageTag(sLang).getLanguageType()); + } + + if (aLangType == LANGUAGE_DONTKNOW || nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) + return; + + if (m_xFormatLB->GetCurLanguage() == aLangType) + { + m_xFormatLB->SetAutomaticLanguage(true); + } + else + { + m_xFormatLB->SetAutomaticLanguage(false); + m_xFormatLB->SetLanguage(aLangType); + + // Change format and change back for regenerating the list + m_xFormatLB->SetFormatType(SvNumFormatType::ALL); + m_xFormatLB->SetFormatType(SvNumFormatType::DATE); + } + m_xFormatLB->SetDefFormat(nFormat); +} + +} // namespace sw + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/ui/fldui/DropDownFieldDialog.cxx b/sw/source/ui/fldui/DropDownFieldDialog.cxx new file mode 100644 index 000000000..d85bc5365 --- /dev/null +++ b/sw/source/ui/fldui/DropDownFieldDialog.cxx @@ -0,0 +1,142 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <wrtsh.hxx> +#include <fldbas.hxx> +#include <DropDownFieldDialog.hxx> +#include <flddropdown.hxx> + +#include <memory> + +using namespace ::com::sun::star; + +// edit insert-field +sw::DropDownFieldDialog::DropDownFieldDialog(weld::Widget *pParent, SwWrtShell &rS, + SwField* pField, bool bPrevButton, bool bNextButton) + : GenericDialogController(pParent, "modules/swriter/ui/dropdownfielddialog.ui", "DropdownFieldDialog") + , m_rSh( rS ) + , m_pDropField(nullptr) + , m_pPressedButton(nullptr) + , m_xListItemsLB(m_xBuilder->weld_tree_view("list")) + , m_xOKPB(m_xBuilder->weld_button("ok")) + , m_xPrevPB(m_xBuilder->weld_button("prev")) + , m_xNextPB(m_xBuilder->weld_button("next")) + , m_xEditPB(m_xBuilder->weld_button("edit")) +{ + m_xListItemsLB->set_size_request(m_xListItemsLB->get_approximate_digit_width() * 24, + m_xListItemsLB->get_height_rows(12)); + Link<weld::TreeView&, bool> aDoubleLk = LINK(this, DropDownFieldDialog, DoubleClickHdl); + m_xListItemsLB->connect_row_activated( aDoubleLk ); + + Link<weld::Button&, void> aEditButtonLk = LINK(this, DropDownFieldDialog, EditHdl); + Link<weld::Button&,void> aPrevButtonLk = LINK(this, DropDownFieldDialog, PrevHdl); + Link<weld::Button&, void> aNextButtonLk = LINK(this, DropDownFieldDialog, NextHdl); + m_xEditPB->connect_clicked(aEditButtonLk); + if( bPrevButton || bNextButton ) + { + m_xPrevPB->show(); + m_xPrevPB->connect_clicked(aPrevButtonLk); + m_xPrevPB->set_sensitive(bPrevButton); + + m_xNextPB->show(); + m_xNextPB->connect_clicked(aNextButtonLk); + m_xNextPB->set_sensitive(bNextButton); + } + if( SwFieldIds::Dropdown == pField->GetTyp()->Which() ) + { + + m_pDropField = static_cast<SwDropDownField*>(pField); + OUString sTitle = m_xDialog->get_title() + + m_pDropField->GetPar2(); + m_xDialog->set_title(sTitle); + const uno::Sequence< OUString > aItems = m_pDropField->GetItemSequence(); + for (const OUString& rItem : aItems) + m_xListItemsLB->append_text(rItem); + m_xListItemsLB->select_text(m_pDropField->GetSelectedItem()); + } + + bool bEnable = !m_rSh.IsCursorReadonly(); + m_xOKPB->set_sensitive(bEnable); + + m_xListItemsLB->grab_focus(); +} + +sw::DropDownFieldDialog::~DropDownFieldDialog() +{ +} + +void sw::DropDownFieldDialog::Apply() +{ + if (!m_pDropField) + return; + + OUString sSelect = m_xListItemsLB->get_selected_text(); + if (m_pDropField->GetPar1() == sSelect) + return; + + m_rSh.StartAllAction(); + + std::unique_ptr<SwDropDownField> const pCopy( + static_cast<SwDropDownField*>(m_pDropField->CopyField().release())); + + pCopy->SetPar1(sSelect); + m_rSh.SwEditShell::UpdateOneField(*pCopy); + + m_rSh.SetUndoNoResetModified(); + m_rSh.EndAllAction(); +} + +bool sw::DropDownFieldDialog::PrevButtonPressed() const +{ + return m_pPressedButton == m_xPrevPB.get(); +} + +bool sw::DropDownFieldDialog::NextButtonPressed() const +{ + return m_pPressedButton == m_xNextPB.get(); +} + +IMPL_LINK_NOARG(sw::DropDownFieldDialog, EditHdl, weld::Button&, void) +{ + m_pPressedButton = m_xEditPB.get(); + m_xDialog->response(RET_YES); +} + +IMPL_LINK_NOARG(sw::DropDownFieldDialog, PrevHdl, weld::Button&, void) +{ + m_pPressedButton = m_xPrevPB.get(); + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(sw::DropDownFieldDialog, NextHdl, weld::Button&, void) +{ + m_pPressedButton = m_xNextPB.get(); + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(sw::DropDownFieldDialog, DoubleClickHdl, weld::TreeView&, bool) +{ + // tdf#114144, when next is available make double-click accept and go to next field + if (m_xNextPB->get_visible() && m_xNextPB->get_sensitive()) + m_pPressedButton = m_xNextPB.get(); + m_xDialog->response(RET_OK); + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/DropDownFormFieldDialog.cxx b/sw/source/ui/fldui/DropDownFormFieldDialog.cxx new file mode 100644 index 000000000..2115bbda4 --- /dev/null +++ b/sw/source/ui/fldui/DropDownFormFieldDialog.cxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <DropDownFormFieldDialog.hxx> +#include <vcl/event.hxx> +#include <IMark.hxx> +#include <xmloff/odffields.hxx> +#include <vcl/svapp.hxx> +#include <strings.hrc> +#include <swtypes.hxx> + +namespace sw +{ +DropDownFormFieldDialog::DropDownFormFieldDialog(weld::Widget* pParent, + mark::IFieldmark* pDropDownField) + : GenericDialogController(pParent, "modules/swriter/ui/dropdownformfielddialog.ui", + "DropDownFormFieldDialog") + , m_pDropDownField(pDropDownField) + , m_bListHasChanged(false) + , m_xListItemEntry(m_xBuilder->weld_entry("item_entry")) + , m_xListAddButton(m_xBuilder->weld_button("add_button")) + , m_xListItemsTreeView(m_xBuilder->weld_tree_view("items_treeview")) + , m_xListRemoveButton(m_xBuilder->weld_button("remove_button")) + , m_xListUpButton(m_xBuilder->weld_button("up_button")) + , m_xListDownButton(m_xBuilder->weld_button("down_button")) +{ + m_xListItemEntry->connect_key_press(LINK(this, DropDownFormFieldDialog, KeyPressedHdl)); + m_xListItemEntry->connect_changed(LINK(this, DropDownFormFieldDialog, EntryChangedHdl)); + + m_xListItemsTreeView->set_size_request(m_xListItemEntry->get_preferred_size().Width(), + m_xListItemEntry->get_preferred_size().Height() * 5); + m_xListItemsTreeView->connect_changed(LINK(this, DropDownFormFieldDialog, ListChangedHdl)); + + Link<weld::Button&, void> aPushButtonLink(LINK(this, DropDownFormFieldDialog, ButtonPushedHdl)); + m_xListAddButton->connect_clicked(aPushButtonLink); + m_xListRemoveButton->connect_clicked(aPushButtonLink); + m_xListUpButton->connect_clicked(aPushButtonLink); + m_xListDownButton->connect_clicked(aPushButtonLink); + + InitControls(); +} + +DropDownFormFieldDialog::~DropDownFormFieldDialog() {} + +IMPL_LINK_NOARG(DropDownFormFieldDialog, ListChangedHdl, weld::TreeView&, void) { UpdateButtons(); } + +IMPL_LINK(DropDownFormFieldDialog, KeyPressedHdl, const KeyEvent&, rEvent, bool) +{ + if (rEvent.GetKeyCode().GetCode() == KEY_RETURN && !m_xListItemEntry->get_text().isEmpty()) + { + AppendItemToList(); + return true; + } + return false; +} + +IMPL_LINK_NOARG(DropDownFormFieldDialog, EntryChangedHdl, weld::Entry&, void) { UpdateButtons(); } + +IMPL_LINK(DropDownFormFieldDialog, ButtonPushedHdl, weld::Button&, rButton, void) +{ + if (&rButton == m_xListAddButton.get()) + { + AppendItemToList(); + } + else if (m_xListItemsTreeView->get_selected_index() != -1) + { + int nSelPos = m_xListItemsTreeView->get_selected_index(); + if (&rButton == m_xListRemoveButton.get()) + { + m_xListItemsTreeView->remove(nSelPos); + if (m_xListItemsTreeView->n_children() > 0) + m_xListItemsTreeView->select(nSelPos ? nSelPos - 1 : 0); + } + else if (&rButton == m_xListUpButton.get()) + { + const OUString sEntry = m_xListItemsTreeView->get_selected_text(); + m_xListItemsTreeView->remove(nSelPos); + nSelPos--; + m_xListItemsTreeView->insert_text(nSelPos, sEntry); + m_xListItemsTreeView->select(nSelPos); + } + else if (&rButton == m_xListDownButton.get()) + { + const OUString sEntry = m_xListItemsTreeView->get_selected_text(); + m_xListItemsTreeView->remove(nSelPos); + nSelPos++; + m_xListItemsTreeView->insert_text(nSelPos, sEntry); + m_xListItemsTreeView->select(nSelPos); + } + m_bListHasChanged = true; + } + UpdateButtons(); +} + +void DropDownFormFieldDialog::InitControls() +{ + if (m_pDropDownField != nullptr) + { + const mark::IFieldmark::parameter_map_t* const pParameters + = m_pDropDownField->GetParameters(); + + auto pListEntries = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY); + if (pListEntries != pParameters->end()) + { + css::uno::Sequence<OUString> vListEntries; + pListEntries->second >>= vListEntries; + for (const OUString& rItem : std::as_const(vListEntries)) + m_xListItemsTreeView->append_text(rItem); + + // Select the current one + auto pResult = pParameters->find(ODF_FORMDROPDOWN_RESULT); + if (pResult != pParameters->end()) + { + sal_Int32 nSelection = -1; + pResult->second >>= nSelection; + if (nSelection >= 0 && nSelection < vListEntries.getLength()) + m_xListItemsTreeView->select_text(vListEntries[nSelection]); + } + } + } + UpdateButtons(); +} + +void DropDownFormFieldDialog::AppendItemToList() +{ + if (!m_xListAddButton->get_sensitive()) + return; + + if (m_xListItemsTreeView->n_children() >= ODF_FORMDROPDOWN_ENTRY_COUNT_LIMIT) + { + std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog( + m_xDialog.get(), VclMessageType::Info, VclButtonsType::Ok, + SwResId(STR_DROP_DOWN_FIELD_ITEM_LIMIT))); + xInfoBox->run(); + return; + } + + const OUString sEntry(m_xListItemEntry->get_text()); + if (!sEntry.isEmpty()) + { + m_xListItemsTreeView->append_text(sEntry); + m_xListItemsTreeView->select_text(sEntry); + m_bListHasChanged = true; + + // Clear entry + m_xListItemEntry->set_text(OUString()); + m_xListItemEntry->grab_focus(); + } + UpdateButtons(); +} + +void DropDownFormFieldDialog::UpdateButtons() +{ + m_xListAddButton->set_sensitive(!m_xListItemEntry->get_text().isEmpty() + && m_xListItemsTreeView->find_text(m_xListItemEntry->get_text()) + == -1); + + int nSelPos = m_xListItemsTreeView->get_selected_index(); + m_xListRemoveButton->set_sensitive(nSelPos != -1); + m_xListUpButton->set_sensitive(nSelPos > 0); + m_xListDownButton->set_sensitive(nSelPos != -1 + && nSelPos < m_xListItemsTreeView->n_children() - 1); +} + +void DropDownFormFieldDialog::Apply() +{ + if (!(m_pDropDownField != nullptr && m_bListHasChanged)) + return; + + mark::IFieldmark::parameter_map_t* pParameters = m_pDropDownField->GetParameters(); + + css::uno::Sequence<OUString> vListEntries(m_xListItemsTreeView->n_children()); + auto vListEntriesRange = asNonConstRange(vListEntries); + for (int nIndex = 0; nIndex < m_xListItemsTreeView->n_children(); ++nIndex) + { + vListEntriesRange[nIndex] = m_xListItemsTreeView->get_text(nIndex); + } + + if (m_xListItemsTreeView->n_children() != 0) + { + (*pParameters)[ODF_FORMDROPDOWN_LISTENTRY] <<= vListEntries; + } + else + { + pParameters->erase(ODF_FORMDROPDOWN_LISTENTRY); + } + + // After editing the drop down field's list we don't specify the selected item + pParameters->erase(ODF_FORMDROPDOWN_RESULT); +} + +} // namespace sw + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/ui/fldui/changedb.cxx b/sw/source/ui/fldui/changedb.cxx new file mode 100644 index 000000000..1fa9e140f --- /dev/null +++ b/sw/source/ui/fldui/changedb.cxx @@ -0,0 +1,258 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/sdb/DatabaseContext.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <comphelper/processfactory.hxx> +#include <comphelper/sequence.hxx> +#include <sfx2/viewfrm.hxx> +#include <o3tl/string_view.hxx> + +#include <view.hxx> +#include <wrtsh.hxx> +#include <dbmgr.hxx> +#include <changedb.hxx> + +#include <strings.hrc> +#include <bitmaps.hlst> + +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::uno; + +// edit insert-field +SwChangeDBDlg::SwChangeDBDlg(SwView const & rVw) + : SfxDialogController(rVw.GetViewFrame()->GetFrameWeld(), "modules/swriter/ui/exchangedatabases.ui", + "ExchangeDatabasesDialog") + , pSh(rVw.GetWrtShellPtr()) + , m_xUsedDBTLB(m_xBuilder->weld_tree_view("inuselb")) + , m_xAvailDBTLB(new SwDBTreeList(m_xBuilder->weld_tree_view("availablelb"))) + , m_xAddDBPB(m_xBuilder->weld_button("browse")) + , m_xDocDBNameFT(m_xBuilder->weld_label("dbnameft")) + , m_xDefineBT(m_xBuilder->weld_button("ok")) +{ + int nWidth = m_xUsedDBTLB->get_approximate_digit_width() * 25; + int nHeight = m_xUsedDBTLB->get_height_rows(8); + m_xUsedDBTLB->set_size_request(nWidth, nHeight); + m_xAvailDBTLB->set_size_request(nWidth, nHeight); + + m_xAvailDBTLB->SetWrtShell(*pSh); + FillDBPopup(); + + ShowDBName(pSh->GetDBData()); + m_xDefineBT->connect_clicked(LINK(this, SwChangeDBDlg, ButtonHdl)); + m_xAddDBPB->connect_clicked(LINK(this, SwChangeDBDlg, AddDBHdl)); + + m_xUsedDBTLB->set_selection_mode(SelectionMode::Multiple); + m_xUsedDBTLB->make_sorted(); + + Link<weld::TreeView&,void> aLink = LINK(this, SwChangeDBDlg, TreeSelectHdl); + + m_xUsedDBTLB->connect_changed(aLink); + m_xAvailDBTLB->connect_changed(aLink); + TreeSelect(); +} + +// initialise database listboxes +void SwChangeDBDlg::FillDBPopup() +{ + Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + Reference<XDatabaseContext> xDBContext = DatabaseContext::create(xContext); + const SwDBData& rDBData = pSh->GetDBData(); + m_xAvailDBTLB->Select(rDBData.sDataSource, rDBData.sCommand, u""); + TreeSelect(); + + Sequence< OUString > aDBNames = xDBContext->getElementNames(); + auto aAllDBNames = comphelper::sequenceToContainer<std::vector<OUString>>(aDBNames); + + std::vector<OUString> aDBNameList; + pSh->GetAllUsedDB( aDBNameList, &aAllDBNames ); + + size_t nCount = aDBNameList.size(); + m_xUsedDBTLB->clear(); + std::unique_ptr<weld::TreeIter> xFirst; + + for(size_t k = 0; k < nCount; k++) + { + std::unique_ptr<weld::TreeIter> xLast = Insert(o3tl::getToken(aDBNameList[k], 0, ';')); + if (!xFirst) + xFirst = std::move(xLast); + } + + if (xFirst) + { + m_xUsedDBTLB->expand_row(*xFirst); + m_xUsedDBTLB->scroll_to_row(*xFirst); + m_xUsedDBTLB->select(*xFirst); + } +} + +std::unique_ptr<weld::TreeIter> SwChangeDBDlg::Insert(std::u16string_view rDBName) +{ + sal_Int32 nIdx{ 0 }; + const OUString sDBName(o3tl::getToken(rDBName, 0, DB_DELIM, nIdx)); + const OUString sTableName(o3tl::getToken(rDBName, 0, DB_DELIM, nIdx)); + OUString sUserData( o3tl::getToken(rDBName, 0, DB_DELIM, nIdx) ); + sal_Int32 nCommandType = sUserData.toInt32(); + + const OUString & rToInsert ( nCommandType ? RID_BMP_DBQUERY : RID_BMP_DBTABLE ); + + std::unique_ptr<weld::TreeIter> xIter(m_xUsedDBTLB->make_iterator()); + if (m_xUsedDBTLB->get_iter_first(*xIter)) + { + do + { + if (sDBName == m_xUsedDBTLB->get_text(*xIter)) + { + if (m_xUsedDBTLB->iter_has_child(*xIter)) + { + std::unique_ptr<weld::TreeIter> xChild(m_xUsedDBTLB->make_iterator(xIter.get())); + if (m_xUsedDBTLB->iter_children(*xChild)) + { + do + { + if (sTableName == m_xUsedDBTLB->get_text(*xChild)) + return xChild; + } while (m_xUsedDBTLB->iter_next_sibling(*xChild)); + } + } + m_xUsedDBTLB->insert(xIter.get(), -1, &sTableName, &sUserData, nullptr, nullptr, + false, xIter.get()); + m_xUsedDBTLB->set_image(*xIter, rToInsert); + return xIter; + } + } while (m_xUsedDBTLB->iter_next_sibling(*xIter)); + } + + m_xUsedDBTLB->insert(nullptr, -1, &sDBName, nullptr, nullptr, nullptr, + false, xIter.get()); + m_xUsedDBTLB->set_image(*xIter, RID_BMP_DB); + m_xUsedDBTLB->insert(xIter.get(), -1, &sTableName, &sUserData, nullptr, nullptr, + false, xIter.get()); + m_xUsedDBTLB->set_image(*xIter, rToInsert); + return xIter; +} + +// destroy dialog +SwChangeDBDlg::~SwChangeDBDlg() +{ +} + +short SwChangeDBDlg::run() +{ + short nRet = SfxDialogController::run(); + if (nRet == RET_OK) + UpdateFields(); + return nRet; +} + +void SwChangeDBDlg::UpdateFields() +{ + std::vector<OUString> aDBNames; + + m_xUsedDBTLB->selected_foreach([this, &aDBNames](weld::TreeIter& rEntry){ + if (m_xUsedDBTLB->get_iter_depth(rEntry)) + { + std::unique_ptr<weld::TreeIter> xIter(m_xUsedDBTLB->make_iterator(&rEntry)); + m_xUsedDBTLB->iter_parent(*xIter); + OUString sTmp(m_xUsedDBTLB->get_text(*xIter) + + OUStringChar(DB_DELIM) + m_xUsedDBTLB->get_text(rEntry) + OUStringChar(DB_DELIM) + + m_xUsedDBTLB->get_id(rEntry)); + aDBNames.push_back(sTmp); + } + return false; + }); + + pSh->StartAllAction(); + OUString sTableName; + OUString sColumnName; + sal_Bool bIsTable = false; + const OUString DBName(m_xAvailDBTLB->GetDBName(sTableName, sColumnName, &bIsTable)); + const OUString sTemp = DBName + + OUStringChar(DB_DELIM) + + sTableName + + OUStringChar(DB_DELIM) + + OUString::number(bIsTable + ? CommandType::TABLE + : CommandType::QUERY); + pSh->ChangeDBFields( aDBNames, sTemp); + pSh->EndAllAction(); +} + +IMPL_LINK_NOARG(SwChangeDBDlg, ButtonHdl, weld::Button&, void) +{ + OUString sTableName; + OUString sColumnName; + SwDBData aData; + sal_Bool bIsTable = false; + aData.sDataSource = m_xAvailDBTLB->GetDBName(sTableName, sColumnName, &bIsTable); + aData.sCommand = sTableName; + aData.nCommandType = bIsTable ? 0 : 1; + pSh->ChgDBData(aData); + ShowDBName(pSh->GetDBData()); + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(SwChangeDBDlg, TreeSelectHdl, weld::TreeView&, void) +{ + TreeSelect(); +} + +void SwChangeDBDlg::TreeSelect() +{ + bool bEnable = false; + std::unique_ptr<weld::TreeIter> xIter(m_xAvailDBTLB->make_iterator()); + if (m_xAvailDBTLB->get_selected(xIter.get())) + { + if (m_xAvailDBTLB->get_iter_depth(*xIter)) + bEnable = true; + } + m_xDefineBT->set_sensitive(bEnable); +} + + +// convert database name for display +void SwChangeDBDlg::ShowDBName(const SwDBData& rDBData) +{ + if (rDBData.sDataSource.isEmpty() && rDBData.sCommand.isEmpty()) + { + m_xDocDBNameFT->set_label(SwResId(SW_STR_NONE)); + } + else + { + const OUString sName(rDBData.sDataSource + "." + rDBData.sCommand); + m_xDocDBNameFT->set_label(sName.replaceAll("~", "~~")); + } +} + +IMPL_LINK_NOARG(SwChangeDBDlg, AddDBHdl, weld::Button&, void) +{ + const OUString sNewDB = SwDBManager::LoadAndRegisterDataSource(m_xDialog.get()); + if (!sNewDB.isEmpty()) + { + m_xAvailDBTLB->AddDataSource(sNewDB); + TreeSelect(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/flddb.cxx b/sw/source/ui/fldui/flddb.cxx new file mode 100644 index 000000000..62dd538f0 --- /dev/null +++ b/sw/source/ui/fldui/flddb.cxx @@ -0,0 +1,541 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <swmodule.hxx> +#include <wrtsh.hxx> +#include <dbfld.hxx> +#include <doc.hxx> + +#include "flddb.hxx" +#include <dbconfig.hxx> +#include <dbmgr.hxx> +#include <o3tl/string_view.hxx> + +#define USER_DATA_VERSION_1 "1" +#define USER_DATA_VERSION USER_DATA_VERSION_1 + +SwFieldDBPage::SwFieldDBPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *const pCoreSet) + : SwFieldPage(pPage, pController, "modules/swriter/ui/flddbpage.ui", "FieldDbPage", pCoreSet) + , m_nOldFormat(0) + , m_nOldSubType(0) + , m_xTypeLB(m_xBuilder->weld_tree_view("type")) + , m_xDatabaseTLB(new SwDBTreeList(m_xBuilder->weld_tree_view("select"))) + , m_xAddDBPB(m_xBuilder->weld_button("browse")) + , m_xCondition(m_xBuilder->weld_widget("condgroup")) + , m_xConditionED(new ConditionEdit(m_xBuilder->weld_entry("condition"))) + , m_xValue(m_xBuilder->weld_widget("recgroup")) + , m_xValueED(m_xBuilder->weld_entry("recnumber")) + , m_xDBFormatRB(m_xBuilder->weld_radio_button("fromdatabasecb")) + , m_xNewFormatRB(m_xBuilder->weld_radio_button("userdefinedcb")) + , m_xNumFormatLB(new NumFormatListBox(m_xBuilder->weld_combo_box("numformat"))) + , m_xFormatLB(m_xBuilder->weld_combo_box("format")) + , m_xFormat(m_xBuilder->weld_widget("formatframe")) +{ + SetTypeSel(-1); //TODO + + m_xTypeLB->make_sorted(); + m_xFormatLB->make_sorted(); + + auto nWidth = m_xTypeLB->get_approximate_digit_width() * FIELD_COLUMN_WIDTH; + auto nHeight = m_xTypeLB->get_height_rows(10); + m_xTypeLB->set_size_request(nWidth, nHeight); + m_xDatabaseTLB->set_size_request(nWidth*2, nHeight); + + m_xNumFormatLB->connect_changed(LINK(this, SwFieldDBPage, NumSelectHdl)); + m_xDatabaseTLB->connect_changed(LINK(this, SwFieldDBPage, TreeSelectHdl)); + m_xDatabaseTLB->connect_row_activated(LINK(this, SwFieldDBPage, TreeViewInsertHdl)); + + m_xValueED->connect_changed(LINK(this, SwFieldDBPage, ModifyHdl)); + m_xAddDBPB->connect_clicked(LINK(this, SwFieldDBPage, AddDBHdl)); + + // uitests + m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-db"); + m_xNumFormatLB->set_buildable_name(m_xNumFormatLB->get_buildable_name() + "-db"); + m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-db"); +} + +SwFieldDBPage::~SwFieldDBPage() +{ + // If we have no stored SwWrtShell, it means we didn't do anything useful - no need to revoke. + if (SwWrtShell* pSh = CheckAndGetWrtShell()) + { + // This would cleanup in the case of cancelled dialog + SwDBManager* pDbManager = pSh->GetDoc()->GetDBManager(); + if (pDbManager) + pDbManager->RevokeLastRegistrations(); + } +} + +// initialise TabPage +void SwFieldDBPage::Reset(const SfxItemSet*) +{ + Init(); // general initialization + + const sal_Int32 nOldPos = m_xTypeLB->get_selected_index(); + m_xTypeLB->freeze(); + m_sOldDBName = m_xDatabaseTLB->GetDBName(m_sOldTableName, m_sOldColumnName); + + m_xTypeLB->clear(); + + if (!IsFieldEdit()) + { + // initialise TypeListBox + const SwFieldGroupRgn& rRg = SwFieldMgr::GetGroupRange(IsFieldDlgHtmlMode(), GetGroup()); + + for(sal_uInt16 i = rRg.nStart; i < rRg.nEnd; ++i) + { + const SwFieldTypesEnum nTypeId = SwFieldMgr::GetTypeId(i); + m_xTypeLB->append(OUString::number(static_cast<sal_uInt16>(nTypeId)), SwFieldMgr::GetTypeStr(i)); + } + } + else + { + const SwFieldTypesEnum nTypeId = GetCurField()->GetTypeId(); + m_xTypeLB->append(OUString::number(static_cast<sal_uInt16>(nTypeId)), + SwFieldMgr::GetTypeStr(SwFieldMgr::GetPos(nTypeId))); + } + + m_xTypeLB->thaw(); + + // select old Pos + if (GetTypeSel() != -1) + m_xTypeLB->select(GetTypeSel()); + + m_xFormatLB->clear(); + + const sal_uInt16 nSize = GetFieldMgr().GetFormatCount(SwFieldTypesEnum::DatabaseSetNumber, IsFieldDlgHtmlMode()); + for( sal_uInt16 i = 0; i < nSize; ++i ) + { + const sal_uInt16 nFormatId = GetFieldMgr().GetFormatId( SwFieldTypesEnum::DatabaseSetNumber, i ); + OUString sId(OUString::number(nFormatId)); + m_xFormatLB->append(sId, GetFieldMgr().GetFormatStr(SwFieldTypesEnum::DatabaseSetNumber, i)); + if (SVX_NUM_ARABIC == nFormatId) + m_xFormatLB->set_active_id(sId); + } + + if (!IsFieldEdit()) + { + if (nOldPos != -1) + m_xTypeLB->select(nOldPos); + + if (!m_sOldDBName.isEmpty()) + { + m_xDatabaseTLB->Select(m_sOldDBName, m_sOldTableName, m_sOldColumnName); + } + else + { + if (SwWrtShell *pSh = CheckAndGetWrtShell()) + { + SwDBData aTmp(pSh->GetDBData()); + m_xDatabaseTLB->Select(aTmp.sDataSource, aTmp.sCommand, u""); + } + } + } + + if( !IsRefresh() ) + { + const OUString sUserData = GetUserData(); + sal_Int32 nIdx{ 0 }; + if (o3tl::equalsIgnoreAsciiCase(o3tl::getToken(sUserData, 0, ';', nIdx), u"" USER_DATA_VERSION_1)) + { + const sal_uInt16 nVal = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(o3tl::getToken(sUserData, 0, ';', nIdx))); + if (nVal != USHRT_MAX) + { + for (sal_Int32 i = 0, nEntryCount = m_xTypeLB->n_children(); i < nEntryCount; ++i) + { + if (nVal == m_xTypeLB->get_id(i).toUInt32()) + { + m_xTypeLB->select(i); + break; + } + } + } + } + } + TypeHdl(nullptr); + + m_xTypeLB->connect_changed(LINK(this, SwFieldDBPage, TypeListBoxHdl)); + m_xTypeLB->connect_row_activated(LINK(this, SwFieldDBPage, TreeViewInsertHdl)); + + if (IsFieldEdit()) + { + m_xConditionED->save_value(); + m_xValueED->save_value(); + m_sOldDBName = m_xDatabaseTLB->GetDBName(m_sOldTableName, m_sOldColumnName); + m_nOldFormat = GetCurField()->GetFormat(); + m_nOldSubType = GetCurField()->GetSubType(); + } +} + +// SwFieldDBPage may ask for password to select current document's data source, +// so only do that when activating the page, not when dialog is creating all pages +bool SwFieldDBPage::DeferResetToFirstActivation() { return true; } + +bool SwFieldDBPage::FillItemSet(SfxItemSet* ) +{ + OUString sTableName; + OUString sColumnName; + SwDBData aData; + sal_Bool bIsTable; + aData.sDataSource = m_xDatabaseTLB->GetDBName(sTableName, sColumnName, &bIsTable); + aData.sCommand = sTableName; + aData.nCommandType = bIsTable ? 0 : 1; + + if (SwWrtShell *pSh = CheckAndGetWrtShell()) + { + SwDBManager* pDbManager = pSh->GetDoc()->GetDBManager(); + if (pDbManager) + pDbManager->CommitLastRegistrations(); + + if (aData.sDataSource.isEmpty()) + aData = pSh->GetDBData(); + } + + if(!aData.sDataSource.isEmpty()) // without database no new field command + { + const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + sal_uLong nFormat = 0; + sal_uInt16 nSubType = 0; + + OUString sDBName = aData.sDataSource + + OUStringChar(DB_DELIM) + + aData.sCommand + + OUStringChar(DB_DELIM) + + OUString::number(aData.nCommandType) + + OUStringChar(DB_DELIM); + if (!sColumnName.isEmpty()) + { + sDBName += sColumnName + OUStringChar(DB_DELIM); + } + OUString aName = sDBName + m_xConditionED->get_text(); + + switch (nTypeId) + { + case SwFieldTypesEnum::Database: + nFormat = m_xNumFormatLB->GetFormat(); + if (m_xNewFormatRB->get_sensitive() && m_xNewFormatRB->get_active()) + nSubType = nsSwExtendedSubType::SUB_OWN_FMT; + aName = sDBName; + break; + + case SwFieldTypesEnum::DatabaseSetNumber: + nFormat = m_xFormatLB->get_active_id().toUInt32(); + break; + default: break; + } + + const OUString aVal(m_xValueED->get_text()); + OUString sTempTableName; + OUString sTempColumnName; + OUString sTempDBName = m_xDatabaseTLB->GetDBName(sTempTableName, sTempColumnName); + bool bDBListBoxChanged = m_sOldDBName != sTempDBName || + m_sOldTableName != sTempTableName || m_sOldColumnName != sTempColumnName; + if (!IsFieldEdit() || + m_xConditionED->get_value_changed_from_saved() || + m_xValueED->get_saved_value() != aVal || + bDBListBoxChanged || + m_nOldFormat != nFormat || m_nOldSubType != nSubType) + { + InsertField( nTypeId, nSubType, aName, aVal, nFormat); + } + } + + return false; +} + +std::unique_ptr<SfxTabPage> SwFieldDBPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet *const pAttrSet ) +{ + return std::make_unique<SwFieldDBPage>( pPage, pController, pAttrSet ); +} + +sal_uInt16 SwFieldDBPage::GetGroup() +{ + return GRP_DB; +} + +IMPL_LINK( SwFieldDBPage, TypeListBoxHdl, weld::TreeView&, rBox, void ) +{ + TypeHdl(&rBox); +} + +void SwFieldDBPage::TypeHdl(const weld::TreeView* pBox) +{ + // save old ListBoxPos + const sal_Int32 nOld = GetTypeSel(); + + // current ListBoxPos + SetTypeSel(m_xTypeLB->get_selected_index()); + + if (GetTypeSel() == -1) + { + SetTypeSel(0); + m_xTypeLB->select(0); + } + + if (nOld == GetTypeSel()) + return; + + bool bCond = false, bSetNo = false, bFormat = false, bDBFormat = false; + const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + + m_xDatabaseTLB->ShowColumns(nTypeId == SwFieldTypesEnum::Database); + + if (IsFieldEdit()) + { + SwDBData aData; + OUString sColumnName; + if (nTypeId == SwFieldTypesEnum::Database) + { + if (auto const*const pField = dynamic_cast<SwDBField*>(GetCurField())) + { + aData = pField->GetDBData(); + sColumnName = static_cast<SwDBFieldType*>(GetCurField()->GetTyp())->GetColumnName(); + } + } + else + { + if (auto *const pField = dynamic_cast<SwDBNameInfField*>(GetCurField())) + { + if(SwWrtShell *pSh = CheckAndGetWrtShell()) + aData = pField->GetDBData(pSh->GetDoc()); + } + } + m_xDatabaseTLB->Select(aData.sDataSource, aData.sCommand, sColumnName); + } + + switch (nTypeId) + { + case SwFieldTypesEnum::Database: + { + bFormat = true; + bDBFormat = true; + m_xNumFormatLB->show(); + m_xFormatLB->hide(); + + weld::Widget& rWidget = m_xNumFormatLB->get_widget(); + rWidget.set_accessible_relation_labeled_by(m_xNewFormatRB.get()); + + if (pBox) // type was changed by user + m_xDBFormatRB->set_active(true); + + if (IsFieldEdit()) + { + if (GetCurField()->GetFormat() != 0 && GetCurField()->GetFormat() != SAL_MAX_UINT32) + m_xNumFormatLB->SetDefFormat(GetCurField()->GetFormat()); + + if (GetCurField()->GetSubType() & nsSwExtendedSubType::SUB_OWN_FMT) + m_xNewFormatRB->set_active(true); + else + m_xDBFormatRB->set_active(true); + } + break; + } + case SwFieldTypesEnum::DatabaseNumberSet: + bSetNo = true; + [[fallthrough]]; + case SwFieldTypesEnum::DatabaseNextSet: + bCond = true; + if (IsFieldEdit()) + { + m_xConditionED->set_text(GetCurField()->GetPar1()); + m_xValueED->set_text(GetCurField()->GetPar2()); + } + break; + + case SwFieldTypesEnum::DatabaseName: + break; + + case SwFieldTypesEnum::DatabaseSetNumber: + { + bFormat = true; + m_xNewFormatRB->set_active(true); + m_xNumFormatLB->hide(); + m_xFormatLB->show(); + + m_xFormatLB->set_accessible_relation_labeled_by(m_xNewFormatRB.get()); + + if( IsFieldEdit() ) + { + for (sal_Int32 nI = m_xFormatLB->get_count(); nI;) + { + if (GetCurField()->GetFormat() == m_xFormatLB->get_id(--nI).toUInt32()) + { + m_xFormatLB->set_active( nI ); + break; + } + } + } + break; + } + default: break; + } + + m_xCondition->set_sensitive(bCond); + m_xValue->set_sensitive(bSetNo); + if (nTypeId != SwFieldTypesEnum::Database) + { + m_xDBFormatRB->set_sensitive(bDBFormat); + m_xNewFormatRB->set_sensitive(bDBFormat || bFormat); + m_xNumFormatLB->set_sensitive(bDBFormat); + m_xFormatLB->set_sensitive(bFormat); + } + m_xFormat->set_sensitive(bDBFormat || bFormat); + + if (!IsFieldEdit()) + { + m_xValueED->set_text(OUString()); + if (bCond) + m_xConditionED->set_text("TRUE"); + else + m_xConditionED->set_text(OUString()); + } + + CheckInsert(); +} + +IMPL_LINK_NOARG(SwFieldDBPage, NumSelectHdl, weld::ComboBox&, void) +{ + m_xNewFormatRB->set_active(true); + m_xNumFormatLB->CallSelectHdl(); +} + +void SwFieldDBPage::CheckInsert() +{ + bool bInsert = true; + const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + + std::unique_ptr<weld::TreeIter> xIter(m_xDatabaseTLB->make_iterator()); + if (m_xDatabaseTLB->get_selected(xIter.get())) + { + bool bEntry = m_xDatabaseTLB->iter_parent(*xIter); + + if (nTypeId == SwFieldTypesEnum::Database && bEntry) + bEntry = m_xDatabaseTLB->iter_parent(*xIter); + + bInsert &= bEntry; + } + else + bInsert = false; + + if (nTypeId == SwFieldTypesEnum::DatabaseNumberSet) + { + bool bHasValue = !m_xValueED->get_text().isEmpty(); + + bInsert &= bHasValue; + } + + EnableInsert(bInsert); +} + +IMPL_LINK(SwFieldDBPage, TreeSelectHdl, weld::TreeView&, rBox, void) +{ + std::unique_ptr<weld::TreeIter> xIter(rBox.make_iterator()); + if (!rBox.get_selected(xIter.get())) + return; + + const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + + bool bEntry = m_xDatabaseTLB->iter_parent(*xIter); + + if (nTypeId == SwFieldTypesEnum::Database && bEntry) + bEntry = m_xDatabaseTLB->iter_parent(*xIter); + + CheckInsert(); + + if (nTypeId != SwFieldTypesEnum::Database) + return; + + bool bNumFormat = false; + + if (bEntry) + { + OUString sTableName; + OUString sColumnName; + sal_Bool bIsTable; + OUString sDBName = m_xDatabaseTLB->GetDBName(sTableName, sColumnName, &bIsTable); + bNumFormat = GetFieldMgr().IsDBNumeric(sDBName, + sTableName, + bIsTable, + sColumnName); + if (!IsFieldEdit()) + m_xDBFormatRB->set_active(true); + } + + m_xDBFormatRB->set_sensitive(bNumFormat); + m_xNewFormatRB->set_sensitive(bNumFormat); + m_xNumFormatLB->set_sensitive(bNumFormat); + m_xFormat->set_sensitive(bNumFormat); +} + +IMPL_LINK_NOARG(SwFieldDBPage, AddDBHdl, weld::Button&, void) +{ + if (SwWrtShell* pSh = CheckAndGetWrtShell()) + { + OUString sNewDB + = SwDBManager::LoadAndRegisterDataSource(GetFrameWeld(), pSh->GetDoc()->GetDocShell()); + if (!sNewDB.isEmpty()) + { + m_xDatabaseTLB->AddDataSource(sNewDB); + } + } +} + +// Modify +IMPL_LINK_NOARG(SwFieldDBPage, ModifyHdl, weld::Entry&, void) +{ + CheckInsert(); +} + +void SwFieldDBPage::FillUserData() +{ + const sal_Int32 nEntryPos = m_xTypeLB->get_selected_index(); + const sal_uInt16 nTypeSel = ( -1 == nEntryPos ) + ? USHRT_MAX : m_xTypeLB->get_id(nEntryPos).toUInt32(); + SetUserData(USER_DATA_VERSION ";" + OUString::number( nTypeSel )); +} + +void SwFieldDBPage::ActivateMailMergeAddress() +{ + m_xTypeLB->select_id(OUString::number(static_cast<sal_uInt16>(SwFieldTypesEnum::Database))); + TypeListBoxHdl(*m_xTypeLB); + const SwDBData& rData = SW_MOD()->GetDBConfig()->GetAddressSource(); + m_xDatabaseTLB->Select(rData.sDataSource, rData.sCommand, u""); +} + +void SwFieldDBPage::SetWrtShell(SwWrtShell& rSh) +{ + // We need to remember the shell to be able to call correct SwDBManager + SwFieldPage::SetWrtShell(&rSh); + m_xDatabaseTLB->SetWrtShell(rSh); +} + +SwWrtShell* SwFieldDBPage::CheckAndGetWrtShell() +{ + SwWrtShell* pSh = GetWrtShell(); + if (!pSh) + { + pSh = ::GetActiveWrtShell(); + if (pSh) // this is not guaranteed: e.g., activating print preview with dialog active + SetWrtShell(*pSh); + } + return pSh; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/flddb.hxx b/sw/source/ui/fldui/flddb.hxx new file mode 100644 index 000000000..b25c38699 --- /dev/null +++ b/sw/source/ui/fldui/flddb.hxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_SW_SOURCE_UI_FLDUI_FLDDB_HXX +#define INCLUDED_SW_SOURCE_UI_FLDUI_FLDDB_HXX + +#include <condedit.hxx> +#include <dbtree.hxx> +#include <numfmtlb.hxx> + +#include "fldpage.hxx" + +class SwFieldDBPage : public SwFieldPage +{ + OUString m_sOldDBName; + OUString m_sOldTableName; + OUString m_sOldColumnName; + sal_uLong m_nOldFormat; + sal_uInt16 m_nOldSubType; + + std::unique_ptr<weld::TreeView> m_xTypeLB; + std::unique_ptr<SwDBTreeList> m_xDatabaseTLB; + std::unique_ptr<weld::Button> m_xAddDBPB; + std::unique_ptr<weld::Widget> m_xCondition; + std::unique_ptr<ConditionEdit> m_xConditionED; + std::unique_ptr<weld::Widget> m_xValue; + std::unique_ptr<weld::Entry> m_xValueED; + std::unique_ptr<weld::RadioButton> m_xDBFormatRB; + std::unique_ptr<weld::RadioButton> m_xNewFormatRB; + std::unique_ptr<NumFormatListBox> m_xNumFormatLB; + std::unique_ptr<weld::ComboBox> m_xFormatLB; + std::unique_ptr<weld::Widget> m_xFormat; + + DECL_LINK( TypeListBoxHdl, weld::TreeView&, void ); + DECL_LINK( NumSelectHdl, weld::ComboBox&, void ); + DECL_LINK( TreeSelectHdl, weld::TreeView&, void ); + DECL_LINK( ModifyHdl, weld::Entry&, void ); + DECL_LINK( AddDBHdl, weld::Button&, void ); + void TypeHdl(const weld::TreeView*); + + void CheckInsert(); + + using SwFieldPage::SetWrtShell; + SwWrtShell* CheckAndGetWrtShell(); + +protected: + virtual sal_uInt16 GetGroup() override; + +public: + SwFieldDBPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet); + + virtual ~SwFieldDBPage() override; + + static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual bool DeferResetToFirstActivation() override; + + virtual void FillUserData() override; + void ActivateMailMergeAddress(); + + void SetWrtShell(SwWrtShell& rSh); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/flddinf.cxx b/sw/source/ui/fldui/flddinf.cxx new file mode 100644 index 000000000..c96cfbc0c --- /dev/null +++ b/sw/source/ui/fldui/flddinf.cxx @@ -0,0 +1,483 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sfx2/frame.hxx> +#include <svl/numformat.hxx> +#include <svl/zforlist.hxx> +#include <svl/zformat.hxx> +#include <o3tl/string_view.hxx> + +#include <swtypes.hxx> +#include <flddinf.hrc> +#include <strings.hrc> +#include <fldbas.hxx> +#include <docufld.hxx> +#include <wrtsh.hxx> +#include <cmdid.h> + +#include "flddinf.hxx" +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <com/sun/star/util/Time.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/util/Date.hpp> + +#define USER_DATA_VERSION_1 "1" +#define USER_DATA_VERSION USER_DATA_VERSION_1 + +using namespace nsSwDocInfoSubType; +using namespace com::sun::star; + +void FillFieldSelect(weld::TreeView& rListBox) +{ + for (size_t i = 0; i < SAL_N_ELEMENTS(FLD_SELECT); ++i) + rListBox.append_text(SwResId(FLD_SELECT[i])); +} + +SwFieldDokInfPage::SwFieldDokInfPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *const pCoreSet) + : SwFieldPage(pPage, pController, "modules/swriter/ui/flddocinfopage.ui", "FieldDocInfoPage", pCoreSet) + , nOldSel(0) + , nOldFormat(0) + , m_xTypeTLB(m_xBuilder->weld_tree_view("type")) + , m_xSelection(m_xBuilder->weld_widget("selectframe")) + , m_xSelectionLB(m_xBuilder->weld_tree_view("select")) + , m_xFormat(m_xBuilder->weld_widget("formatframe")) + , m_xFormatLB(new SwNumFormatTreeView(m_xBuilder->weld_tree_view("format"))) + , m_xFixedCB(m_xBuilder->weld_check_button("fixed")) +{ + m_xTypeTLB->make_sorted(); + FillFieldSelect(*m_xSelectionLB); + + auto nWidth = m_xTypeTLB->get_approximate_digit_width() * FIELD_COLUMN_WIDTH; + auto nHeight = m_xTypeTLB->get_height_rows(10); + m_xTypeTLB->set_size_request(nWidth, nHeight); + m_xFormatLB->get_widget().set_size_request(nWidth * 2, nHeight); + m_xSelectionLB->set_size_request(nWidth, nHeight); + + //enable 'active' language selection + m_xFormatLB->SetShowLanguageControl(true); + + const SfxUnoAnyItem* pItem = pCoreSet + ? pCoreSet->GetItem(FN_FIELD_DIALOG_DOC_PROPS, false) + : nullptr; + if ( pItem ) + pItem->GetValue() >>= xCustomPropertySet; + + // uitests + m_xTypeTLB->set_buildable_name(m_xTypeTLB->get_buildable_name() + "-docinf"); + m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-docinf"); + m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-docinf"); +} + +SwFieldDokInfPage::~SwFieldDokInfPage() +{ +} + +void SwFieldDokInfPage::Reset(const SfxItemSet* ) +{ + Init(); // general initialisation + + // initialise TypeListBox + m_xTypeTLB->freeze(); + m_xTypeTLB->clear(); + m_xSelEntry.reset(); + + // display SubTypes in TypeLB + sal_uInt16 nSubType = USHRT_MAX; + if (IsFieldEdit()) + { + const SwField* pCurField = GetCurField(); + nSubType = pCurField->GetSubType() & 0xff; + if( nSubType == DI_CUSTOM ) + { + if (auto const pField = dynamic_cast<SwDocInfoField const*>(pCurField)) + { + m_sOldCustomFieldName = pField->GetName(); + } + } + m_xFormatLB->SetAutomaticLanguage(pCurField->IsAutomaticLanguage()); + SwWrtShell *pSh = GetWrtShell(); + if(pSh) + { + const SvNumberformat* pFormat = pSh->GetNumberFormatter()->GetEntry(pCurField->GetFormat()); + if(pFormat) + m_xFormatLB->SetLanguage(pFormat->GetLanguage()); + } + } + + sal_Int32 nSelEntryData = -1; + const OUString sUserData = GetUserData(); + sal_Int32 nIdx{ 0 }; + if (o3tl::equalsIgnoreAsciiCase(o3tl::getToken(sUserData, 0, ';', nIdx), u"" USER_DATA_VERSION_1)) + { + nSelEntryData = o3tl::toInt32(o3tl::getToken(sUserData, 0, ';', nIdx)); + } + + std::vector<OUString> aLst; + GetFieldMgr().GetSubTypes(SwFieldTypesEnum::DocumentInfo, aLst); + std::unique_ptr<weld::TreeIter> xEntry(m_xTypeTLB->make_iterator()); + std::unique_ptr<weld::TreeIter> xExpandEntry; + for(size_t i = 0; i < aLst.size(); ++i) + { + if (!IsFieldEdit() || nSubType == i) + { + const OUString sId(OUString::number(i)); + if (DI_CUSTOM == i) + { + if(xCustomPropertySet.is() ) + { + uno::Reference< beans::XPropertySetInfo > xSetInfo = xCustomPropertySet->getPropertySetInfo(); + const uno::Sequence< beans::Property > rProperties = xSetInfo->getProperties(); + + if( rProperties.hasElements() ) + { + std::unique_ptr<weld::TreeIter> xInfo(m_xTypeTLB->make_iterator()); + + OUString sText(SwResId(STR_CUSTOM_FIELD)); + OUString sEntryId(OUString::number(USHRT_MAX)); + m_xTypeTLB->insert(nullptr, -1, &sText, &sEntryId, nullptr, + nullptr, false, xInfo.get()); + for (const auto& rProperty : rProperties) + { + const OUString sEntry = rProperty.Name; + + m_xTypeTLB->insert(xInfo.get(), -1, &sEntry, &sId, + nullptr, nullptr, false, xEntry.get()); + if (m_sOldCustomFieldName == sEntry) + { + m_xSelEntry = m_xTypeTLB->make_iterator(xEntry.get()); + xExpandEntry = m_xTypeTLB->make_iterator(xInfo.get()); + } + } + } + } + } + else + { + if (!(IsFieldDlgHtmlMode() && (i == DI_EDIT || i == DI_SUBJECT || i == DI_PRINT))) + { + m_xTypeTLB->insert(nullptr, -1, &aLst[i], &sId, + nullptr, nullptr, false, xEntry.get()); + } + } + if (static_cast<size_t>(nSelEntryData) == i) + m_xSelEntry = std::move(xEntry); + } + } + + m_xTypeTLB->thaw(); + + if (xExpandEntry) + m_xTypeTLB->expand_row(*xExpandEntry); + + // select old Pos + if (m_xSelEntry) + { + m_xTypeTLB->select(*m_xSelEntry); + nSubType = m_xTypeTLB->get_id(*m_xSelEntry).toUInt32(); + } + else + { + m_xSelEntry = m_xTypeTLB->make_iterator(); + if (m_xTypeTLB->get_iter_first(*m_xSelEntry)) + nSubType = m_xTypeTLB->get_id(*m_xSelEntry).toUInt32(); + else + m_xSelEntry.reset(); + } + + FillSelectionLB(nSubType); + if (m_xSelEntry) + TypeHdl(*m_xTypeTLB); + + m_xTypeTLB->connect_changed(LINK(this, SwFieldDokInfPage, TypeHdl)); + m_xTypeTLB->connect_row_activated(LINK(this, SwFieldDokInfPage, TreeViewInsertHdl)); + m_xSelectionLB->connect_changed(LINK(this, SwFieldDokInfPage, SubTypeHdl)); + m_xSelectionLB->connect_row_activated(LINK(this, SwFieldDokInfPage, TreeViewInsertHdl)); + m_xFormatLB->connect_row_activated(LINK(this, SwFieldDokInfPage, TreeViewInsertHdl)); + + if (IsFieldEdit()) + { + nOldSel = m_xSelectionLB->get_selected_index(); + nOldFormat = GetCurField()->GetFormat(); + m_xFixedCB->save_state(); + } +} + +IMPL_LINK_NOARG(SwFieldDokInfPage, TypeHdl, weld::TreeView&, void) +{ + // current ListBoxPos + if (!m_xTypeTLB->get_selected(m_xSelEntry.get()) && + m_xTypeTLB->get_iter_first(*m_xSelEntry)) + { + m_xTypeTLB->select(*m_xSelEntry); + } + FillSelectionLB(m_xTypeTLB->get_id(*m_xSelEntry).toUInt32()); + SubTypeHdl(*m_xSelectionLB); +} + +IMPL_LINK_NOARG(SwFieldDokInfPage, SubTypeHdl, weld::TreeView&, void) +{ + sal_uInt16 nSubType = m_xTypeTLB->get_id(*m_xSelEntry).toUInt32(); + sal_Int32 nPos = m_xSelectionLB->get_selected_index(); + sal_uInt16 nExtSubType; + SvNumFormatType nNewType = SvNumFormatType::ALL; + + if (nSubType != DI_EDIT) + { + if (nPos == -1) + { + if (!m_xSelectionLB->n_children()) + { + m_xFormatLB->clear(); + m_xFormat->set_sensitive(false); + if( nSubType == DI_CUSTOM ) + { + //find out which type the custom field has - for a start set to DATE format + const OUString sName = m_xTypeTLB->get_text(*m_xSelEntry); + try + { + uno::Any aVal = xCustomPropertySet->getPropertyValue( sName ); + const uno::Type& rValueType = aVal.getValueType(); + if( rValueType == ::cppu::UnoType<util::DateTime>::get()) + { + nNewType = SvNumFormatType::DATETIME; + } + else if( rValueType == ::cppu::UnoType<util::Date>::get()) + { + nNewType = SvNumFormatType::DATE; + } + else if( rValueType == ::cppu::UnoType<util::Time>::get()) + { + nNewType = SvNumFormatType::TIME; + } + } + catch( const uno::Exception& ) + { + } + } + else + return; + } + nPos = 0; + } + + nExtSubType = m_xSelectionLB->get_id(nPos).toUInt32(); + } + else + nExtSubType = DI_SUB_TIME; + + SvNumFormatType nOldType = SvNumFormatType::ALL; + bool bEnable = false; + bool bOneArea = false; + + if (m_xFormatLB->get_active()) + nOldType = m_xFormatLB->GetFormatType(); + + switch (nExtSubType) + { + case DI_SUB_AUTHOR: + break; + + case DI_SUB_DATE: + nNewType = SvNumFormatType::DATE; + bOneArea = true; + break; + + case DI_SUB_TIME: + nNewType = SvNumFormatType::TIME; + bOneArea = true; + break; + } + if (nNewType == SvNumFormatType::ALL) + { + m_xFormatLB->clear(); + } + else + { + if (nOldType != nNewType) + { + m_xFormatLB->SetFormatType(nNewType); + m_xFormatLB->SetOneArea(bOneArea); + } + bEnable = true; + } + + sal_uInt32 nFormat = 0; + + sal_uInt16 nOldSubType = 0; + + if (IsFieldEdit()) + { + if (auto const pField = dynamic_cast<SwDocInfoField const*>(GetCurField())) + { + nFormat = pField->GetFormat(); + nOldSubType = pField->GetSubType() & 0xff00; + } + nPos = m_xSelectionLB->get_selected_index(); + if (nPos != -1) + { + nSubType = m_xSelectionLB->get_id(nPos).toUInt32(); + + nOldSubType &= ~DI_SUB_FIXED; + if (nOldSubType == nSubType) + { + if (!nFormat && (nNewType == SvNumFormatType::DATE || nNewType == SvNumFormatType::TIME)) + { + SwWrtShell *pSh = GetWrtShell(); + if(pSh) + { + SvNumberFormatter* pFormatter = pSh->GetNumberFormatter(); + LanguageType eLang = m_xFormatLB->GetCurLanguage(); + if (nNewType == SvNumFormatType::DATE) + nFormat = pFormatter->GetFormatIndex( NF_DATE_SYSTEM_SHORT, eLang); + else if (nNewType == SvNumFormatType::TIME) + nFormat = pFormatter->GetFormatIndex( NF_TIME_HHMM, eLang); + } + } + m_xFormatLB->SetDefFormat(nFormat); + } + } + else if( (nSubType == DI_CUSTOM) && (nNewType != SvNumFormatType::ALL) ) + { + m_xFormatLB->SetDefFormat(nFormat); + } + } + + // Always allow Fixed Content to be turned off if it is currently on + m_xFormat->set_sensitive(bEnable || m_xFixedCB->get_active()); + + if (!bEnable) + m_xFormatLB->clear(); + else if (m_xFormatLB->get_selected_index() == -1) + m_xFormatLB->select(0); +} + +sal_Int32 SwFieldDokInfPage::FillSelectionLB(sal_uInt16 nSubType) +{ + // fill Format-Listbox + SwFieldTypesEnum nTypeId = SwFieldTypesEnum::DocumentInfo; + + EnableInsert(nSubType != USHRT_MAX); + + if (nSubType == USHRT_MAX) // Info-Text + nSubType = DI_SUBTYPE_BEGIN; + + m_xSelectionLB->clear(); + + sal_uInt16 nSize = 0; + sal_Int32 nSelPos = -1; + sal_uInt16 nExtSubType = 0; + + if (IsFieldEdit()) + { + if (auto const pField = dynamic_cast<SwDocInfoField const*>(GetCurField())) + { + nExtSubType = pField->GetSubType() & 0xff00; + } + m_xFixedCB->set_active((nExtSubType & DI_SUB_FIXED) != 0); + nExtSubType = ((nExtSubType & ~DI_SUB_FIXED) >> 8) - 1; + } + + if (nSubType < DI_CREATE || nSubType == DI_DOCNO || nSubType == DI_EDIT|| nSubType == DI_CUSTOM ) + { + // Format Box is empty for Title and Time + } + else + { + nSize = GetFieldMgr().GetFormatCount(nTypeId, IsFieldDlgHtmlMode()); + for (sal_uInt16 i = 0; i < nSize; ++i) + { + OUString sId(OUString::number(GetFieldMgr().GetFormatId(nTypeId, i))); + m_xSelectionLB->append(sId, GetFieldMgr().GetFormatStr(nTypeId, i)); + if (IsFieldEdit() && i == nExtSubType) + nSelPos = i; + } + } + + bool bEnable = nSize != 0; + + if (nSize) + { + if (m_xSelectionLB->get_selected_index() == -1) + m_xSelectionLB->select(nSelPos == USHRT_MAX ? 0 : nSelPos); + bEnable = true; + } + + m_xSelection->set_sensitive(bEnable); + + return nSize; +} + +bool SwFieldDokInfPage::FillItemSet(SfxItemSet* ) +{ + if (!m_xSelEntry) + return false; + + sal_uInt16 nSubType = m_xTypeTLB->get_id(*m_xSelEntry).toUInt32(); + if (nSubType == USHRT_MAX) + return false; + + sal_uInt32 nFormat = 0; + + sal_Int32 nPos = m_xSelectionLB->get_selected_index(); + + OUString aName; + if (DI_CUSTOM == nSubType) + aName = m_xTypeTLB->get_text(*m_xSelEntry); + + if (nPos != -1) + nSubType |= m_xSelectionLB->get_id(nPos).toUInt32(); + + if (m_xFixedCB->get_active()) + nSubType |= DI_SUB_FIXED; + + nPos = m_xFormatLB->get_selected_index(); + if(nPos != -1) + nFormat = m_xFormatLB->GetFormat(); + + if (!IsFieldEdit() || nOldSel != m_xSelectionLB->get_selected_index() || + nOldFormat != nFormat || m_xFixedCB->get_state_changed_from_saved() + || (DI_CUSTOM == nSubType && aName != m_sOldCustomFieldName )) + { + InsertField(SwFieldTypesEnum::DocumentInfo, nSubType, aName, OUString(), nFormat, + ' ', m_xFormatLB->IsAutomaticLanguage()); + } + + return false; +} + +std::unique_ptr<SfxTabPage> SwFieldDokInfPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet *const pAttrSet) +{ + return std::make_unique<SwFieldDokInfPage>(pPage, pController, pAttrSet); +} + +sal_uInt16 SwFieldDokInfPage::GetGroup() +{ + return GRP_REG; +} + +void SwFieldDokInfPage::FillUserData() +{ + int nEntry = m_xTypeTLB->get_selected_index(); + sal_uInt16 nTypeSel = nEntry != -1 ? m_xTypeTLB->get_id(nEntry).toUInt32() : USHRT_MAX; + SetUserData(USER_DATA_VERSION ";" + OUString::number( nTypeSel )); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/flddinf.hxx b/sw/source/ui/fldui/flddinf.hxx new file mode 100644 index 000000000..fb6fffff8 --- /dev/null +++ b/sw/source/ui/fldui/flddinf.hxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_SW_SOURCE_UI_FLDUI_FLDDINF_HXX +#define INCLUDED_SW_SOURCE_UI_FLDUI_FLDDINF_HXX + +#include <sfx2/tabdlg.hxx> +#include <numfmtlb.hxx> +#include "fldpage.hxx" + +namespace com::sun::star::beans { class XPropertySet; } + +class SwFieldDokInfPage : public SwFieldPage +{ + std::unique_ptr<weld::TreeIter> m_xSelEntry; + css::uno::Reference < css::beans::XPropertySet > xCustomPropertySet; + + sal_Int32 nOldSel; + sal_uLong nOldFormat; + OUString m_sOldCustomFieldName; + + std::unique_ptr<weld::TreeView> m_xTypeTLB; + std::unique_ptr<weld::Widget> m_xSelection; + std::unique_ptr<weld::TreeView> m_xSelectionLB; + std::unique_ptr<weld::Widget> m_xFormat; + std::unique_ptr<SwNumFormatTreeView> m_xFormatLB; + std::unique_ptr<weld::CheckButton> m_xFixedCB; + + DECL_LINK(TypeHdl, weld::TreeView&, void); + DECL_LINK(SubTypeHdl, weld::TreeView&, void); + + sal_Int32 FillSelectionLB(sal_uInt16 nSubTypeId); + +protected: + virtual sal_uInt16 GetGroup() override; + +public: + SwFieldDokInfPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pSet); + virtual ~SwFieldDokInfPage() override; + + static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + + virtual void FillUserData() override; +}; + +void FillFieldSelect(weld::TreeView& rListBox); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/flddok.cxx b/sw/source/ui/fldui/flddok.cxx new file mode 100644 index 000000000..4e65a7c3f --- /dev/null +++ b/sw/source/ui/fldui/flddok.cxx @@ -0,0 +1,641 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <flddat.hxx> +#include <docufld.hxx> +#include <strings.hrc> +#include <chpfld.hxx> +#include "flddok.hxx" +#include <swmodule.hxx> +#include <wrtsh.hxx> +#include <svl/numformat.hxx> +#include <svl/zformat.hxx> +#include <o3tl/string_view.hxx> + +#define USER_DATA_VERSION_1 "1" +#define USER_DATA_VERSION USER_DATA_VERSION_1 + +SwFieldDokPage::SwFieldDokPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *const pCoreSet) + : SwFieldPage(pPage, pController, "modules/swriter/ui/flddocumentpage.ui", + "FieldDocumentPage", pCoreSet) + , nOldSel(0) + , nOldFormat(0) + , m_xTypeLB(m_xBuilder->weld_tree_view("type")) + , m_xSelection(m_xBuilder->weld_widget("selectframe")) + , m_xSelectionLB(m_xBuilder->weld_tree_view("select")) + , m_xValueFT(m_xBuilder->weld_label("valueft")) + , m_xValueED(m_xBuilder->weld_entry("value")) + , m_xLevelFT(m_xBuilder->weld_label("levelft")) + , m_xLevelED(m_xBuilder->weld_spin_button("level")) + , m_xDateFT(m_xBuilder->weld_label("daysft")) + , m_xTimeFT(m_xBuilder->weld_label("minutesft")) + , m_xDateOffsetED(m_xBuilder->weld_spin_button("offset")) + , m_xFormat(m_xBuilder->weld_widget("formatframe")) + , m_xFormatLB(m_xBuilder->weld_tree_view("format")) + , m_xNumFormatLB(new SwNumFormatTreeView(m_xBuilder->weld_tree_view("numformat"))) + , m_xFixedCB(m_xBuilder->weld_check_button("fixed")) +{ + m_xTypeLB->make_sorted(); + m_xFormatLB->make_sorted(); + + auto nWidth = m_xTypeLB->get_approximate_digit_width() * FIELD_COLUMN_WIDTH; + auto nHeight = m_xTypeLB->get_height_rows(10); + + m_xTypeLB->set_size_request(nWidth, nHeight); + m_xSelectionLB->set_size_request(nWidth, nHeight); + m_xFormatLB->set_size_request(nWidth * 2, nHeight); + + m_xSelectionLB->connect_row_activated(LINK(this, SwFieldDokPage, TreeViewInsertHdl)); + m_xFormatLB->connect_row_activated(LINK(this, SwFieldDokPage, TreeViewInsertHdl)); + m_xNumFormatLB->connect_row_activated(LINK(this, SwFieldDokPage, NumFormatHdl)); + + m_xLevelED->set_max(MAXLEVEL); + m_xDateOffsetED->set_range(INT_MIN, INT_MAX); + //enable 'active' language selection + m_xNumFormatLB->SetShowLanguageControl(true); + + // uitests + m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-doc"); + m_xValueED->set_buildable_name(m_xValueED->get_buildable_name() + "-doc"); + m_xNumFormatLB->set_buildable_name(m_xNumFormatLB->get_buildable_name() + "-doc"); + m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-doc"); + m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-doc"); +} + +SwFieldDokPage::~SwFieldDokPage() +{ +} + +void SwFieldDokPage::Reset(const SfxItemSet* ) +{ + SavePos(*m_xTypeLB); + Init(); // general initialisation + + // initialise TypeListBox + const SwFieldGroupRgn& rRg = SwFieldMgr::GetGroupRange(IsFieldDlgHtmlMode(), GetGroup()); + + m_xTypeLB->freeze(); + m_xTypeLB->clear(); + + if (!IsFieldEdit()) + { + bool bPage = false; + // fill Type-Listbox + for(sal_uInt16 i = rRg.nStart; i < rRg.nEnd; ++i) + { + const SwFieldTypesEnum nTypeId = SwFieldMgr::GetTypeId(i); + + switch (nTypeId) + { + case SwFieldTypesEnum::PreviousPage: + case SwFieldTypesEnum::NextPage: + case SwFieldTypesEnum::PageNumber: + if (!bPage) + { + m_xTypeLB->append(OUString::number(USHRT_MAX), SwResId(FMT_REF_PAGE)); + bPage = true; + } + break; + + default: + m_xTypeLB->append(OUString::number(static_cast<sal_uInt16>(nTypeId)), SwFieldMgr::GetTypeStr(i)); + break; + } + } + } + else + { + const SwField* pCurField = GetCurField(); + SwFieldTypesEnum nTypeId = pCurField->GetTypeId(); + if (nTypeId == SwFieldTypesEnum::FixedDate) + nTypeId = SwFieldTypesEnum::Date; + if (nTypeId == SwFieldTypesEnum::FixedTime) + nTypeId = SwFieldTypesEnum::Time; + m_xTypeLB->append(OUString::number(static_cast<sal_uInt16>(nTypeId)), SwFieldMgr::GetTypeStr(SwFieldMgr::GetPos(nTypeId))); + m_xNumFormatLB->SetAutomaticLanguage(pCurField->IsAutomaticLanguage()); + SwWrtShell *pSh = GetWrtShell(); + if(!pSh) + pSh = ::GetActiveWrtShell(); + if(pSh) + { + const SvNumberformat* pFormat = pSh->GetNumberFormatter()->GetEntry(pCurField->GetFormat()); + if(pFormat) + m_xNumFormatLB->SetLanguage(pFormat->GetLanguage()); + } + } + + + m_xTypeLB->thaw(); + + // select old Pos + RestorePos(*m_xTypeLB); + + m_xTypeLB->connect_row_activated(LINK(this, SwFieldDokPage, TreeViewInsertHdl)); + m_xTypeLB->connect_changed(LINK(this, SwFieldDokPage, TypeHdl)); + m_xFormatLB->connect_changed(LINK(this, SwFieldDokPage, FormatHdl)); + + if( !IsRefresh() ) + { + const OUString sUserData = GetUserData(); + sal_Int32 nIdx{ 0 }; + if (o3tl::equalsIgnoreAsciiCase(o3tl::getToken(sUserData, 0, ';', nIdx), u"" USER_DATA_VERSION_1)) + { + const sal_uInt16 nVal = static_cast< sal_uInt16 >(o3tl::toInt32(o3tl::getToken(sUserData, 0, ';', nIdx))); + if(nVal != USHRT_MAX) + { + for (int i = 0, nEntryCount = m_xTypeLB->n_children(); i < nEntryCount; i++) + { + if (nVal == m_xTypeLB->get_id(i).toUInt32()) + { + m_xTypeLB->select(i); + break; + } + } + } + } + } + TypeHdl(*m_xTypeLB); + + if (IsFieldEdit()) + { + nOldSel = m_xSelectionLB->get_selected_index(); + nOldFormat = GetCurField()->GetFormat(); + m_xFixedCB->save_state(); + m_xValueED->save_value(); + m_xLevelED->save_value(); + m_xDateOffsetED->save_value(); + } +} + +IMPL_LINK_NOARG(SwFieldDokPage, TypeHdl, weld::TreeView&, void) +{ + // save old ListBoxPos + const sal_Int32 nOld = GetTypeSel(); + + // current ListBoxPos + SetTypeSel(m_xTypeLB->get_selected_index()); + + if(GetTypeSel() == -1) + { + SetTypeSel(0); + m_xTypeLB->select(0); + } + + if (nOld == GetTypeSel()) + return; + + size_t nCount; + + m_xDateFT->hide(); + m_xTimeFT->hide(); + + SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + + // fill Selection-Listbox + m_xSelectionLB->clear(); + + if (nTypeId != SwFieldTypesEnum::Unknown) + { + std::vector<OUString> aLst; + GetFieldMgr().GetSubTypes(nTypeId, aLst); + + if (nTypeId != SwFieldTypesEnum::Author) + nCount = aLst.size(); + else + nCount = GetFieldMgr().GetFormatCount(nTypeId, IsFieldDlgHtmlMode()); + + for (size_t i = 0; i < nCount; ++i) + { + if (!IsFieldEdit()) + { + OUString sId(OUString::number(i)); + if (nTypeId != SwFieldTypesEnum::Author) + m_xSelectionLB->append(sId, aLst[i]); + else + m_xSelectionLB->append(sId, GetFieldMgr().GetFormatStr(nTypeId, i)); + } + else + { + bool bInsert = false; + + OUString sId(OUString::number(i)); + + switch (nTypeId) + { + case SwFieldTypesEnum::Date: + case SwFieldTypesEnum::Time: + m_xSelectionLB->append(sId, aLst[i]); + if (static_cast<SwDateTimeField*>(GetCurField())->IsFixed() && !i) + m_xSelectionLB->select_id(sId); + if (!static_cast<SwDateTimeField*>(GetCurField())->IsFixed() && i) + m_xSelectionLB->select_id(sId); + break; + case SwFieldTypesEnum::ExtendedUser: + case SwFieldTypesEnum::DocumentStatistics: + m_xSelectionLB->append(sId, aLst[i]); + if (GetCurField()->GetSubType() == i) + m_xSelectionLB->select_id(sId); + break; + + case SwFieldTypesEnum::Author: + { + const OUString sFormat(GetFieldMgr().GetFormatStr(nTypeId, i)); + m_xSelectionLB->append(sId, sFormat); + m_xSelectionLB->select_text(GetFieldMgr().GetFormatStr(nTypeId, GetCurField()->GetFormat())); + break; + } + + default: + if (aLst[i] == GetCurField()->GetPar1()) + bInsert = true; + break; + } + if (bInsert) + { + m_xSelectionLB->append(sId, aLst[i]); + break; + } + } + } + m_xSelectionLB->connect_changed(Link<weld::TreeView&,void>()); + } + else + { + AddSubType(SwFieldTypesEnum::PageNumber); + AddSubType(SwFieldTypesEnum::PreviousPage); + AddSubType(SwFieldTypesEnum::NextPage); + nTypeId = static_cast<SwFieldTypesEnum>(m_xSelectionLB->get_id(0).toUInt32()); + nCount = 3; + m_xSelectionLB->connect_changed(LINK(this, SwFieldDokPage, SubTypeHdl)); + } + + bool bEnable = nCount != 0; + + if (bEnable && m_xSelectionLB->get_selected_index() == -1) + m_xSelectionLB->select(0); + + m_xSelection->set_sensitive( bEnable ); + + // fill Format-Listbox + sal_Int32 nSize = FillFormatLB(nTypeId); + + bool bValue = false, bLevel = false, bNumFormat = false, bOffset = false; + bool bFormat = nSize != 0; + bool bOneArea = false; + bool bFixed = false; + SvNumFormatType nFormatType = SvNumFormatType::ALL; + + switch (nTypeId) + { + case SwFieldTypesEnum::Date: + bFormat = bNumFormat = bOneArea = bOffset = true; + + nFormatType = SvNumFormatType::DATE; + + m_xDateFT->show(); + + m_xDateOffsetED->set_range(INT_MIN, INT_MAX); // no limit + + if (IsFieldEdit()) + m_xDateOffsetED->set_value( static_cast<SwDateTimeField*>(GetCurField())->GetOffset() / 24 / 60); + break; + + case SwFieldTypesEnum::Time: + bFormat = bNumFormat = bOneArea = bOffset = true; + + nFormatType = SvNumFormatType::TIME; + + m_xTimeFT->show(); + + m_xDateOffsetED->set_range(-1440, 1440); // one day + + if (IsFieldEdit()) + m_xDateOffsetED->set_value( static_cast<SwDateTimeField*>(GetCurField())->GetOffset() ); + break; + + case SwFieldTypesEnum::PreviousPage: + case SwFieldTypesEnum::NextPage: + if (IsFieldEdit()) + { + const sal_uInt16 nTmp = m_xFormatLB->get_selected_id().toUInt32(); + + if(SVX_NUM_CHAR_SPECIAL != nTmp) + { + sal_Int32 nOff = GetCurField()->GetPar2().toInt32(); + if( SwFieldTypesEnum::NextPage == nTypeId && 1 != nOff ) + m_xValueED->set_text( + OUString::number(nOff - 1) ); + else if( SwFieldTypesEnum::PreviousPage == nTypeId && -1 != nOff ) + m_xValueED->set_text( + OUString::number(nOff + 1) ); + else + m_xValueED->set_text(OUString()); + } + else + m_xValueED->set_text(static_cast<SwPageNumberField*>(GetCurField())->GetUserString()); + } + bValue = true; + break; + + case SwFieldTypesEnum::Chapter: + m_xValueFT->set_label(SwResId(STR_LEVEL)); + if (IsFieldEdit()) + m_xLevelED->set_text(OUString::number(static_cast<SwChapterField*>(GetCurField())->GetLevel(GetWrtShell()->GetLayout()) + 1)); + bLevel = true; + break; + + case SwFieldTypesEnum::PageNumber: + m_xValueFT->set_label( SwResId( STR_OFFSET )); + if (IsFieldEdit()) + m_xValueED->set_text(GetCurField()->GetPar2()); + bValue = true; + break; + + case SwFieldTypesEnum::ExtendedUser: + case SwFieldTypesEnum::Author: + case SwFieldTypesEnum::Filename: + bFixed = true; + break; + + default: + break; + } + + if (bNumFormat) + { + if (IsFieldEdit()) + { + m_xNumFormatLB->SetDefFormat(GetCurField()->GetFormat()); + + if (m_xNumFormatLB->GetFormatType() == (SvNumFormatType::DATE|SvNumFormatType::TIME)) + { + // always set Format-Type because otherwise when date/time formats are combined, + // both formats would be displayed at the same time + m_xNumFormatLB->SetFormatType(SvNumFormatType::ALL); + m_xNumFormatLB->SetFormatType(nFormatType); + // set correct format once again + m_xNumFormatLB->SetDefFormat(GetCurField()->GetFormat()); + } + } + else + m_xNumFormatLB->SetFormatType(nFormatType); + + m_xNumFormatLB->SetOneArea(bOneArea); + } + + m_xFormatLB->set_visible(!bNumFormat); + m_xNumFormatLB->set_visible(bNumFormat); + + m_xValueFT->set_visible(bValue); + m_xValueED->set_visible(bValue); + m_xLevelFT->set_visible(bLevel); + m_xLevelED->set_visible(bLevel); + m_xDateOffsetED->set_visible(bOffset); + m_xFixedCB->set_visible(!bValue && !bLevel && !bOffset); + + m_xFormat->set_sensitive(bFormat); + m_xFixedCB->set_sensitive(bFixed); + + if (IsFieldEdit()) + m_xFixedCB->set_active((GetCurField()->GetFormat() & AF_FIXED) != 0 && bFixed); + + if (m_xNumFormatLB->get_selected_index() == -1) + m_xNumFormatLB->select(0); + m_xValueFT->set_sensitive(bValue || bLevel || bOffset); + m_xValueED->set_sensitive(bValue); +} + +void SwFieldDokPage::AddSubType(SwFieldTypesEnum nTypeId) +{ + m_xSelectionLB->append(OUString::number(static_cast<sal_uInt16>(nTypeId)), SwFieldType::GetTypeStr(nTypeId)); +} + +IMPL_LINK_NOARG(SwFieldDokPage, SubTypeHdl, weld::TreeView&, void) +{ + sal_Int32 nPos = m_xSelectionLB->get_selected_index(); + if(nPos == -1) + nPos = 0; + + const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xSelectionLB->get_id(nPos).toUInt32()); + FillFormatLB(nTypeId); + + TranslateId pTextRes; + switch (nTypeId) + { + case SwFieldTypesEnum::Chapter: + pTextRes = STR_LEVEL; + break; + + case SwFieldTypesEnum::PreviousPage: + case SwFieldTypesEnum::NextPage: + pTextRes = SVX_NUM_CHAR_SPECIAL == m_xFormatLB->get_selected_id().toUInt32() + ? STR_VALUE : STR_OFFSET; + break; + + case SwFieldTypesEnum::PageNumber: + pTextRes = STR_OFFSET; + break; + default: break; + } + + if (pTextRes) + m_xValueFT->set_label(SwResId(pTextRes)); +} + +sal_Int32 SwFieldDokPage::FillFormatLB(SwFieldTypesEnum nTypeId) +{ + // fill Format-Listbox + m_xFormatLB->clear(); + + if (nTypeId == SwFieldTypesEnum::Author) + return m_xFormatLB->n_children(); + + const sal_uInt16 nSize = GetFieldMgr().GetFormatCount(nTypeId, IsFieldDlgHtmlMode()); + + for( sal_uInt16 i = 0; i < nSize; ++i ) + { + const sal_uInt16 nFormatId = GetFieldMgr().GetFormatId( nTypeId, i ); + OUString sId(OUString::number(nFormatId)); + m_xFormatLB->append(sId, GetFieldMgr().GetFormatStr(nTypeId, i)); + } + + if (IsFieldEdit()) + { + m_xFormatLB->select_id(OUString::number(GetCurField()->GetFormat() & ~AF_FIXED)); + } + else + { + // Select default selected value for "Insert" dialog + switch (nTypeId) + { + case SwFieldTypesEnum::PageNumber: + case SwFieldTypesEnum::DocumentStatistics: + m_xFormatLB->select_text(SwResId(FMT_NUM_PAGEDESC)); + break; + default: + m_xFormatLB->select(0); + } + } + + FormatHdl(*m_xFormatLB); + + return nSize; +} + +IMPL_LINK_NOARG(SwFieldDokPage, FormatHdl, weld::TreeView&, void) +{ + SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + + if (nTypeId == SwFieldTypesEnum::Unknown) + { + sal_Int32 nPos = m_xSelectionLB->get_selected_index(); + if(nPos == -1) + nPos = 0; + + nTypeId = static_cast<SwFieldTypesEnum>(m_xSelectionLB->get_id(nPos).toUInt32()); + } + + if (nTypeId != SwFieldTypesEnum::NextPage && nTypeId != SwFieldTypesEnum::PreviousPage) + return; + + // Prev/Next - PageNumFields special treatment: + sal_uInt16 nTmp = m_xFormatLB->get_selected_id().toUInt32(); + const OUString sOldText( m_xValueFT->get_label() ); + const OUString sNewText( SwResId( SVX_NUM_CHAR_SPECIAL == nTmp ? STR_VALUE + : STR_OFFSET )); + + if (sOldText != sNewText) + m_xValueFT->set_label(sNewText); + + if (sOldText != m_xValueFT->get_label()) + m_xValueED->set_text(OUString()); +} + +bool SwFieldDokPage::FillItemSet(SfxItemSet* ) +{ + SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + + if (nTypeId == SwFieldTypesEnum::Unknown) + { + sal_Int32 nPos = m_xSelectionLB->get_selected_index(); + if(nPos == -1) + nPos = 0; + nTypeId = static_cast<SwFieldTypesEnum>(m_xSelectionLB->get_id(nPos).toUInt32()); + } + + OUString aVal(m_xValueED->get_text()); + sal_uLong nFormat = 0; + sal_uInt16 nSubType = 0; + + if (m_xFormatLB->get_sensitive()) + { + sal_Int32 nPos = m_xFormatLB->get_selected_index(); + if(nPos != -1) + nFormat = m_xFormatLB->get_id(nPos).toUInt32(); + } + + if (m_xSelectionLB->get_sensitive()) + { + sal_Int32 nPos = m_xSelectionLB->get_selected_index(); + if(nPos != -1) + nSubType = m_xSelectionLB->get_id(nPos).toUInt32(); + } + + switch (nTypeId) + { + case SwFieldTypesEnum::Author: + nFormat = nSubType; + nSubType = 0; + [[fallthrough]]; + case SwFieldTypesEnum::ExtendedUser: + nFormat |= m_xFixedCB->get_active() ? AF_FIXED : 0; + break; + + case SwFieldTypesEnum::Filename: + nFormat |= m_xFixedCB->get_active() ? FF_FIXED : 0; + break; + + case SwFieldTypesEnum::Date: + case SwFieldTypesEnum::Time: + { + nFormat = m_xNumFormatLB->GetFormat(); + tools::Long nVal = static_cast< tools::Long >(m_xDateOffsetED->get_value()); + if (nTypeId == SwFieldTypesEnum::Date) + aVal = OUString::number(nVal * 60 * 24); + else + aVal = OUString::number(nVal); + break; + } + + case SwFieldTypesEnum::NextPage: + case SwFieldTypesEnum::PreviousPage: + case SwFieldTypesEnum::PageNumber: + case SwFieldTypesEnum::GetRefPage: + { + if( SVX_NUM_CHAR_SPECIAL != nFormat && + (SwFieldTypesEnum::PreviousPage == nTypeId || SwFieldTypesEnum::NextPage == nTypeId)) + { + sal_Int32 nVal = m_xValueED->get_text().toInt32(); + aVal = OUString::number(nVal); + } + break; + } + + case SwFieldTypesEnum::Chapter: + aVal = m_xLevelED->get_text(); + break; + + default: + break; + } + + if (!IsFieldEdit() || + nOldSel != m_xSelectionLB->get_selected_index() || + nOldFormat != nFormat || + m_xFixedCB->get_state_changed_from_saved() || + m_xValueED->get_value_changed_from_saved() || + m_xLevelED->get_value_changed_from_saved() || + m_xDateOffsetED->get_value_changed_from_saved()) + { + InsertField(nTypeId, nSubType, OUString(), aVal, nFormat, ' ', m_xNumFormatLB->IsAutomaticLanguage()); + } + + return false; +} + +std::unique_ptr<SfxTabPage> SwFieldDokPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet *const pAttrSet) +{ + return std::make_unique<SwFieldDokPage>(pPage, pController, pAttrSet); +} + +sal_uInt16 SwFieldDokPage::GetGroup() +{ + return GRP_DOC; +} + +void SwFieldDokPage::FillUserData() +{ + const sal_Int32 nEntryPos = m_xTypeLB->get_selected_index(); + const sal_uInt16 nTypeSel = ( -1 == nEntryPos ) + ? USHRT_MAX : m_xTypeLB->get_id(nEntryPos).toUInt32(); + SetUserData(USER_DATA_VERSION ";" + OUString::number( nTypeSel )); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/flddok.hxx b/sw/source/ui/fldui/flddok.hxx new file mode 100644 index 000000000..ce61dd15e --- /dev/null +++ b/sw/source/ui/fldui/flddok.hxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_SW_SOURCE_UI_FLDUI_FLDDOK_HXX +#define INCLUDED_SW_SOURCE_UI_FLDUI_FLDDOK_HXX + +#include <sfx2/tabdlg.hxx> + +#include <numfmtlb.hxx> +#include "fldpage.hxx" + +class SwFieldDokPage : public SwFieldPage +{ + sal_Int32 nOldSel; + sal_uLong nOldFormat; + + std::unique_ptr<weld::TreeView> m_xTypeLB; + std::unique_ptr<weld::Widget> m_xSelection; + std::unique_ptr<weld::TreeView> m_xSelectionLB; + std::unique_ptr<weld::Label> m_xValueFT; + std::unique_ptr<weld::Entry> m_xValueED; + std::unique_ptr<weld::Label> m_xLevelFT; + std::unique_ptr<weld::SpinButton> m_xLevelED; + std::unique_ptr<weld::Label> m_xDateFT; + std::unique_ptr<weld::Label> m_xTimeFT; + std::unique_ptr<weld::SpinButton> m_xDateOffsetED; + std::unique_ptr<weld::Widget> m_xFormat; + std::unique_ptr<weld::TreeView> m_xFormatLB; + std::unique_ptr<SwNumFormatTreeView> m_xNumFormatLB; + std::unique_ptr<weld::CheckButton> m_xFixedCB; + + DECL_LINK(TypeHdl, weld::TreeView&, void); + DECL_LINK(FormatHdl, weld::TreeView&, void); + DECL_LINK(SubTypeHdl, weld::TreeView&, void); + + void AddSubType(SwFieldTypesEnum nTypeId); + sal_Int32 FillFormatLB(SwFieldTypesEnum nTypeId); + +protected: + virtual sal_uInt16 GetGroup() override; + +public: + SwFieldDokPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet * pSet); + + virtual ~SwFieldDokPage() override; + + static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + + virtual void FillUserData() override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/fldedt.cxx b/sw/source/ui/fldui/fldedt.cxx new file mode 100644 index 000000000..ae009a025 --- /dev/null +++ b/sw/source/ui/fldui/fldedt.cxx @@ -0,0 +1,336 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> +#include <config_fuzzers.h> + +#include <sfx2/basedlgs.hxx> +#include <sfx2/viewfrm.hxx> +#include <svx/optgenrl.hxx> +#include <docufld.hxx> +#include <expfld.hxx> +#include <view.hxx> +#include <wrtsh.hxx> +#include "flddb.hxx" +#include "flddinf.hxx" +#include "fldvar.hxx" +#include "flddok.hxx" +#include "fldfunc.hxx" +#include "fldref.hxx" +#include <fldedt.hxx> + +#include <cmdid.h> +#include <swabstdlg.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/document/XDocumentProperties.hpp> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <memory> +#include <swuiexp.hxx> + +void SwFieldEditDlg::EnsureSelection(SwField *pCurField, SwFieldMgr &rMgr) +{ + if (pSh->CursorInsideInputField()) + { + // move cursor to start of Input Field + SwInputField* pInputField = dynamic_cast<SwInputField*>(pCurField); + if (pInputField && pInputField->GetFormatField()) + { + pSh->GotoField( *(pInputField->GetFormatField()) ); + } + else + { + SwSetExpField *const pSetField(dynamic_cast<SwSetExpField*>(pCurField)); + if (pSetField) + { + assert(pSetField->GetFormatField()); + pSh->GotoField( *(pSetField->GetFormatField()) ); + } + else + { + assert(!"what input field is this"); + } + } + } + + /* Only create selection if there is none already. + Normalize PaM instead of swapping. */ + if (!pSh->HasSelection()) + { + SwShellCursor* pCursor = pSh->getShellCursor(true); + SwPosition aOrigPos(*pCursor->GetPoint()); + + //After this attempt it is possible that rMgr.GetCurField() != pCurField if + //the field was in e.g. a zero height portion and so invisible in which + //case it will be skipped over + pSh->Right(CRSR_SKIP_CHARS, true, 1, false ); + //So (fdo#50640) if it didn't work then reposition back to the original + //location where the field was + SwField *pRealCurField = rMgr.GetCurField(); + bool bSelectionFailed = pCurField != pRealCurField; + if (bSelectionFailed) + { + pCursor->DeleteMark(); + *pCursor->GetPoint() = aOrigPos; + } + } + + pSh->NormalizePam(); + + assert(pCurField == rMgr.GetCurField()); +} + +SwFieldEditDlg::SwFieldEditDlg(SwView const & rVw) + : SfxSingleTabDialogController(rVw.GetViewFrame()->GetFrameWeld(), nullptr, + "modules/swriter/ui/editfielddialog.ui", "EditFieldDialog") + , pSh(rVw.GetWrtShellPtr()) + , m_xPrevBT(m_xBuilder->weld_button("prev")) + , m_xNextBT(m_xBuilder->weld_button("next")) + , m_xAddressBT(m_xBuilder->weld_button("edit")) +{ + SwFieldMgr aMgr(pSh); + + SwField *pCurField = aMgr.GetCurField(); + if (!pCurField) + return; + + SwViewShell::SetCareDialog(m_xDialog); + + EnsureSelection(pCurField, aMgr); + + sal_uInt16 nGroup = SwFieldMgr::GetGroup(pCurField->GetTypeId(), pCurField->GetSubType()); + + CreatePage(nGroup); + + GetOKButton().connect_clicked(LINK(this, SwFieldEditDlg, OKHdl)); + + m_xPrevBT->connect_clicked(LINK(this, SwFieldEditDlg, NextPrevHdl)); + m_xNextBT->connect_clicked(LINK(this, SwFieldEditDlg, NextPrevHdl)); + + m_xAddressBT->connect_clicked(LINK(this, SwFieldEditDlg, AddressHdl)); + + Init(); +} + +// initialise controls +void SwFieldEditDlg::Init() +{ + SwFieldPage* pTabPage = static_cast<SwFieldPage*>(GetTabPage()); + if (pTabPage) + { + SwFieldMgr& rMgr = pTabPage->GetFieldMgr(); + + SwField *pCurField = rMgr.GetCurField(); + + if(!pCurField) + return; + + // Traveling only when more than one field + pSh->StartAction(); + pSh->ClearMark(); + pSh->CreateCursor(); + + bool bMove = rMgr.GoNext(); + if( bMove ) + rMgr.GoPrev(); + m_xNextBT->set_sensitive(bMove); + + bMove = rMgr.GoPrev(); + if( bMove ) + rMgr.GoNext(); + m_xPrevBT->set_sensitive( bMove ); + + if (pCurField->GetTypeId() == SwFieldTypesEnum::ExtendedUser) + m_xAddressBT->set_sensitive(true); + else + m_xAddressBT->set_sensitive(false); + + pSh->DestroyCursor(); + pSh->EndAction(); + } + + GetOKButton().set_sensitive(!pSh->IsReadOnlyAvailable() || + !pSh->HasReadonlySel()); +} + +SfxTabPage* SwFieldEditDlg::CreatePage(sal_uInt16 nGroup) +{ + // create TabPage + std::unique_ptr<SfxTabPage> xTabPage; + + switch (nGroup) + { + case GRP_DOC: + xTabPage = SwFieldDokPage::Create(get_content_area(), this, nullptr); + break; + case GRP_FKT: + xTabPage = SwFieldFuncPage::Create(get_content_area(), this, nullptr); + break; + case GRP_REF: + xTabPage = SwFieldRefPage::Create(get_content_area(), this, nullptr); + break; + case GRP_REG: + if (SfxObjectShell* pDocSh = SfxObjectShell::Current()) + { + auto pSet = new SfxItemSetFixed<FN_FIELD_DIALOG_DOC_PROPS, FN_FIELD_DIALOG_DOC_PROPS>( pDocSh->GetPool() ); + using namespace ::com::sun::star; + uno::Reference<document::XDocumentPropertiesSupplier> xDPS( + pDocSh->GetModel(), uno::UNO_QUERY_THROW); + uno::Reference<document::XDocumentProperties> xDocProps + = xDPS->getDocumentProperties(); + uno::Reference< beans::XPropertySet > xUDProps( + xDocProps->getUserDefinedProperties(), + uno::UNO_QUERY_THROW); + pSet->Put( SfxUnoAnyItem( FN_FIELD_DIALOG_DOC_PROPS, uno::Any(xUDProps) ) ); + xTabPage = SwFieldDokInfPage::Create(get_content_area(), this, pSet); + } + break; +#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS + case GRP_DB: + xTabPage = SwFieldDBPage::Create(get_content_area(), this, nullptr); + static_cast<SwFieldDBPage*>(xTabPage.get())->SetWrtShell(*pSh); + break; +#endif + case GRP_VAR: + xTabPage = SwFieldVarPage::Create(get_content_area(), this, nullptr); + break; + + } + + assert(xTabPage); + + static_cast<SwFieldPage*>(xTabPage.get())->SetWrtShell(pSh); + SetTabPage(std::move(xTabPage)); + + return GetTabPage(); +} + +SwFieldEditDlg::~SwFieldEditDlg() +{ + SwViewShell::SetCareDialog(nullptr); + pSh->EnterStdMode(); +} + +void SwFieldEditDlg::EnableInsert(bool bEnable) +{ + if( bEnable && pSh->IsReadOnlyAvailable() && pSh->HasReadonlySel() ) + bEnable = false; + GetOKButton().set_sensitive(bEnable); +} + +void SwFieldEditDlg::InsertHdl() +{ + GetOKButton().clicked(); +} + +// kick off changing of the field +IMPL_LINK_NOARG(SwFieldEditDlg, OKHdl, weld::Button&, void) +{ + if (GetOKButton().get_sensitive()) + { + SfxTabPage* pTabPage = GetTabPage(); + if (pTabPage) + pTabPage->FillItemSet(nullptr); + m_xDialog->response(RET_OK); + } +} + +short SwFieldEditDlg::run() +{ + // without TabPage no dialog + return GetTabPage() ? SfxSingleTabDialogController::run() : static_cast<short>(RET_CANCEL); +} + +// Traveling between fields of the same type +IMPL_LINK(SwFieldEditDlg, NextPrevHdl, weld::Button&, rButton, void) +{ + bool bNext = &rButton == m_xNextBT.get(); + + pSh->EnterStdMode(); + + SwFieldType *pOldTyp = nullptr; + SwFieldPage* pTabPage = static_cast<SwFieldPage*>(GetTabPage()); + + //#112462# FillItemSet may delete the current field + //that's why it has to be called before accessing the current field + if (GetOKButton().get_sensitive()) + pTabPage->FillItemSet(nullptr); + + SwFieldMgr& rMgr = pTabPage->GetFieldMgr(); + SwField *pCurField = rMgr.GetCurField(); + if (pCurField->GetTypeId() == SwFieldTypesEnum::Database) + pOldTyp = pCurField->GetTyp(); + + rMgr.GoNextPrev( bNext, pOldTyp ); + pCurField = rMgr.GetCurField(); + + sal_uInt16 nGroup = SwFieldMgr::GetGroup(pCurField->GetTypeId(), pCurField->GetSubType()); + + if (nGroup != pTabPage->GetGroup()) + pTabPage = static_cast<SwFieldPage*>(CreatePage(nGroup)); + + pTabPage->EditNewField(); + + Init(); + EnsureSelection(pCurField, rMgr); +} + +IMPL_LINK_NOARG(SwFieldEditDlg, AddressHdl, weld::Button&, void) +{ + SwFieldPage* pTabPage = static_cast<SwFieldPage*>(GetTabPage()); + SwFieldMgr& rMgr = pTabPage->GetFieldMgr(); + SwField *pCurField = rMgr.GetCurField(); + + SfxItemSetFixed<SID_FIELD_GRABFOCUS, SID_FIELD_GRABFOCUS> aSet( pSh->GetAttrPool() ); + + EditPosition nEditPos = EditPosition::UNKNOWN; + + switch(pCurField->GetSubType()) + { + case EU_FIRSTNAME: nEditPos = EditPosition::FIRSTNAME; break; + case EU_NAME: nEditPos = EditPosition::LASTNAME; break; + case EU_SHORTCUT: nEditPos = EditPosition::SHORTNAME; break; + case EU_COMPANY: nEditPos = EditPosition::COMPANY; break; + case EU_STREET: nEditPos = EditPosition::STREET; break; + case EU_TITLE: nEditPos = EditPosition::TITLE; break; + case EU_POSITION: nEditPos = EditPosition::POSITION; break; + case EU_PHONE_PRIVATE:nEditPos = EditPosition::TELPRIV; break; + case EU_PHONE_COMPANY:nEditPos = EditPosition::TELCOMPANY; break; + case EU_FAX: nEditPos = EditPosition::FAX; break; + case EU_EMAIL: nEditPos = EditPosition::EMAIL; break; + case EU_COUNTRY: nEditPos = EditPosition::COUNTRY; break; + case EU_ZIP: nEditPos = EditPosition::PLZ; break; + case EU_CITY: nEditPos = EditPosition::CITY; break; + case EU_STATE: nEditPos = EditPosition::STATE; break; + + default: nEditPos = EditPosition::UNKNOWN; break; + + } + aSet.Put(SfxUInt16Item(SID_FIELD_GRABFOCUS, static_cast<sal_uInt16>(nEditPos))); + SwAbstractDialogFactory& rFact = swui::GetFactory(); + + ScopedVclPtr<SfxAbstractDialog> pDlg(rFact.CreateSwAddressAbstractDlg(m_xDialog.get(), aSet)); + if (RET_OK == pDlg->Execute()) + { + pSh->UpdateOneField(*pCurField); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/fldfunc.cxx b/sw/source/ui/fldui/fldfunc.cxx new file mode 100644 index 000000000..a129f7413 --- /dev/null +++ b/sw/source/ui/fldui/fldfunc.cxx @@ -0,0 +1,614 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <swtypes.hxx> +#include <strings.hrc> +#include <fldbas.hxx> +#include <docufld.hxx> +#include <wrtsh.hxx> +#include <swmodule.hxx> +#include "fldfunc.hxx" +#include "flddinf.hxx" +#include <flddropdown.hxx> +#include <o3tl/string_view.hxx> + +#define USER_DATA_VERSION_1 "1" +#define USER_DATA_VERSION USER_DATA_VERSION_1 + +using namespace ::com::sun::star; + +SwFieldFuncPage::SwFieldFuncPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *const pCoreSet) + : SwFieldPage(pPage, pController, "modules/swriter/ui/fldfuncpage.ui", "FieldFuncPage", pCoreSet) + , nOldFormat(0) + , bDropDownLBChanged(false) + , m_xTypeLB(m_xBuilder->weld_tree_view("type")) + , m_xSelectionLB(m_xBuilder->weld_tree_view("select")) + , m_xFormat(m_xBuilder->weld_widget("formatframe")) + , m_xFormatLB(m_xBuilder->weld_tree_view("format")) + , m_xNameFT(m_xBuilder->weld_label("nameft")) + , m_xNameED(new ConditionEdit(m_xBuilder->weld_entry("condFunction"))) + , m_xValueGroup(m_xBuilder->weld_widget("valuegroup")) + , m_xValueFT(m_xBuilder->weld_label("valueft")) + , m_xValueED(m_xBuilder->weld_entry("value")) + , m_xCond1FT(m_xBuilder->weld_label("cond1ft")) + , m_xCond1ED(new ConditionEdit(m_xBuilder->weld_entry("cond1"))) + , m_xCond2FT(m_xBuilder->weld_label("cond2ft")) + , m_xCond2ED(new ConditionEdit(m_xBuilder->weld_entry("cond2"))) + , m_xMacroBT(m_xBuilder->weld_button("macro")) + , m_xListGroup(m_xBuilder->weld_widget("listgroup")) + , m_xListItemFT(m_xBuilder->weld_label("itemft")) + , m_xListItemED(m_xBuilder->weld_entry("item")) + , m_xListAddPB(m_xBuilder->weld_button("add")) + , m_xListItemsFT(m_xBuilder->weld_label("listitemft")) + , m_xListItemsLB(m_xBuilder->weld_tree_view("listitems")) + , m_xListRemovePB(m_xBuilder->weld_button("remove")) + , m_xListUpPB(m_xBuilder->weld_button("up")) + , m_xListDownPB(m_xBuilder->weld_button("down")) + , m_xListNameFT(m_xBuilder->weld_label("listnameft")) + , m_xListNameED(m_xBuilder->weld_entry("listname")) +{ + FillFieldSelect(*m_xSelectionLB); + FillFieldSelect(*m_xFormatLB); + m_xListItemsLB->set_size_request(m_xListItemED->get_preferred_size().Width(), + m_xListItemsLB->get_height_rows(5)); + + auto nWidth = m_xTypeLB->get_approximate_digit_width() * FIELD_COLUMN_WIDTH; + auto nHeight = m_xTypeLB->get_height_rows(10); + m_xTypeLB->set_size_request(nWidth, nHeight); + m_xFormatLB->set_size_request(nWidth, nHeight); + + m_xNameED->connect_changed(LINK(this, SwFieldFuncPage, ModifyHdl)); + + m_sOldValueFT = m_xValueFT->get_label(); + m_sOldNameFT = m_xNameFT->get_label(); + + m_xCond1ED->ShowBrackets(false); + m_xCond2ED->ShowBrackets(false); + + // uitests + m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-func"); + m_xValueED->set_buildable_name(m_xValueED->get_buildable_name() + "-func"); + m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-func"); + m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-func"); +} + +SwFieldFuncPage::~SwFieldFuncPage() +{ +} + +void SwFieldFuncPage::Reset(const SfxItemSet* ) +{ + SavePos(*m_xTypeLB); + Init(); // general initialisation + + m_xTypeLB->freeze(); + m_xTypeLB->clear(); + + if (!IsFieldEdit()) + { + // initialise TypeListBox + const SwFieldGroupRgn& rRg = SwFieldMgr::GetGroupRange(IsFieldDlgHtmlMode(), GetGroup()); + + // fill Typ-Listbox + for(sal_uInt16 i = rRg.nStart; i < rRg.nEnd; ++i) + { + const SwFieldTypesEnum nTypeId = SwFieldMgr::GetTypeId(i); + m_xTypeLB->append(OUString::number(static_cast<sal_uInt16>(nTypeId)), SwFieldMgr::GetTypeStr(i)); + } + } + else + { + const SwFieldTypesEnum nTypeId = GetCurField()->GetTypeId(); + m_xTypeLB->append(OUString::number(static_cast<sal_uInt16>(nTypeId)), SwFieldMgr::GetTypeStr(SwFieldMgr::GetPos(nTypeId))); + + if (nTypeId == SwFieldTypesEnum::Macro) + { + GetFieldMgr().SetMacroPath(GetCurField()->GetPar1()); + } + } + + m_xTypeLB->connect_row_activated(LINK(this, SwFieldFuncPage, TreeViewInsertHdl)); + m_xTypeLB->connect_changed(LINK(this, SwFieldFuncPage, TypeHdl)); + m_xSelectionLB->connect_changed(LINK(this, SwFieldFuncPage, SelectHdl)); + m_xSelectionLB->connect_row_activated(LINK(this, SwFieldFuncPage, InsertMacroHdl)); + m_xFormatLB->connect_row_activated(LINK(this, SwFieldFuncPage, TreeViewInsertHdl)); + m_xMacroBT->connect_clicked(LINK(this, SwFieldFuncPage, MacroHdl)); + Link<weld::Button&,void> aListModifyLk( LINK(this, SwFieldFuncPage, ListModifyButtonHdl)); + m_xListAddPB->connect_clicked(aListModifyLk); + m_xListRemovePB->connect_clicked(aListModifyLk); + m_xListUpPB->connect_clicked(aListModifyLk); + m_xListDownPB->connect_clicked(aListModifyLk); + m_xListItemED->connect_activate(LINK(this, SwFieldFuncPage, ListModifyReturnActionHdl)); + Link<weld::Entry&,void> aListEnableLk = LINK(this, SwFieldFuncPage, ListEnableHdl); + m_xListItemED->connect_changed(aListEnableLk); + m_xListItemsLB->connect_changed(LINK(this, SwFieldFuncPage, ListEnableListBoxHdl)); + + int nSelect = -1; + if( !IsRefresh() ) + { + const OUString sUserData = GetUserData(); + sal_Int32 nIdx{ 0 }; + if(o3tl::equalsIgnoreAsciiCase(o3tl::getToken(sUserData, 0, ';', nIdx), u"" USER_DATA_VERSION_1)) + { + const sal_uInt16 nVal = static_cast< sal_uInt16 >(o3tl::toInt32(o3tl::getToken(sUserData, 0, ';', nIdx))); + if(nVal != USHRT_MAX) + { + for (sal_Int32 i = 0, nEntryCount = m_xTypeLB->n_children(); i < nEntryCount; ++i) + { + if (nVal == m_xTypeLB->get_id(i).toUInt32()) + { + nSelect = i; + break; + } + } + } + } + } + + m_xTypeLB->thaw(); + if (nSelect != -1) + m_xTypeLB->select(nSelect); + else + { + // select old Pos + RestorePos(*m_xTypeLB); + } + TypeHdl(*m_xTypeLB); + + if (IsFieldEdit()) + { + m_xNameED->save_value(); + m_xValueED->save_value(); + m_xCond1ED->save_value(); + m_xCond2ED->save_value(); + nOldFormat = GetCurField()->GetFormat(); + } +} + +const TranslateId FMT_MARK_ARY[] = +{ + FMT_MARK_TEXT, + FMT_MARK_TABLE, + FMT_MARK_FRAME, + FMT_MARK_GRAFIC, + FMT_MARK_OLE +}; + +IMPL_LINK_NOARG(SwFieldFuncPage, TypeHdl, weld::TreeView&, void) +{ + // save old ListBoxPos + const sal_Int32 nOld = GetTypeSel(); + + // current ListBoxPos + SetTypeSel(m_xTypeLB->get_selected_index()); + + if(GetTypeSel() == -1) + { + SetTypeSel(0); + m_xTypeLB->select(0); + } + + if (nOld == GetTypeSel()) + return; + + const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + + // fill Selection-Listbox + UpdateSubType(); + + // fill Format-Listbox + m_xFormatLB->clear(); + + const sal_uInt16 nSize = GetFieldMgr().GetFormatCount(nTypeId, IsFieldDlgHtmlMode()); + + for (sal_uInt16 i = 0; i < nSize; i++) + { + m_xFormatLB->append(OUString::number(GetFieldMgr().GetFormatId(nTypeId, i)), + GetFieldMgr().GetFormatStr(nTypeId, i)); + } + + if (nSize) + { + if (IsFieldEdit() && nTypeId == SwFieldTypesEnum::JumpEdit) + m_xFormatLB->select_text(SwResId(FMT_MARK_ARY[GetCurField()->GetFormat()])); + + if (m_xFormatLB->get_selected_index() == -1) + m_xFormatLB->select(0); + } + + bool bValue = false, bName = false, bMacro = false, bInsert = true; + bool bFormat = nSize != 0; + + // two controls for conditional text + bool bDropDown = SwFieldTypesEnum::Dropdown == nTypeId; + bool bCondTextField = SwFieldTypesEnum::ConditionalText == nTypeId; + + m_xCond1FT->set_visible(!bDropDown && bCondTextField); + m_xCond1ED->set_visible(!bDropDown && bCondTextField); + m_xCond2FT->set_visible(!bDropDown && bCondTextField); + m_xCond2ED->set_visible(!bDropDown && bCondTextField); + m_xValueGroup->set_visible(!bDropDown && !bCondTextField); + m_xMacroBT->set_visible(!bDropDown); + m_xNameED->set_visible(!bDropDown); + m_xNameFT->set_visible(!bDropDown); + + m_xListGroup->set_visible(bDropDown); + + m_xNameED->SetDropEnable(false); + + if (IsFieldEdit()) + { + if(bDropDown) + { + const SwDropDownField* pDrop = static_cast<const SwDropDownField*>(GetCurField()); + const uno::Sequence<OUString> aItems = pDrop->GetItemSequence(); + m_xListItemsLB->clear(); + for (const OUString& rItem : aItems) + m_xListItemsLB->append_text(rItem); + m_xListItemsLB->select_text(pDrop->GetSelectedItem()); + m_xListNameED->set_text(pDrop->GetPar2()); + m_xListNameED->save_value(); + bDropDownLBChanged = false; + } + else + { + m_xNameED->set_text(GetCurField()->GetPar1()); + m_xValueED->set_text(GetCurField()->GetPar2()); + } + } + else + { + m_xNameED->set_text(OUString()); + m_xValueED->set_text(OUString()); + } + if(bDropDown) + ListEnableHdl(*m_xListItemED); + + if (m_xNameFT->get_label() != m_sOldNameFT) + m_xNameFT->set_label(m_sOldNameFT); + if (m_xValueFT->get_label() != m_sOldValueFT) + m_xValueFT->set_label(m_sOldValueFT); + + switch (nTypeId) + { + case SwFieldTypesEnum::Macro: + bMacro = true; + if (!GetFieldMgr().GetMacroPath().isEmpty()) + bValue = true; + else + bInsert = false; + + m_xNameFT->set_label(SwResId(STR_MACNAME)); + m_xValueFT->set_label(SwResId(STR_PROMPT)); + m_xNameED->set_text(GetFieldMgr().GetMacroName()); + m_xNameED->set_accessible_name(m_xNameFT->get_label()); + m_xValueED->set_accessible_name(m_xValueFT->get_label()); + break; + + case SwFieldTypesEnum::HiddenParagraph: + m_xNameFT->set_label(SwResId(STR_COND)); + m_xNameED->SetDropEnable(true); + bName = true; + m_xNameED->set_accessible_name(m_xNameFT->get_label()); + m_xValueED->set_accessible_name(m_xValueFT->get_label()); + break; + + case SwFieldTypesEnum::HiddenText: + { + m_xNameFT->set_label(SwResId(STR_COND)); + m_xNameED->SetDropEnable(true); + m_xValueFT->set_label(SwResId(STR_INSTEXT)); + SwWrtShell* pSh = GetActiveWrtShell(); + if (!IsFieldEdit() && pSh) + m_xValueED->set_text(pSh->GetSelText()); + bName = bValue = true; + m_xNameED->set_accessible_name(m_xNameFT->get_label()); + m_xValueED->set_accessible_name(m_xValueFT->get_label()); + } + break; + + case SwFieldTypesEnum::ConditionalText: + m_xNameFT->set_label(SwResId(STR_COND)); + m_xNameED->SetDropEnable(true); + if (IsFieldEdit()) + { + sal_Int32 nIdx{ 0 }; + m_xCond1ED->set_text(GetCurField()->GetPar2().getToken(0, '|', nIdx)); + m_xCond2ED->set_text(GetCurField()->GetPar2().getToken(0, '|', nIdx)); + } + + bName = bValue = true; + m_xNameED->set_accessible_name(m_xNameFT->get_label()); + m_xValueED->set_accessible_name(m_xValueFT->get_label()); + break; + + case SwFieldTypesEnum::JumpEdit: + m_xNameFT->set_label(SwResId(STR_JUMPEDITFLD)); + m_xValueFT->set_label(SwResId(STR_PROMPT)); + bName = bValue = true; + m_xNameED->set_accessible_name(m_xNameFT->get_label()); + m_xValueED->set_accessible_name(m_xValueFT->get_label()); + break; + + case SwFieldTypesEnum::Input: + m_xValueFT->set_label(SwResId(STR_PROMPT)); + bValue = true; + m_xNameED->set_accessible_name(m_xNameFT->get_label()); + m_xValueED->set_accessible_name(m_xValueFT->get_label()); + break; + + case SwFieldTypesEnum::CombinedChars: + { + m_xNameFT->set_label(SwResId(STR_COMBCHRS_FT)); + m_xNameED->SetDropEnable(true); + bName = true; + + const sal_Int32 nLen = m_xNameED->get_text().getLength(); + if( !nLen || nLen > MAX_COMBINED_CHARACTERS ) + bInsert = false; + m_xNameED->set_accessible_name(m_xNameFT->get_label()); + m_xValueED->set_accessible_name(m_xValueFT->get_label()); + } + break; + case SwFieldTypesEnum::Dropdown : + break; + default: + break; + } + + m_xSelectionLB->hide(); + + m_xFormat->set_sensitive(bFormat); + m_xNameFT->set_sensitive(bName); + m_xNameED->set_sensitive(bName); + m_xValueGroup->set_sensitive(bValue); + m_xMacroBT->set_sensitive(bMacro); + + EnableInsert( bInsert ); +} + +IMPL_LINK_NOARG(SwFieldFuncPage, SelectHdl, weld::TreeView&, void) +{ + const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + + if( SwFieldTypesEnum::Macro == nTypeId ) + m_xNameED->set_text( m_xSelectionLB->get_selected_text() ); +} + +IMPL_LINK_NOARG(SwFieldFuncPage, InsertMacroHdl, weld::TreeView&, bool) +{ + SelectHdl(*m_xSelectionLB); + InsertHdl(nullptr); + return true; +} + +IMPL_LINK(SwFieldFuncPage, ListModifyButtonHdl, weld::Button&, rControl, void) +{ + ListModifyHdl(&rControl); +} + +IMPL_LINK(SwFieldFuncPage, ListModifyReturnActionHdl, weld::Entry&, rControl, bool) +{ + ListModifyHdl(&rControl); + return true; +} + +void SwFieldFuncPage::ListModifyHdl(const weld::Widget* pControl) +{ + if (pControl == m_xListAddPB.get() || + (pControl == m_xListItemED.get() && m_xListAddPB->get_sensitive())) + { + const OUString sEntry(m_xListItemED->get_text()); + m_xListItemsLB->append_text(sEntry); + m_xListItemsLB->select_text(sEntry); + } + else if (m_xListItemsLB->get_selected_index() != -1) + { + sal_Int32 nSelPos = m_xListItemsLB->get_selected_index(); + if (pControl == m_xListRemovePB.get()) + { + m_xListItemsLB->remove(nSelPos); + m_xListItemsLB->select(nSelPos ? nSelPos - 1 : 0); + } + else if (pControl == m_xListUpPB.get()) + { + if(nSelPos) + { + const OUString sEntry = m_xListItemsLB->get_selected_text(); + m_xListItemsLB->remove(nSelPos); + nSelPos--; + m_xListItemsLB->insert_text(nSelPos, sEntry); + m_xListItemsLB->select(nSelPos); + } + } + else if (pControl == m_xListDownPB.get()) + { + if( nSelPos < m_xListItemsLB->n_children() - 1) + { + const OUString sEntry = m_xListItemsLB->get_selected_text(); + m_xListItemsLB->remove(nSelPos); + nSelPos++; + m_xListItemsLB->insert_text(nSelPos, sEntry); + m_xListItemsLB->select(nSelPos); + } + } + } + bDropDownLBChanged = true; + ListEnableHdl(*m_xListItemED); +} + +IMPL_LINK_NOARG(SwFieldFuncPage, ListEnableListBoxHdl, weld::TreeView&, void) +{ + ListEnableHdl(*m_xListItemED); +} + +IMPL_LINK_NOARG(SwFieldFuncPage, ListEnableHdl, weld::Entry&, void) +{ + //enable "Add" button when text is in the Edit that's not already member of the box + m_xListAddPB->set_sensitive(!m_xListItemED->get_text().isEmpty() && + -1 == m_xListItemsLB->find_text(m_xListItemED->get_text())); + bool bEnableButtons = m_xListItemsLB->get_selected_index() != -1; + m_xListRemovePB->set_sensitive(bEnableButtons); + m_xListUpPB->set_sensitive(bEnableButtons && (m_xListItemsLB->get_selected_index() > 0)); + m_xListDownPB->set_sensitive(bEnableButtons && + (m_xListItemsLB->get_selected_index() < (m_xListItemsLB->n_children() - 1))); +} + +// renew types in SelectionBox +void SwFieldFuncPage::UpdateSubType() +{ + const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + + // fill Selection-Listbox + m_xSelectionLB->freeze(); + m_xSelectionLB->clear(); + + std::vector<OUString> aLst; + GetFieldMgr().GetSubTypes(nTypeId, aLst); + const size_t nCount = aLst.size(); + + for (size_t i = 0; i < nCount; ++i) + m_xSelectionLB->append(OUString::number(i), aLst[i]); + m_xSelectionLB->thaw(); + + bool bEnable = nCount != 0; + + m_xSelectionLB->set_sensitive( bEnable ); + + if (bEnable) + m_xSelectionLB->select(0); + + if (nTypeId == SwFieldTypesEnum::Macro) + { + const bool bHasMacro = !GetFieldMgr().GetMacroPath().isEmpty(); + + if (bHasMacro) + { + m_xNameED->set_text(GetFieldMgr().GetMacroName()); + m_xValueGroup->set_sensitive(true); + } + EnableInsert(bHasMacro); + } +} + +// call MacroBrowser, fill Listbox with Macros +IMPL_LINK_NOARG( SwFieldFuncPage, MacroHdl, weld::Button&, void) +{ + if (GetFieldMgr().ChooseMacro(GetFrameWeld())) + UpdateSubType(); +} + +bool SwFieldFuncPage::FillItemSet(SfxItemSet* ) +{ + const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + + sal_uInt16 nSubType = 0; + + const sal_Int32 nEntryPos = m_xFormatLB->get_selected_index(); + const sal_uLong nFormat = (nEntryPos == -1) + ? 0 : m_xFormatLB->get_id(nEntryPos).toUInt32(); + + OUString aVal(m_xValueED->get_text()); + OUString aName(m_xNameED->get_text()); + + switch(nTypeId) + { + case SwFieldTypesEnum::Input: + nSubType = INP_TXT; + // to prevent removal of CR/LF restore old content + if (!m_xNameED->get_value_changed_from_saved() && IsFieldEdit()) + aName = GetCurField()->GetPar1(); + + break; + + case SwFieldTypesEnum::Macro: + // use the full script URL, not the name in the Edit control + aName = GetFieldMgr().GetMacroPath(); + break; + + case SwFieldTypesEnum::ConditionalText: + aVal = m_xCond1ED->get_text() + "|" + m_xCond2ED->get_text(); + break; + case SwFieldTypesEnum::Dropdown : + { + aName = m_xListNameED->get_text(); + for (sal_Int32 i = 0, nEntryCount = m_xListItemsLB->n_children(); i < nEntryCount; ++i) + { + if(i) + aVal += OUStringChar(DB_DELIM); + aVal += m_xListItemsLB->get_text(i); + } + } + break; + default: + break; + } + + if (!IsFieldEdit() || + m_xNameED->get_value_changed_from_saved() || + m_xValueED->get_value_changed_from_saved() || + m_xCond1ED->get_value_changed_from_saved() || + m_xCond2ED->get_value_changed_from_saved() || + m_xListNameED->get_value_changed_from_saved() || + bDropDownLBChanged || + nOldFormat != nFormat) + { + InsertField( nTypeId, nSubType, aName, aVal, nFormat ); + } + + ModifyHdl(m_xNameED->get_widget()); // enable/disable Insert if applicable + + return false; +} + +std::unique_ptr<SfxTabPage> SwFieldFuncPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet *const pAttrSet) +{ + return std::make_unique<SwFieldFuncPage>(pPage, pController, pAttrSet); +} + +sal_uInt16 SwFieldFuncPage::GetGroup() +{ + return GRP_FKT; +} + +void SwFieldFuncPage::FillUserData() +{ + const sal_Int32 nEntryPos = m_xTypeLB->get_selected_index(); + const sal_uInt16 nTypeSel = ( -1 == nEntryPos ) + ? USHRT_MAX + : m_xTypeLB->get_id(nEntryPos).toUInt32(); + SetUserData(USER_DATA_VERSION ";" + OUString::number( nTypeSel )); +} + +IMPL_LINK_NOARG(SwFieldFuncPage, ModifyHdl, weld::Entry&, void) +{ + const sal_Int32 nLen = m_xNameED->get_text().getLength(); + + bool bEnable = true; + SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + + if( SwFieldTypesEnum::CombinedChars == nTypeId && + (!nLen || nLen > MAX_COMBINED_CHARACTERS )) + bEnable = false; + + EnableInsert( bEnable ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/fldfunc.hxx b/sw/source/ui/fldui/fldfunc.hxx new file mode 100644 index 000000000..364a71d8e --- /dev/null +++ b/sw/source/ui/fldui/fldfunc.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_SW_SOURCE_UI_FLDUI_FLDFUNC_HXX +#define INCLUDED_SW_SOURCE_UI_FLDUI_FLDFUNC_HXX + +#include <sfx2/tabdlg.hxx> + +#include <condedit.hxx> +#include "fldpage.hxx" + +class SwFieldFuncPage : public SwFieldPage +{ + OUString m_sOldValueFT; + OUString m_sOldNameFT; + + sal_uLong nOldFormat; + bool bDropDownLBChanged; + + std::unique_ptr<weld::TreeView> m_xTypeLB; + std::unique_ptr<weld::TreeView> m_xSelectionLB; + std::unique_ptr<weld::Widget> m_xFormat; + std::unique_ptr<weld::TreeView> m_xFormatLB; + std::unique_ptr<weld::Label> m_xNameFT; + std::unique_ptr<ConditionEdit> m_xNameED; + std::unique_ptr<weld::Widget> m_xValueGroup; + std::unique_ptr<weld::Label> m_xValueFT; + std::unique_ptr<weld::Entry> m_xValueED; + std::unique_ptr<weld::Label> m_xCond1FT; + std::unique_ptr<ConditionEdit> m_xCond1ED; + std::unique_ptr<weld::Label> m_xCond2FT; + std::unique_ptr<ConditionEdit> m_xCond2ED; + std::unique_ptr<weld::Button> m_xMacroBT; + + //controls of "Input list" + std::unique_ptr<weld::Widget> m_xListGroup; + std::unique_ptr<weld::Label> m_xListItemFT; + std::unique_ptr<weld::Entry> m_xListItemED; + std::unique_ptr<weld::Button> m_xListAddPB; + std::unique_ptr<weld::Label> m_xListItemsFT; + std::unique_ptr<weld::TreeView> m_xListItemsLB; + std::unique_ptr<weld::Button> m_xListRemovePB; + std::unique_ptr<weld::Button> m_xListUpPB; + std::unique_ptr<weld::Button> m_xListDownPB; + std::unique_ptr<weld::Label> m_xListNameFT; + std::unique_ptr<weld::Entry> m_xListNameED; + + DECL_LINK( TypeHdl, weld::TreeView&, void ); + DECL_LINK( SelectHdl, weld::TreeView&, void ); + DECL_LINK( InsertMacroHdl, weld::TreeView&, bool ); + DECL_LINK( ModifyHdl, weld::Entry&, void ); + DECL_LINK( ListModifyReturnActionHdl, weld::Entry&, bool ); + DECL_LINK( ListModifyButtonHdl, weld::Button&, void ); + DECL_LINK( ListEnableHdl, weld::Entry&, void ); + DECL_LINK( ListEnableListBoxHdl, weld::TreeView&, void ); + void ListModifyHdl(const weld::Widget*); + + // select Macro + DECL_LINK( MacroHdl, weld::Button&, void ); + + void UpdateSubType(); + +protected: + virtual sal_uInt16 GetGroup() override; + +public: + SwFieldFuncPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pSet); + virtual ~SwFieldFuncPage() override; + + static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + + virtual void FillUserData() override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/fldpage.cxx b/sw/source/ui/fldui/fldpage.cxx new file mode 100644 index 000000000..00c31c9ba --- /dev/null +++ b/sw/source/ui/fldui/fldpage.cxx @@ -0,0 +1,348 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <svl/stritem.hxx> +#include <sfx2/request.hxx> +#include <sfx2/htmlmode.hxx> +#include <sfx2/viewfrm.hxx> +#include <dbfld.hxx> +#include <flddat.hxx> +#include <fmtfld.hxx> +#include <viewopt.hxx> +#include <fldedt.hxx> +#include <docsh.hxx> +#include <swmodule.hxx> +#include <view.hxx> +#include <wrtsh.hxx> +#include <expfld.hxx> +#include <fldtdlg.hxx> +#include "fldpage.hxx" +#include <docufld.hxx> +#include <cmdid.h> +#include <sfx2/bindings.hxx> +#include <o3tl/string_view.hxx> + +using namespace ::com::sun::star; + +// note: pAttrSet may be null if the dialog is restored on startup +SwFieldPage::SwFieldPage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, + const OString& rID, const SfxItemSet *pAttrSet) + : SfxTabPage(pPage, pController, rUIXMLDescription, rID, pAttrSet) + , m_pCurField(nullptr) + , m_pWrtShell(nullptr) + , m_nTypeSel(-1) + , m_nSelectionSel(-1) + , m_bFieldEdit(false) + , m_bInsert(true) + , m_bFieldDlgHtmlMode(false) + , m_bRefresh(false) + , m_bFirstHTMLInit(true) +{ +} + +SwFieldPage::~SwFieldPage() +{ +} + +// initialise TabPage +void SwFieldPage::Init() +{ + SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current()); + bool bNewMode = 0 != (::GetHtmlMode(pDocSh) & HTMLMODE_ON); + + m_bFieldEdit = nullptr == dynamic_cast<SwFieldDlg*>(GetDialogController()); + + // newly initialise FieldManager. important for + // Dok-Switch (fldtdlg:ReInitTabPage) + m_pCurField = m_aMgr.GetCurField(); + + if( bNewMode == m_bFieldDlgHtmlMode ) + return; + + m_bFieldDlgHtmlMode = bNewMode; + + // initialise Rangelistbox + if( !(m_bFieldDlgHtmlMode && m_bFirstHTMLInit) ) + return; + + m_bFirstHTMLInit = false; + SwWrtShell *pSh = m_pWrtShell; + if(! pSh) + pSh = ::GetActiveWrtShell(); + if(pSh) + { + SwDoc* pDoc = pSh->GetDoc(); + pSh->InsertFieldType( SwSetExpFieldType( pDoc, + "HTML_ON", 1)); + pSh->InsertFieldType( SwSetExpFieldType(pDoc, + "HTML_OFF", 1)); + } +} + +// newly initialise page +void SwFieldPage::Activate() +{ + EnableInsert(m_bInsert); +} + +// complete reset; edit new field +void SwFieldPage::EditNewField( bool bOnlyActivate ) +{ + if (!bOnlyActivate) + m_nTypeSel = -1; + m_nSelectionSel = -1; + m_bRefresh = true; + Reset(nullptr); + m_bRefresh = false; +} + +// insert field +void SwFieldPage::InsertField(SwFieldTypesEnum nTypeId, sal_uInt16 nSubType, const OUString& rPar1, + const OUString& rPar2, sal_uInt32 nFormatId, + sal_Unicode cSeparator, bool bIsAutomaticLanguage) +{ + SwView* pView = GetActiveView(); + if (!pView) + return; + + SwWrtShell *pSh = m_pWrtShell ? m_pWrtShell : pView->GetWrtShellPtr(); + + if (!IsFieldEdit()) // insert new field + { + SwInsertField_Data aData(nTypeId, nSubType, rPar1, rPar2, nFormatId, nullptr, cSeparator, bIsAutomaticLanguage ); + //#i26566# provide parent for SwWrtShell::StartInputFieldDlg + aData.m_pParent = &GetDialogController()->GetOKButton(); + m_aMgr.InsertField( aData ); + + uno::Reference< frame::XDispatchRecorder > xRecorder = + pView->GetViewFrame()->GetBindings().GetRecorder(); + if ( xRecorder.is() ) + { + bool bRecordDB = SwFieldTypesEnum::Database == nTypeId || + SwFieldTypesEnum::DatabaseSetNumber == nTypeId || + SwFieldTypesEnum::DatabaseNumberSet == nTypeId || + SwFieldTypesEnum::DatabaseNextSet == nTypeId || + SwFieldTypesEnum::DatabaseName == nTypeId ; + + SfxRequest aReq( pView->GetViewFrame(), + bRecordDB ? FN_INSERT_DBFIELD : FN_INSERT_FIELD ); + if(bRecordDB) + { + sal_Int32 nIdx{ 0 }; + aReq.AppendItem(SfxStringItem + (FN_INSERT_DBFIELD,rPar1.getToken(0, DB_DELIM, nIdx))); + aReq.AppendItem(SfxStringItem + (FN_PARAM_1,rPar1.getToken(0, DB_DELIM, nIdx))); + aReq.AppendItem(SfxInt32Item + (FN_PARAM_3, o3tl::toInt32(o3tl::getToken(rPar1, 0, DB_DELIM, nIdx)))); + aReq.AppendItem(SfxStringItem + (FN_PARAM_2,rPar1.getToken(0, DB_DELIM, nIdx))); + } + else + { + aReq.AppendItem(SfxStringItem(FN_INSERT_FIELD, rPar1)); + aReq.AppendItem(SfxStringItem + (FN_PARAM_3, OUString(cSeparator))); + aReq.AppendItem(SfxUInt16Item(FN_PARAM_FIELD_SUBTYPE, nSubType)); + } + aReq.AppendItem(SfxUInt16Item(FN_PARAM_FIELD_TYPE , static_cast<sal_uInt16>(nTypeId))); + aReq.AppendItem(SfxStringItem(FN_PARAM_FIELD_CONTENT, rPar2)); + aReq.AppendItem(SfxUInt32Item(FN_PARAM_FIELD_FORMAT , nFormatId)); + aReq.Done(); + } + + } + else // change field + { + std::unique_ptr<SwField> pTmpField = m_pCurField->CopyField(); + + OUString sPar1(rPar1); + OUString sPar2(rPar2); + switch( nTypeId ) + { + case SwFieldTypesEnum::Date: + case SwFieldTypesEnum::Time: + nSubType = static_cast< sal_uInt16 >(((nTypeId == SwFieldTypesEnum::Date) ? DATEFLD : TIMEFLD) | + ((nSubType == DATE_VAR) ? 0 : FIXEDFLD)); + break; + + case SwFieldTypesEnum::DatabaseName: + case SwFieldTypesEnum::DatabaseNextSet: + case SwFieldTypesEnum::DatabaseNumberSet: + case SwFieldTypesEnum::DatabaseSetNumber: + { + sal_Int32 nPos = 0; + SwDBData aData; + + aData.sDataSource = rPar1.getToken(0, DB_DELIM, nPos); + aData.sCommand = rPar1.getToken(0, DB_DELIM, nPos); + aData.nCommandType = o3tl::toInt32(o3tl::getToken(rPar1, 0, DB_DELIM, nPos)); + sPar1 = rPar1.copy(nPos); + + static_cast<SwDBNameInfField*>(pTmpField.get())->SetDBData(aData); + } + break; + + case SwFieldTypesEnum::Database: + { + SwDBData aData; + sal_Int32 nIdx{ 0 }; + aData.sDataSource = rPar1.getToken(0, DB_DELIM, nIdx); + aData.sCommand = rPar1.getToken(0, DB_DELIM, nIdx); + aData.nCommandType = o3tl::toInt32(o3tl::getToken(rPar1, 0, DB_DELIM, nIdx)); + OUString sColumn = rPar1.getToken(0, DB_DELIM, nIdx); + + auto pOldType = static_cast<SwDBFieldType*>(pTmpField->GetTyp()); + auto pType = static_cast<SwDBFieldType*>(pSh->InsertFieldType(SwDBFieldType(pSh->GetDoc(), sColumn, aData))); + if(auto pFormatField = pOldType->FindFormatForField(m_pCurField)) + { + pFormatField->RegisterToFieldType(*pType); + pTmpField->ChgTyp(pType); + } + } + break; + + case SwFieldTypesEnum::Sequence: + { + SwSetExpFieldType* pTyp = static_cast<SwSetExpFieldType*>(pTmpField->GetTyp()); + pTyp->SetOutlineLvl( static_cast< sal_uInt8 >(nSubType & 0xff)); + pTyp->SetDelimiter(OUString(cSeparator)); + + nSubType = nsSwGetSetExpType::GSE_SEQ; + } + break; + + case SwFieldTypesEnum::Input: + { + // User- or SetField ? + if (m_aMgr.GetFieldType(SwFieldIds::User, sPar1) == nullptr && + !(pTmpField->GetSubType() & INP_TXT)) // SETEXPFLD + { + SwSetExpField* pField = static_cast<SwSetExpField*>(pTmpField.get()); + pField->SetPromptText(sPar2); + sPar2 = pField->GetPar2(); + } + } + break; + case SwFieldTypesEnum::DocumentInfo: + { + if( nSubType == nsSwDocInfoSubType::DI_CUSTOM ) + { + SwDocInfoField* pDocInfo = static_cast<SwDocInfoField*>( pTmpField.get() ); + pDocInfo->SetName( rPar1 ); + } + } + break; + default: break; + } + + pSh->StartAllAction(); + + pTmpField->SetSubType(nSubType); + pTmpField->SetAutomaticLanguage(bIsAutomaticLanguage); + + m_aMgr.UpdateCurField( nFormatId, sPar1, sPar2, std::move(pTmpField) ); + + m_pCurField = m_aMgr.GetCurField(); + + switch (nTypeId) + { + case SwFieldTypesEnum::HiddenText: + case SwFieldTypesEnum::HiddenParagraph: + m_aMgr.EvalExpFields(pSh); + break; + default: break; + } + + pSh->SetUndoNoResetModified(); + pSh->EndAllAction(); + } +} + +void SwFieldPage::SavePos( const weld::TreeView& rLst1 ) +{ + if (rLst1.n_children()) + m_aLstStrArr[ 0 ] = rLst1.get_selected_text(); + else + m_aLstStrArr[ 0 ].clear(); + m_aLstStrArr[ 1 ].clear(); + m_aLstStrArr[ 2 ].clear(); +} + +void SwFieldPage::RestorePos(weld::TreeView& rLst1) +{ + sal_Int32 nPos = 0; + if (rLst1.n_children() && !m_aLstStrArr[ 0 ].isEmpty() && + -1 != ( nPos = rLst1.find_text(m_aLstStrArr[ 0 ] ) ) ) + rLst1.select( nPos ); +} + +// Insert new fields +IMPL_LINK( SwFieldPage, TreeViewInsertHdl, weld::TreeView&, rBox, bool ) +{ + InsertHdl(&rBox); + return true; +} + +void SwFieldPage::InsertHdl(weld::Widget* pBtn) +{ + if (SwFieldDlg *pDlg = dynamic_cast<SwFieldDlg*>(GetDialogController())) + { + pDlg->InsertHdl(); + + if (pBtn) + pBtn->grab_focus(); // because of InputField-Dlg + } + else + { + SwFieldEditDlg *pEditDlg = static_cast<SwFieldEditDlg*>(GetDialogController()); + pEditDlg->InsertHdl(); + } +} + +// enable/disable "Insert"-Button +void SwFieldPage::EnableInsert(bool bEnable) +{ + if (SwFieldDlg *pDlg = dynamic_cast<SwFieldDlg*>(GetDialogController())) + { + if (pDlg->GetCurTabPage() == this) + pDlg->EnableInsert(bEnable); + } + else + { + SwFieldEditDlg *pEditDlg = static_cast<SwFieldEditDlg*>(GetDialogController()); + pEditDlg->EnableInsert(bEnable); + } + + m_bInsert = bEnable; +} + +IMPL_LINK_NOARG(SwFieldPage, NumFormatHdl, weld::TreeView&, bool) +{ + InsertHdl(nullptr); + return true; +} + +void SwFieldPage::SetWrtShell( SwWrtShell* pShell ) +{ + m_pWrtShell = pShell; + m_aMgr.SetWrtShell( pShell ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/fldpage.hxx b/sw/source/ui/fldui/fldpage.hxx new file mode 100644 index 000000000..9c0cecf5a --- /dev/null +++ b/sw/source/ui/fldui/fldpage.hxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_SW_SOURCE_UI_FLDUI_FLDPAGE_HXX +#define INCLUDED_SW_SOURCE_UI_FLDUI_FLDPAGE_HXX + +#include <sfx2/tabdlg.hxx> +#include <fldmgr.hxx> + +#define FIELD_COLUMN_WIDTH 19 + +const int coLBCount = 3; + +class SwFieldPage : public SfxTabPage +{ + OUString m_aLstStrArr[ coLBCount ]; + SwFieldMgr m_aMgr; + SwField *m_pCurField; + SwWrtShell* m_pWrtShell; + sal_Int32 m_nTypeSel; + sal_Int32 m_nSelectionSel; + bool m_bFieldEdit; + bool m_bInsert; + bool m_bFieldDlgHtmlMode; + bool m_bRefresh; + bool m_bFirstHTMLInit; + +protected: + + sal_Int32 GetTypeSel() const { return m_nTypeSel;} + void SetTypeSel(sal_Int32 nSet) { m_nTypeSel = nSet;} + sal_Int32 GetSelectionSel() const { return m_nSelectionSel;} + void SetSelectionSel(sal_Int32 nSet){ m_nSelectionSel = nSet;} + bool IsFieldDlgHtmlMode() const { return m_bFieldDlgHtmlMode;} + bool IsRefresh() const { return m_bRefresh;} + SwField* GetCurField() { return m_pCurField;} + SwWrtShell* GetWrtShell() { return m_pWrtShell;} + + DECL_LINK( TreeViewInsertHdl, weld::TreeView&, bool ); + DECL_LINK( NumFormatHdl, weld::TreeView&, bool ); + void InsertHdl(weld::Widget*); + + void Init(); + void SavePos( const weld::TreeView& rLst1); + void RestorePos( weld::TreeView& rLst1 ); + void EnableInsert(bool bEnable); + bool IsFieldEdit() const { return m_bFieldEdit; } + + // insert field + void InsertField(SwFieldTypesEnum nTypeId, + sal_uInt16 nSubType, + const OUString& rPar1, + const OUString& rPar2, + sal_uInt32 nFormatId, + sal_Unicode cDelim = ' ', + bool bIsAutomaticLanguage = true); + +public: + SwFieldPage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, + const OString& rID, const SfxItemSet *pAttrSet); + + virtual ~SwFieldPage() override; + + virtual void Activate() override; + + SwFieldMgr& GetFieldMgr() { return m_aMgr; } + void SetWrtShell( SwWrtShell* m_pWrtShell ); + void EditNewField( bool bOnlyActivate = false ); + virtual sal_uInt16 GetGroup() = 0; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/fldref.cxx b/sw/source/ui/fldui/fldref.cxx new file mode 100644 index 000000000..08a44c5c8 --- /dev/null +++ b/sw/source/ui/fldui/fldref.cxx @@ -0,0 +1,1154 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <swtypes.hxx> +#include <IMark.hxx> +#include <expfld.hxx> +#include <swmodule.hxx> +#include "fldref.hxx" +#include <frmatr.hxx> +#include <reffld.hxx> +#include <wrtsh.hxx> + +#include <fldref.hrc> +#include <strings.hrc> +#include <SwNodeNum.hxx> +#include <IDocumentMarkAccess.hxx> +#include <unotools/syslocaleoptions.hxx> +#include <unotools/charclass.hxx> +#include <osl/diagnose.h> + +#include <comphelper/string.hxx> +#include <editeng/frmdiritem.hxx> +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> +#include <vcl/settings.hxx> + +#define REFFLDFLAG 0x4000 +#define REFFLDFLAG_BOOKMARK 0x4800 +#define REFFLDFLAG_FOOTNOTE 0x5000 +#define REFFLDFLAG_ENDNOTE 0x6000 +// #i83479# +#define REFFLDFLAG_HEADING 0x7100 +#define REFFLDFLAG_NUMITEM 0x7200 + +static sal_uInt16 nFieldDlgFormatSel = 0; + +#define USER_DATA_VERSION_1 "1" +#define USER_DATA_VERSION USER_DATA_VERSION_1 + +SwFieldRefPage::SwFieldRefPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *const pCoreSet ) + : SwFieldPage(pPage, pController, "modules/swriter/ui/fldrefpage.ui", "FieldRefPage", pCoreSet) + , mpSavedSelectedTextNode(nullptr) + , mnSavedSelectedPos(0) + , m_xTypeLB(m_xBuilder->weld_tree_view("type")) + , m_xSelection(m_xBuilder->weld_widget("selectframe")) + , m_xSelectionLB(m_xBuilder->weld_tree_view("select")) + , m_xSelectionToolTipLB(m_xBuilder->weld_tree_view("selecttip")) + , m_xFormat(m_xBuilder->weld_widget("formatframe")) + , m_xFormatLB(m_xBuilder->weld_tree_view("format")) + , m_xNameFT(m_xBuilder->weld_label("nameft")) + , m_xNameED(m_xBuilder->weld_entry("name")) + , m_xValueED(m_xBuilder->weld_entry("value")) + , m_xFilterED(m_xBuilder->weld_entry("filter")) +{ + m_xSelectionLB->make_sorted(); + // #i83479# + for (size_t i = 0; i < SAL_N_ELEMENTS(FLD_REF_PAGE_TYPES); ++i) + { + m_xTypeLB->append_text(SwResId(FLD_REF_PAGE_TYPES[i])); + m_xFormatLB->append_text(SwResId(FLD_REF_PAGE_TYPES[i])); + } + + sBookmarkText = m_xTypeLB->get_text(0); + sFootnoteText = m_xTypeLB->get_text(1); + sEndnoteText = m_xTypeLB->get_text(2); + // #i83479# + sHeadingText = m_xTypeLB->get_text(3); + sNumItemText = m_xTypeLB->get_text(4); + + auto nHeight = m_xTypeLB->get_height_rows(8); + auto nWidth = m_xTypeLB->get_approximate_digit_width() * FIELD_COLUMN_WIDTH; + m_xTypeLB->set_size_request(nWidth * 1.33, nHeight); + m_xFormatLB->set_size_request(nWidth * 1.33, nHeight); + m_xSelection->set_size_request(nWidth * 2, nHeight); + nHeight = m_xTypeLB->get_height_rows(8); + m_xSelectionToolTipLB->set_size_request(nHeight, nWidth*2); + + m_xTypeLB->clear(); + + m_xNameED->connect_changed(LINK(this, SwFieldRefPage, ModifyHdl)); + m_xFilterED->connect_changed( LINK( this, SwFieldRefPage, ModifyHdl_Impl ) ); + + m_xTypeLB->connect_row_activated(LINK(this, SwFieldRefPage, TreeViewInsertHdl)); + m_xTypeLB->connect_changed(LINK(this, SwFieldRefPage, TypeHdl)); + m_xSelectionLB->connect_changed(LINK(this, SwFieldRefPage, SubTypeListBoxHdl)); + m_xSelectionLB->connect_row_activated(LINK(this, SwFieldRefPage, TreeViewInsertHdl)); + m_xFormatLB->connect_row_activated(LINK(this, SwFieldRefPage, TreeViewInsertHdl)); + + // #i83479# + m_xSelectionToolTipLB->connect_changed( LINK(this, SwFieldRefPage, SubTypeTreeListBoxHdl) ); + m_xSelectionToolTipLB->connect_row_activated( LINK(this, SwFieldRefPage, TreeViewInsertHdl) ); + m_xFilterED->grab_focus(); + + // uitests + m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-ref"); + m_xNameED->set_buildable_name(m_xNameED->get_buildable_name() + "-ref"); + m_xValueED->set_buildable_name(m_xValueED->get_buildable_name() + "-ref"); + m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-ref"); + m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-ref"); +} + +SwFieldRefPage::~SwFieldRefPage() +{ +} + +IMPL_LINK_NOARG(SwFieldRefPage, ModifyHdl_Impl, weld::Entry&, void) +{ + UpdateSubType(comphelper::string::strip(m_xFilterED->get_text(), ' ')); + // tdf#135938 - refresh cross-reference name after filter selection has changed + SubTypeHdl(); +} + +// #i83479# +void SwFieldRefPage::SaveSelectedTextNode() +{ + mpSavedSelectedTextNode = nullptr; + mnSavedSelectedPos = 0; + if ( !m_xSelectionToolTipLB->get_visible() ) + return; + + int nEntry = m_xSelectionToolTipLB->get_selected_index(); + if (nEntry == -1) + return; + + const sal_uInt16 nTypeId = m_xTypeLB->get_id(GetTypeSel()).toUInt32(); + + if ( nTypeId == REFFLDFLAG_HEADING ) + { + mnSavedSelectedPos = m_xSelectionToolTipLB->get_id(nEntry).toUInt32(); + if ( mnSavedSelectedPos < maOutlineNodes.size() ) + { + mpSavedSelectedTextNode = maOutlineNodes[mnSavedSelectedPos]; + } + } + else if ( nTypeId == REFFLDFLAG_NUMITEM ) + { + mnSavedSelectedPos = m_xSelectionToolTipLB->get_id(nEntry).toUInt32(); + if ( mnSavedSelectedPos < maNumItems.size() ) + { + mpSavedSelectedTextNode = maNumItems[mnSavedSelectedPos]->GetTextNode(); + } + } +} + +void SwFieldRefPage::Reset(const SfxItemSet* ) +{ + if (!IsFieldEdit()) + { + SavePos(*m_xTypeLB); + // #i83479# + SaveSelectedTextNode(); + } + SetSelectionSel(-1); + SetTypeSel(-1); + Init(); // general initialisation + + // initialise TypeListBox + m_xTypeLB->freeze(); + m_xTypeLB->clear(); + + // fill Type-Listbox + + // set/insert reference + const SwFieldGroupRgn& rRg = SwFieldMgr::GetGroupRange(IsFieldDlgHtmlMode(), GetGroup()); + + for (short i = rRg.nStart; i < rRg.nEnd; ++i) + { + const SwFieldTypesEnum nTypeId = SwFieldMgr::GetTypeId(i); + + if (!IsFieldEdit() || nTypeId != SwFieldTypesEnum::SetRef) + { + m_xTypeLB->append(OUString::number(static_cast<sal_uInt16>(nTypeId)), SwFieldMgr::GetTypeStr(i)); + } + } + + // #i83479# + // entries for headings and numbered items + m_xTypeLB->append(OUString::number(REFFLDFLAG_HEADING), sHeadingText); + m_xTypeLB->append(OUString::number(REFFLDFLAG_NUMITEM), sNumItemText); + + // fill up with the sequence types + SwWrtShell *pSh = GetWrtShell(); + if (!pSh) + pSh = ::GetActiveWrtShell(); + if (!pSh) + return; + + // tdf#148432 in LTR UI override the navigator treeview direction based on + // the first page directionality + if (!AllSettings::GetLayoutRTL()) + { + const SwPageDesc& rDesc = pSh->GetPageDesc(0); + const SvxFrameDirectionItem& rFrameDir = rDesc.GetMaster().GetFrameDir(); + m_xSelectionToolTipLB->set_direction(rFrameDir.GetValue() == SvxFrameDirection::Horizontal_RL_TB); + } + + const size_t nFieldTypeCnt = pSh->GetFieldTypeCount(SwFieldIds::SetExp); + + OSL_ENSURE( nFieldTypeCnt < o3tl::make_unsigned(REFFLDFLAG), "<SwFieldRefPage::Reset> - Item index will overlap flags!" ); + + for (size_t n = 0; n < nFieldTypeCnt; ++n) + { + SwSetExpFieldType* pType = static_cast<SwSetExpFieldType*>(pSh->GetFieldType(n, SwFieldIds::SetExp)); + + if ((nsSwGetSetExpType::GSE_SEQ & pType->GetType()) && pType->HasWriterListeners() && pSh->IsUsed(*pType)) + { + m_xTypeLB->append(OUString::number(REFFLDFLAG | n), pType->GetName()); + } + } + + // text marks - now always (because of globaldocuments) + m_xTypeLB->append(OUString::number(REFFLDFLAG_BOOKMARK), sBookmarkText); + + // footnotes: + if( pSh->HasFootnotes() ) + { + m_xTypeLB->append(OUString::number(REFFLDFLAG_FOOTNOTE), sFootnoteText); + } + + // endnotes: + if ( pSh->HasFootnotes(true) ) + { + m_xTypeLB->append(OUString::number(REFFLDFLAG_ENDNOTE), sEndnoteText); + } + + m_xTypeLB->thaw(); + + // select old Pos + if (!IsFieldEdit()) + RestorePos(*m_xTypeLB); + + nFieldDlgFormatSel = 0; + + sal_uInt16 nFormatBoxPosition = USHRT_MAX; + if( !IsRefresh() ) + { + sal_Int32 nIdx{ 0 }; + const OUString sUserData = GetUserData(); + if(!IsRefresh() && o3tl::equalsIgnoreAsciiCase(o3tl::getToken(sUserData, 0, ';', nIdx), + u"" USER_DATA_VERSION_1)) + { + const sal_uInt16 nVal = static_cast< sal_uInt16 >(o3tl::toInt32(o3tl::getToken(sUserData, 0, ';', nIdx))); + if(nVal != USHRT_MAX) + { + for(sal_Int32 i = 0, nEntryCount = m_xTypeLB->n_children(); i < nEntryCount; ++i) + { + if (nVal == m_xTypeLB->get_id(i).toUInt32()) + { + m_xTypeLB->select(i); + break; + } + } + if (nIdx>=0 && nIdx<sUserData.getLength()) + { + nFormatBoxPosition = static_cast< sal_uInt16 >(o3tl::toInt32(o3tl::getToken(sUserData, 0, ';', nIdx))); + } + } + } + } + TypeHdl(*m_xTypeLB); + if (nFormatBoxPosition < m_xFormatLB->n_children()) + { + m_xFormatLB->select(nFormatBoxPosition); + } + if (IsFieldEdit()) + { + m_xTypeLB->save_value(); + m_xSelectionLB->save_value(); + m_xFormatLB->save_value(); + m_xNameED->save_value(); + m_xValueED->save_value(); + m_xFilterED->set_text(OUString()); + } +} + +IMPL_LINK_NOARG(SwFieldRefPage, TypeHdl, weld::TreeView&, void) +{ + // save old ListBoxPos + const sal_Int32 nOld = GetTypeSel(); + + // current ListBoxPos + SetTypeSel(m_xTypeLB->get_selected_index()); + + if(GetTypeSel() == -1) + { + if (IsFieldEdit()) + { + // select positions + OUString sName; + sal_uInt16 nFlag = 0; + + switch( GetCurField()->GetSubType() ) + { + case REF_BOOKMARK: + { + // #i83479# + SwGetRefField* pRefField = dynamic_cast<SwGetRefField*>(GetCurField()); + if ( pRefField && + pRefField->IsRefToHeadingCrossRefBookmark() ) + { + sName = sHeadingText; + nFlag = REFFLDFLAG_HEADING; + } + else if ( pRefField && + pRefField->IsRefToNumItemCrossRefBookmark() ) + { + sName = sNumItemText; + nFlag = REFFLDFLAG_NUMITEM; + } + else + { + sName = sBookmarkText; + nFlag = REFFLDFLAG_BOOKMARK; + } + } + break; + + case REF_FOOTNOTE: + sName = sFootnoteText; + nFlag = REFFLDFLAG_FOOTNOTE; + break; + + case REF_ENDNOTE: + sName = sEndnoteText; + nFlag = REFFLDFLAG_ENDNOTE; + break; + + case REF_SETREFATTR: + sName = SwResId(STR_GETREFFLD); + nFlag = REF_SETREFATTR; + break; + + case REF_SEQUENCEFLD: + { + SwGetRefField const*const pRefField(dynamic_cast<SwGetRefField*>(GetCurField())); + if (pRefField) + { + sName = pRefField->GetSetRefName(); + } + nFlag = REFFLDFLAG; + break; + } + } + + if (m_xTypeLB->find_text(sName) == -1) // reference to deleted mark + { + m_xTypeLB->append(OUString::number(nFlag), sName); + } + + m_xTypeLB->select_text(sName); + SetTypeSel(m_xTypeLB->get_selected_index()); + } + else + { + SetTypeSel(0); + m_xTypeLB->select(0); + } + } + + if (nOld == GetTypeSel()) + return; + + sal_uInt16 nTypeId = m_xTypeLB->get_id(GetTypeSel()).toUInt32(); + + bool bName = false; + nFieldDlgFormatSel = 0; + + if ( ( !IsFieldEdit() || m_xSelectionLB->n_children() ) && + nOld != -1 ) + { + m_xNameED->set_text(OUString()); + m_xValueED->set_text(OUString()); + m_xFilterED->set_text(OUString()); + } + + // fill selection-ListBox + UpdateSubType(comphelper::string::strip(m_xFilterED->get_text(), ' ')); + + switch (nTypeId) + { + case static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef): + if (nOld != -1 && REFFLDFLAG & m_xTypeLB->get_id(nOld).toUInt32()) + // the old one stays + nFieldDlgFormatSel = m_xFormatLB->get_selected_index(); + bName = true; + break; + + case static_cast<sal_uInt16>(SwFieldTypesEnum::SetRef): + bName = true; + break; + + case REFFLDFLAG_BOOKMARK: + bName = true; + [[fallthrough]]; + default: + if( REFFLDFLAG & nTypeId ) + { + const sal_uInt16 nOldId = nOld != -1 ? m_xTypeLB->get_id(nOld).toUInt32() : 0; + if( nOldId & REFFLDFLAG || nOldId == static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef) ) + // then the old one stays + nFieldDlgFormatSel = m_xFormatLB->get_selected_index(); + } + break; + } + + m_xNameED->set_sensitive(bName); + m_xNameFT->set_sensitive(bName); + + // fill Format-Listbox + sal_Int32 nSize = FillFormatLB(nTypeId); + bool bFormat = nSize != 0; + m_xFormat->set_sensitive(bFormat); + + SubTypeHdl(); + ModifyHdl(*m_xNameED); + ModifyHdl(*m_xFilterED); +} + +IMPL_LINK_NOARG(SwFieldRefPage, SubTypeTreeListBoxHdl, weld::TreeView&, void) +{ + SubTypeHdl(); +} + +IMPL_LINK_NOARG(SwFieldRefPage, SubTypeListBoxHdl, weld::TreeView&, void) +{ + SubTypeHdl(); +} + +void SwFieldRefPage::SubTypeHdl() +{ + sal_uInt16 nTypeId = m_xTypeLB->get_id(GetTypeSel()).toUInt32(); + + switch(nTypeId) + { + case static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef): + if (!IsFieldEdit() || m_xSelectionLB->get_selected_index() != -1) + { + m_xNameED->set_text(m_xSelectionLB->get_selected_text()); + ModifyHdl(*m_xNameED); + } + break; + + case static_cast<sal_uInt16>(SwFieldTypesEnum::SetRef): + { + SwWrtShell *pSh = GetWrtShell(); + if(!pSh) + pSh = ::GetActiveWrtShell(); + if(pSh) + { + m_xValueED->set_text(pSh->GetSelText()); + } + + } + break; + // #i83479# + case REFFLDFLAG_HEADING: + case REFFLDFLAG_NUMITEM: + { + int nEntry = m_xSelectionToolTipLB->get_selected_index(); + if (nEntry != -1) + m_xNameED->set_text(m_xSelectionToolTipLB->get_text(nEntry)); + } + break; + + default: + if (!IsFieldEdit() || m_xSelectionLB->get_selected_index() != -1) + m_xNameED->set_text(m_xSelectionLB->get_selected_text()); + break; + } +} + +// renew types in SelectionLB after filtering +void SwFieldRefPage::UpdateSubType(const OUString& filterString) +{ + SwWrtShell *pSh = GetWrtShell(); + if (!pSh) + pSh = ::GetActiveWrtShell(); + if (!pSh) + return; + + SwGetRefField const*const pRefField(dynamic_cast<SwGetRefField*>(GetCurField())); + const sal_uInt16 nTypeId = m_xTypeLB->get_id(GetTypeSel()).toUInt32(); + + OUString sOldSel; + // #i83479# + if ( m_xSelectionLB->get_visible() ) + { + const sal_Int32 nSelectionSel = m_xSelectionLB->get_selected_index(); + if (nSelectionSel != -1) + sOldSel = m_xSelectionLB->get_text(nSelectionSel); + } + if (IsFieldEdit() && pRefField && sOldSel.isEmpty()) + sOldSel = OUString::number( pRefField->GetSeqNo() + 1 ); + + m_xSelectionLB->freeze(); + m_xSelectionLB->clear(); + + if (REFFLDFLAG & nTypeId) + { + if (nTypeId == REFFLDFLAG_FOOTNOTE || nTypeId == REFFLDFLAG_ENDNOTE) + { + m_xSelectionLB->thaw(); + m_xSelectionLB->make_unsorted(); + m_xSelectionLB->freeze(); + } + // #i83479# + else if (nTypeId != REFFLDFLAG_HEADING && nTypeId != REFFLDFLAG_NUMITEM) + { + m_xSelectionLB->thaw(); + m_xSelectionLB->make_sorted(); + m_xSelectionLB->freeze(); + } + } + + // #i83479# + m_xSelectionToolTipLB->freeze(); + m_xSelectionToolTipLB->clear(); + OUString m_sSelectionToolTipLBId; + bool bShowSelectionToolTipLB( false ); + + if( REFFLDFLAG & nTypeId ) + { + if (nTypeId == REFFLDFLAG_BOOKMARK) // text marks! + { + // get all text marks + IDocumentMarkAccess* const pMarkAccess = pSh->getIDocumentMarkAccess(); + for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getBookmarksBegin(); + ppMark != pMarkAccess->getBookmarksEnd(); + ++ppMark) + { + const ::sw::mark::IMark* pBkmk = *ppMark; + if(IDocumentMarkAccess::MarkType::BOOKMARK == IDocumentMarkAccess::GetType(*pBkmk)) + { + bool isSubstring = MatchSubstring(pBkmk->GetName(), filterString); + if(isSubstring) + { + m_xSelectionLB->append_text( pBkmk->GetName() ); + } + } + } + if (IsFieldEdit() && pRefField) + sOldSel = pRefField->GetSetRefName(); + } + else if (nTypeId == REFFLDFLAG_FOOTNOTE) + { + SwSeqFieldList aArr; + const size_t nCnt = pSh->GetSeqFootnoteList( aArr ); + + for( size_t n = 0; n < nCnt; ++n ) + { + bool isSubstring = MatchSubstring(aArr[ n ].sDlgEntry, filterString); + if(isSubstring) + { + m_xSelectionLB->append_text( aArr[ n ].sDlgEntry ); + } + if (IsFieldEdit() && pRefField && pRefField->GetSeqNo() == aArr[ n ].nSeqNo) + sOldSel = aArr[n].sDlgEntry; + } + } + else if (nTypeId == REFFLDFLAG_ENDNOTE) + { + SwSeqFieldList aArr; + const size_t nCnt = pSh->GetSeqFootnoteList( aArr, true ); + + for( size_t n = 0; n < nCnt; ++n ) + { + bool isSubstring = MatchSubstring(aArr[ n ].sDlgEntry, filterString); + if(isSubstring) + { + m_xSelectionLB->append_text( aArr[ n ].sDlgEntry ); + } + if (IsFieldEdit() && pRefField && pRefField->GetSeqNo() == aArr[ n ].nSeqNo) + sOldSel = aArr[n].sDlgEntry; + } + } + // #i83479# + else if ( nTypeId == REFFLDFLAG_HEADING ) + { + bShowSelectionToolTipLB = true; + + const IDocumentOutlineNodes* pIDoc( pSh->getIDocumentOutlineNodesAccess() ); + pIDoc->getOutlineNodes( maOutlineNodes ); + bool bCertainTextNodeSelected( false ); + for ( size_t nOutlIdx = 0; nOutlIdx < maOutlineNodes.size(); ++nOutlIdx ) + { + if (!pIDoc->isOutlineInLayout(nOutlIdx, *pSh->GetLayout())) + { + continue; // skip it + } + bool isSubstring = MatchSubstring(pIDoc->getOutlineText(nOutlIdx, pSh->GetLayout(), true, true, false), filterString); + if(isSubstring) + { + OUString sId(OUString::number(nOutlIdx)); + m_xSelectionToolTipLB->append(sId, + pIDoc->getOutlineText(nOutlIdx, pSh->GetLayout(), true, true, false)); + if ((IsFieldEdit() && pRefField + && pRefField->GetReferencedTextNode() == maOutlineNodes[nOutlIdx]) + || mpSavedSelectedTextNode == maOutlineNodes[nOutlIdx]) + { + m_sSelectionToolTipLBId = sId; + sOldSel.clear(); + bCertainTextNodeSelected = true; + } + else if ( !bCertainTextNodeSelected && mnSavedSelectedPos == nOutlIdx ) + { + m_sSelectionToolTipLBId = sId; + sOldSel.clear(); + } + } + } + } + else if ( nTypeId == REFFLDFLAG_NUMITEM ) + { + bShowSelectionToolTipLB = true; + + const IDocumentListItems* pIDoc( pSh->getIDocumentListItemsAccess() ); + pIDoc->getNumItems( maNumItems ); + bool bCertainTextNodeSelected( false ); + for ( size_t nNumItemIdx = 0; nNumItemIdx < maNumItems.size(); ++nNumItemIdx ) + { + if (!pIDoc->isNumberedInLayout(*maNumItems[nNumItemIdx], *pSh->GetLayout())) + { + continue; // skip it + } + bool isSubstring = MatchSubstring(pIDoc->getListItemText(*maNumItems[nNumItemIdx], *pSh->GetLayout()), filterString); + if(isSubstring) + { + OUString sId(OUString::number(nNumItemIdx)); + m_xSelectionToolTipLB->append(sId, + pIDoc->getListItemText(*maNumItems[nNumItemIdx], *pSh->GetLayout())); + if ((IsFieldEdit() && pRefField + && pRefField->GetReferencedTextNode() == maNumItems[nNumItemIdx]->GetTextNode()) + || mpSavedSelectedTextNode == maNumItems[nNumItemIdx]->GetTextNode()) + { + m_sSelectionToolTipLBId = sId; + sOldSel.clear(); + bCertainTextNodeSelected = true; + } + else if ( !bCertainTextNodeSelected && mnSavedSelectedPos == nNumItemIdx ) + { + m_sSelectionToolTipLBId = sId; + sOldSel.clear(); + } + } + } + } + else + { + // get the fields to Seq-FieldType: + + SwSetExpFieldType* pType = static_cast<SwSetExpFieldType*>(pSh->GetFieldType( + nTypeId & ~REFFLDFLAG, SwFieldIds::SetExp )); + if( pType ) + { + SwSeqFieldList aArr; + // old selection should be kept in non-edit mode + if(IsFieldEdit()) + sOldSel.clear(); + + const size_t nCnt = pType->GetSeqFieldList(aArr, pSh->GetLayout()); + for( size_t n = 0; n < nCnt; ++n ) + { + bool isSubstring = MatchSubstring(aArr[ n ].sDlgEntry, filterString); + if(isSubstring) + { + m_xSelectionLB->append_text( aArr[ n ].sDlgEntry ); + } + if (IsFieldEdit() && pRefField && sOldSel.isEmpty() && + aArr[ n ].nSeqNo == pRefField->GetSeqNo()) + sOldSel = aArr[ n ].sDlgEntry; + } + + if (IsFieldEdit() && pRefField && sOldSel.isEmpty()) + sOldSel = OUString::number( pRefField->GetSeqNo() + 1); + } + } + } + else + { + std::vector<OUString> aLst; + GetFieldMgr().GetSubTypes(static_cast<SwFieldTypesEnum>(nTypeId), aLst); + for(const OUString & i : aLst) + { + bool isSubstring = MatchSubstring( i , filterString ); + if(isSubstring) + { + m_xSelectionLB->append_text(i); + } + } + + if (IsFieldEdit() && pRefField) + sOldSel = pRefField->GetSetRefName(); + } + + // #i83479# + m_xSelectionLB->thaw(); + m_xSelectionToolTipLB->thaw(); + if (!m_sSelectionToolTipLBId.isEmpty()) + m_xSelectionToolTipLB->select_id(m_sSelectionToolTipLBId); + m_xSelectionToolTipLB->set_visible( bShowSelectionToolTipLB ); + m_xSelectionLB->set_visible( !bShowSelectionToolTipLB ); + if ( bShowSelectionToolTipLB ) + { + bool bEnable = m_xSelectionToolTipLB->n_children() != 0; + m_xSelection->set_sensitive( bEnable ); + + int nEntry = m_xSelectionToolTipLB->get_selected_index(); + if (nEntry != -1) + m_xSelectionToolTipLB->scroll_to_row(nEntry); + + if (IsFieldEdit() && nEntry == -1) + { + m_xNameED->set_text(sOldSel); + } + } + else + { + // enable or disable + bool bEnable = m_xSelectionLB->n_children() != 0; + m_xSelection->set_sensitive( bEnable ); + + if ( bEnable ) + { + m_xSelectionLB->select_text(sOldSel); + if (m_xSelectionLB->get_selected_index() == -1 && !IsFieldEdit()) + m_xSelectionLB->select(0); + } + + if (IsFieldEdit() && m_xSelectionLB->get_selected_index() == -1) // in case the reference was already deleted... + m_xNameED->set_text(sOldSel); + } +} + +bool SwFieldRefPage::MatchSubstring( const OUString& rListString, const OUString& rSubstr ) +{ + if(rSubstr.isEmpty()) + return true; + OUString aListString = GetAppCharClass().lowercase(rListString); + OUString aSubstr = GetAppCharClass().lowercase(rSubstr); + return aListString.indexOf(aSubstr) >= 0; +} + +namespace { + +enum FMT_REF_IDX +{ + FMT_REF_PAGE_IDX = 0, + FMT_REF_CHAPTER_IDX = 1, + FMT_REF_TEXT_IDX = 2, + FMT_REF_UPDOWN_IDX = 3, + FMT_REF_PAGE_PGDSC_IDX = 4, + FMT_REF_ONLYNUMBER_IDX = 5, + FMT_REF_ONLYCAPTION_IDX = 6, + FMT_REF_ONLYSEQNO_IDX = 7, + FMT_REF_NUMBER_IDX = 8, + FMT_REF_NUMBER_NO_CONTEXT_IDX = 9, + FMT_REF_NUMBER_FULL_CONTEXT_IDX = 10 +}; + +} + +const TranslateId FMT_REF_ARY[] = +{ + FMT_REF_PAGE, + FMT_REF_CHAPTER, + FMT_REF_TEXT, + FMT_REF_UPDOWN, + FMT_REF_PAGE_PGDSC, + FMT_REF_ONLYNUMBER, + FMT_REF_ONLYCAPTION, + FMT_REF_ONLYSEQNO, + FMT_REF_NUMBER, + FMT_REF_NUMBER_NO_CONTEXT, + FMT_REF_NUMBER_FULL_CONTEXT +}; + +sal_Int32 SwFieldRefPage::FillFormatLB(sal_uInt16 nTypeId) +{ + OUString sOldSel; + + sal_Int32 nFormatSel = m_xFormatLB->get_selected_index(); + if (nFormatSel != -1) + sOldSel = m_xFormatLB->get_text(nFormatSel); + + // fill Format-Listbox + m_xFormatLB->clear(); + + // reference has less that the annotation + sal_uInt16 nSize( 0 ); + bool bAddCrossRefFormats( false ); + switch (nTypeId) + { + // #i83479# + case REFFLDFLAG_HEADING: + case REFFLDFLAG_NUMITEM: + bAddCrossRefFormats = true; + [[fallthrough]]; + + case static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef): + case REFFLDFLAG_BOOKMARK: + case REFFLDFLAG_FOOTNOTE: + case REFFLDFLAG_ENDNOTE: + nSize = FMT_REF_PAGE_PGDSC_IDX + 1; + break; + + default: + // #i83479# + + if ( REFFLDFLAG & nTypeId ) + { + nSize = FMT_REF_ONLYSEQNO_IDX + 1; + } + else + { + nSize = GetFieldMgr().GetFormatCount( static_cast<SwFieldTypesEnum>(nTypeId), IsFieldDlgHtmlMode() ); + } + break; + } + + if (REFFLDFLAG & nTypeId) + nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef); + + SwFieldTypesEnum nFieldType = static_cast<SwFieldTypesEnum>(nTypeId); + for (sal_uInt16 i = 0; i < nSize; i++) + { + OUString sId(OUString::number(GetFieldMgr().GetFormatId( nFieldType, i ))); + m_xFormatLB->append(sId, GetFieldMgr().GetFormatStr(nFieldType, i)); + } + // #i83479# + + sal_uInt16 nExtraSize( 0 ); + if ( bAddCrossRefFormats ) + { + sal_uInt16 nFormat = FMT_REF_NUMBER_IDX; + OUString sId(OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat))); + m_xFormatLB->append(sId, GetFieldMgr().GetFormatStr( nFieldType, nFormat )); + nFormat = FMT_REF_NUMBER_NO_CONTEXT_IDX; + sId = OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat)); + m_xFormatLB->append(sId, GetFieldMgr().GetFormatStr( nFieldType, nFormat )); + nFormat = FMT_REF_NUMBER_FULL_CONTEXT_IDX; + sId = OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat)); + m_xFormatLB->append(sId, GetFieldMgr().GetFormatStr( nFieldType, nFormat )); + nExtraSize = 3; + } + + // extra list items optionally, depending from reference-language + SvtSysLocaleOptions aSysLocaleOptions; + static const LanguageTag& rLang = aSysLocaleOptions.GetRealLanguageTag(); + + if (rLang.getLanguage() == "hu") + { + for (sal_uInt16 i = 0; i < nSize; i++) + { + OUString sId(OUString::number(GetFieldMgr().GetFormatId( nFieldType, i + SAL_N_ELEMENTS(FMT_REF_ARY)))); + m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_LOWERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, i )); + } + nExtraSize += nSize; + + if ( bAddCrossRefFormats ) + { + sal_uInt16 nFormat = FMT_REF_NUMBER_IDX + SAL_N_ELEMENTS(FMT_REF_ARY); + OUString sId(OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat))); + m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_LOWERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, nFormat % SAL_N_ELEMENTS(FMT_REF_ARY))); + nFormat = FMT_REF_NUMBER_NO_CONTEXT_IDX + SAL_N_ELEMENTS(FMT_REF_ARY); + sId = OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat)); + m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_LOWERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, nFormat % SAL_N_ELEMENTS(FMT_REF_ARY))); + nFormat = FMT_REF_NUMBER_FULL_CONTEXT_IDX + SAL_N_ELEMENTS(FMT_REF_ARY); + sId = OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat)); + m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_LOWERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, nFormat % SAL_N_ELEMENTS(FMT_REF_ARY))); + nExtraSize += 3; + } + // uppercase article + for (sal_uInt16 i = 0; i < nSize; i++) + { + OUString sId(OUString::number(GetFieldMgr().GetFormatId( nFieldType, i + 2 * SAL_N_ELEMENTS(FMT_REF_ARY)))); + m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_UPPERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, i )); + } + nExtraSize += nSize; + if ( bAddCrossRefFormats ) + { + sal_uInt16 nFormat = FMT_REF_NUMBER_IDX + 2 * SAL_N_ELEMENTS(FMT_REF_ARY); + OUString sId(OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat))); + m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_UPPERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, nFormat % SAL_N_ELEMENTS(FMT_REF_ARY))); + nFormat = FMT_REF_NUMBER_NO_CONTEXT_IDX + 2 * SAL_N_ELEMENTS(FMT_REF_ARY); + sId = OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat)); + m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_UPPERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, nFormat % SAL_N_ELEMENTS(FMT_REF_ARY))); + nFormat = FMT_REF_NUMBER_FULL_CONTEXT_IDX + 2 * SAL_N_ELEMENTS(FMT_REF_ARY); + sId = OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat)); + m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_UPPERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, nFormat % SAL_N_ELEMENTS(FMT_REF_ARY))); + nExtraSize += 3; + } + } + + nSize += nExtraSize; + + // select a certain entry + if (nSize) + { + if (!IsFieldEdit()) + m_xFormatLB->select_text(sOldSel); + else + m_xFormatLB->select_text(SwResId(FMT_REF_ARY[GetCurField()->GetFormat() % SAL_N_ELEMENTS(FMT_REF_ARY)])); + + if (m_xFormatLB->get_selected_index() == -1) + { + if (nFieldDlgFormatSel < m_xFormatLB->n_children()) + m_xFormatLB->select(nFieldDlgFormatSel); + else + m_xFormatLB->select(0); + } + } + + return nSize; +} + +// Modify +IMPL_LINK_NOARG(SwFieldRefPage, ModifyHdl, weld::Entry&, void) +{ + OUString aName(m_xNameED->get_text()); + const bool bEmptyName = aName.isEmpty(); + + bool bEnable = true; + sal_uInt16 nTypeId = m_xTypeLB->get_id(GetTypeSel()).toUInt32(); + + if ((nTypeId == static_cast<sal_uInt16>(SwFieldTypesEnum::SetRef) && !GetFieldMgr().CanInsertRefMark(aName)) || + (bEmptyName && (nTypeId == static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef) || nTypeId == static_cast<sal_uInt16>(SwFieldTypesEnum::SetRef) || + nTypeId == REFFLDFLAG_BOOKMARK))) + bEnable = false; + + EnableInsert(bEnable); + + m_xSelectionLB->select_text(aName); +} + +bool SwFieldRefPage::FillItemSet(SfxItemSet* ) +{ + bool bModified = false; + sal_uInt16 nTypeId = m_xTypeLB->get_id(GetTypeSel()).toUInt32(); + + sal_uInt16 nSubType = 0; + const sal_Int32 nEntryPos = m_xFormatLB->get_selected_index(); + const sal_uLong nFormat = (nEntryPos == -1) + ? 0 : m_xFormatLB->get_id(nEntryPos).toUInt32(); + + OUString aVal(m_xValueED->get_text()); + OUString aName(m_xNameED->get_text()); + + switch(nTypeId) + { + case static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef): + nSubType = REF_SETREFATTR; + break; + + case static_cast<sal_uInt16>(SwFieldTypesEnum::SetRef): + { + SwFieldType* pType = GetFieldMgr().GetFieldType(SwFieldIds::SetExp, aName); + + if(!pType) // Only insert when the name doesn't exist yet + { + m_xSelectionLB->append_text(aName); + m_xSelection->set_sensitive(true); + } + break; + } + } + + SwGetRefField const*const pRefField(dynamic_cast<SwGetRefField*>(GetCurField())); + + SwWrtShell *pSh = GetWrtShell(); + if(!pSh) + pSh = ::GetActiveWrtShell(); + + if (pSh && REFFLDFLAG & nTypeId) + { + if (nTypeId == REFFLDFLAG_BOOKMARK) // text marks! + { + aName = m_xNameED->get_text(); + nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef); + nSubType = REF_BOOKMARK; + } + else if (REFFLDFLAG_FOOTNOTE == nTypeId) // footnotes + { + SwSeqFieldList aArr; + SeqFieldLstElem aElem( m_xSelectionLB->get_selected_text(), 0 ); + + size_t nPos = 0; + + nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef); + nSubType = REF_FOOTNOTE; + aName.clear(); + + if (pSh->GetSeqFootnoteList(aArr) && aArr.SeekEntry(aElem, &nPos)) + { + aVal = OUString::number( aArr[nPos].nSeqNo ); + + if (IsFieldEdit() && pRefField && aArr[nPos].nSeqNo == pRefField->GetSeqNo()) + bModified = true; // can happen with fields of which the references were deleted + } + else if (IsFieldEdit() && pRefField) + aVal = OUString::number( pRefField->GetSeqNo() ); + } + else if (REFFLDFLAG_ENDNOTE == nTypeId) // endnotes + { + SwSeqFieldList aArr; + SeqFieldLstElem aElem( m_xSelectionLB->get_selected_text(), 0 ); + + size_t nPos = 0; + + nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef); + nSubType = REF_ENDNOTE; + aName.clear(); + + if (pSh->GetSeqFootnoteList(aArr, true) && aArr.SeekEntry(aElem, &nPos)) + { + aVal = OUString::number( aArr[nPos].nSeqNo ); + + if (IsFieldEdit() && pRefField && aArr[nPos].nSeqNo == pRefField->GetSeqNo()) + bModified = true; // can happen with fields of which the reference was deleted + } + else if (IsFieldEdit() && pRefField) + aVal = OUString::number( pRefField->GetSeqNo() ); + } + // #i83479# + else if ( nTypeId == REFFLDFLAG_HEADING ) + { + int nEntry = m_xSelectionToolTipLB->get_selected_index(); + OSL_ENSURE( nEntry != -1, + "<SwFieldRefPage::FillItemSet(..)> - no entry selected in selection tool tip listbox!" ); + if (nEntry != -1) + { + const size_t nOutlIdx(m_xSelectionToolTipLB->get_id(nEntry).toUInt32()); + pSh->getIDocumentOutlineNodesAccess()->getOutlineNodes( maOutlineNodes ); + if ( nOutlIdx < maOutlineNodes.size() ) + { + ::sw::mark::IMark const * const pMark = pSh->getIDocumentMarkAccess()->getMarkForTextNode( + *(maOutlineNodes[nOutlIdx]), + IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK); + aName = pMark->GetName(); + nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef); + nSubType = REF_BOOKMARK; + } + } + } + else if ( nTypeId == REFFLDFLAG_NUMITEM ) + { + int nEntry = m_xSelectionToolTipLB->get_selected_index(); + OSL_ENSURE( nEntry != -1, + "<SwFieldRefPage::FillItemSet(..)> - no entry selected in selection tool tip listbox!" ); + if (nEntry != -1) + { + const size_t nNumItemIdx(m_xSelectionToolTipLB->get_id(nEntry).toUInt32()); + pSh->getIDocumentListItemsAccess()->getNumItems(maNumItems); + if ( nNumItemIdx < maNumItems.size() ) + { + ::sw::mark::IMark const * const pMark = pSh->getIDocumentMarkAccess()->getMarkForTextNode( + *(maNumItems[nNumItemIdx]->GetTextNode()), + IDocumentMarkAccess::MarkType::CROSSREF_NUMITEM_BOOKMARK); + aName = pMark->GetName(); + nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef); + nSubType = REF_BOOKMARK; + } + } + } + else // SequenceFields + { + // get fields for Seq-FieldType: + SwSetExpFieldType* pType = static_cast<SwSetExpFieldType*>(pSh->GetFieldType( + nTypeId & ~REFFLDFLAG, SwFieldIds::SetExp )); + if( pType ) + { + SwSeqFieldList aArr; + SeqFieldLstElem aElem( m_xSelectionLB->get_selected_text(), 0 ); + + size_t nPos = 0; + + nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef); + nSubType = REF_SEQUENCEFLD; + aName = pType->GetName(); + + if (pType->GetSeqFieldList(aArr, pSh->GetLayout()) + && aArr.SeekEntry(aElem, &nPos)) + { + aVal = OUString::number( aArr[nPos].nSeqNo ); + + if (IsFieldEdit() && pRefField && aArr[nPos].nSeqNo == pRefField->GetSeqNo()) + bModified = true; // can happen with fields of which the reference was deleted + } + else if (IsFieldEdit() && pRefField) + aVal = OUString::number( pRefField->GetSeqNo() ); + } + } + } + + if (IsFieldEdit() && nTypeId == static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef)) + { + aVal = OUString::number(nSubType) + "|" + aVal; + } + + if (!IsFieldEdit() || bModified || + m_xNameED->get_value_changed_from_saved() || + m_xValueED->get_value_changed_from_saved() || + m_xTypeLB->get_value_changed_from_saved() || + m_xSelectionLB->get_value_changed_from_saved() || + m_xFormatLB->get_value_changed_from_saved()) + { + InsertField( static_cast<SwFieldTypesEnum>(nTypeId), nSubType, aName, aVal, nFormat ); + } + + ModifyHdl(*m_xNameED); // enable/disable insert if applicable + + return false; +} + +std::unique_ptr<SfxTabPage> SwFieldRefPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet *const pAttrSet) +{ + return std::make_unique<SwFieldRefPage>(pPage, pController, pAttrSet); +} + +sal_uInt16 SwFieldRefPage::GetGroup() +{ + return GRP_REF; +} + +void SwFieldRefPage::FillUserData() +{ + const sal_Int32 nEntryPos = m_xTypeLB->get_selected_index(); + const sal_uInt16 nTypeSel = ( -1 == nEntryPos ) + ? USHRT_MAX + : m_xTypeLB->get_id(nEntryPos).toUInt32(); + const sal_Int32 nFormatEntryPos = m_xFormatLB->get_selected_index(); + const sal_uInt32 nFormatSel = -1 == nFormatEntryPos ? USHRT_MAX : nFormatEntryPos; + SetUserData( USER_DATA_VERSION ";" + + OUString::number( nTypeSel ) + ";" + + OUString::number( nFormatSel )); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/fldref.hxx b/sw/source/ui/fldui/fldref.hxx new file mode 100644 index 000000000..8dc9a311b --- /dev/null +++ b/sw/source/ui/fldui/fldref.hxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_SW_SOURCE_UI_FLDUI_FLDREF_HXX +#define INCLUDED_SW_SOURCE_UI_FLDUI_FLDREF_HXX + +#include <sfx2/tabdlg.hxx> + +#include "fldpage.hxx" +#include <IDocumentOutlineNodes.hxx> +#include <IDocumentListItems.hxx> +class SwTextNode; + +class SwFieldRefPage : public SwFieldPage +{ + OUString sBookmarkText; + OUString sFootnoteText; + OUString sEndnoteText; + // #i83479# + OUString sHeadingText; + OUString sNumItemText; + + IDocumentOutlineNodes::tSortedOutlineNodeList maOutlineNodes; + IDocumentListItems::tSortedNodeNumList maNumItems; + + // selected text node in the listbox for headings and numbered items + // in order to restore selection after update of selection listbox + const SwTextNode* mpSavedSelectedTextNode; + // fallback, if previously selected text node doesn't exist anymore + size_t mnSavedSelectedPos; + + std::unique_ptr<weld::TreeView> m_xTypeLB; + std::unique_ptr<weld::Widget> m_xSelection; + std::unique_ptr<weld::TreeView> m_xSelectionLB; + // #i83479# + std::unique_ptr<weld::TreeView> m_xSelectionToolTipLB; + std::unique_ptr<weld::Widget> m_xFormat; + std::unique_ptr<weld::TreeView> m_xFormatLB; + std::unique_ptr<weld::Label> m_xNameFT; + std::unique_ptr<weld::Entry> m_xNameED; + std::unique_ptr<weld::Entry> m_xValueED; + std::unique_ptr<weld::Entry> m_xFilterED; + + DECL_LINK(TypeHdl, weld::TreeView&, void); + DECL_LINK(SubTypeListBoxHdl, weld::TreeView&, void); + DECL_LINK(SubTypeTreeListBoxHdl, weld::TreeView&, void); + DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(ModifyHdl_Impl, weld::Entry&, void); + + void SubTypeHdl(); + + void UpdateSubType(const OUString& filterString); + + static bool MatchSubstring( const OUString& list_string, const OUString& substr ); + + sal_Int32 FillFormatLB(sal_uInt16 nTypeId); + + // #i83479# + void SaveSelectedTextNode(); + +protected: + virtual sal_uInt16 GetGroup() override; + +public: + SwFieldRefPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pSet); + virtual ~SwFieldRefPage() override; + + static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + + virtual void FillUserData() override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/fldtdlg.cxx b/sw/source/ui/fldui/fldtdlg.cxx new file mode 100644 index 000000000..f0deba6d3 --- /dev/null +++ b/sw/source/ui/fldui/fldtdlg.cxx @@ -0,0 +1,307 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> +#include <config_fuzzers.h> + +#include <cmdid.h> +#include <unotools/confignode.hxx> +#include <comphelper/processfactory.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/htmlmode.hxx> +#include <sfx2/viewfrm.hxx> +#include <osl/diagnose.h> +#include <viewopt.hxx> +#include <chldwrap.hxx> +#include <docsh.hxx> +#include "flddb.hxx" +#include "flddinf.hxx" +#include "fldvar.hxx" +#include "flddok.hxx" +#include "fldfunc.hxx" +#include "fldref.hxx" +#include <wrtsh.hxx> +#include <view.hxx> +#include <fldtdlg.hxx> +#include <swmodule.hxx> +#include <comphelper/lok.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/document/XDocumentProperties.hpp> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/frame/XModel.hpp> + +// carrier of the dialog +SwFieldDlg::SwFieldDlg(SfxBindings* pB, SwChildWinWrapper* pCW, weld::Window *pParent) + : SfxTabDialogController(pParent, "modules/swriter/ui/fielddialog.ui", "FieldDialog") + , m_pChildWin(pCW) + , m_pBindings(pB) + , m_bDataBaseMode(false) + , m_bClosing(false) +{ + m_bHtmlMode = (::GetHtmlMode(static_cast<SwDocShell*>(SfxObjectShell::Current())) & HTMLMODE_ON) != 0; + + GetCancelButton().connect_clicked(LINK(this, SwFieldDlg, CancelHdl)); + GetOKButton().connect_clicked(LINK(this, SwFieldDlg, OKHdl)); + + AddTabPage("document", SwFieldDokPage::Create, nullptr); + AddTabPage("variables", SwFieldVarPage::Create, nullptr); + AddTabPage("docinfo", SwFieldDokInfPage::Create, nullptr); + + if (!m_bHtmlMode) + { + AddTabPage("ref", SwFieldRefPage::Create, nullptr); + AddTabPage("functions", SwFieldFuncPage::Create, nullptr); + + utl::OConfigurationTreeRoot aCfgRoot + = utl::OConfigurationTreeRoot::createWithComponentContext( + ::comphelper::getProcessComponentContext(), + "/org.openoffice.Office.DataAccess/Policies/Features/Writer", + -1, + utl::OConfigurationTreeRoot::CM_READONLY); + +#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS + bool bDatabaseFields = true; + aCfgRoot.getNodeValue( + OUString("DatabaseFields")) >>= bDatabaseFields; + + if (bDatabaseFields) + AddTabPage("database", SwFieldDBPage::Create, nullptr); + else +#endif + RemoveTabPage("database"); + } + else + { + RemoveTabPage("ref"); + RemoveTabPage("functions"); + RemoveTabPage("database"); + } + + if (comphelper::LibreOfficeKit::isActive()) + RemoveTabPage("database"); +} + +SwFieldDlg::~SwFieldDlg() +{ +} + +void SwFieldDlg::EndDialog(int nResponse) +{ + m_bClosing = true; + SfxTabDialogController::EndDialog(nResponse); + m_bClosing = false; +} + +void SwFieldDlg::Close() +{ + if (m_bClosing) + return; + const SfxPoolItem* pResult = m_pBindings->GetDispatcher()-> + Execute(m_bDataBaseMode ? FN_INSERT_FIELD_DATA_ONLY : FN_INSERT_FIELD, + SfxCallMode::SYNCHRON|SfxCallMode::RECORD); + if (!pResult) + { + // If Execute action did fail for whatever reason, this means that request + // to close did fail or wasn't delivered to SwTextShell::ExecField(). + // Just explicitly close dialog in this case. + SfxTabDialogController::EndDialog(RET_CLOSE); + } +} + +void SwFieldDlg::Initialize(SfxChildWinInfo const *pInfo) +{ + OString aWinState = pInfo->aWinState; + if (aWinState.isEmpty()) + return; + m_xDialog->set_window_state(aWinState); +} + +SfxItemSet* SwFieldDlg::CreateInputItemSet(const OString& rID) +{ + SwDocShell *const pDocSh(static_cast<SwDocShell*>(SfxObjectShell::Current())); + if (rID == "docinfo" && pDocSh) // might not have a shell if the dialog is restored on startup + { + mxInputItemSet = std::make_unique<SfxItemSetFixed<FN_FIELD_DIALOG_DOC_PROPS, FN_FIELD_DIALOG_DOC_PROPS>>( pDocSh->GetPool() ); + using namespace ::com::sun::star; + uno::Reference<document::XDocumentPropertiesSupplier> xDPS( + pDocSh->GetModel(), uno::UNO_QUERY_THROW); + uno::Reference<document::XDocumentProperties> xDocProps + = xDPS->getDocumentProperties(); + uno::Reference< beans::XPropertySet > xUDProps( + xDocProps->getUserDefinedProperties(), + uno::UNO_QUERY_THROW); + mxInputItemSet->Put( SfxUnoAnyItem( FN_FIELD_DIALOG_DOC_PROPS, uno::Any(xUDProps) ) ); + return mxInputItemSet.get(); + } + else + return nullptr; +} + +// kick off inserting of new fields +IMPL_LINK_NOARG(SwFieldDlg, OKHdl, weld::Button&, void) +{ + if (GetOKButton().get_sensitive()) + { + SfxTabPage* pPage = GetTabPage(GetCurPageId()); + assert(pPage); + pPage->FillItemSet(nullptr); + + GetOKButton().grab_focus(); // because of InputField-Dlg + } +} + +IMPL_LINK_NOARG(SwFieldDlg, CancelHdl, weld::Button&, void) +{ + Close(); +} + +// newly initialise dialog after Doc-Switch +void SwFieldDlg::ReInitDlg() +{ + SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current()); + bool bNewMode = (::GetHtmlMode(pDocSh) & HTMLMODE_ON) != 0; + + if (bNewMode != m_bHtmlMode) + { + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + { + pViewFrm->GetDispatcher()-> + Execute(FN_INSERT_FIELD, SfxCallMode::ASYNCHRON|SfxCallMode::RECORD); + } + Close(); + } + + SwView* pActiveView = ::GetActiveView(); + if(!pActiveView) + return; + const SwWrtShell& rSh = pActiveView->GetWrtShell(); + GetOKButton().set_sensitive(!rSh.IsReadOnlyAvailable() || + !rSh.HasReadonlySel()); + + ReInitTabPage("document"); + ReInitTabPage("variables"); + ReInitTabPage("docinfo"); + + if (!m_bHtmlMode) + { + ReInitTabPage("ref"); + ReInitTabPage("functions"); + ReInitTabPage("database"); + } + + m_pChildWin->SetOldDocShell(pDocSh); +} + +// newly initialise TabPage after Doc-Switch +void SwFieldDlg::ReInitTabPage(std::string_view rPageId, bool bOnlyActivate) +{ + SwFieldPage* pPage = static_cast<SwFieldPage*>(GetTabPage(rPageId)); + if (pPage) + pPage->EditNewField( bOnlyActivate ); // newly initialise TabPage +} + +// newly initialise after activation of a few TabPages +void SwFieldDlg::Activate() +{ + SwView* pView = GetActiveView(); + if( !pView ) + return; + + bool bHtmlMode = (::GetHtmlMode(static_cast<SwDocShell*>(SfxObjectShell::Current())) & HTMLMODE_ON) != 0; + const SwWrtShell& rSh = pView->GetWrtShell(); + GetOKButton().set_sensitive(!rSh.IsReadOnlyAvailable() || + !rSh.HasReadonlySel()); + + ReInitTabPage("variables", true); + + if( !bHtmlMode ) + { + ReInitTabPage("ref", true); + ReInitTabPage("functions", true); + } +} + +void SwFieldDlg::EnableInsert(bool bEnable) +{ + if( bEnable ) + { + SwView* pView = ::GetActiveView(); + if( !pView || + (pView->GetWrtShell().IsReadOnlyAvailable() && + pView->GetWrtShell().HasReadonlySel()) ) + bEnable = false; + } + GetOKButton().set_sensitive(bEnable); +} + +void SwFieldDlg::InsertHdl() +{ + GetOKButton().clicked(); +} + +void SwFieldDlg::ActivateDatabasePage() +{ +#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS + m_bDataBaseMode = true; + ShowPage("database"); + SfxTabPage* pDBPage = GetTabPage("database"); + if( pDBPage ) + { + static_cast<SwFieldDBPage*>(pDBPage)->ActivateMailMergeAddress(); + } + //remove all other pages + RemoveTabPage("document"); + RemoveTabPage("variables"); + RemoveTabPage("docinfo"); + RemoveTabPage("ref"); + RemoveTabPage("functions"); +#endif +} + +void SwFieldDlg::ShowReferencePage() +{ + ShowPage("ref"); +} + +void SwFieldDlg::PageCreated(const OString& rId, SfxTabPage& rPage) +{ +#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS + if (rId != "database") + return; + + SfxDispatcher* pDispatch = m_pBindings->GetDispatcher(); + SfxViewFrame* pViewFrame = pDispatch ? pDispatch->GetFrame() : nullptr; + if(pViewFrame) + { + SfxViewShell* pViewShell = SfxViewShell::GetFirst( true, checkSfxViewShell<SwView> ); + while(pViewShell && pViewShell->GetViewFrame() != pViewFrame) + { + pViewShell = SfxViewShell::GetNext( *pViewShell, true, checkSfxViewShell<SwView> ); + } + if(pViewShell) + static_cast<SwFieldDBPage&>(rPage).SetWrtShell(static_cast<SwView*>(pViewShell)->GetWrtShell()); + } +#else + (void) rId; + (void) rPage; +#endif +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/fldvar.cxx b/sw/source/ui/fldui/fldvar.cxx new file mode 100644 index 000000000..13621af70 --- /dev/null +++ b/sw/source/ui/fldui/fldvar.cxx @@ -0,0 +1,1250 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <swtypes.hxx> +#include <sfx2/linkmgr.hxx> +#include <IDocumentFieldsAccess.hxx> +#include <usrfld.hxx> +#include <docufld.hxx> +#include <expfld.hxx> +#include <ddefld.hxx> +#include <wrtsh.hxx> +#include <doc.hxx> +#include <docary.hxx> +#include <swmodule.hxx> +#include "fldvar.hxx" +#include "flddinf.hxx" +#include <calc.hxx> +#include <svl/numformat.hxx> +#include <svl/zformat.hxx> +#include <o3tl/string_view.hxx> +#include <strings.hrc> + +#define USER_DATA_VERSION_1 "1" +#define USER_DATA_VERSION USER_DATA_VERSION_1 + +SwFieldVarPage::SwFieldVarPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *const pCoreSet ) + : SwFieldPage(pPage, pController, "modules/swriter/ui/fldvarpage.ui", "FieldVarPage", pCoreSet) + , m_xTypeLB(m_xBuilder->weld_tree_view("type")) + , m_xSelection(m_xBuilder->weld_widget("selectframe")) + , m_xSelectionLB(m_xBuilder->weld_tree_view("select")) + , m_xNameFT(m_xBuilder->weld_label("nameft")) + , m_xNameED(m_xBuilder->weld_entry("name")) + , m_xValueFT(m_xBuilder->weld_label("valueft")) + , m_xValueED(new ConditionEdit(m_xBuilder->weld_entry("value"))) + , m_xFormat(m_xBuilder->weld_widget("formatframe")) + , m_xNumFormatLB(new SwNumFormatTreeView(m_xBuilder->weld_tree_view("numformat"))) + , m_xFormatLB(m_xBuilder->weld_tree_view("format")) + , m_xChapterFrame(m_xBuilder->weld_widget("chapterframe")) + , m_xChapterLevelLB(m_xBuilder->weld_combo_box("level")) + , m_xInvisibleCB(m_xBuilder->weld_check_button("invisible")) + , m_xSeparatorFT(m_xBuilder->weld_label("separatorft")) + , m_xSeparatorED(m_xBuilder->weld_entry("separator")) + , m_xNewPB(m_xBuilder->weld_button("apply")) + , m_xDelPB(m_xBuilder->weld_button("delete")) + , nOldFormat(0) + , bInit(true) +{ + FillFieldSelect(*m_xTypeLB); + m_xSelectionLB->make_sorted(); + FillFieldSelect(*m_xFormatLB); + + auto nWidth = m_xTypeLB->get_approximate_digit_width() * FIELD_COLUMN_WIDTH; + auto nHeight = m_xTypeLB->get_height_rows(10); + m_xTypeLB->set_size_request(nWidth, nHeight); + m_xSelectionLB->set_size_request(nWidth, nHeight); + m_xFormatLB->set_size_request(nWidth, nHeight/2); + + sOldValueFT = m_xValueFT->get_label(); + sOldNameFT = m_xNameFT->get_label(); + + for (sal_uInt16 i = 1; i <= MAXLEVEL; i++) + m_xChapterLevelLB->append_text(OUString::number(i)); + + m_xChapterLevelLB->set_active(0); + //enable 'active' language selection + m_xNumFormatLB->SetShowLanguageControl(true); + + // uitests + m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-var"); + m_xNameED->set_buildable_name(m_xNameED->get_buildable_name() + "-var"); + m_xValueED->set_buildable_name(m_xValueED->get_buildable_name() + "-var"); + m_xNumFormatLB->set_buildable_name(m_xNumFormatLB->get_buildable_name() + "-var"); + m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-var"); + m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-var"); +} + +SwFieldVarPage::~SwFieldVarPage() +{ +} + +void SwFieldVarPage::Reset(const SfxItemSet* ) +{ + SavePos(*m_xTypeLB); + + Init(); // general initialisation + + m_xTypeLB->freeze(); + m_xTypeLB->clear(); + + SwFieldTypesEnum nTypeId; + + if (!IsFieldEdit()) + { + // initialise TypeListBox + const SwFieldGroupRgn& rRg = SwFieldMgr::GetGroupRange(IsFieldDlgHtmlMode(), GetGroup()); + + for (short i = rRg.nStart; i < rRg.nEnd; ++i) + { + nTypeId = SwFieldMgr::GetTypeId(i); + m_xTypeLB->append(OUString::number(static_cast<sal_uInt16>(nTypeId)), SwFieldMgr::GetTypeStr(i)); + } + } + else + { + const SwField* pCurField = GetCurField(); + assert(pCurField && "<SwFieldVarPage::Reset(..)> - <SwField> instance missing!"); + nTypeId = pCurField->GetTypeId(); + if (nTypeId == SwFieldTypesEnum::SetInput) + nTypeId = SwFieldTypesEnum::Input; + m_xTypeLB->append(OUString::number(static_cast<sal_uInt16>(nTypeId)), SwFieldMgr::GetTypeStr(SwFieldMgr::GetPos(nTypeId))); + m_xNumFormatLB->SetAutomaticLanguage(pCurField->IsAutomaticLanguage()); + SwWrtShell *pSh = GetWrtShell(); + if(!pSh) + pSh = ::GetActiveWrtShell(); + if(pSh) + { + const SvNumberformat* pFormat = pSh->GetNumberFormatter()->GetEntry(pCurField->GetFormat()); + if(pFormat) + m_xNumFormatLB->SetLanguage(pFormat->GetLanguage()); + } + } + + m_xTypeLB->thaw(); + + // select old Pos + RestorePos(*m_xTypeLB); + + m_xTypeLB->connect_row_activated(LINK(this, SwFieldVarPage, TreeViewInsertHdl)); + m_xTypeLB->connect_changed(LINK(this, SwFieldVarPage, TypeHdl)); + m_xSelectionLB->connect_changed(LINK(this, SwFieldVarPage, SubTypeListBoxHdl)); + m_xSelectionLB->connect_row_activated(LINK(this, SwFieldVarPage, SubTypeInsertHdl)); + m_xFormatLB->connect_row_activated(LINK(this, SwFieldVarPage, TreeViewInsertHdl)); + m_xNumFormatLB->connect_row_activated(LINK(this, SwFieldVarPage, TreeViewInsertHdl)); + m_xNameED->connect_changed(LINK(this, SwFieldVarPage, ModifyHdl)); + m_xValueED->connect_changed(LINK(this, SwFieldVarPage, ModifyHdl)); + m_xNewPB->connect_clicked(LINK(this, SwFieldVarPage, TBClickHdl)); + m_xDelPB->connect_clicked(LINK(this, SwFieldVarPage, TBClickHdl)); + m_xChapterLevelLB->connect_changed(LINK(this, SwFieldVarPage, ChapterHdl)); + m_xSeparatorED->connect_changed(LINK(this, SwFieldVarPage, SeparatorHdl)); + + if( !IsRefresh() ) + { + OUString sUserData = GetUserData(); + sal_Int32 nIdx{ 0 }; + if(!IsRefresh() && o3tl::equalsIgnoreAsciiCase(o3tl::getToken(sUserData, 0, ';', nIdx), u"" USER_DATA_VERSION_1)) + { + std::u16string_view sVal = o3tl::getToken(sUserData, 0, ';', nIdx); + sal_uInt16 nVal = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(sVal)); + if (USHRT_MAX != nVal) + { + for (sal_Int32 i = 0, nEntryCount = m_xTypeLB->n_children(); i < nEntryCount; i++) + { + if (nVal == m_xTypeLB->get_id(i).toUInt32()) + { + m_xTypeLB->select(i); + break; + } + } + } + } + } + TypeHdl(*m_xTypeLB); + + if (IsFieldEdit()) + { + m_xSelectionLB->save_value(); + m_xFormatLB->save_value(); + nOldFormat = m_xNumFormatLB->GetFormat(); + m_xNameED->save_value(); + m_xValueED->save_value(); + m_xInvisibleCB->save_state(); + m_xChapterLevelLB->save_value(); + m_xSeparatorED->save_value(); + } +} + +IMPL_LINK_NOARG(SwFieldVarPage, TypeHdl, weld::TreeView&, void) +{ + // save old ListBoxPos + const sal_Int32 nOld = GetTypeSel(); + + // current ListBoxPos + SetTypeSel(m_xTypeLB->get_selected_index()); + + if(GetTypeSel() == -1) + { + SetTypeSel(0); + m_xTypeLB->select(0); + } + + if (nOld != GetTypeSel() || nOld == -1) + { + bInit = true; + if (nOld != -1) + { + m_xNameED->set_text(OUString()); + m_xValueED->set_text(OUString()); + } + + m_xValueED->SetDropEnable(false); + UpdateSubType(); // initialise selection-listboxes + } + + bInit = false; +} + +IMPL_LINK( SwFieldVarPage, SubTypeListBoxHdl, weld::TreeView&, rBox, void ) +{ + SubTypeHdl(&rBox); +} + +void SwFieldVarPage::SubTypeHdl(const weld::TreeView* pBox) +{ + SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + sal_Int32 nSelPos = m_xSelectionLB->get_selected_index(); + size_t nSelData = SIZE_MAX; + + if (nSelPos != -1) + nSelData = m_xSelectionLB->get_id(nSelPos).toUInt32(); + + if (IsFieldEdit() && (!pBox || bInit)) + { + if (nTypeId != SwFieldTypesEnum::Formel) + m_xNameED->set_text(GetFieldMgr().GetCurFieldPar1()); + + m_xValueED->set_text(GetFieldMgr().GetCurFieldPar2()); + } + + if (m_xNameFT->get_label() != sOldNameFT) + m_xNameFT->set_label(sOldNameFT); + if (m_xValueFT->get_label() != sOldValueFT) + m_xValueFT->set_label(sOldValueFT); + + FillFormatLB(nTypeId); + + sal_Int32 nSize = m_xFormatLB->n_children(); + + bool bValue = false, bName = false, bNumFormat = false, + bInvisible = false, bShowChapterFrame = false; + bool bFormat = nSize != 0; + + switch (nTypeId) + { + case SwFieldTypesEnum::User: + { + // change or create user type + SwUserFieldType* pType = static_cast<SwUserFieldType*>( + GetFieldMgr().GetFieldType(SwFieldIds::User, nSelData)); + + if (pType) + { + if (!IsFieldEdit()) + { + if (pBox || (bInit && !IsRefresh())) // only when interacting via mouse + { + m_xNameED->set_text(pType->GetName()); + + if (pType->GetType() == UF_STRING) + { + m_xValueED->set_text(pType->GetContent()); + m_xNumFormatLB->select(0); + } + else + m_xValueED->set_text(pType->GetContent()); + } + } + else + m_xValueED->set_text(pType->GetContent()); + } + else + { + if (pBox) // only when interacting via mouse + { + m_xNameED->set_text(OUString()); + m_xValueED->set_text(OUString()); + } + } + bValue = bName = bNumFormat = bInvisible = true; + + m_xValueED->SetDropEnable(true); + break; + } + + case SwFieldTypesEnum::Set: + bValue = true; + + bNumFormat = bInvisible = true; + + if (!IsFieldDlgHtmlMode()) + bName = true; + else + { + m_xNumFormatLB->clear(); + m_xNumFormatLB->append(OUString::number(NUMBERFORMAT_ENTRY_NOT_FOUND), SwResId(FMT_SETVAR_TEXT)); + m_xNumFormatLB->select(0); + } + // is there a corresponding SetField + if (IsFieldEdit() || pBox) // only when interacting via mouse + { + if (nSelPos != -1) + { + OUString sName(m_xSelectionLB->get_selected_text()); + m_xNameED->set_text(sName); + + if (!IsFieldDlgHtmlMode()) + { + SwWrtShell *pSh = GetWrtShell(); + if(!pSh) + pSh = ::GetActiveWrtShell(); + if(pSh) + { + SwSetExpFieldType* pSetTyp = static_cast<SwSetExpFieldType*>( + pSh->GetFieldType(SwFieldIds::SetExp, sName)); + + if (pSetTyp && pSetTyp->GetType() == nsSwGetSetExpType::GSE_STRING) + m_xNumFormatLB->select(0); // textual + } + } + } + } + if (GetCurField() != nullptr && IsFieldEdit()) + { + // GetFormula leads to problems with date formats because + // only the numeric value without formatting is returned. + // It must be used though because otherwise in GetPar2 only + // the value calculated by Kalkulator would be displayed + // (instead of test2 = test + 1) + m_xValueED->set_text(static_cast<SwSetExpField*>(GetCurField())->GetFormula()); + } + m_xValueED->SetDropEnable(true); + break; + + case SwFieldTypesEnum::Formel: + { + bValue = true; + bNumFormat = true; + m_xValueFT->set_label(SwResId(STR_FORMULA)); + m_xValueED->SetDropEnable(true); + } + break; + + case SwFieldTypesEnum::Get: + { + if (!IsFieldEdit()) + { + m_xNameED->set_text(OUString()); + m_xValueED->set_text(OUString()); + } + + if (nSelPos != -1) + { + OUString sName(m_xSelectionLB->get_selected_text()); + if (!IsFieldEdit()) + m_xNameED->set_text(sName); + + // is there a corresponding SetField + SwWrtShell *pSh = GetWrtShell(); + if(!pSh) + pSh = ::GetActiveWrtShell(); + if(pSh) + { + SwSetExpFieldType* pSetTyp = static_cast<SwSetExpFieldType*>( + pSh->GetFieldType(SwFieldIds::SetExp, sName)); + + if(pSetTyp) + { + if (pSetTyp->GetType() & nsSwGetSetExpType::GSE_STRING) // textual? + bFormat = true; + else // numeric + bNumFormat = true; + } + } + } + else + bFormat = false; + + EnableInsert(bFormat || bNumFormat); + } + break; + + case SwFieldTypesEnum::Input: + m_xValueFT->set_label(SwResId(STR_PROMPT)); + + if (nSelPos != -1) + { + bValue = bNumFormat = true; + + OUString sName = m_xSelectionLB->get_selected_text(); + m_xNameED->set_text( sName ); + + // User- or SetField ? + if (!GetFieldMgr().GetFieldType(SwFieldIds::User, sName)) // SetExp + { + // is there a corresponding SetField + SwSetExpFieldType* pSetTyp = static_cast<SwSetExpFieldType*>( + GetFieldMgr().GetFieldType(SwFieldIds::SetExp, sName)); + + if(pSetTyp) + { + if (pSetTyp->GetType() == nsSwGetSetExpType::GSE_STRING) // textual? + { + m_xNumFormatLB->clear(); + m_xNumFormatLB->append(OUString::number(NUMBERFORMAT_ENTRY_NOT_FOUND), SwResId(FMT_USERVAR_TEXT)); + m_xNumFormatLB->select(0); + } + } + if (GetCurField() && IsFieldEdit() && (!pBox || bInit) ) + m_xValueED->set_text(static_cast<SwSetExpField*>(GetCurField())->GetPromptText()); + } + else // USERFLD + bFormat = bNumFormat = false; + } + break; + + case SwFieldTypesEnum::DDE: + m_xValueFT->set_label(SwResId(STR_DDE_CMD)); + + if (IsFieldEdit() || pBox) // only when interacting via mouse + { + if (nSelPos != -1) + { + SwDDEFieldType* pType = + static_cast<SwDDEFieldType*>( GetFieldMgr().GetFieldType(SwFieldIds::Dde, nSelData) ); + + if(pType) + { + m_xNameED->set_text(pType->GetName()); + + //JP 28.08.95: DDE-Topics/-Items can have blanks in their names! + // That's not considered here yet + OUString sCmd( pType->GetCmd() ); + sal_Int32 nTmpPos = 0; + sCmd = sCmd.replaceFirst( OUStringChar(sfx2::cTokenSeparator), " ", &nTmpPos ); + sCmd = sCmd.replaceFirst( OUStringChar(sfx2::cTokenSeparator), " ", &nTmpPos ); + + m_xValueED->set_text( sCmd ); + m_xFormatLB->select(static_cast<int>(pType->GetType())); + } + } + } + bName = bValue = true; + break; + + case SwFieldTypesEnum::Sequence: + { + bName = bValue = bShowChapterFrame = true; + + SwFieldType* pFieldTyp; + if( GetCurField() && IsFieldEdit() ) + pFieldTyp = GetCurField()->GetTyp(); + else + { + OUString sFieldTypeName(m_xSelectionLB->get_text(nSelPos)); + if( !sFieldTypeName.isEmpty() ) + pFieldTyp = GetFieldMgr().GetFieldType( SwFieldIds::SetExp, + sFieldTypeName ); + else + pFieldTyp = nullptr; + } + + if( GetCurField() && IsFieldEdit() ) + m_xValueED->set_text( static_cast<SwSetExpField*>(GetCurField())-> + GetFormula() ); + + if( IsFieldEdit() || pBox ) // only when interacting via mouse + m_xNameED->set_text( m_xSelectionLB->get_selected_text() ); + + if( pFieldTyp ) + { + sal_uInt8 nLevel = static_cast<SwSetExpFieldType*>(pFieldTyp)->GetOutlineLvl(); + if( 0x7f == nLevel ) + m_xChapterLevelLB->set_active(0); + else + m_xChapterLevelLB->set_active(nLevel + 1); + OUString sDelim = static_cast<SwSetExpFieldType*>(pFieldTyp)->GetDelimiter(); + m_xSeparatorED->set_text( sDelim ); + ChapterHdl(*m_xChapterLevelLB); + } + } + break; + + case SwFieldTypesEnum::SetRefPage: + { + bValue = false; + m_xValueFT->set_label( SwResId( STR_OFFSET )); + + if (IsFieldEdit() || pBox) // only when interacting via mouse + m_xNameED->set_text(OUString()); + + if (nSelData != 0 && nSelData != SIZE_MAX) + { + bValue = true; // SubType OFF - knows no Offset + if (GetCurField() && IsFieldEdit()) + m_xValueED->set_text(OUString::number(static_cast<SwRefPageSetField*>(GetCurField())->GetOffset())); + } + } + break; + + case SwFieldTypesEnum::GetRefPage: + m_xNameED->set_text(OUString()); + m_xValueED->set_text(OUString()); + break; + + default: break; + } + + m_xNumFormatLB->set_visible(bNumFormat); + m_xFormatLB->set_visible(!bNumFormat); + + if (IsFieldEdit()) + bName = false; + + m_xFormat->set_sensitive(bFormat || bNumFormat); + m_xNameFT->set_sensitive(bName); + m_xNameED->set_sensitive(bName); + m_xValueFT->set_sensitive(bValue); + m_xValueED->set_sensitive(bValue); + + m_xInvisibleCB->set_visible(!bShowChapterFrame); + m_xChapterFrame->set_visible(bShowChapterFrame); + m_xInvisibleCB->set_sensitive(bInvisible); + + ModifyHdl(*m_xNameED); // apply/insert/delete status update +} + +IMPL_LINK(SwFieldVarPage, SubTypeInsertHdl, weld::TreeView&, rBox, bool) +{ + if (!bInit) + { + SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + if (nTypeId == SwFieldTypesEnum::Formel) + { + auto nSelPos = m_xSelectionLB->get_selected_index(); + if (nSelPos != -1) + { + m_xValueED->replace_selection(m_xSelectionLB->get_text(nSelPos)); + ModifyHdl(*m_xNameED); + return true; + } + } + } + TreeViewInsertHdl(rBox); + return true; +} + +// renew types in SelectionBox +void SwFieldVarPage::UpdateSubType() +{ + SetSelectionSel(m_xSelectionLB->get_selected_index()); + + OUString sOldSel; + if (GetSelectionSel() != -1) + sOldSel = m_xSelectionLB->get_text(GetSelectionSel()); + + // fill Selection-Listbox + m_xSelectionLB->freeze(); + m_xSelectionLB->clear(); + + const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + std::vector<OUString> aList; + GetFieldMgr().GetSubTypes(nTypeId, aList); + const size_t nCount = aList.size(); + for (size_t i = 0; i < nCount; ++i) + { + if (nTypeId != SwFieldTypesEnum::Input || i) + { + if (!IsFieldEdit()) + { + m_xSelectionLB->append(OUString::number(i), aList[i]); + } + else + { + bool bInsert = false; + + switch (nTypeId) + { + case SwFieldTypesEnum::Input: + if (GetCurField() && aList[i] == GetCurField()->GetPar1()) + bInsert = true; + break; + + case SwFieldTypesEnum::Formel: + bInsert = true; + break; + + case SwFieldTypesEnum::Get: + if (GetCurField() && aList[i] == static_cast<const SwFormulaField*>(GetCurField())->GetFormula()) + bInsert = true; + break; + + case SwFieldTypesEnum::Set: + case SwFieldTypesEnum::User: + if (GetCurField() && aList[i] == GetCurField()->GetTyp()->GetName()) + { + bInsert = true; + if (GetCurField()->GetSubType() & nsSwExtendedSubType::SUB_INVISIBLE) + m_xInvisibleCB->set_active(true); + } + break; + + case SwFieldTypesEnum::SetRefPage: + { + if (GetCurField() != nullptr + && ((static_cast<SwRefPageSetField*>(GetCurField())->IsOn() + && i) || (!static_cast<SwRefPageSetField*>(GetCurField()) + ->IsOn() && !i))) + { + sOldSel = aList[i]; + } + + // allow all entries for selection: + m_xSelectionLB->append(OUString::number(i), aList[i]); + break; + } + default: + if (GetCurField() && aList[i] == GetCurField()->GetPar1()) + bInsert = true; + break; + } + + if (bInsert) + { + m_xSelectionLB->append(OUString::number(i), aList[i]); + if (nTypeId != SwFieldTypesEnum::Formel) + break; + } + } + } + } + + m_xSelectionLB->thaw(); + + const bool bEnable = m_xSelectionLB->n_children() != 0; + weld::TreeView* pLB = nullptr; + + if (bEnable) + { + int nIndex = m_xSelectionLB->find_text(sOldSel); + if (nIndex != -1) + m_xSelectionLB->select(nIndex); + else + { + m_xSelectionLB->select(0); + pLB = m_xSelectionLB.get(); // newly initialise all controls + } + } + + m_xSelection->set_sensitive(bEnable); + + SubTypeHdl(pLB); +} + +void SwFieldVarPage::FillFormatLB(SwFieldTypesEnum nTypeId) +{ + OUString sOldSel; + const sal_Int32 nFormatSel = m_xFormatLB->get_selected_index(); + if (nFormatSel != -1) + sOldSel = m_xFormatLB->get_text(nFormatSel); + + weld::TreeView& rWidget = dynamic_cast<weld::TreeView&>(m_xNumFormatLB->get_widget()); + + OUString sOldNumSel; + sal_uInt32 nOldNumFormat = 0; + sal_Int32 nNumFormatSel = rWidget.get_selected_index(); + if (nNumFormatSel != -1) + { + sOldNumSel = rWidget.get_text(nNumFormatSel); + nOldNumFormat = m_xNumFormatLB->GetFormat(); + } + + // fill Format-Listbox + m_xFormatLB->freeze(); + m_xFormatLB->clear(); + m_xNumFormatLB->clear(); // flags list as dirty and needing refilling with stock entries + bool bSpecialFormat = false; + + if( SwFieldTypesEnum::GetRefPage != nTypeId ) + { + if (GetCurField() != nullptr && IsFieldEdit()) + { + bSpecialFormat = GetCurField()->GetFormat() == NUMBERFORMAT_ENTRY_NOT_FOUND; + + if (!bSpecialFormat) + { + m_xNumFormatLB->SetDefFormat(GetCurField()->GetFormat()); + sOldNumSel.clear(); + } + else if (nTypeId == SwFieldTypesEnum::Get || nTypeId == SwFieldTypesEnum::Formel) + { + m_xNumFormatLB->SetFormatType(SvNumFormatType::NUMBER); + } + } + else + { + if (nOldNumFormat && nOldNumFormat != NUMBERFORMAT_ENTRY_NOT_FOUND) + m_xNumFormatLB->SetDefFormat(nOldNumFormat); + else + m_xNumFormatLB->SetFormatType(SvNumFormatType::NUMBER); + } + } + + switch (nTypeId) + { + case SwFieldTypesEnum::User: + { + if (!IsFieldEdit() || bSpecialFormat) + { + OUString sId(OUString::number(NUMBERFORMAT_ENTRY_NOT_FOUND)); + int nOldIndex = rWidget.get_selected_index(); + rWidget.insert(0, SwResId(FMT_MARK_TEXT), &sId, nullptr, nullptr); + rWidget.insert(1, SwResId(FMT_USERVAR_CMD), &sId, nullptr, nullptr); + if (nOldIndex != -1) + rWidget.select(nOldIndex + 2); + } + } + break; + + case SwFieldTypesEnum::Set: + { + if (!IsFieldEdit() || bSpecialFormat) + { + OUString sId(OUString::number(NUMBERFORMAT_ENTRY_NOT_FOUND)); + int nOldIndex = rWidget.get_selected_index(); + rWidget.insert(0, SwResId(FMT_SETVAR_TEXT), &sId, nullptr, nullptr); + if (nOldIndex != -1) + rWidget.select(nOldIndex + 1); + } + } + break; + + case SwFieldTypesEnum::Formel: + { + OUString sId(OUString::number(NUMBERFORMAT_ENTRY_NOT_FOUND)); + int nOldIndex = rWidget.get_selected_index(); + rWidget.insert(0, SwResId(FMT_GETVAR_NAME), &sId, nullptr, nullptr); + if (nOldIndex != -1) + rWidget.select(nOldIndex + 1); + } + break; + + case SwFieldTypesEnum::Get: + { + OUString sId(OUString::number(NUMBERFORMAT_ENTRY_NOT_FOUND)); + int nOldIndex = rWidget.get_selected_index(); + rWidget.insert(0, SwResId(FMT_GETVAR_NAME), &sId, nullptr, nullptr); + if (nOldIndex != -1) + rWidget.select(nOldIndex + 1); + } + break; + + default: break; + } + + if (IsFieldEdit() && bSpecialFormat) + { + if (nTypeId == SwFieldTypesEnum::User && (GetCurField()->GetSubType() & nsSwExtendedSubType::SUB_CMD)) + rWidget.select(1); + else + rWidget.select(0); + } + else + { + if (!nOldNumFormat && (nNumFormatSel = rWidget.find_text(sOldNumSel)) != -1) + rWidget.select(nNumFormatSel); + else if (nOldNumFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) + rWidget.select_text(sOldSel); + } + + const sal_uInt16 nSize = GetFieldMgr().GetFormatCount(nTypeId, IsFieldDlgHtmlMode()); + + OUString sSelectId; + + for (sal_uInt16 i = 0; i < nSize; i++) + { + const sal_uInt16 nFieldId = GetFieldMgr().GetFormatId( nTypeId, i ); + OUString sId(OUString::number(nFieldId)); + m_xFormatLB->append(sId, GetFieldMgr().GetFormatStr(nTypeId, i)); + if (IsFieldEdit() && GetCurField() && nFieldId == GetCurField()->GetFormat()) + sSelectId = sId; + } + + m_xFormatLB->thaw(); + if (!sSelectId.isEmpty()) + m_xFormatLB->select_id(sSelectId); + + if (nSize && (!IsFieldEdit() || m_xFormatLB->get_selected_index() == -1)) + { + int nIndex = m_xFormatLB->find_text(sOldSel); + if (nIndex == -1) + nIndex = m_xFormatLB->find_text(SwResId(FMT_NUM_PAGEDESC)); + if (nIndex == -1) + nIndex = m_xFormatLB->find_text(SwResId(FMT_NUM_ARABIC)); + if (nIndex == -1) + nIndex = 0; + m_xFormatLB->select(nIndex); + } +} + +// Modify +IMPL_LINK_NOARG(SwFieldVarPage, ModifyHdl, weld::Entry&, void) +{ + OUString sValue(m_xValueED->get_text()); + bool bHasValue = !sValue.isEmpty(); + const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + bool bInsert = false, bApply = false, bDelete = false; + + OUString sName( m_xNameED->get_text() ); + sal_Int32 nLen = sName.getLength(); + + switch( nTypeId ) + { + case SwFieldTypesEnum::DDE: + case SwFieldTypesEnum::User: + case SwFieldTypesEnum::Set: + case SwFieldTypesEnum::Sequence: + SwCalc::IsValidVarName( sName, &sName ); + if ( sName.getLength() != nLen ) + { + nLen = sName.getLength(); + int nStartPos, nEndPos; + m_xNameED->get_selection_bounds(nStartPos, nEndPos); + m_xNameED->set_text( sName ); + m_xNameED->select_region(nStartPos, nEndPos); // restore Cursorpos + } + break; + default: break; + } + + // check buttons + switch (nTypeId) + { + case SwFieldTypesEnum::DDE: + if( nLen ) + { + // is there already a corresponding type + bInsert = bApply = true; + + SwFieldType* pType = GetFieldMgr().GetFieldType(SwFieldIds::Dde, sName); + + SwWrtShell *pSh = GetWrtShell(); + if(!pSh) + pSh = ::GetActiveWrtShell(); + if(pSh && pType) + bDelete = !pSh->IsUsed( *pType ); + } + break; + + case SwFieldTypesEnum::User: + if( nLen ) + { + // is there already a corresponding type + SwFieldType* pType = GetFieldMgr().GetFieldType(SwFieldIds::User, sName); + + SwWrtShell *pSh = GetWrtShell(); + if(!pSh) + pSh = ::GetActiveWrtShell(); + if(pSh && pType) + bDelete = !pSh->IsUsed( *pType ); + + pType = GetFieldMgr().GetFieldType(SwFieldIds::SetExp, sName); + if (!pType) // no name conflict with variables + { + // user fields can also be inserted without content! + // Bug #56845 + bInsert = bApply = true; + } + } + break; + + default: + bInsert = true; + + if (nTypeId == SwFieldTypesEnum::Set || nTypeId == SwFieldTypesEnum::Sequence) + { + SwSetExpFieldType* pFieldType = static_cast<SwSetExpFieldType*>( + GetFieldMgr().GetFieldType(SwFieldIds::SetExp, sName)); + + if (pFieldType) + { + + SwWrtShell *pSh = GetWrtShell(); + if(!pSh) + pSh = ::GetActiveWrtShell(); + if(pSh) + { + const SwFieldTypes* p = pSh->GetDoc()->getIDocumentFieldsAccess().GetFieldTypes(); + sal_uInt16 i; + + for (i = 0; i < INIT_FLDTYPES; i++) + { + SwFieldType* pType = (*p)[ i ].get(); + if (pType == pFieldType) + break; + } + + if (i >= INIT_FLDTYPES && !pSh->IsUsed(*pFieldType)) + bDelete = true; + + if (nTypeId == SwFieldTypesEnum::Sequence && !(pFieldType->GetType() & nsSwGetSetExpType::GSE_SEQ)) + bInsert = false; + + if (nTypeId == SwFieldTypesEnum::Set && (pFieldType->GetType() & nsSwGetSetExpType::GSE_SEQ)) + bInsert = false; + } + } + if (GetFieldMgr().GetFieldType(SwFieldIds::User, sName)) + bInsert = false; + } + + if (!nLen && (nTypeId == SwFieldTypesEnum::Set || nTypeId == SwFieldTypesEnum::Input || + (!IsFieldEdit() && nTypeId == SwFieldTypesEnum::Get ) ) ) + bInsert = false; + + if( (nTypeId == SwFieldTypesEnum::Set || nTypeId == SwFieldTypesEnum::Formel) && + !bHasValue ) + bInsert = false; + break; + } + + m_xNewPB->set_sensitive(bApply); + m_xDelPB->set_sensitive(bDelete); + EnableInsert(bInsert); +} + +IMPL_LINK(SwFieldVarPage, TBClickHdl, weld::Button&, rBox, void) +{ + const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + + if (&rBox == m_xDelPB.get()) + { + if( nTypeId == SwFieldTypesEnum::User ) + GetFieldMgr().RemoveFieldType(SwFieldIds::User, m_xSelectionLB->get_selected_text()); + else + { + SwFieldIds nWhich; + + switch(nTypeId) + { + case SwFieldTypesEnum::Set: + case SwFieldTypesEnum::Sequence: + nWhich = SwFieldIds::SetExp; + break; + default: + nWhich = SwFieldIds::Dde; + break; + } + + GetFieldMgr().RemoveFieldType(nWhich, m_xSelectionLB->get_selected_text()); + } + + UpdateSubType(); + SwWrtShell *pSh = GetWrtShell(); + if(!pSh) + pSh = ::GetActiveWrtShell(); + if(pSh) + { + pSh->SetModified(); + } + } + else if (&rBox == m_xNewPB.get()) + { + OUString sName(m_xNameED->get_text()), sValue(m_xValueED->get_text()); + SwFieldType* pType = nullptr; + SwFieldIds nId = SwFieldIds::Database; + sal_Int32 nNumFormatPos = m_xNumFormatLB->get_selected_index(); + + switch (nTypeId) + { + case SwFieldTypesEnum::User: nId = SwFieldIds::User; break; + case SwFieldTypesEnum::DDE: nId = SwFieldIds::Dde; break; + case SwFieldTypesEnum::Set: nId = SwFieldIds::SetExp;break; + default: break; + } + pType = GetFieldMgr().GetFieldType(nId, sName); + + int nFormat = m_xFormatLB->get_selected_index(); + if (nFormat != -1) + nFormat = m_xFormatLB->get_id(nFormat).toUInt32(); + + if (pType) // change + { + SwWrtShell *pSh = GetWrtShell(); + if(!pSh) + pSh = ::GetActiveWrtShell(); + if(pSh) + { + pSh->StartAllAction(); + + if (nTypeId == SwFieldTypesEnum::User) + { + if (nNumFormatPos != -1) + { + sal_uLong nNumberFormat = nNumFormatPos == 0 ? 0 : m_xNumFormatLB->GetFormat(); + if (nNumberFormat) + { // Switch language to office-language because Kalkulator expects + // String in office format and it should be fed into dialog like + // that + nNumberFormat = SwValueField::GetSystemFormat(pSh->GetNumberFormatter(), nNumberFormat); + } + static_cast<SwUserFieldType*>(pType)->SetContent(m_xValueED->get_text(), nNumberFormat); + static_cast<SwUserFieldType*>(pType)->SetType( + nNumFormatPos == 0 ? nsSwGetSetExpType::GSE_STRING : nsSwGetSetExpType::GSE_EXPR ); + } + } + else + { + if (nFormat != -1) + { + // DDE-Topics/-Items can have blanks in their names! + // That's not being considered here yet. + sal_Int32 nTmpPos = 0; + sValue = sValue.replaceFirst( " ", OUStringChar(sfx2::cTokenSeparator), &nTmpPos ); + sValue = sValue.replaceFirst( " ", OUStringChar(sfx2::cTokenSeparator), &nTmpPos ); + static_cast<SwDDEFieldType*>(pType)->SetCmd(sValue); + static_cast<SwDDEFieldType*>(pType)->SetType(static_cast<SfxLinkUpdateMode>(nFormat)); + } + } + pType->UpdateFields(); + + pSh->EndAllAction(); + } + } + else // new + { + if(nTypeId == SwFieldTypesEnum::User) + { + SwWrtShell *pSh = GetWrtShell(); + if(!pSh) + pSh = ::GetActiveWrtShell(); + if(pSh) + { + SwUserFieldType aType( pSh->GetDoc(), sName ); + + if (nNumFormatPos != -1) + { + aType.SetType(nNumFormatPos == 0 ? nsSwGetSetExpType::GSE_STRING : nsSwGetSetExpType::GSE_EXPR); + aType.SetContent( sValue, nNumFormatPos == 0 ? 0 : m_xNumFormatLB->GetFormat() ); + m_xSelectionLB->append_text(sName); + m_xSelectionLB->select_text(sName); + GetFieldMgr().InsertFieldType( aType ); // Userfld new + } + } + } + else + { + if (nFormat != -1) + { + // DDE-Topics/-Items can have blanks in their names! + // That's not being considered here yet. + sal_Int32 nTmpPos = 0; + sValue = sValue.replaceFirst( " ", OUStringChar(sfx2::cTokenSeparator), &nTmpPos ); + sValue = sValue.replaceFirst( " ", OUStringChar(sfx2::cTokenSeparator), &nTmpPos ); + + SwDDEFieldType aType(sName, sValue, static_cast<SfxLinkUpdateMode>(nFormat)); + m_xSelectionLB->append_text(sName); + m_xSelectionLB->select_text(sName); + GetFieldMgr().InsertFieldType(aType); // DDE-Field new + } + } + } + if (IsFieldEdit()) + GetFieldMgr().GetCurField(); // update FieldManager + + UpdateSubType(); + } +} + +IMPL_LINK_NOARG(SwFieldVarPage, ChapterHdl, weld::ComboBox&, void) +{ + bool bEnable = m_xChapterLevelLB->get_active() != 0; + + m_xSeparatorED->set_sensitive(bEnable); + m_xSeparatorFT->set_sensitive(bEnable); + SeparatorHdl(*m_xSeparatorED); +} + +IMPL_LINK_NOARG(SwFieldVarPage, SeparatorHdl, weld::Entry&, void) +{ + bool bEnable = !m_xSeparatorED->get_text().isEmpty() || + m_xChapterLevelLB->get_active() == 0; + EnableInsert(bEnable); +} + +bool SwFieldVarPage::FillItemSet(SfxItemSet* ) +{ + const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32()); + + OUString aVal(m_xValueED->get_text()); + OUString aName(m_xNameED->get_text()); + + const sal_Int32 nSubPos = m_xSelectionLB->get_selected_index(); + sal_uInt16 nSubType = (nSubPos == -1) ? 0 : m_xSelectionLB->get_id(nSubPos).toUInt32(); + + sal_uInt32 nFormat; + + if (!m_xNumFormatLB->get_visible()) + { + sal_Int32 nFormatPos = m_xFormatLB->get_selected_index(); + + if(nFormatPos == -1) + nFormat = 0; + else + nFormat = m_xFormatLB->get_id(nFormatPos).toUInt32(); + } + else + { + nFormat = m_xNumFormatLB->GetFormat(); + + if (nFormat && nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND && m_xNumFormatLB->IsAutomaticLanguage()) + { + // Switch language to office language because Kalkulator expects + // String in office format and it should be fed into the dialog + // like that + SwWrtShell *pSh = GetWrtShell(); + if(!pSh) + pSh = ::GetActiveWrtShell(); + if(pSh) + { + nFormat = SwValueField::GetSystemFormat(pSh->GetNumberFormatter(), nFormat); + } + } + } + sal_Unicode cSeparator = ' '; + switch (nTypeId) + { + case SwFieldTypesEnum::User: + { + nSubType = (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) ? nsSwGetSetExpType::GSE_STRING : nsSwGetSetExpType::GSE_EXPR; + + if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND && m_xNumFormatLB->get_selected_text() == SwResId(FMT_USERVAR_CMD)) + nSubType |= nsSwExtendedSubType::SUB_CMD; + + if (m_xInvisibleCB->get_active()) + nSubType |= nsSwExtendedSubType::SUB_INVISIBLE; + break; + } + case SwFieldTypesEnum::Formel: + { + nSubType = nsSwGetSetExpType::GSE_FORMULA; + if (m_xNumFormatLB->get_visible() && nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) + nSubType |= nsSwExtendedSubType::SUB_CMD; + break; + } + case SwFieldTypesEnum::Get: + { + nSubType &= 0xff00; + if (m_xNumFormatLB->get_visible() && nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) + nSubType |= nsSwExtendedSubType::SUB_CMD; + break; + } + case SwFieldTypesEnum::Input: + { + SwFieldType* pType = GetFieldMgr().GetFieldType(SwFieldIds::User, aName); + nSubType = static_cast< sal_uInt16 >((nSubType & 0xff00) | (pType ? INP_USR : INP_VAR)); + break; + } + + case SwFieldTypesEnum::Set: + { + if (IsFieldDlgHtmlMode()) + { + nSubType = 0x0100; + nSubType = (nSubType & 0xff00) | nsSwGetSetExpType::GSE_STRING; + } + else + nSubType = (nSubType & 0xff00) | ((nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) ? nsSwGetSetExpType::GSE_STRING : nsSwGetSetExpType::GSE_EXPR); + + if (m_xInvisibleCB->get_active()) + nSubType |= nsSwExtendedSubType::SUB_INVISIBLE; + break; + } + case SwFieldTypesEnum::Sequence: + { + nSubType = static_cast< sal_uInt16 >(m_xChapterLevelLB->get_active()); + if (nSubType == 0) + nSubType = 0x7f; + else + { + nSubType--; + OUString sSeparator(m_xSeparatorED->get_text()[0]); + cSeparator = !sSeparator.isEmpty() ? sSeparator[0] : ' '; + } + break; + } + case SwFieldTypesEnum::GetRefPage: + if( SVX_NUM_CHAR_SPECIAL == nFormat ) + aVal = m_xValueED->get_text(); + break; + default: break; + } + + if (!IsFieldEdit() || + m_xNameED->get_value_changed_from_saved() || + m_xValueED->get_value_changed_from_saved() || + m_xSelectionLB->get_value_changed_from_saved() || + m_xFormatLB->get_value_changed_from_saved() || + nOldFormat != m_xNumFormatLB->GetFormat() || + m_xInvisibleCB->get_state_changed_from_saved() || + m_xChapterLevelLB->get_value_changed_from_saved() || + m_xSeparatorED->get_value_changed_from_saved()) + { + InsertField( nTypeId, nSubType, aName, aVal, nFormat, + cSeparator, m_xNumFormatLB->IsAutomaticLanguage() ); + } + + UpdateSubType(); + + return false; +} + +std::unique_ptr<SfxTabPage> SwFieldVarPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet *const pAttrSet) +{ + return std::make_unique<SwFieldVarPage>( pPage, pController, pAttrSet ); +} + +sal_uInt16 SwFieldVarPage::GetGroup() +{ + return GRP_VAR; +} + +void SwFieldVarPage::FillUserData() +{ + OUString sData = USER_DATA_VERSION ";"; + sal_Int32 nTypeSel = m_xTypeLB->get_selected_index(); + if( -1 == nTypeSel ) + nTypeSel = USHRT_MAX; + else + nTypeSel = m_xTypeLB->get_id(nTypeSel).toUInt32(); + sData += OUString::number( nTypeSel ); + SetUserData(sData); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/fldvar.hxx b/sw/source/ui/fldui/fldvar.hxx new file mode 100644 index 000000000..b214e5adf --- /dev/null +++ b/sw/source/ui/fldui/fldvar.hxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_SW_SOURCE_UI_FLDUI_FLDVAR_HXX +#define INCLUDED_SW_SOURCE_UI_FLDUI_FLDVAR_HXX + +#include <sfx2/tabdlg.hxx> + +#include "fldpage.hxx" +#include <condedit.hxx> +#include <numfmtlb.hxx> + +class SwFieldVarPage; + +class SwFieldVarPage : public SwFieldPage +{ + std::unique_ptr<weld::TreeView> m_xTypeLB; + std::unique_ptr<weld::Widget> m_xSelection; + std::unique_ptr<weld::TreeView> m_xSelectionLB; + std::unique_ptr<weld::Label> m_xNameFT; + std::unique_ptr<weld::Entry> m_xNameED; + std::unique_ptr<weld::Label> m_xValueFT; + std::unique_ptr<ConditionEdit> m_xValueED; + std::unique_ptr<weld::Widget> m_xFormat; + std::unique_ptr<SwNumFormatTreeView> m_xNumFormatLB; + std::unique_ptr<weld::TreeView> m_xFormatLB; + std::unique_ptr<weld::Widget> m_xChapterFrame; + std::unique_ptr<weld::ComboBox> m_xChapterLevelLB; + std::unique_ptr<weld::CheckButton> m_xInvisibleCB; + std::unique_ptr<weld::Label> m_xSeparatorFT; + std::unique_ptr<weld::Entry> m_xSeparatorED; + std::unique_ptr<weld::Button> m_xNewPB; + std::unique_ptr<weld::Button> m_xDelPB; + + OUString sOldValueFT; + OUString sOldNameFT; + + sal_uInt32 nOldFormat; + bool bInit; + + DECL_LINK( TypeHdl, weld::TreeView&, void ); + DECL_LINK( SubTypeListBoxHdl, weld::TreeView&, void ); + DECL_LINK( ModifyHdl, weld::Entry&, void ); + DECL_LINK( TBClickHdl, weld::Button&, void ); + DECL_LINK( ChapterHdl, weld::ComboBox&, void ); + DECL_LINK( SeparatorHdl, weld::Entry&, void ); + DECL_LINK( SubTypeInsertHdl, weld::TreeView&, bool ); + void SubTypeHdl(const weld::TreeView*); + + void UpdateSubType(); + void FillFormatLB(SwFieldTypesEnum nTypeId); + +protected: + virtual sal_uInt16 GetGroup() override; + +public: + SwFieldVarPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* pSet); + static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + virtual ~SwFieldVarPage() override; + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + + virtual void FillUserData() override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/inpdlg.cxx b/sw/source/ui/fldui/inpdlg.cxx new file mode 100644 index 000000000..7eaa19e9f --- /dev/null +++ b/sw/source/ui/fldui/inpdlg.cxx @@ -0,0 +1,176 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <tools/lineend.hxx> +#include <unotools/charclass.hxx> +#include <wrtsh.hxx> +#include <fldbas.hxx> +#include <expfld.hxx> +#include <usrfld.hxx> +#include <inpdlg.hxx> + +// edit field-insert +SwFieldInputDlg::SwFieldInputDlg(weld::Widget *pParent, SwWrtShell &rS, + SwField* pField, bool bPrevButton, bool bNextButton) + : GenericDialogController(pParent, "modules/swriter/ui/inputfielddialog.ui", "InputFieldDialog") + , rSh( rS ) + , pInpField(nullptr) + , pSetField(nullptr) + , pUsrType(nullptr) + , m_pPressedButton(nullptr) + , m_xLabelED(m_xBuilder->weld_entry("name")) + , m_xEditED(m_xBuilder->weld_text_view("text")) + , m_xPrevBT(m_xBuilder->weld_button("prev")) + , m_xNextBT(m_xBuilder->weld_button("next")) + , m_xOKBT(m_xBuilder->weld_button("ok")) +{ + m_xEditED->set_size_request(-1, m_xEditED->get_height_rows(8)); + + if( bPrevButton || bNextButton ) + { + m_xPrevBT->show(); + m_xPrevBT->connect_clicked(LINK(this, SwFieldInputDlg, PrevHdl)); + m_xPrevBT->set_sensitive(bPrevButton); + + m_xNextBT->show(); + m_xNextBT->connect_clicked(LINK(this, SwFieldInputDlg, NextHdl)); + m_xNextBT->set_sensitive(bNextButton); + } + + // evaluation here + OUString aStr; + if( SwFieldIds::Input == pField->GetTyp()->Which() ) + { // it is an input field + + pInpField = static_cast<SwInputField*>(pField); + m_xLabelED->set_text(pInpField->GetPar2()); + sal_uInt16 nSubType = pInpField->GetSubType(); + + switch(nSubType & 0xff) + { + case INP_TXT: + aStr = pInpField->GetPar1(); + break; + + case INP_USR: + // user field + pUsrType = static_cast<SwUserFieldType*>(rSh.GetFieldType( + SwFieldIds::User, pInpField->GetPar1() )); + if( nullptr != pUsrType ) + aStr = pUsrType->GetContent(); + break; + } + } + else + { + // it is a SetExpression + pSetField = static_cast<SwSetExpField*>(pField); + OUString sFormula(pSetField->GetFormula()); + //values are formatted - formulas are not + CharClass aCC( LanguageTag( pSetField->GetLanguage() )); + if( aCC.isNumeric( sFormula )) + { + aStr = pSetField->ExpandField(true, rS.GetLayout()); + } + else + aStr = sFormula; + m_xLabelED->set_text(pSetField->GetPromptText()); + } + + // JP 31.3.00: Inputfields in readonly regions must be allowed to + // input any content. - 74639 + bool bEnable = !rSh.IsCursorReadonly(); + + m_xOKBT->set_sensitive( bEnable ); + m_xEditED->set_editable( bEnable ); + + if( !aStr.isEmpty() ) + m_xEditED->set_text(convertLineEnd(aStr, GetSystemLineEnd())); + m_xEditED->grab_focus(); + + // preselect all text to allow quickly changing the content + if (bEnable) + m_xEditED->select_region(0, -1); +} + +SwFieldInputDlg::~SwFieldInputDlg() +{ +} + +// Close +void SwFieldInputDlg::Apply() +{ + OUString aTmp = m_xEditED->get_text().replaceAll("\r", ""); + rSh.StartAllAction(); + bool bModified = false; + if(pInpField) + { + if(pUsrType) + { + if( aTmp != pUsrType->GetContent() ) + { + pUsrType->SetContent(aTmp); + pUsrType->UpdateFields(); + bModified = true; + } + } + else if( aTmp != pInpField->GetPar1() ) + { + pInpField->SetPar1(aTmp); + rSh.SwEditShell::UpdateOneField(*pInpField); + bModified = true; + } + } + else if( aTmp != pSetField->GetPar2()) + { + pSetField->SetPar2(aTmp); + rSh.SwEditShell::UpdateOneField(*pSetField); + bModified = true; + } + + if( bModified ) + rSh.SetUndoNoResetModified(); + + rSh.EndAllAction(); +} + +bool SwFieldInputDlg::PrevButtonPressed() const +{ + return m_pPressedButton == m_xPrevBT.get(); +} + +bool SwFieldInputDlg::NextButtonPressed() const +{ + return m_pPressedButton == m_xNextBT.get(); +} + +IMPL_LINK_NOARG(SwFieldInputDlg, PrevHdl, weld::Button&, void) +{ + m_pPressedButton = m_xPrevBT.get(); + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(SwFieldInputDlg, NextHdl, weld::Button&, void) +{ + m_pPressedButton = m_xNextBT.get(); + m_xDialog->response(RET_OK); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/fldui/javaedit.cxx b/sw/source/ui/fldui/javaedit.cxx new file mode 100644 index 000000000..b13c9828d --- /dev/null +++ b/sw/source/ui/fldui/javaedit.cxx @@ -0,0 +1,253 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <svl/urihelper.hxx> +#include <view.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/filedlghelper.hxx> +#include <docsh.hxx> +#include <wrtsh.hxx> +#include <fldbas.hxx> +#include <fldmgr.hxx> +#include <docufld.hxx> +#include <javaedit.hxx> + +#include <strings.hrc> + +using namespace ::com::sun::star; + +SwJavaEditDialog::SwJavaEditDialog(weld::Window* pParent, SwWrtShell* pWrtSh) + : GenericDialogController(pParent, "modules/swriter/ui/insertscript.ui", "InsertScriptDialog") + , m_bNew(true) + , m_bIsUrl(false) + , m_pSh(pWrtSh) + , m_xTypeED(m_xBuilder->weld_entry("scripttype")) + , m_xUrlRB(m_xBuilder->weld_radio_button("url")) + , m_xEditRB(m_xBuilder->weld_radio_button("text")) + , m_xUrlPB(m_xBuilder->weld_button("browse")) + , m_xUrlED(m_xBuilder->weld_entry("urlentry")) + , m_xEditED(m_xBuilder->weld_text_view("textentry")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) + , m_xPrevBtn(m_xBuilder->weld_button("previous")) + , m_xNextBtn(m_xBuilder->weld_button("next")) +{ + // install handler + m_xPrevBtn->connect_clicked( LINK( this, SwJavaEditDialog, PrevHdl ) ); + m_xNextBtn->connect_clicked( LINK( this, SwJavaEditDialog, NextHdl ) ); + m_xOKBtn->connect_clicked( LINK( this, SwJavaEditDialog, OKHdl ) ); + + Link<weld::Toggleable&,void> aLk = LINK(this, SwJavaEditDialog, RadioButtonHdl); + m_xUrlRB->connect_toggled(aLk); + m_xEditRB->connect_toggled(aLk); + m_xUrlPB->connect_clicked(LINK(this, SwJavaEditDialog, InsertFileHdl)); + + m_pMgr.reset(new SwFieldMgr(m_pSh)); + m_pField = static_cast<SwScriptField*>(m_pMgr->GetCurField()); + + m_bNew = !(m_pField && m_pField->GetTyp()->Which() == SwFieldIds::Script); + + CheckTravel(); + + if (!m_bNew) + m_xDialog->set_title(SwResId(STR_JAVA_EDIT)); + + UpdateFromRadioButtons(); +} + +SwJavaEditDialog::~SwJavaEditDialog() +{ + m_pSh->EnterStdMode(); + m_pMgr.reset(); + m_pFileDlg.reset(); +} + +IMPL_LINK_NOARG(SwJavaEditDialog, PrevHdl, weld::Button&, void) +{ + m_pSh->EnterStdMode(); + + SetField(); + m_pMgr->GoPrev(); + m_pField = static_cast<SwScriptField*>(m_pMgr->GetCurField()); + CheckTravel(); + UpdateFromRadioButtons(); +} + +IMPL_LINK_NOARG(SwJavaEditDialog, NextHdl, weld::Button&, void) +{ + m_pSh->EnterStdMode(); + + SetField(); + m_pMgr->GoNext(); + m_pField = static_cast<SwScriptField*>(m_pMgr->GetCurField()); + CheckTravel(); + UpdateFromRadioButtons(); +} + +IMPL_LINK_NOARG(SwJavaEditDialog, OKHdl, weld::Button&, void) +{ + SetField(); + m_xDialog->response(RET_OK); +} + +void SwJavaEditDialog::CheckTravel() +{ + bool bTravel = false; + bool bNext(false), bPrev(false); + + if (!m_bNew) + { + // Traveling only when more than one field + m_pSh->StartAction(); + m_pSh->CreateCursor(); + + bNext = m_pMgr->GoNext(); + if( bNext ) + m_pMgr->GoPrev(); + + bPrev = m_pMgr->GoPrev(); + if( bPrev ) + m_pMgr->GoNext(); + bTravel |= bNext || bPrev; + + m_pSh->DestroyCursor(); + m_pSh->EndAction(); + + if (m_pField->IsCodeURL()) + { + OUString sURL(m_pField->GetPar2()); + if(!sURL.isEmpty()) + { + INetURLObject aINetURL(sURL); + if(INetProtocol::File == aINetURL.GetProtocol()) + sURL = aINetURL.PathToFileName(); + } + m_xUrlED->set_text(sURL); + m_xEditED->set_text(OUString()); + m_xUrlRB->set_active(true); + } + else + { + m_xEditED->set_text(m_pField->GetPar2()); + m_xUrlED->set_text(OUString()); + m_xEditRB->set_active(true); + } + m_xTypeED->set_text(m_pField->GetPar1()); + } + + if ( !bTravel ) + { + m_xPrevBtn->hide(); + m_xNextBtn->hide(); + } + else + { + m_xPrevBtn->set_sensitive(bPrev); + m_xNextBtn->set_sensitive(bNext); + } +} + +void SwJavaEditDialog::SetField() +{ + if( !m_xOKBtn->get_sensitive() ) + return ; + + m_aType = m_xTypeED->get_text(); + m_bIsUrl = m_xUrlRB->get_active(); + + if (m_bIsUrl) + { + m_aText = m_xUrlED->get_text(); + if (!m_aText.isEmpty()) + { + SfxMedium* pMedium = m_pSh->GetView().GetDocShell()->GetMedium(); + INetURLObject aAbs; + if( pMedium ) + aAbs = pMedium->GetURLObject(); + + m_aText = URIHelper::SmartRel2Abs( + aAbs, m_aText, URIHelper::GetMaybeFileHdl()); + } + } + else + m_aText = m_xEditED->get_text(); + + if (m_aType.isEmpty()) + m_aType = "JavaScript"; +} + +bool SwJavaEditDialog::IsUpdate() const +{ + return m_pField && ( sal_uInt32(m_bIsUrl ? 1 : 0) != m_pField->GetFormat() || m_pField->GetPar2() != m_aType || m_pField->GetPar1() != m_aText ); +} + +IMPL_LINK(SwJavaEditDialog, RadioButtonHdl, weld::Toggleable&, rButton, void) +{ + if (!rButton.get_active()) + return; + UpdateFromRadioButtons(); +} + +void SwJavaEditDialog::UpdateFromRadioButtons() +{ + bool bEnable = m_xUrlRB->get_active(); + m_xUrlPB->set_sensitive(bEnable); + m_xUrlED->set_sensitive(bEnable); + m_xEditED->set_sensitive(!bEnable); + + if (!m_bNew) + { + bEnable = !m_pSh->IsReadOnlyAvailable() || !m_pSh->HasReadonlySel(); + m_xOKBtn->set_sensitive(bEnable); + m_xUrlED->set_editable(bEnable); + m_xEditED->set_editable(bEnable); + m_xTypeED->set_editable(bEnable); + if( m_xUrlPB->get_sensitive() && !bEnable ) + m_xUrlPB->set_sensitive( false ); + } +} + +IMPL_LINK_NOARG( SwJavaEditDialog, InsertFileHdl, weld::Button&, void ) +{ + if (!m_pFileDlg) + { + m_pFileDlg.reset(new ::sfx2::FileDialogHelper( + ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, + FileDialogFlags::Insert, "swriter", SfxFilterFlags::NONE, SfxFilterFlags::NONE, m_xDialog.get())); + } + m_pFileDlg->SetContext(sfx2::FileDialogHelper::WriterInsertScript); + m_pFileDlg->StartExecuteModal( LINK( this, SwJavaEditDialog, DlgClosedHdl ) ); +} + +IMPL_LINK_NOARG(SwJavaEditDialog, DlgClosedHdl, sfx2::FileDialogHelper *, void) +{ + if (m_pFileDlg->GetError() == ERRCODE_NONE) + { + OUString sFileName = m_pFileDlg->GetPath(); + if ( !sFileName.isEmpty() ) + { + INetURLObject aINetURL( sFileName ); + if ( INetProtocol::File == aINetURL.GetProtocol() ) + sFileName = aINetURL.PathToFileName(); + } + m_xUrlED->set_text(sFileName); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |