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/xmlnmspe.hxx>
25 #include <xmloff/xmltoken.hxx>
26 #include <xmloff/nmspmap.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  SAL_WARN("xmloff", "unknown attribute " << SvXMLImport::getPrefixAndNameFromToken(aIter.getToken()) << "=" << aIter.toString());
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 startFastElement(
322  sal_Int32 /*nElement*/,
323  const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ ) override {}
324 
325  virtual void SAL_CALL endFastElement(sal_Int32 /*Element*/) override
326  {
327  assert(m_Contexts.size() < SwChapterNumRules::nMaxRules);
328  for (auto iter = m_Contexts.begin(); iter != m_Contexts.end(); ++iter)
329  {
330  uno::Reference<container::XIndexReplace> const xRule(
331  new sw::StoredChapterNumberingRules(m_rNumRules,
332  iter - m_Contexts.begin()));
333  (*iter)->FillUnoNumRule(xRule);
334  // TODO: xmloff's outline-style import seems to ignore this???
335  uno::Reference<container::XNamed> const xNamed(xRule, uno::UNO_QUERY);
336  xNamed->setName((*iter)->GetDisplayName());
337  }
338  }
339 
340  virtual SvXMLImportContextRef CreateChildContext(
341  sal_uInt16 nPrefix,
342  const OUString& rLocalName,
343  const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList ) override
344  {
345  if (XML_NAMESPACE_TEXT == nPrefix && IsXMLToken(rLocalName, XML_OUTLINE_STYLE))
346  {
347  ++m_nCounter;
348  if (m_nCounter <= SwChapterNumRules::nMaxRules)
349  {
350  SvxXMLListStyleContext *const pContext(
351  new SvxXMLListStyleContext(GetImport(),
352  nPrefix, rLocalName, xAttrList, true));
353  m_Contexts.emplace_back(pContext);
354  return pContext;
355  }
356  }
357  return nullptr;
358  }
359 
360  virtual css::uno::Reference<XFastContextHandler> SAL_CALL createFastChildContext(
361  sal_Int32 Element,
362  const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override
363  {
364  if (Element == XML_ELEMENT(TEXT, XML_OUTLINE_STYLE))
365  {
366  // handled in CreateChildContext
367  }
368  else if (Element == XML_ELEMENT(STYLE, XML_STYLE))
369  {
370  return new StoredChapterNumberingDummyStyleContext(GetImport(), xAttrList);
371  }
372 
373  return nullptr;
374  }
375 };
376 
377 class StoredChapterNumberingImport
378  : public SvXMLImport
379 {
380 private:
381  SwChapterNumRules & m_rNumRules;
382 
383 public:
384  StoredChapterNumberingImport(
385  uno::Reference<uno::XComponentContext> const& xContext,
386  SwChapterNumRules & rNumRules)
387  : SvXMLImport(xContext, "sw::StoredChapterNumberingImport", SvXMLImportFlags::ALL)
388  , m_rNumRules(rNumRules)
389  {
390  }
391 
392  virtual SvXMLImportContext *CreateFastContext( sal_Int32 Element,
393  const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*xAttrList*/ ) override
394  {
395  if (Element == XML_ELEMENT(OFFICE, XML_STYLES))
396  return new StoredChapterNumberingRootContext(m_rNumRules, *this);
397  return nullptr;
398  }
399 };
400 
401 }
402 
404  SvStream & rStream, OUString const& rFileName)
405 {
406  uno::Reference<uno::XComponentContext> const xContext(
408 
409  uno::Reference<io::XOutputStream> const xOutStream(
410  new ::utl::OOutputStreamWrapper(rStream));
411 
412  uno::Reference<xml::sax::XWriter> const xWriter(
413  xml::sax::Writer::create(xContext));
414 
415  xWriter->setOutputStream(xOutStream);
416 
417  rtl::Reference<StoredChapterNumberingExport> exp(new StoredChapterNumberingExport(xContext, rFileName, xWriter));
418 
419  // if style name contains a space then name != display-name
420  // ... and the import needs to map from name to display-name then!
421  std::set<OUString> charStyles;
422  std::vector<uno::Reference<container::XIndexReplace>> numRules;
423  for (size_t i = 0; i < SwChapterNumRules::nMaxRules; ++i)
424  {
425  if (SwNumRulesWithName const* pRule = rRules.GetRules(i))
426  {
427  for (size_t j = 0; j < MAXLEVEL; ++j)
428  {
429  SwNumFormat const* pDummy(nullptr);
430  OUString const* pCharStyleName(nullptr);
431  pRule->GetNumFormat(j, pDummy, pCharStyleName);
432  if (pCharStyleName && !pCharStyleName->isEmpty())
433  {
434  charStyles.insert(*pCharStyleName);
435  }
436  }
437  numRules.push_back(new StoredChapterNumberingRules(rRules, i));
438  }
439  }
440 
441  try
442  {
443  exp->ExportRules(charStyles, numRules);
444  }
445  catch (uno::Exception const&)
446  {
447  TOOLS_WARN_EXCEPTION("sw.ui", "ExportStoredChapterNumberingRules");
448  }
449 }
450 
452  SvStream & rStream, OUString const& rFileName)
453 {
454  uno::Reference<uno::XComponentContext> const xContext(
456 
457  uno::Reference<io::XInputStream> const xInStream(
458  new ::utl::OInputStreamWrapper(rStream));
459 
460  rtl::Reference<StoredChapterNumberingImport> const xImport(new StoredChapterNumberingImport(xContext, rRules));
461 
462  xml::sax::InputSource const source(xInStream, "", "", rFileName);
463 
464  try
465  {
466  xImport->parseStream(source);
467  }
468  catch (uno::Exception const&)
469  {
470  TOOLS_WARN_EXCEPTION("sw.ui", "ImportStoredChapterNumberingRules");
471  }
472 }
473 
474 } // namespace sw
475 
476 /* 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)
constexpr sal_uInt16 XML_NAMESPACE_STYLE
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)
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
static OUString getPrefixAndNameFromToken(sal_Int32 nToken)
#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:1309
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:1527
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