1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sfx2/frame.hxx>
21 #include <svl/numformat.hxx>
22 #include <svl/zforlist.hxx>
23 #include <svl/zformat.hxx>
24 #include <o3tl/string_view.hxx>
26 #include <swtypes.hxx>
27 #include <flddinf.hrc>
28 #include <strings.hrc>
30 #include <docufld.hxx>
34 #include "flddinf.hxx"
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/beans/XPropertySetInfo.hpp>
37 #include <com/sun/star/util/Time.hpp>
38 #include <com/sun/star/util/DateTime.hpp>
39 #include <com/sun/star/util/Date.hpp>
41 #define USER_DATA_VERSION_1 "1"
42 #define USER_DATA_VERSION USER_DATA_VERSION_1
44 using namespace nsSwDocInfoSubType
;
45 using namespace com::sun::star
;
47 void FillFieldSelect(weld::TreeView
& rListBox
)
49 for (auto const& aID
: FLD_SELECT
)
50 rListBox
.append_text(SwResId(aID
));
53 SwFieldDokInfPage::SwFieldDokInfPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
*const pCoreSet
)
54 : SwFieldPage(pPage
, pController
, "modules/swriter/ui/flddocinfopage.ui", "FieldDocInfoPage", pCoreSet
)
57 , m_xTypeList(m_xBuilder
->weld_tree_view("type-list"))
58 , m_xTypeTree(m_xBuilder
->weld_tree_view("type-tree"))
59 // tdf#104278 have two tree views, one with expander and one without, the one with is only used
60 // when there are custom properties which use the expander, so the common case of no custom
61 // properties doesn't have an 'unexplained' expander margin
62 , m_pTypeView(m_xTypeTree
.get())
63 , m_xSelection(m_xBuilder
->weld_widget("selectframe"))
64 , m_xSelectionLB(m_xBuilder
->weld_tree_view("select"))
65 , m_xFormat(m_xBuilder
->weld_widget("formatframe"))
66 , m_xFormatLB(new SwNumFormatTreeView(m_xBuilder
->weld_tree_view("format")))
67 , m_xFixedCB(m_xBuilder
->weld_check_button("fixed"))
69 m_xTypeList
->make_sorted();
70 m_xTypeTree
->make_sorted();
71 FillFieldSelect(*m_xSelectionLB
);
73 auto nWidth
= m_pTypeView
->get_approximate_digit_width() * FIELD_COLUMN_WIDTH
;
74 auto nHeight
= m_pTypeView
->get_height_rows(10);
75 m_xTypeTree
->set_size_request(nWidth
, nHeight
);
76 m_xTypeList
->set_size_request(nWidth
, nHeight
);
77 m_xFormatLB
->get_widget().set_size_request(nWidth
* 2, nHeight
);
78 m_xSelectionLB
->set_size_request(nWidth
, nHeight
);
80 //enable 'active' language selection
81 m_xFormatLB
->SetShowLanguageControl(true);
83 const SfxUnoAnyItem
* pItem
= pCoreSet
84 ? pCoreSet
->GetItem(FN_FIELD_DIALOG_DOC_PROPS
, false)
87 pItem
->GetValue() >>= m_xCustomPropertySet
;
90 m_pTypeView
->set_buildable_name("type-docinf");
91 m_xSelectionLB
->set_buildable_name(m_xSelectionLB
->get_buildable_name() + "-docinf");
92 m_xFormatLB
->set_buildable_name(m_xFormatLB
->get_buildable_name() + "-docinf");
95 SwFieldDokInfPage::~SwFieldDokInfPage()
99 void SwFieldDokInfPage::Reset(const SfxItemSet
* )
101 Init(); // general initialisation
103 uno::Sequence
<beans::Property
> aCustomProperties
;
104 if (m_xCustomPropertySet
.is())
106 uno::Reference
<beans::XPropertySetInfo
> xSetInfo
= m_xCustomPropertySet
->getPropertySetInfo();
107 aCustomProperties
= xSetInfo
->getProperties();
110 if (aCustomProperties
.hasElements())
113 m_xTypeList
->set_buildable_name("type-list");
115 m_pTypeView
= m_xTypeTree
.get();
120 m_xTypeTree
->set_buildable_name("type-tree");
122 m_pTypeView
= m_xTypeList
.get();
125 m_pTypeView
->set_buildable_name("type-docinf");
127 // initialise TypeListBox
128 m_pTypeView
->freeze();
129 m_pTypeView
->clear();
132 // display SubTypes in TypeLB
133 sal_uInt16 nSubType
= USHRT_MAX
;
136 const SwField
* pCurField
= GetCurField();
137 nSubType
= pCurField
->GetSubType() & 0xff;
138 if( nSubType
== DI_CUSTOM
)
140 if (auto const pField
= dynamic_cast<SwDocInfoField
const*>(pCurField
))
142 m_sOldCustomFieldName
= pField
->GetName();
145 m_xFormatLB
->SetAutomaticLanguage(pCurField
->IsAutomaticLanguage());
146 SwWrtShell
*pSh
= GetWrtShell();
149 const SvNumberformat
* pFormat
= pSh
->GetNumberFormatter()->GetEntry(pCurField
->GetFormat());
151 m_xFormatLB
->SetLanguage(pFormat
->GetLanguage());
155 sal_Int32 nSelEntryData
= -1;
156 const OUString sUserData
= GetUserData();
158 if (o3tl::equalsIgnoreAsciiCase(o3tl::getToken(sUserData
, 0, ';', nIdx
), u
"" USER_DATA_VERSION_1
))
160 nSelEntryData
= o3tl::toInt32(o3tl::getToken(sUserData
, 0, ';', nIdx
));
163 std::vector
<OUString
> aLst
;
164 GetFieldMgr().GetSubTypes(SwFieldTypesEnum::DocumentInfo
, aLst
);
165 std::unique_ptr
<weld::TreeIter
> xEntry(m_pTypeView
->make_iterator());
166 std::unique_ptr
<weld::TreeIter
> xExpandEntry
;
167 for(size_t i
= 0; i
< aLst
.size(); ++i
)
169 if (!IsFieldEdit() || nSubType
== i
)
171 const OUString
sId(OUString::number(i
));
174 if(m_xCustomPropertySet
.is() )
176 if (aCustomProperties
.hasElements())
178 std::unique_ptr
<weld::TreeIter
> xInfo(m_pTypeView
->make_iterator());
180 OUString
sText(SwResId(STR_CUSTOM_FIELD
));
181 OUString
sEntryId(OUString::number(USHRT_MAX
));
182 m_pTypeView
->insert(nullptr, -1, &sText
, &sEntryId
, nullptr,
183 nullptr, false, xInfo
.get());
184 for (const auto& rProperty
: aCustomProperties
)
186 const OUString sEntry
= rProperty
.Name
;
188 m_pTypeView
->insert(xInfo
.get(), -1, &sEntry
, &sId
,
189 nullptr, nullptr, false, xEntry
.get());
190 if (m_sOldCustomFieldName
== sEntry
)
192 m_xSelEntry
= m_pTypeView
->make_iterator(xEntry
.get());
193 xExpandEntry
= m_pTypeView
->make_iterator(xInfo
.get());
201 if (!(IsFieldDlgHtmlMode() && (i
== DI_EDIT
|| i
== DI_SUBJECT
|| i
== DI_PRINT
)))
203 m_pTypeView
->insert(nullptr, -1, &aLst
[i
], &sId
,
204 nullptr, nullptr, false, xEntry
.get());
207 if (static_cast<size_t>(nSelEntryData
) == i
)
208 m_xSelEntry
= std::move(xEntry
);
215 m_pTypeView
->expand_row(*xExpandEntry
);
220 m_pTypeView
->select(*m_xSelEntry
);
221 nSubType
= m_pTypeView
->get_id(*m_xSelEntry
).toUInt32();
225 m_xSelEntry
= m_pTypeView
->make_iterator();
226 if (m_pTypeView
->get_iter_first(*m_xSelEntry
))
227 nSubType
= m_pTypeView
->get_id(*m_xSelEntry
).toUInt32();
232 FillSelectionLB(nSubType
);
234 TypeHdl(*m_pTypeView
);
236 m_pTypeView
->connect_changed(LINK(this, SwFieldDokInfPage
, TypeHdl
));
237 m_pTypeView
->connect_row_activated(LINK(this, SwFieldDokInfPage
, TreeViewInsertHdl
));
238 m_xSelectionLB
->connect_changed(LINK(this, SwFieldDokInfPage
, SubTypeHdl
));
239 m_xSelectionLB
->connect_row_activated(LINK(this, SwFieldDokInfPage
, TreeViewInsertHdl
));
240 m_xFormatLB
->connect_row_activated(LINK(this, SwFieldDokInfPage
, TreeViewInsertHdl
));
244 m_nOldSel
= m_xSelectionLB
->get_selected_index();
245 m_nOldFormat
= GetCurField()->GetFormat();
246 m_xFixedCB
->save_state();
250 IMPL_LINK_NOARG(SwFieldDokInfPage
, TypeHdl
, weld::TreeView
&, void)
252 // current ListBoxPos
253 if (!m_pTypeView
->get_selected(m_xSelEntry
.get()) &&
254 m_pTypeView
->get_iter_first(*m_xSelEntry
))
256 m_pTypeView
->select(*m_xSelEntry
);
258 FillSelectionLB(m_pTypeView
->get_id(*m_xSelEntry
).toUInt32());
259 SubTypeHdl(*m_xSelectionLB
);
262 IMPL_LINK_NOARG(SwFieldDokInfPage
, SubTypeHdl
, weld::TreeView
&, void)
264 sal_uInt16 nSubType
= m_pTypeView
->get_id(*m_xSelEntry
).toUInt32();
265 sal_Int32 nPos
= m_xSelectionLB
->get_selected_index();
266 sal_uInt16 nExtSubType
;
267 SvNumFormatType nNewType
= SvNumFormatType::ALL
;
269 if (nSubType
!= DI_EDIT
)
273 if (!m_xSelectionLB
->n_children())
275 m_xFormatLB
->clear();
276 m_xFormat
->set_sensitive(false);
277 if( nSubType
== DI_CUSTOM
)
279 //find out which type the custom field has - for a start set to DATE format
280 const OUString sName
= m_pTypeView
->get_text(*m_xSelEntry
);
283 uno::Any aVal
= m_xCustomPropertySet
->getPropertyValue( sName
);
284 const uno::Type
& rValueType
= aVal
.getValueType();
285 if( rValueType
== ::cppu::UnoType
<util::DateTime
>::get())
287 nNewType
= SvNumFormatType::DATETIME
;
289 else if( rValueType
== ::cppu::UnoType
<util::Date
>::get())
291 nNewType
= SvNumFormatType::DATE
;
293 else if( rValueType
== ::cppu::UnoType
<util::Time
>::get())
295 nNewType
= SvNumFormatType::TIME
;
298 catch( const uno::Exception
& )
308 nExtSubType
= m_xSelectionLB
->get_id(nPos
).toUInt32();
311 nExtSubType
= DI_SUB_TIME
;
313 SvNumFormatType nOldType
= SvNumFormatType::ALL
;
314 bool bEnable
= false;
315 bool bOneArea
= false;
317 if (m_xFormatLB
->get_active())
318 nOldType
= m_xFormatLB
->GetFormatType();
326 nNewType
= SvNumFormatType::DATE
;
331 nNewType
= SvNumFormatType::TIME
;
335 if (nNewType
== SvNumFormatType::ALL
)
337 m_xFormatLB
->clear();
341 if (nOldType
!= nNewType
)
343 m_xFormatLB
->SetFormatType(nNewType
);
344 m_xFormatLB
->SetOneArea(bOneArea
);
349 sal_uInt32 nFormat
= 0;
351 sal_uInt16 nOldSubType
= 0;
355 if (auto const pField
= dynamic_cast<SwDocInfoField
const*>(GetCurField()))
357 nFormat
= pField
->GetFormat();
358 nOldSubType
= pField
->GetSubType() & 0xff00;
360 nPos
= m_xSelectionLB
->get_selected_index();
363 nSubType
= m_xSelectionLB
->get_id(nPos
).toUInt32();
365 nOldSubType
&= ~DI_SUB_FIXED
;
366 if (nOldSubType
== nSubType
)
368 if (!nFormat
&& (nNewType
== SvNumFormatType::DATE
|| nNewType
== SvNumFormatType::TIME
))
370 SwWrtShell
*pSh
= GetWrtShell();
373 SvNumberFormatter
* pFormatter
= pSh
->GetNumberFormatter();
374 LanguageType eLang
= m_xFormatLB
->GetCurLanguage();
375 if (nNewType
== SvNumFormatType::DATE
)
376 nFormat
= pFormatter
->GetFormatIndex( NF_DATE_SYSTEM_SHORT
, eLang
);
377 else if (nNewType
== SvNumFormatType::TIME
)
378 nFormat
= pFormatter
->GetFormatIndex( NF_TIME_HHMM
, eLang
);
381 m_xFormatLB
->SetDefFormat(nFormat
);
384 else if( (nSubType
== DI_CUSTOM
) && (nNewType
!= SvNumFormatType::ALL
) )
386 m_xFormatLB
->SetDefFormat(nFormat
);
390 // Always allow Fixed Content to be turned off if it is currently on
391 m_xFormat
->set_sensitive(bEnable
|| m_xFixedCB
->get_active());
394 m_xFormatLB
->clear();
395 else if (m_xFormatLB
->get_selected_index() == -1)
396 m_xFormatLB
->select(0);
399 sal_Int32
SwFieldDokInfPage::FillSelectionLB(sal_uInt16 nSubType
)
401 // fill Format-Listbox
402 SwFieldTypesEnum nTypeId
= SwFieldTypesEnum::DocumentInfo
;
404 EnableInsert(nSubType
!= USHRT_MAX
);
406 if (nSubType
== USHRT_MAX
) // Info-Text
407 nSubType
= DI_SUBTYPE_BEGIN
;
409 m_xSelectionLB
->clear();
411 sal_uInt16 nSize
= 0;
412 sal_Int32 nSelPos
= -1;
413 sal_uInt16 nExtSubType
= 0;
417 if (auto const pField
= dynamic_cast<SwDocInfoField
const*>(GetCurField()))
419 nExtSubType
= pField
->GetSubType() & 0xff00;
421 m_xFixedCB
->set_active((nExtSubType
& DI_SUB_FIXED
) != 0);
422 nExtSubType
= ((nExtSubType
& ~DI_SUB_FIXED
) >> 8) - 1;
425 if (nSubType
< DI_CREATE
|| nSubType
== DI_DOCNO
|| nSubType
== DI_EDIT
|| nSubType
== DI_CUSTOM
)
427 // Format Box is empty for Title and Time
431 nSize
= GetFieldMgr().GetFormatCount(nTypeId
, IsFieldDlgHtmlMode());
432 for (sal_uInt16 i
= 0; i
< nSize
; ++i
)
434 OUString
sId(OUString::number(GetFieldMgr().GetFormatId(nTypeId
, i
)));
435 m_xSelectionLB
->append(sId
, GetFieldMgr().GetFormatStr(nTypeId
, i
));
436 if (IsFieldEdit() && i
== nExtSubType
)
441 bool bEnable
= nSize
!= 0;
445 if (m_xSelectionLB
->get_selected_index() == -1)
446 m_xSelectionLB
->select(nSelPos
== USHRT_MAX
? 0 : nSelPos
);
450 m_xSelection
->set_sensitive(bEnable
);
455 bool SwFieldDokInfPage::FillItemSet(SfxItemSet
* )
460 sal_uInt16 nSubType
= m_pTypeView
->get_id(*m_xSelEntry
).toUInt32();
461 if (nSubType
== USHRT_MAX
)
464 sal_uInt32 nFormat
= 0;
466 sal_Int32 nPos
= m_xSelectionLB
->get_selected_index();
469 if (DI_CUSTOM
== nSubType
)
470 aName
= m_pTypeView
->get_text(*m_xSelEntry
);
473 nSubType
|= m_xSelectionLB
->get_id(nPos
).toUInt32();
475 if (m_xFixedCB
->get_active())
476 nSubType
|= DI_SUB_FIXED
;
478 nPos
= m_xFormatLB
->get_selected_index();
480 nFormat
= m_xFormatLB
->GetFormat();
482 if (!IsFieldEdit() || m_nOldSel
!= m_xSelectionLB
->get_selected_index() ||
483 m_nOldFormat
!= nFormat
|| m_xFixedCB
->get_state_changed_from_saved()
484 || (DI_CUSTOM
== nSubType
&& aName
!= m_sOldCustomFieldName
))
486 InsertField(SwFieldTypesEnum::DocumentInfo
, nSubType
, aName
, OUString(), nFormat
,
487 ' ', m_xFormatLB
->IsAutomaticLanguage());
493 std::unique_ptr
<SfxTabPage
> SwFieldDokInfPage::Create( weld::Container
* pPage
, weld::DialogController
* pController
,
494 const SfxItemSet
*const pAttrSet
)
496 return std::make_unique
<SwFieldDokInfPage
>(pPage
, pController
, pAttrSet
);
499 sal_uInt16
SwFieldDokInfPage::GetGroup()
504 void SwFieldDokInfPage::FillUserData()
506 int nEntry
= m_pTypeView
->get_selected_index();
507 sal_uInt16 nTypeSel
= nEntry
!= -1 ? m_pTypeView
->get_id(nEntry
).toUInt32() : USHRT_MAX
;
508 SetUserData(USER_DATA_VERSION
";" + OUString::number( nTypeSel
));
511 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */