xref: /core/sw/source/ui/config/optcomp.cxx (revision cade37fa)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <optcomp.hxx>
21 
22 #include <cmdid.h>
23 #include <docsh.hxx>
24 #include <strings.hrc>
25 #include <uiitems.hxx>
26 #include <view.hxx>
27 #include <wrtsh.hxx>
28 
29 #include <vcl/svapp.hxx>
30 #include <vcl/weld.hxx>
31 #include <sfx2/docfilt.hxx>
32 #include <sfx2/fcontnr.hxx>
33 #include <IDocumentSettingAccess.hxx>
34 #include <vector>
35 #include <svtools/restartdialog.hxx>
36 #include <comphelper/processfactory.hxx>
37 #include <officecfg/Office/Compatibility.hxx>
38 #include <osl/diagnose.h>
39 
40 using namespace ::com::sun::star::beans;
41 using namespace ::com::sun::star::document;
42 
43 namespace
44 {
45 // Option ID, TranslateId
46 constexpr std::pair<OUString, TranslateId> options_list[]{
47     { u"AddSpacing"_ustr, STR_COMPAT_OPT_ADDSPACING },
48     { u"AddSpacingAtPages"_ustr, STR_COMPAT_OPT_ADDSPACINGATPAGES },
49     { u"UseOurTabStopFormat"_ustr, STR_COMPAT_OPT_USEOURTABSTOPFORMAT },
50     { u"NoExternalLeading"_ustr, STR_COMPAT_OPT_NOEXTERNALLEADING },
51     { u"UseLineSpacing"_ustr, STR_COMPAT_OPT_USELINESPACING },
52     { u"AddTableSpacing"_ustr, STR_COMPAT_OPT_ADDTABLESPACING },
53     { u"UseObjectPositioning"_ustr, STR_COMPAT_OPT_USEOBJECTPOSITIONING },
54     { u"UseOurTextWrapping"_ustr, STR_COMPAT_OPT_USEOURTEXTWRAPPING },
55     { u"ConsiderWrappingStyle"_ustr, STR_COMPAT_OPT_CONSIDERWRAPPINGSTYLE },
56     { u"ExpandWordSpace"_ustr, STR_COMPAT_OPT_EXPANDWORDSPACE },
57     { u"ProtectForm"_ustr, STR_COMPAT_OPT_PROTECTFORM },
58     { u"MsWordCompTrailingBlanks"_ustr, STR_COMPAT_OPT_MSWORDCOMPTRAILINGBLANKS },
59     { u"SubtractFlysAnchoredAtFlys"_ustr, STR_COMPAT_OPT_SUBTRACTFLYSANCHOREDATFLYS },
60     { u"EmptyDbFieldHidesPara"_ustr, STR_COMPAT_OPT_EMPTYDBFIELDHIDESPARA },
61     { u"UseVariableWidthNBSP"_ustr, STR_COMPAT_OPT_USEVARIABLEWIDTHNBSP },
62     { u"NoGapAfterNoteNumber"_ustr, STR_COMPAT_OPT_NOGAPAFTERNOTENUMBER },
63     { u"TabsRelativeToIndent"_ustr, STR_COMPAT_OPT_TABSRELATIVETOINDENT },
64     { u"TabOverMargin"_ustr, STR_COMPAT_OPT_TABOVERMARGIN },
65     { u"DoNotMirrorRtlDrawObjs"_ustr, STR_COMPAT_OPT_DO_NOT_MIRROR_RTL_DRAW_OBJS },
66     { u"ContinuousEndnotes"_ustr, STR_COMPAT_OPT_CONTINUOUS_ENDNOTES },
67 };
68 
69 // DocumentSettingId, negate?
DocumentSettingForOption(const OUString & option)70 std::pair<DocumentSettingId, bool> DocumentSettingForOption(const OUString& option)
71 {
72     static const std::map<OUString, std::pair<DocumentSettingId, bool>> map{
73         { u"AddSpacing"_ustr, { DocumentSettingId::PARA_SPACE_MAX, false } },
74         { u"AddSpacingAtPages"_ustr, { DocumentSettingId::PARA_SPACE_MAX_AT_PAGES, false } },
75         { u"UseOurTabStopFormat"_ustr, { DocumentSettingId::TAB_COMPAT, true } },
76         { u"NoExternalLeading"_ustr, { DocumentSettingId::ADD_EXT_LEADING, true } },
77         { u"UseLineSpacing"_ustr, { DocumentSettingId::OLD_LINE_SPACING, false } },
78         { u"AddTableSpacing"_ustr, { DocumentSettingId::ADD_PARA_SPACING_TO_TABLE_CELLS, false } },
79         { u"UseObjectPositioning"_ustr, { DocumentSettingId::USE_FORMER_OBJECT_POS, false } },
80         { u"UseOurTextWrapping"_ustr, { DocumentSettingId::USE_FORMER_TEXT_WRAPPING, false } },
81         { u"ConsiderWrappingStyle"_ustr, { DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION, false } },
82         { u"ExpandWordSpace"_ustr, { DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, true } },
83         { u"ProtectForm"_ustr, { DocumentSettingId::PROTECT_FORM, false } },
84         { u"MsWordCompTrailingBlanks"_ustr, { DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS, false } },
85         { u"SubtractFlysAnchoredAtFlys"_ustr, { DocumentSettingId::SUBTRACT_FLYS, false } },
86         { u"EmptyDbFieldHidesPara"_ustr, { DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA, false } },
87         { u"UseVariableWidthNBSP"_ustr, { DocumentSettingId::USE_VARIABLE_WIDTH_NBSP, false } },
88         { u"NoGapAfterNoteNumber"_ustr, { DocumentSettingId::NO_GAP_AFTER_NOTE_NUMBER, false } },
89         { u"TabsRelativeToIndent"_ustr, { DocumentSettingId::TABS_RELATIVE_TO_INDENT, false } },
90         { u"TabOverMargin"_ustr, { DocumentSettingId::TAB_OVER_MARGIN, false } },
91         { u"DoNotMirrorRtlDrawObjs"_ustr, { DocumentSettingId::DO_NOT_MIRROR_RTL_DRAW_OBJS, false } },
92         { u"ContinuousEndnotes"_ustr, { DocumentSettingId::CONTINUOUS_ENDNOTES, false } },
93 //        { u"AddTableLineSpacing"_ustr, { DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS, false } },
94     };
95     return map.at(option);
96 }
97 }
98 
SwCompatibilityOptPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)99 SwCompatibilityOptPage::SwCompatibilityOptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
100     : SfxTabPage(pPage, pController, u"modules/swriter/ui/optcompatpage.ui"_ustr, u"OptCompatPage"_ustr, &rSet)
101     , m_pWrtShell(nullptr)
102     , m_xMain(m_xBuilder->weld_frame(u"compatframe"_ustr))
103     , m_xOptionsLB(m_xBuilder->weld_tree_view(u"options"_ustr))
104     , m_xDefaultPB(m_xBuilder->weld_button(u"default"_ustr))
105 {
106     m_xOptionsLB->enable_toggle_buttons(weld::ColumnToggleType::Check);
107 
108     auto pos = m_xOptionsLB->make_iterator();
109     for (const auto& [compatId, translateId] : options_list)
110     {
111         m_xOptionsLB->append(pos.get());
112         m_xOptionsLB->set_id(*pos, compatId);
113         m_xOptionsLB->set_text(*pos, SwResId(translateId), 0);
114     }
115 
116     InitControls( rSet );
117 
118     // set handler
119     m_xDefaultPB->connect_clicked( LINK( this, SwCompatibilityOptPage, UseAsDefaultHdl ) );
120 }
121 
~SwCompatibilityOptPage()122 SwCompatibilityOptPage::~SwCompatibilityOptPage()
123 {
124 }
125 
InitControls(const SfxItemSet & rSet)126 void SwCompatibilityOptPage::InitControls( const SfxItemSet& rSet )
127 {
128     // init objectshell and detect document name
129     OUString sDocTitle;
130     SfxObjectShell* pObjShell = nullptr;
131     if ( const SwPtrItem* pItem = rSet.GetItemIfSet( FN_PARAM_WRTSHELL, false ) )
132         m_pWrtShell = static_cast<SwWrtShell*>(pItem->GetValue());
133     if ( m_pWrtShell )
134     {
135         pObjShell = m_pWrtShell->GetView().GetDocShell();
136         if ( pObjShell )
137             sDocTitle = pObjShell->GetTitle();
138     }
139     else
140     {
141         m_xMain->set_sensitive(false);
142     }
143     const OUString& rText = m_xMain->get_label();
144     m_xMain->set_label(rText.replaceAll("%DOCNAME", sDocTitle));
145 }
146 
IMPL_LINK_NOARG(SwCompatibilityOptPage,UseAsDefaultHdl,weld::Button &,void)147 IMPL_LINK_NOARG(SwCompatibilityOptPage, UseAsDefaultHdl, weld::Button&, void)
148 {
149     std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), u"modules/swriter/ui/querydefaultcompatdialog.ui"_ustr));
150     std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog(u"QueryDefaultCompatDialog"_ustr));
151     if (xQueryBox->run() != RET_YES)
152         return;
153 
154     auto batch = comphelper::ConfigurationChanges::create();
155     SvtCompatibilityDefault defaultCompatOptions(batch);
156 
157     const sal_Int32 nCount = m_xOptionsLB->n_children();
158     for ( sal_Int32 i = 0; i < nCount; ++i )
159     {
160         OUString option = m_xOptionsLB->get_id(i);
161         bool bChecked = m_xOptionsLB->get_toggle(i);
162         defaultCompatOptions.set(option, bChecked);
163 
164         if (option == "AddTableSpacing")
165         {
166             bool const isLineSpacing = m_xOptionsLB->get_toggle(i) == TRISTATE_TRUE;
167             defaultCompatOptions.set(u"AddTableLineSpacing"_ustr, isLineSpacing);
168         }
169         else
170         {
171             assert(m_xOptionsLB->get_toggle(i) != TRISTATE_INDET);
172         }
173     }
174 
175     batch->commit();
176 }
177 
SetCurrentOptions()178 void SwCompatibilityOptPage::SetCurrentOptions()
179 {
180     bool hasReadOnly = false;
181     if (m_pWrtShell)
182     {
183         m_aSavedOptions.clear();
184         // get document options
185         const auto& rIDocumentSettingAccess = m_pWrtShell->getIDocumentSettingAccess();
186         auto batch = comphelper::ConfigurationChanges::create(); // needed to obtain RO status
187         const SvtCompatibilityDefault defaultCompatOptions(batch);
188         const sal_Int32 nCount = m_xOptionsLB->n_children();
189         for (sal_Int32 i = 0; i < nCount; ++i)
190         {
191             OUString option = m_xOptionsLB->get_id(i);
192             const bool bReadOnly = defaultCompatOptions.getPropertyReadOnly(option);
193             if (bReadOnly)
194                 hasReadOnly = true;
195             const auto& [docSettingId, shouldNegate] = DocumentSettingForOption(option);
196             bool bChecked = rIDocumentSettingAccess.get(docSettingId);
197             if (shouldNegate)
198                 bChecked = !bChecked;
199             TriState value = bChecked ? TRISTATE_TRUE : TRISTATE_FALSE;
200             if (option == "AddTableSpacing")
201             { // hack: map 2 bools to 1 tristate
202                 if (value == TRISTATE_TRUE)
203                 {
204                     if (!rIDocumentSettingAccess.get(
205                             DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS))
206                         value = TRISTATE_INDET; // 3 values possible here
207                 }
208             }
209             m_xOptionsLB->set_toggle(i, value);
210             m_xOptionsLB->set_sensitive(i, !bReadOnly);
211             m_aSavedOptions[option] = value;
212         }
213     }
214 
215     m_xDefaultPB->set_sensitive(!hasReadOnly);
216 }
217 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rAttrSet)218 std::unique_ptr<SfxTabPage> SwCompatibilityOptPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet)
219 {
220     return std::make_unique<SwCompatibilityOptPage>(pPage, pController, *rAttrSet);
221 }
222 
GetAllStrings()223 OUString SwCompatibilityOptPage::GetAllStrings()
224 {
225     OUString sAllStrings;
226 
227     if (const auto& pString = m_xBuilder->weld_label(u"label11"_ustr))
228         sAllStrings += pString->get_label() + " ";
229 
230     sAllStrings += m_xDefaultPB->get_label() + " ";
231 
232     return sAllStrings.replaceAll("_", "");
233 }
234 
FillItemSet(SfxItemSet *)235 bool SwCompatibilityOptPage::FillItemSet( SfxItemSet*  )
236 {
237     bool bModified = false;
238     if ( m_pWrtShell )
239     {
240         const int nCount = m_xOptionsLB->n_children();
241         for (int i = 0; i < nCount; ++i)
242         {
243             OUString option = m_xOptionsLB->get_id(i);
244             TriState const current = m_xOptionsLB->get_toggle(i);
245             TriState saved = m_aSavedOptions[option];
246             if (current != saved)
247             {
248                 bool const bChecked(current != TRISTATE_FALSE);
249                 assert(current != TRISTATE_INDET); // can't *change* it to that
250                 switch (DocumentSettingForOption(option).first)
251                 {
252                     case DocumentSettingId::PARA_SPACE_MAX:
253                         m_pWrtShell->SetParaSpaceMax( bChecked );
254                         break;
255 
256                     case DocumentSettingId::PARA_SPACE_MAX_AT_PAGES:
257                         m_pWrtShell->SetParaSpaceMaxAtPages( bChecked );
258                         break;
259 
260                     case DocumentSettingId::TAB_COMPAT:
261                         m_pWrtShell->SetTabCompat( !bChecked );
262                         break;
263 
264                     case DocumentSettingId::ADD_EXT_LEADING:
265                         m_pWrtShell->SetAddExtLeading( !bChecked );
266                         break;
267 
268                     case DocumentSettingId::OLD_LINE_SPACING:
269                         m_pWrtShell->SetUseFormerLineSpacing( bChecked );
270                         break;
271 
272                     case DocumentSettingId::ADD_PARA_SPACING_TO_TABLE_CELLS:
273                         m_pWrtShell->SetAddParaSpacingToTableCells( bChecked );
274                         break;
275 
276                     case DocumentSettingId::USE_FORMER_OBJECT_POS:
277                         m_pWrtShell->SetUseFormerObjectPositioning( bChecked );
278                         break;
279 
280                     case DocumentSettingId::USE_FORMER_TEXT_WRAPPING:
281                         m_pWrtShell->SetUseFormerTextWrapping( bChecked );
282                         break;
283 
284                     case DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION:
285                         m_pWrtShell->SetConsiderWrapOnObjPos( bChecked );
286                         break;
287 
288                     case DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK:
289                         m_pWrtShell->SetDoNotJustifyLinesWithManualBreak( !bChecked );
290                         break;
291 
292                     case DocumentSettingId::PROTECT_FORM:
293                         m_pWrtShell->SetProtectForm( bChecked );
294                         break;
295 
296                     case DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS:
297                         m_pWrtShell->SetMsWordCompTrailingBlanks( bChecked );
298                         break;
299 
300                     case DocumentSettingId::SUBTRACT_FLYS:
301                         m_pWrtShell->SetSubtractFlysAnchoredAtFlys(bChecked);
302                         break;
303 
304                     case DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA:
305                         m_pWrtShell->SetEmptyDbFieldHidesPara(bChecked);
306                         break;
307 
308                     case DocumentSettingId::USE_VARIABLE_WIDTH_NBSP:
309                         m_pWrtShell->GetDoc()->getIDocumentSettingAccess()
310                             .set(DocumentSettingId::USE_VARIABLE_WIDTH_NBSP, bChecked);
311                         break;
312 
313                     case DocumentSettingId::NO_GAP_AFTER_NOTE_NUMBER:
314                         m_pWrtShell->SetNoGapAfterNoteNumber(bChecked);
315                         break;
316 
317                     case DocumentSettingId::TABS_RELATIVE_TO_INDENT:
318                         m_pWrtShell->SetTabsRelativeToIndent(bChecked);
319                         break;
320 
321                     case DocumentSettingId::TAB_OVER_MARGIN:
322                         m_pWrtShell->SetTabOverMargin(bChecked);
323                         break;
324 
325                     case DocumentSettingId::DO_NOT_MIRROR_RTL_DRAW_OBJS:
326                         m_pWrtShell->SetDoNotMirrorRtlDrawObjs(bChecked);
327                         break;
328 
329                     case DocumentSettingId::CONTINUOUS_ENDNOTES:
330                         m_pWrtShell->SetContinuousEndnotes(bChecked);
331                         break;
332 
333                     default:
334                         break;
335                 }
336                 bModified = true;
337             }
338         }
339     }
340 
341     return bModified;
342 }
343 
Reset(const SfxItemSet *)344 void SwCompatibilityOptPage::Reset( const SfxItemSet*  )
345 {
346     SetCurrentOptions();
347 }
348 
349 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
350