LibreOffice Module sw (master) 1
StoredChapterNumbering.cxx
Go to the documentation of this file.
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
10#include <uinums.hxx>
11
13
14#include <com/sun/star/container/XIndexReplace.hpp>
15#include <com/sun/star/container/XNamed.hpp>
16#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
17#include <com/sun/star/util/MeasureUnit.hpp>
18#include <com/sun/star/xml/sax/Writer.hpp>
19
21
23
25#include <xmloff/xmltoken.hxx>
27#include <xmloff/xmlexp.hxx>
28#include <xmloff/xmlnume.hxx>
29#include <xmloff/xmlimp.hxx>
30#include <xmloff/xmlictxt.hxx>
31#include <xmloff/xmlnumi.hxx>
32
33#include <vcl/svapp.hxx>
35
36#include <unosett.hxx>
37
38
39using namespace ::com::sun::star;
40using namespace ::xmloff::token;
41
42namespace sw {
43
45 : public ::cppu::WeakImplHelper<container::XNamed,container::XIndexReplace>
46{
47private:
48 // TODO in case this ever becomes accessible via API need an invalidate
50 sal_uInt16 const m_nIndex;
51
53 {
55 if (!pRules)
56 {
59 assert(pRules);
60 }
61 return const_cast<SwNumRulesWithName*>(pRules);
62 }
63
64public:
66 SwChapterNumRules & rNumRules, sal_uInt16 const nIndex)
67 : m_rNumRules(rNumRules)
69 {
71 }
72
73 // XNamed
74 virtual OUString SAL_CALL getName() override
75 {
78 if (!pRules)
79 {
80 return OUString();
81 }
82 return pRules->GetName();
83 }
84
85 virtual void SAL_CALL setName(OUString const& rName) override
86 {
88 SwNumRulesWithName *const pRules(GetOrCreateRules());
89 pRules->SetName(rName);
90 }
91
92 // XElementAccess
93 virtual uno::Type SAL_CALL getElementType() override
94 {
95 return ::cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get();
96 }
97
98 virtual ::sal_Bool SAL_CALL hasElements() override
99 {
100 return true;
101 }
102
103 // XIndexAccess
104 virtual sal_Int32 SAL_CALL getCount() override
105 {
106 return MAXLEVEL;
107 }
108
109 virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override
110 {
111 if (nIndex < 0 || MAXLEVEL <= nIndex)
112 throw lang::IndexOutOfBoundsException();
113
116 if (!pRules)
117 {
118 return uno::Any();
119 }
120 SwNumFormat const* pNumFormat(nullptr);
121 OUString const* pCharStyleName(nullptr);
122 pRules->GetNumFormat(nIndex, pNumFormat, pCharStyleName);
123 if (!pNumFormat)
124 { // the dialog only fills in those levels that are non-default
125 return uno::Any(); // the export will ignore this level, yay
126 }
127 assert(pCharStyleName);
128 OUString dummy; // pass in empty HeadingStyleName - can't import anyway
129 uno::Sequence<beans::PropertyValue> const ret(
131 *pNumFormat, *pCharStyleName, &dummy, ""));
132 return uno::Any(ret);
133 }
134
135 // XIndexReplace
136 virtual void SAL_CALL replaceByIndex(
137 sal_Int32 nIndex, uno::Any const& rElement) override
138 {
139 if (nIndex < 0 || MAXLEVEL <= nIndex)
140 throw lang::IndexOutOfBoundsException();
141 uno::Sequence<beans::PropertyValue> props;
142 if (!(rElement >>= props))
143 throw lang::IllegalArgumentException("invalid type",
144 static_cast< ::cppu::OWeakObject*>(this), 1);
145
147 SwNumFormat aNumberFormat;
148 OUString charStyleName;
150 aNumberFormat,
151 charStyleName,
152 nullptr, nullptr, nullptr, nullptr, nullptr,
153 props);
154 SwNumRulesWithName *const pRules(GetOrCreateRules());
155 pRules->SetNumFormat(nIndex, aNumberFormat, charStyleName);
156 }
157};
158
159namespace {
160
161class StoredChapterNumberingExport
162 : public SvXMLExport
163{
164public:
165 StoredChapterNumberingExport(
166 uno::Reference<uno::XComponentContext> const& xContext,
167 OUString const& rFileName,
168 uno::Reference<xml::sax::XDocumentHandler> const& xHandler)
169 : SvXMLExport(xContext, "sw::StoredChapterNumberingExport", rFileName,
170 util::MeasureUnit::CM, xHandler)
171 {
172 GetNamespaceMap_().Add(GetXMLToken(XML_NP_OFFICE),
173 GetXMLToken(XML_N_OFFICE), XML_NAMESPACE_OFFICE);
174 GetNamespaceMap_().Add(GetXMLToken(XML_NP_TEXT),
175 GetXMLToken(XML_N_TEXT), XML_NAMESPACE_TEXT);
176 GetNamespaceMap_().Add(GetXMLToken(XML_NP_STYLE),
177 GetXMLToken(XML_N_STYLE), XML_NAMESPACE_STYLE);
178 GetNamespaceMap_().Add(GetXMLToken(XML_NP_FO),
179 GetXMLToken(XML_N_FO), XML_NAMESPACE_FO);
180 GetNamespaceMap_().Add(GetXMLToken(XML_NP_SVG),
181 GetXMLToken(XML_N_SVG), XML_NAMESPACE_SVG);
182 }
183
184 virtual void ExportAutoStyles_() override {}
185 virtual void ExportMasterStyles_() override {}
186 virtual void ExportContent_() override {}
187
188 void ExportRule(SvxXMLNumRuleExport & rExport,
189 uno::Reference<container::XIndexReplace> const& xRule)
190 {
191 uno::Reference<container::XNamed> const xNamed(xRule, uno::UNO_QUERY);
192 OUString const name(xNamed->getName());
193 bool bEncoded(false);
194 AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
195 EncodeStyleName(name, &bEncoded) );
196 if (bEncoded)
197 {
198 AddAttribute(XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, name);
199 }
200
201 SvXMLElementExport aElem( *this, XML_NAMESPACE_TEXT,
202 XML_OUTLINE_STYLE, true, true );
203 rExport.exportLevelStyles(xRule, true);
204 }
205
206 void ExportRules(
207 std::set<OUString> const& rCharStyles,
208 std::vector<uno::Reference<container::XIndexReplace>> const& rRules)
209 {
210 GetDocHandler()->startDocument();
211
212 AddAttribute(XML_NAMESPACE_NONE,
213 GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_OFFICE),
214 GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_OFFICE));
215 AddAttribute(XML_NAMESPACE_NONE,
216 GetNamespaceMap_().GetAttrNameByKey (XML_NAMESPACE_TEXT),
217 GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_TEXT));
218 AddAttribute(XML_NAMESPACE_NONE,
219 GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_STYLE),
220 GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_STYLE));
221 AddAttribute(XML_NAMESPACE_NONE,
222 GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_FO),
223 GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_FO));
224 AddAttribute(XML_NAMESPACE_NONE,
225 GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_SVG),
226 GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_SVG));
227
228 {
229 // let's just have an office:styles as a dummy root
231 XML_NAMESPACE_OFFICE, XML_STYLES, true, true);
232
233 // horrible hack for char styles to get display-name mapping
234 for (const auto& rCharStyle : rCharStyles)
235 {
236 AddAttribute( XML_NAMESPACE_STYLE, XML_FAMILY, XML_TEXT );
237 bool bEncoded(false);
238 AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
239 EncodeStyleName(rCharStyle, &bEncoded) );
240 if (bEncoded)
241 {
242 AddAttribute(XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, rCharStyle);
243 }
244
245 SvXMLElementExport style(*this,
246 XML_NAMESPACE_STYLE, XML_STYLE, true, true);
247 }
248
249 SvxXMLNumRuleExport numRuleExport(*this);
250
251 for (const auto& rRule : rRules)
252 {
253 ExportRule(numRuleExport, rRule);
254 }
255 }
256
257 GetDocHandler()->endDocument();
258 }
259};
260
267class StoredChapterNumberingDummyStyleContext
268 : public SvXMLImportContext
269{
270public:
271 StoredChapterNumberingDummyStyleContext(
272 SvXMLImport & rImport,
273 uno::Reference<xml::sax::XFastAttributeList> const& xAttrList)
274 : SvXMLImportContext(rImport)
275 {
276 OUString name;
277 OUString displayName;
278 XmlStyleFamily nFamily(XmlStyleFamily::DATA_STYLE);
279
280 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
281 if (aIter.getToken() == (XML_NAMESPACE_STYLE | XML_FAMILY))
282 {
283 if (IsXMLToken(aIter, XML_TEXT))
284 nFamily = XmlStyleFamily::TEXT_TEXT;
285 else if (IsXMLToken(aIter, XML_NAME))
286 name = aIter.toString();
287 else if (IsXMLToken(aIter, XML_DISPLAY_NAME))
288 displayName = aIter.toString();
289 else
290 SAL_WARN("xmloff", "unknown value for style:family=" << aIter.toString());
291 }
292 else
293 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
294
295 if (nFamily != XmlStyleFamily::DATA_STYLE && !name.isEmpty() && !displayName.isEmpty())
296 {
297 rImport.AddStyleDisplayName(nFamily, name, displayName);
298 }
299 }
300};
301
302class StoredChapterNumberingImport;
303
304class StoredChapterNumberingRootContext
305 : public SvXMLImportContext
306{
307private:
308 SwChapterNumRules & m_rNumRules;
309 size_t m_nCounter;
310 std::vector<rtl::Reference<SvxXMLListStyleContext>> m_Contexts;
311
312public:
313 StoredChapterNumberingRootContext(
314 SwChapterNumRules & rNumRules, SvXMLImport & rImport)
315 : SvXMLImportContext(rImport)
316 , m_rNumRules(rNumRules)
317 , m_nCounter(0)
318 {
319 }
320
321 virtual void SAL_CALL endFastElement(sal_Int32 /*Element*/) override
322 {
323 assert(m_Contexts.size() <= SwChapterNumRules::nMaxRules);
324 for (auto iter = m_Contexts.begin(); iter != m_Contexts.end(); ++iter)
325 {
326 uno::Reference<container::XIndexReplace> const xRule(
327 new sw::StoredChapterNumberingRules(m_rNumRules,
328 iter - m_Contexts.begin()));
329 (*iter)->FillUnoNumRule(xRule);
330 // TODO: xmloff's outline-style import seems to ignore this???
331 uno::Reference<container::XNamed> const xNamed(xRule, uno::UNO_QUERY);
332 xNamed->setName((*iter)->GetDisplayName());
333 }
334 }
335
336 virtual css::uno::Reference<XFastContextHandler> SAL_CALL createFastChildContext(
337 sal_Int32 Element,
338 const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override
339 {
340 if (Element == XML_ELEMENT(STYLE, XML_STYLE))
341 {
342 return new StoredChapterNumberingDummyStyleContext(GetImport(), xAttrList);
343 }
344 else if (Element == XML_ELEMENT(TEXT, XML_OUTLINE_STYLE))
345 {
346 ++m_nCounter;
347 if (m_nCounter <= SwChapterNumRules::nMaxRules)
348 {
349 SvxXMLListStyleContext *const pContext(
350 new SvxXMLListStyleContext(GetImport(), true));
351 m_Contexts.emplace_back(pContext);
352 return pContext;
353 }
354 }
355
356 return nullptr;
357 }
358};
359
360class StoredChapterNumberingImport
361 : public SvXMLImport
362{
363private:
364 SwChapterNumRules & m_rNumRules;
365
366public:
367 StoredChapterNumberingImport(
368 uno::Reference<uno::XComponentContext> const& xContext,
369 SwChapterNumRules & rNumRules)
370 : SvXMLImport(xContext, "sw::StoredChapterNumberingImport", SvXMLImportFlags::ALL)
371 , m_rNumRules(rNumRules)
372 {
373 }
374
375 virtual SvXMLImportContext *CreateFastContext( sal_Int32 Element,
376 const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*xAttrList*/ ) override
377 {
378 if (Element == XML_ELEMENT(OFFICE, XML_STYLES))
379 return new StoredChapterNumberingRootContext(m_rNumRules, *this);
380 return nullptr;
381 }
382};
383
384}
385
387 SvStream & rStream, OUString const& rFileName)
388{
389 uno::Reference<uno::XComponentContext> const xContext(
390 ::comphelper::getProcessComponentContext());
391
392 uno::Reference<io::XOutputStream> const xOutStream(
393 new ::utl::OOutputStreamWrapper(rStream));
394
395 uno::Reference<xml::sax::XWriter> const xWriter(
396 xml::sax::Writer::create(xContext));
397
398 xWriter->setOutputStream(xOutStream);
399
400 rtl::Reference<StoredChapterNumberingExport> exp(new StoredChapterNumberingExport(xContext, rFileName, xWriter));
401
402 // if style name contains a space then name != display-name
403 // ... and the import needs to map from name to display-name then!
404 std::set<OUString> charStyles;
405 std::vector<uno::Reference<container::XIndexReplace>> numRules;
406 for (size_t i = 0; i < SwChapterNumRules::nMaxRules; ++i)
407 {
408 if (SwNumRulesWithName const* pRule = rRules.GetRules(i))
409 {
410 for (size_t j = 0; j < MAXLEVEL; ++j)
411 {
412 SwNumFormat const* pDummy(nullptr);
413 OUString const* pCharStyleName(nullptr);
414 pRule->GetNumFormat(j, pDummy, pCharStyleName);
415 if (pCharStyleName && !pCharStyleName->isEmpty())
416 {
417 charStyles.insert(*pCharStyleName);
418 }
419 }
420 numRules.push_back(new StoredChapterNumberingRules(rRules, i));
421 }
422 }
423
424 try
425 {
426 exp->ExportRules(charStyles, numRules);
427 }
428 catch (uno::Exception const&)
429 {
430 TOOLS_WARN_EXCEPTION("sw.ui", "ExportStoredChapterNumberingRules");
431 }
432}
433
435 SvStream & rStream, OUString const& rFileName)
436{
437 uno::Reference<uno::XComponentContext> const xContext(
438 ::comphelper::getProcessComponentContext());
439
440 uno::Reference<io::XInputStream> const xInStream(
441 new ::utl::OInputStreamWrapper(rStream));
442
443 rtl::Reference<StoredChapterNumberingImport> const xImport(new StoredChapterNumberingImport(xContext, rRules));
444
445 xml::sax::InputSource const source(xInStream, "", "", rFileName);
446
447 try
448 {
449 xImport->parseStream(source);
450 }
451 catch (uno::Exception const&)
452 {
453 TOOLS_WARN_EXCEPTION("sw.ui", "ImportStoredChapterNumberingRules");
454 }
455}
456
457} // namespace sw
458
459/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void AddStyleDisplayName(XmlStyleFamily nFamily, const OUString &rName, const OUString &rDisplayName)
void exportLevelStyles(const css::uno::Reference< css::container::XIndexReplace > &xNumRule, bool bOutline=false)
const SwNumRulesWithName * GetRules(sal_uInt16 nIdx) const
Definition: uinums.hxx:100
void CreateEmptyNumRule(sal_uInt16 nIdx)
Definition: uinums.cxx:90
void GetNumFormat(size_t, SwNumFormat const *&, OUString const *&) const
Definition: uinums.cxx:161
void SetName(const OUString &rSet)
Definition: uinums.hxx:63
void SetNumFormat(size_t, SwNumFormat const &, OUString const &)
Definition: uinums.cxx:168
const OUString & GetName() const
Definition: uinums.hxx:74
static css::uno::Sequence< css::beans::PropertyValue > GetPropertiesForNumFormat(const SwNumFormat &rFormat, OUString const &rCharFormatName, OUString const *pHeadingStyleName, OUString const &referer)
Definition: unosett.cxx:1283
static void SetPropertiesToNumFormat(SwNumFormat &aFormat, OUString &rCharStyleName, OUString *const pBulletFontName, OUString *const pHeadingStyleName, OUString *const pParagraphStyleName, SwDoc *const pDoc, SwDocShell *const pDocShell, css::uno::Sequence< css::beans::PropertyValue > const &rProperties)
Definition: unosett.cxx:1503
virtual void SAL_CALL setName(OUString const &rName) override
virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override
virtual uno::Type SAL_CALL getElementType() override
virtual ::sal_Bool SAL_CALL hasElements() override
StoredChapterNumberingRules(SwChapterNumRules &rNumRules, sal_uInt16 const nIndex)
virtual OUString SAL_CALL getName() override
virtual sal_Int32 SAL_CALL getCount() override
virtual void SAL_CALL replaceByIndex(sal_Int32 nIndex, uno::Any const &rElement) override
#define TOOLS_WARN_EXCEPTION(area, stream)
sal_Int32 & m_nCounter
XmlStyleFamily
const char * name
sal_Int32 nIndex
#define SAL_WARN(area, stream)
int i
dictionary props
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
Dialog to specify the properties of date form field.
void ExportStoredChapterNumberingRules(SwChapterNumRules &rRules, SvStream &rStream, OUString const &rFileName)
void ImportStoredChapterNumberingRules(SwChapterNumRules &rRules, SvStream &rStream, OUString const &rFileName)
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
constexpr sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:92
PointerStyles const styles[]
#define XMLOFF_WARN_UNKNOWN(area, rIter)
#define XML_ELEMENT(prefix, name)
SvXMLImportFlags