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 <config_features.h>
22 #include <osl/diagnose.h>
23 #include <unotools/charclass.hxx>
27 #include <IDocumentFieldsAccess.hxx>
28 #include <IDocumentState.hxx>
38 #include <fieldhint.hxx>
39 #include <DocumentSettingManager.hxx>
40 #include <IDocumentContentOperations.hxx>
42 /// count field types with a ResId, if SwFieldIds::Unknown count all
43 size_t SwEditShell::GetFieldTypeCount(SwFieldIds nResId
) const
45 const SwFieldTypes
* pFieldTypes
= GetDoc()->getIDocumentFieldsAccess().GetFieldTypes();
47 if(nResId
== SwFieldIds::Unknown
)
49 return static_cast<sal_uInt16
>(pFieldTypes
->size());
52 // all types with the same ResId
54 for(const auto & pFieldType
: *pFieldTypes
)
56 // same ResId -> increment index
57 if(pFieldType
->Which() == nResId
)
63 /// get field types with a ResId, if 0 get all
64 SwFieldType
* SwEditShell::GetFieldType(size_t nField
, SwFieldIds nResId
) const
66 const SwFieldTypes
* pFieldTypes
= GetDoc()->getIDocumentFieldsAccess().GetFieldTypes();
68 if(nResId
== SwFieldIds::Unknown
&& nField
< pFieldTypes
->size())
70 return (*pFieldTypes
)[nField
].get();
74 for(const auto & pFieldType
: *pFieldTypes
)
76 // same ResId -> increment index
77 if(pFieldType
->Which() == nResId
)
80 return pFieldType
.get();
87 /// get first type with given ResId and name
88 SwFieldType
* SwEditShell::GetFieldType(SwFieldIds nResId
, const OUString
& rName
) const
90 return GetDoc()->getIDocumentFieldsAccess().GetFieldType( nResId
, rName
, false );
94 void SwEditShell::RemoveFieldType(size_t nField
)
96 GetDoc()->getIDocumentFieldsAccess().RemoveFieldType(nField
);
99 /// delete field type based on its name
100 void SwEditShell::RemoveFieldType(SwFieldIds nResId
, const OUString
& rStr
)
102 const SwFieldTypes
* pFieldTypes
= GetDoc()->getIDocumentFieldsAccess().GetFieldTypes();
103 const SwFieldTypes::size_type nSize
= pFieldTypes
->size();
104 const CharClass
& rCC
= GetAppCharClass();
106 OUString
aTmp( rCC
.lowercase( rStr
));
108 for(SwFieldTypes::size_type i
= 0; i
< nSize
; ++i
)
110 // same ResId -> increment index
111 SwFieldType
* pFieldType
= (*pFieldTypes
)[i
].get();
112 if( pFieldType
->Which() == nResId
)
114 if( aTmp
== rCC
.lowercase( pFieldType
->GetName() ) )
116 GetDoc()->getIDocumentFieldsAccess().RemoveFieldType(i
);
123 void SwEditShell::FieldToText( SwFieldType
const * pType
)
125 if( !pType
->HasWriterListeners() )
128 CurrShell
aCurr( this );
130 StartUndo( SwUndoId::DELETE
);
132 SwPaM
* pPaM
= GetCursor();
133 const SwFieldHint
aHint(pPaM
, GetLayout());
134 CallSwClientNotify(aHint
);
136 Pop(PopMode::DeleteCurrent
);
138 EndUndo( SwUndoId::DELETE
);
141 /// add a field at the cursor position
142 void SwEditShell::Insert2(SwField
const & rField
, const bool bForceExpandHints
)
144 CurrShell
aCurr( this );
146 SwFormatField
aField( rField
);
148 const SetAttrMode nInsertFlags
= bForceExpandHints
149 ? SetAttrMode::FORCEHINTEXPAND
150 : SetAttrMode::DEFAULT
;
152 for(const SwPaM
& rPaM
: GetCursor()->GetRingContainer()) // for each PaM
154 const bool bSuccess(GetDoc()->getIDocumentContentOperations().InsertPoolItem(rPaM
, aField
, nInsertFlags
));
155 OSL_ENSURE( bSuccess
, "Doc->Insert(Field) failed");
161 /// Are the PaMs positioned on fields?
162 static SwTextField
* lcl_FindInputField( SwDoc
* pDoc
, SwField
& rField
)
164 // Search field via its address. For input fields this needs to be done in protected fields.
165 SwTextField
* pTField
= nullptr;
166 if (SwFieldIds::Input
== rField
.Which()
167 || (SwFieldIds::SetExp
== rField
.Which()
168 && static_cast<SwSetExpField
&>(rField
).GetInputFlag()
169 && (static_cast<SwSetExpFieldType
*>(rField
.GetTyp())->GetType()
170 & nsSwGetSetExpType::GSE_STRING
)))
172 for (const SfxPoolItem
* pItem
: pDoc
->GetAttrPool().GetItemSurrogates(RES_TXTATR_INPUTFIELD
))
174 auto pFormatField
= dynamic_cast<const SwFormatField
*>(pItem
);
175 if( pFormatField
&& pFormatField
->GetField() == &rField
)
177 pTField
= const_cast<SwFormatField
*>(pFormatField
)->GetTextField();
182 else if( SwFieldIds::SetExp
== rField
.Which()
183 && static_cast<SwSetExpField
&>(rField
).GetInputFlag() )
185 for (const SfxPoolItem
* pItem
: pDoc
->GetAttrPool().GetItemSurrogates(RES_TXTATR_FIELD
))
187 auto pFormatField
= dynamic_cast<const SwFormatField
*>(pItem
);
188 if( pFormatField
&& pFormatField
->GetField() == &rField
)
190 pTField
= const_cast<SwFormatField
*>(pFormatField
)->GetTextField();
198 void SwEditShell::UpdateOneField(SwField
&rField
)
200 CurrShell
aCurr( this );
203 // If there are no selections so take the value of the current cursor position.
204 SwMsgPoolItem
* pMsgHint
= nullptr;
205 SwRefMarkFieldUpdate
aRefMkHt( GetOut() );
206 SwFieldIds nFieldWhich
= rField
.GetTyp()->Which();
207 if( SwFieldIds::GetRef
== nFieldWhich
)
208 pMsgHint
= &aRefMkHt
;
210 SwPaM
* pCursor
= GetCursor();
211 SwTextField
*pTextField
;
212 SwFormatField
*pFormatField
;
214 if ( !pCursor
->IsMultiSelection() && !pCursor
->HasMark())
216 pTextField
= GetTextFieldAtPos( pCursor
->Start(), true );
218 if (!pTextField
) // #i30221#
219 pTextField
= lcl_FindInputField( GetDoc(), rField
);
221 if (pTextField
!= nullptr)
222 GetDoc()->getIDocumentFieldsAccess().UpdateField(pTextField
, rField
, pMsgHint
, true);
225 // bOkay (instead of return because of EndAllAction) becomes false,
226 // 1) if only one PaM has more than one field or
227 // 2) if there are mixed field types
229 bool bTableSelBreak
= false;
231 SwMsgPoolItem
aFieldHint( RES_TXTATR_FIELD
); // Search-Hint
232 SwMsgPoolItem
aAnnotationFieldHint( RES_TXTATR_ANNOTATION
);
233 SwMsgPoolItem
aInputFieldHint( RES_TXTATR_INPUTFIELD
);
234 for(SwPaM
& rPaM
: GetCursor()->GetRingContainer()) // for each PaM
236 if( rPaM
.HasMark() && bOkay
) // ... with selection
239 SwPaM
aCurPam( *rPaM
.GetMark(), *rPaM
.GetPoint() );
240 SwPaM
aPam( *rPaM
.GetPoint() );
242 SwPosition
*pCurStt
= aCurPam
.Start(), *pCurEnd
=
245 * In case that there are two contiguous fields in a PaM, the aPam goes step by step
246 * to the end. aCurPam is reduced in each loop. If aCurPam was searched completely,
247 * the loop terminates because Start = End.
250 // Search for SwTextField ...
252 && pCurStt
->nContent
!= pCurEnd
->nContent
253 && (sw::FindAttrImpl(aPam
, aFieldHint
, fnMoveForward
, aCurPam
, true, GetLayout())
254 || sw::FindAttrImpl(aPam
, aAnnotationFieldHint
, fnMoveForward
, aCurPam
, false, GetLayout())
255 || sw::FindAttrImpl(aPam
, aInputFieldHint
, fnMoveForward
, aCurPam
, false, GetLayout())))
257 // if only one PaM has more than one field ...
258 if( aPam
.Start()->nContent
!= pCurStt
->nContent
)
261 pTextField
= GetTextFieldAtPos( pCurStt
, true );
262 if( nullptr != pTextField
)
264 pFormatField
= const_cast<SwFormatField
*>(&pTextField
->GetFormatField());
265 SwField
*pCurField
= pFormatField
->GetField();
267 // if there are mixed field types
268 if( pCurField
->GetTyp()->Which() !=
269 rField
.GetTyp()->Which() )
272 bTableSelBreak
= GetDoc()->getIDocumentFieldsAccess().UpdateField(pTextField
, rField
,
275 // The search area is reduced by the found area:
280 if( bTableSelBreak
) // If table section and table formula are updated -> finish
285 GetDoc()->getIDocumentState().SetModified();
289 SwDBData
const & SwEditShell::GetDBData() const
291 return GetDoc()->GetDBData();
294 const SwDBData
& SwEditShell::GetDBDesc() const
296 return GetDoc()->GetDBDesc();
299 void SwEditShell::ChgDBData(const SwDBData
& rNewData
)
301 GetDoc()->ChgDBData(rNewData
);
304 void SwEditShell::GetAllUsedDB( std::vector
<OUString
>& rDBNameList
,
305 std::vector
<OUString
> const * pAllDBNames
)
307 GetDoc()->GetAllUsedDB( rDBNameList
, pAllDBNames
);
310 void SwEditShell::ChangeDBFields( const std::vector
<OUString
>& rOldNames
,
311 const OUString
& rNewName
)
313 GetDoc()->ChangeDBFields( rOldNames
, rNewName
);
316 /// Update all expression fields
317 void SwEditShell::UpdateExpFields(bool bCloseDB
)
319 CurrShell
aCurr( this );
321 GetDoc()->getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
324 #if HAVE_FEATURE_DBCONNECTIVITY
325 GetDoc()->GetDBManager()->CloseAll(); // close all database connections
331 SwDBManager
* SwEditShell::GetDBManager() const
333 #if HAVE_FEATURE_DBCONNECTIVITY
334 return GetDoc()->GetDBManager();
340 /// insert field type
341 SwFieldType
* SwEditShell::InsertFieldType(const SwFieldType
& rFieldType
)
343 return GetDoc()->getIDocumentFieldsAccess().InsertFieldType(rFieldType
);
346 void SwEditShell::LockExpFields()
348 GetDoc()->getIDocumentFieldsAccess().LockExpFields();
351 void SwEditShell::UnlockExpFields()
353 GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
356 bool SwEditShell::IsExpFieldsLocked() const
358 return GetDoc()->getIDocumentFieldsAccess().IsExpFieldsLocked();
361 void SwEditShell::SetFieldUpdateFlags( SwFieldUpdateFlags eFlags
)
363 getIDocumentSettingAccess().setFieldUpdateFlags( eFlags
);
366 SwFieldUpdateFlags
SwEditShell::GetFieldUpdateFlags() const
368 return getIDocumentSettingAccess().getFieldUpdateFlags( false );
371 void SwEditShell::SetLabelDoc( bool bFlag
)
373 GetDoc()->GetDocumentSettingManager().set(DocumentSettingId::LABEL_DOCUMENT
, bFlag
);
376 bool SwEditShell::IsLabelDoc() const
378 return getIDocumentSettingAccess().get(DocumentSettingId::LABEL_DOCUMENT
);
381 void SwEditShell::ChangeAuthorityData(const SwAuthEntry
* pNewData
)
383 GetDoc()->ChangeAuthorityData(pNewData
);
386 bool SwEditShell::IsAnyDatabaseFieldInDoc()const
388 const SwFieldTypes
* pFieldTypes
= GetDoc()->getIDocumentFieldsAccess().GetFieldTypes();
389 for(const auto & pFieldType
: *pFieldTypes
)
391 if(IsUsed(*pFieldType
))
393 switch(pFieldType
->Which())
395 case SwFieldIds::Database
:
396 case SwFieldIds::DbNextSet
:
397 case SwFieldIds::DbNumSet
:
398 case SwFieldIds::DbSetNumber
:
400 std::vector
<SwFormatField
*> vFields
;
401 pFieldType
->GatherFields(vFields
);
402 return vFields
.size();
412 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */