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 <optcomp.hxx>
24 #include <uiitems.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/weld.hxx>
30 #include <sfx2/docfilt.hxx>
31 #include <sfx2/fcontnr.hxx>
32 #include <IDocumentSettingAccess.hxx>
34 #include <svtools/restartdialog.hxx>
35 #include <comphelper/processfactory.hxx>
36 #include <officecfg/Office/Compatibility.hxx>
37 #include <osl/diagnose.h>
39 using namespace ::com::sun::star::beans
;
40 using namespace ::com::sun::star::document
;
41 using namespace ::com::sun::star::uno
;
43 struct SwCompatibilityOptPage_Impl
45 std::vector
< SvtCompatibilityEntry
> m_aList
;
48 SwCompatibilityOptPage::SwCompatibilityOptPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rSet
)
49 : SfxTabPage(pPage
, pController
, "modules/swriter/ui/optcompatpage.ui", "OptCompatPage", &rSet
)
50 , m_pWrtShell(nullptr)
51 , m_pImpl(new SwCompatibilityOptPage_Impl
)
53 , m_bSavedMSFormsMenuOption(false)
54 , m_xMain(m_xBuilder
->weld_frame("compatframe"))
55 , m_xGlobalOptionsFrame(m_xBuilder
->weld_frame("globalcompatframe"))
56 , m_xFormattingLB(m_xBuilder
->weld_combo_box("format"))
57 , m_xGlobalOptionsLB(m_xBuilder
->weld_combo_box("globaloptions"))
58 , m_xOptionsLB(m_xBuilder
->weld_tree_view("options"))
59 , m_xGlobalOptionsCLB(m_xBuilder
->weld_tree_view("globaloptioncheckbox"))
60 , m_xDefaultPB(m_xBuilder
->weld_button("default"))
62 m_xOptionsLB
->enable_toggle_buttons(weld::ColumnToggleType::Check
);
63 m_xGlobalOptionsCLB
->enable_toggle_buttons(weld::ColumnToggleType::Check
);
66 for (int i
= static_cast<int>(SvtCompatibilityEntry::Index::Module
) + 1;
67 i
< static_cast<int>(SvtCompatibilityEntry::Index::INVALID
) - 1; // omit AddTableLineSpacing
70 int nCoptIdx
= i
- 2; /* Do not consider "Name" & "Module" indexes */
72 const OUString sEntry
= m_xFormattingLB
->get_text(nCoptIdx
);
73 m_xOptionsLB
->append();
74 m_xOptionsLB
->set_toggle(nPos
, TRISTATE_FALSE
);
75 m_xOptionsLB
->set_text(nPos
, sEntry
, 0);
79 m_sUserEntry
= m_xFormattingLB
->get_text(m_xFormattingLB
->get_count() - 1);
81 m_xFormattingLB
->clear();
83 // Set MSOCompatibleFormsMenu entry attributes
84 const bool bReadOnly
= officecfg::Office::Compatibility::View::MSCompatibleFormsMenu::isReadOnly();
85 m_xGlobalOptionsCLB
->set_sensitive(!bReadOnly
);
87 m_xGlobalOptionsCLB
->append();
88 const bool bChecked
= officecfg::Office::Compatibility::View::MSCompatibleFormsMenu::get();
89 m_xGlobalOptionsCLB
->set_toggle(0, bChecked
? TRISTATE_TRUE
: TRISTATE_FALSE
);
90 m_xGlobalOptionsCLB
->set_text(0, m_xGlobalOptionsLB
->get_text(0), 0);
92 m_xGlobalOptionsLB
->clear();
94 // tdf#125799, we let only the doc options grow/shrink but give this one more than its bare
95 // min request height because there's only one row in it and that looks somewhat abrupt
96 m_xGlobalOptionsCLB
->set_size_request(-1, m_xGlobalOptionsCLB
->get_preferred_size().Height() * 2);
101 m_xFormattingLB
->connect_changed( LINK( this, SwCompatibilityOptPage
, SelectHdl
) );
102 m_xDefaultPB
->connect_clicked( LINK( this, SwCompatibilityOptPage
, UseAsDefaultHdl
) );
105 SwCompatibilityOptPage::~SwCompatibilityOptPage()
109 static sal_uInt32 convertBools2Ulong_Impl
112 bool _bAddSpacingAtPages
,
113 bool _bUseOurTabStops
,
115 bool _bUseLineSpacing
,
116 bool _bAddTableSpacing
,
117 bool _bAddTableLineSpacing
,
119 bool _bUseOurTextWrapping
,
120 bool _bConsiderWrappingStyle
,
121 bool _bExpandWordSpace
,
123 bool _bMsWordCompTrailingBlanks
,
124 bool bSubtractFlysAnchoredAtFlys
,
125 bool bEmptyDbFieldHidesPara
129 sal_uInt32 nSetBit
= 1;
133 nSetBit
= nSetBit
<< 1;
134 if ( _bAddSpacingAtPages
)
136 nSetBit
= nSetBit
<< 1;
137 if ( _bUseOurTabStops
)
139 nSetBit
= nSetBit
<< 1;
140 if ( _bNoExtLeading
)
142 nSetBit
= nSetBit
<< 1;
143 if ( _bUseLineSpacing
)
145 nSetBit
= nSetBit
<< 1;
146 if ( _bAddTableSpacing
)
148 nSetBit
= nSetBit
<< 1;
149 if (_bAddTableLineSpacing
)
151 nSetBit
= nSetBit
<< 1;
154 nSetBit
= nSetBit
<< 1;
155 if ( _bUseOurTextWrapping
)
157 nSetBit
= nSetBit
<< 1;
158 if ( _bConsiderWrappingStyle
)
160 nSetBit
= nSetBit
<< 1;
161 if ( _bExpandWordSpace
)
163 nSetBit
= nSetBit
<< 1;
166 nSetBit
= nSetBit
<< 1;
167 if ( _bMsWordCompTrailingBlanks
)
169 nSetBit
= nSetBit
<< 1;
170 if (bSubtractFlysAnchoredAtFlys
)
172 nSetBit
= nSetBit
<< 1;
173 if (bEmptyDbFieldHidesPara
)
179 void SwCompatibilityOptPage::InitControls( const SfxItemSet
& rSet
)
181 // init objectshell and detect document name
183 SfxObjectShell
* pObjShell
= nullptr;
184 if ( const SwPtrItem
* pItem
= rSet
.GetItemIfSet( FN_PARAM_WRTSHELL
, false ) )
185 m_pWrtShell
= static_cast<SwWrtShell
*>(pItem
->GetValue());
188 pObjShell
= m_pWrtShell
->GetView().GetDocShell();
190 sDocTitle
= pObjShell
->GetTitle();
194 m_xMain
->set_sensitive(false);
195 m_xGlobalOptionsFrame
->set_sensitive(false);
197 const OUString
& rText
= m_xMain
->get_label();
198 m_xMain
->set_label(rText
.replaceAll("%DOCNAME", sDocTitle
));
200 // loading file formats
201 const std::vector
< SvtCompatibilityEntry
> aList
= m_aConfigItem
.GetList();
203 for ( const SvtCompatibilityEntry
& rEntry
: aList
)
205 const OUString sEntryName
= rEntry
.getValue
<OUString
>( SvtCompatibilityEntry::Index::Name
);
206 const bool bIsUserEntry
= ( sEntryName
== SvtCompatibilityEntry::USER_ENTRY_NAME
);
207 const bool bIsDefaultEntry
= ( sEntryName
== SvtCompatibilityEntry::DEFAULT_ENTRY_NAME
);
209 m_pImpl
->m_aList
.push_back( rEntry
);
211 if ( bIsDefaultEntry
)
216 sNewEntry
= m_sUserEntry
;
218 else if ( pObjShell
&& !sEntryName
.isEmpty() )
220 SfxFilterContainer
* pFacCont
= pObjShell
->GetFactory().GetFilterContainer();
221 std::shared_ptr
<const SfxFilter
> pFilter
= pFacCont
->GetFilter4FilterName( sEntryName
);
223 sNewEntry
= pFilter
->GetUIName();
226 if ( sNewEntry
.isEmpty() )
227 sNewEntry
= sEntryName
;
229 sal_uInt32 nOptions
= convertBools2Ulong_Impl(
230 rEntry
.getValue
<bool>( SvtCompatibilityEntry::Index::AddSpacing
),
231 rEntry
.getValue
<bool>( SvtCompatibilityEntry::Index::AddSpacingAtPages
),
232 rEntry
.getValue
<bool>( SvtCompatibilityEntry::Index::UseOurTabStops
),
233 rEntry
.getValue
<bool>( SvtCompatibilityEntry::Index::NoExtLeading
),
234 rEntry
.getValue
<bool>( SvtCompatibilityEntry::Index::UseLineSpacing
),
235 rEntry
.getValue
<bool>( SvtCompatibilityEntry::Index::AddTableSpacing
),
236 rEntry
.getValue
<bool>(SvtCompatibilityEntry::Index::AddTableLineSpacing
),
237 rEntry
.getValue
<bool>( SvtCompatibilityEntry::Index::UseObjectPositioning
),
238 rEntry
.getValue
<bool>( SvtCompatibilityEntry::Index::UseOurTextWrapping
),
239 rEntry
.getValue
<bool>( SvtCompatibilityEntry::Index::ConsiderWrappingStyle
),
240 rEntry
.getValue
<bool>( SvtCompatibilityEntry::Index::ExpandWordSpace
),
241 rEntry
.getValue
<bool>( SvtCompatibilityEntry::Index::ProtectForm
),
242 rEntry
.getValue
<bool>( SvtCompatibilityEntry::Index::MsWordTrailingBlanks
),
243 rEntry
.getValue
<bool>( SvtCompatibilityEntry::Index::SubtractFlysAnchoredAtFlys
),
244 rEntry
.getValue
<bool>( SvtCompatibilityEntry::Index::EmptyDbFieldHidesPara
));
245 m_xFormattingLB
->append(OUString::number(nOptions
), sNewEntry
);
249 IMPL_LINK_NOARG(SwCompatibilityOptPage
, SelectHdl
, weld::ComboBox
&, void)
251 sal_uInt32 nOptions
= m_xFormattingLB
->get_active_id().toUInt32();
252 SetCurrentOptions(nOptions
);
255 IMPL_LINK_NOARG(SwCompatibilityOptPage
, UseAsDefaultHdl
, weld::Button
&, void)
257 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/querydefaultcompatdialog.ui"));
258 std::unique_ptr
<weld::MessageDialog
> xQueryBox(xBuilder
->weld_message_dialog("QueryDefaultCompatDialog"));
259 if (xQueryBox
->run() != RET_YES
)
262 auto pItem
= std::find_if(m_pImpl
->m_aList
.begin(), m_pImpl
->m_aList
.end(),
263 [](const SvtCompatibilityEntry
& rItem
)
265 const OUString sEntryName
= rItem
.getValue
<OUString
>( SvtCompatibilityEntry::Index::Name
);
266 const bool bIsDefaultEntry
= ( sEntryName
== SvtCompatibilityEntry::DEFAULT_ENTRY_NAME
);
267 return bIsDefaultEntry
;
269 if (pItem
!= m_pImpl
->m_aList
.end())
271 const sal_Int32 nCount
= m_xOptionsLB
->n_children();
272 for ( sal_Int32 i
= 0; i
< nCount
; ++i
)
274 bool bChecked
= m_xOptionsLB
->get_toggle(i
);
276 int nCoptIdx
= i
+ 2; /* Consider "Name" & "Module" indexes */
277 pItem
->setValue
<bool>( SvtCompatibilityEntry::Index(nCoptIdx
), bChecked
);
278 if (nCoptIdx
== int(SvtCompatibilityEntry::Index::AddTableSpacing
))
280 bool const isLineSpacing
= m_xOptionsLB
->get_toggle(i
) == TRISTATE_TRUE
;
281 pItem
->setValue
<bool>(SvtCompatibilityEntry::Index::AddTableLineSpacing
, isLineSpacing
);
285 assert(m_xOptionsLB
->get_toggle(i
) != TRISTATE_INDET
);
293 void SwCompatibilityOptPage::SetCurrentOptions( sal_uInt32 nOptions
)
295 const int nCount
= m_xOptionsLB
->n_children();
296 OSL_ENSURE( nCount
<= 32, "SwCompatibilityOptPage::Reset(): entry overflow" );
297 for (int i
= 0; i
< nCount
; ++i
)
299 bool bChecked
= ( ( nOptions
& 0x00000001 ) == 0x00000001 );
300 TriState value
= bChecked
? TRISTATE_TRUE
: TRISTATE_FALSE
;
301 if (i
== int(SvtCompatibilityEntry::Index::AddTableSpacing
) - 2)
302 { // hack: map 2 bools to 1 tristate
303 nOptions
= nOptions
>> 1;
304 if (value
== TRISTATE_TRUE
305 && (nOptions
& 0x00000001) != 0x00000001) // ADD_PARA_LINE_SPACING_TO_TABLE_CELLS
307 value
= TRISTATE_INDET
; // 3 values possible here
310 m_xOptionsLB
->set_toggle(i
, value
);
311 nOptions
= nOptions
>> 1;
315 sal_uInt32
SwCompatibilityOptPage::GetDocumentOptions() const
320 const IDocumentSettingAccess
& rIDocumentSettingAccess
= m_pWrtShell
->getIDocumentSettingAccess();
321 nRet
= convertBools2Ulong_Impl(
322 rIDocumentSettingAccess
.get( DocumentSettingId::PARA_SPACE_MAX
),
323 rIDocumentSettingAccess
.get( DocumentSettingId::PARA_SPACE_MAX_AT_PAGES
),
324 !rIDocumentSettingAccess
.get( DocumentSettingId::TAB_COMPAT
),
325 !rIDocumentSettingAccess
.get( DocumentSettingId::ADD_EXT_LEADING
),
326 rIDocumentSettingAccess
.get( DocumentSettingId::OLD_LINE_SPACING
),
327 rIDocumentSettingAccess
.get( DocumentSettingId::ADD_PARA_SPACING_TO_TABLE_CELLS
),
328 rIDocumentSettingAccess
.get( DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS
),
329 rIDocumentSettingAccess
.get( DocumentSettingId::USE_FORMER_OBJECT_POS
),
330 rIDocumentSettingAccess
.get( DocumentSettingId::USE_FORMER_TEXT_WRAPPING
),
331 rIDocumentSettingAccess
.get( DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION
),
332 !rIDocumentSettingAccess
.get( DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK
),
333 rIDocumentSettingAccess
.get( DocumentSettingId::PROTECT_FORM
),
334 rIDocumentSettingAccess
.get( DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS
),
335 rIDocumentSettingAccess
.get( DocumentSettingId::SUBTRACT_FLYS
),
336 rIDocumentSettingAccess
.get( DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA
) );
341 void SwCompatibilityOptPage::WriteOptions()
343 m_aConfigItem
.Clear();
344 for ( const auto& rItem
: m_pImpl
->m_aList
)
345 m_aConfigItem
.AppendItem(rItem
);
348 std::unique_ptr
<SfxTabPage
> SwCompatibilityOptPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rAttrSet
)
350 return std::make_unique
<SwCompatibilityOptPage
>(pPage
, pController
, *rAttrSet
);
353 bool SwCompatibilityOptPage::FillItemSet( SfxItemSet
* )
355 bool bModified
= false;
358 sal_uInt32 nSavedOptions
= m_nSavedOptions
;
359 const int nCount
= m_xOptionsLB
->n_children();
360 OSL_ENSURE( nCount
<= 32, "SwCompatibilityOptPage::Reset(): entry overflow" );
362 for (int i
= 0; i
< nCount
; ++i
)
364 TriState
const current
= m_xOptionsLB
->get_toggle(i
);
365 TriState saved
= ((nSavedOptions
& 0x00000001) == 0x00000001) ? TRISTATE_TRUE
: TRISTATE_FALSE
;
366 if (i
== int(SvtCompatibilityEntry::Index::AddTableSpacing
) - 2)
367 { // hack: map 2 bools to 1 tristate
368 nSavedOptions
= nSavedOptions
>> 1;
369 if (saved
== TRISTATE_TRUE
370 && ((nSavedOptions
& 0x00000001) != 0x00000001))
372 saved
= TRISTATE_INDET
;
375 if (current
!= saved
)
377 bool const bChecked(current
!= TRISTATE_FALSE
);
378 assert(current
!= TRISTATE_INDET
); // can't *change* it to that
379 int nCoptIdx
= i
+ 2; /* Consider "Name" & "Module" indexes */
380 switch ( SvtCompatibilityEntry::Index(nCoptIdx
) )
382 case SvtCompatibilityEntry::Index::AddSpacing
:
383 m_pWrtShell
->SetParaSpaceMax( bChecked
);
386 case SvtCompatibilityEntry::Index::AddSpacingAtPages
:
387 m_pWrtShell
->SetParaSpaceMaxAtPages( bChecked
);
390 case SvtCompatibilityEntry::Index::UseOurTabStops
:
391 m_pWrtShell
->SetTabCompat( !bChecked
);
394 case SvtCompatibilityEntry::Index::NoExtLeading
:
395 m_pWrtShell
->SetAddExtLeading( !bChecked
);
398 case SvtCompatibilityEntry::Index::UseLineSpacing
:
399 m_pWrtShell
->SetUseFormerLineSpacing( bChecked
);
402 case SvtCompatibilityEntry::Index::AddTableSpacing
:
403 m_pWrtShell
->SetAddParaSpacingToTableCells( bChecked
);
406 case SvtCompatibilityEntry::Index::UseObjectPositioning
:
407 m_pWrtShell
->SetUseFormerObjectPositioning( bChecked
);
410 case SvtCompatibilityEntry::Index::UseOurTextWrapping
:
411 m_pWrtShell
->SetUseFormerTextWrapping( bChecked
);
414 case SvtCompatibilityEntry::Index::ConsiderWrappingStyle
:
415 m_pWrtShell
->SetConsiderWrapOnObjPos( bChecked
);
418 case SvtCompatibilityEntry::Index::ExpandWordSpace
:
419 m_pWrtShell
->SetDoNotJustifyLinesWithManualBreak( !bChecked
);
422 case SvtCompatibilityEntry::Index::ProtectForm
:
423 m_pWrtShell
->SetProtectForm( bChecked
);
426 case SvtCompatibilityEntry::Index::MsWordTrailingBlanks
:
427 m_pWrtShell
->SetMsWordCompTrailingBlanks( bChecked
);
430 case SvtCompatibilityEntry::Index::SubtractFlysAnchoredAtFlys
:
431 m_pWrtShell
->SetSubtractFlysAnchoredAtFlys(bChecked
);
434 case SvtCompatibilityEntry::Index::EmptyDbFieldHidesPara
:
435 m_pWrtShell
->SetEmptyDbFieldHidesPara(bChecked
);
444 nSavedOptions
= nSavedOptions
>> 1;
451 bool bNewMSFormsMenuOption
= m_xGlobalOptionsCLB
->get_toggle(0);
452 if (m_bSavedMSFormsMenuOption
!= bNewMSFormsMenuOption
)
454 std::shared_ptr
<comphelper::ConfigurationChanges
> batch(comphelper::ConfigurationChanges::create());
455 officecfg::Office::Compatibility::View::MSCompatibleFormsMenu::set(bNewMSFormsMenuOption
, batch
);
458 m_bSavedMSFormsMenuOption
= bNewMSFormsMenuOption
;
461 // Show a message about that the option needs a restart to be applied
463 SolarMutexGuard aGuard
;
464 if (svtools::executeRestartDialog(comphelper::getProcessComponentContext(),
465 GetFrameWeld(), svtools::RESTART_REASON_MSCOMPATIBLE_FORMS_MENU
))
467 GetDialogController()->response(RET_OK
);
475 void SwCompatibilityOptPage::Reset( const SfxItemSet
* )
477 m_xOptionsLB
->select(0);
479 sal_uInt32 nOptions
= GetDocumentOptions();
480 SetCurrentOptions( nOptions
);
481 m_nSavedOptions
= nOptions
;
483 m_bSavedMSFormsMenuOption
= officecfg::Office::Compatibility::View::MSCompatibleFormsMenu::get();
484 m_xGlobalOptionsCLB
->set_toggle(0, m_bSavedMSFormsMenuOption
? TRISTATE_TRUE
: TRISTATE_FALSE
);
487 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */