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