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 
12 #include <cppuhelper/implbase.hxx>
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 
22 #include <unotools/streamwrap.hxx>
23 
24 #include <xmloff/xmlnamespace.hxx>
25 #include <xmloff/xmltoken.hxx>
26 #include <xmloff/namespacemap.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>
34 #include <tools/diagnose_ex.h>
35 
36 #include <unosett.hxx>
37 
38 
39 using namespace ::com::sun::star;
40 using namespace ::xmloff::token;
41 
42 namespace sw {
43 
45  : public ::cppu::WeakImplHelper<container::XNamed,container::XIndexReplace>
46 {
47 private:
48  // TODO in case this ever becomes accessible via API need an invalidate
50  sal_uInt16 const m_nIndex;
51 
53  {
54  SwNumRulesWithName const* pRules(m_rNumRules.GetRules(m_nIndex));
55  if (!pRules)
56  {
57  m_rNumRules.CreateEmptyNumRule(m_nIndex);
58  pRules = m_rNumRules.GetRules(m_nIndex);
59  assert(pRules);
60  }
61  return const_cast<SwNumRulesWithName*>(pRules);
62  }
63 
64 public:
66  SwChapterNumRules & rNumRules, sal_uInt16 const nIndex)
67  : m_rNumRules(rNumRules)
68  , m_nIndex(nIndex)
69  {
71  }
72 
73  // XNamed
74  virtual OUString SAL_CALL getName() override
75  {
77  SwNumRulesWithName const* pRules(m_rNumRules.GetRules(m_nIndex));
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 
114  SolarMutexGuard g;
115  SwNumRulesWithName const* pRules(m_rNumRules.GetRules(m_nIndex));
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::makeAny(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 
146  SolarMutexGuard g;
147  SwNumFormat aNumberFormat;
148  OUString charStyleName;
150  aNumberFormat,
151  charStyleName,
152  nullptr, nullptr, nullptr, nullptr,
153  props);
154  SwNumRulesWithName *const pRules(GetOrCreateRules());
155  pRules->SetNumFormat(nIndex, aNumberFormat, charStyleName);
156  }
157 };
158 
159 namespace {
160 
161 class StoredChapterNumberingExport
162  : public SvXMLExport
163 {
164 public:
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 
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 
267 class StoredChapterNumberingDummyStyleContext
268  : public SvXMLImportContext
269 {
270 public:
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 
302 class StoredChapterNumberingImport;
303 
304 class StoredChapterNumberingRootContext
305  : public SvXMLImportContext
306 {
307 private:
308  SwChapterNumRules & m_rNumRules;
309  size_t m_nCounter;
310  std::vector<rtl::Reference<SvxXMLListStyleContext>> m_Contexts;
311 
312 public:
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 
360 class StoredChapterNumberingImport
361  : public SvXMLImport
362 {
363 private:
364  SwChapterNumRules & m_rNumRules;
365 
366 public:
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(
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(
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: */
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
void SetNumFormat(size_t, SwNumFormat const &, OUString const &)
Definition: uinums.cxx:168
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
void CreateEmptyNumRule(sal_uInt16 nIdx)
Definition: uinums.cxx:89
void ImportStoredChapterNumberingRules(SwChapterNumRules &rRules, SvStream &rStream, OUString const &rFileName)
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
Dialog to specify the properties of date form field.
void ExportStoredChapterNumberingRules(SwChapterNumRules &rRules, SvStream &rStream, OUString const &rFileName)
virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override
void SetName(const OUString &rSet)
Definition: uinums.hxx:63
XmlStyleFamily
virtual OUString SAL_CALL getName() override
SvXMLImportFlags
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
#define XMLOFF_WARN_UNKNOWN(area, rIter)
const SwNumRulesWithName * GetRules(sal_uInt16 nIdx) const
Definition: uinums.hxx:100
const sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:95
virtual ::sal_Bool SAL_CALL hasElements() override
#define TOOLS_WARN_EXCEPTION(area, stream)
int i
sal_Int32 & m_nCounter
dictionary props
virtual sal_Int32 SAL_CALL getCount() override
static css::uno::Sequence< css::beans::PropertyValue > GetPropertiesForNumFormat(const SwNumFormat &rFormat, OUString const &rCharFormatName, OUString const *pHeadingStyleName, OUString const &referer)
Definition: unosett.cxx:1310
exports com.sun.star. style
StoredChapterNumberingRules(SwChapterNumRules &rNumRules, sal_uInt16 const nIndex)
PointerStyles const styles[]
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
void exportLevelStyles(const css::uno::Reference< css::container::XIndexReplace > &xNumRule, bool bOutline=false)
static void SetPropertiesToNumFormat(SwNumFormat &aFormat, OUString &rCharStyleName, OUString *const pBulletFontName, OUString *const pHeadingStyleName, OUString *const pParagraphStyleName, SwDoc *const pDoc, css::uno::Sequence< css::beans::PropertyValue > const &rProperties)
Definition: unosett.cxx:1530
virtual uno::Type SAL_CALL getElementType() override
#define XML_ELEMENT(prefix, name)
virtual void SAL_CALL replaceByIndex(sal_Int32 nIndex, uno::Any const &rElement) override
Reference< XComponentContext > getProcessComponentContext()
const char * name
void AddStyleDisplayName(XmlStyleFamily nFamily, const OUString &rName, const OUString &rDisplayName)
#define SAL_WARN(area, stream)
virtual void SAL_CALL setName(OUString const &rName) override
XML_FAMILY
constexpr sal_uInt16 XML_NAMESPACE_STYLE