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/io/XActiveDataSource.hpp>
17 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
18 #include <com/sun/star/util/MeasureUnit.hpp>
19 #include <com/sun/star/xml/sax/Parser.hpp>
20 #include <com/sun/star/xml/sax/Writer.hpp>
21 
23 
24 #include <unotools/streamwrap.hxx>
25 
26 #include <xmloff/xmlnmspe.hxx>
27 #include <xmloff/xmltoken.hxx>
28 #include <xmloff/nmspmap.hxx>
29 #include <xmloff/xmlexp.hxx>
30 #include <xmloff/xmlnume.hxx>
31 #include <xmloff/xmlimp.hxx>
32 #include <xmloff/xmlictxt.hxx>
33 #include <xmloff/xmlnumi.hxx>
34 
35 #include <vcl/svapp.hxx>
36 #include <sal/log.hxx>
37 #include <tools/diagnose_ex.h>
38 
39 #include <unosett.hxx>
40 
41 
42 using namespace ::com::sun::star;
43 using namespace ::xmloff::token;
44 
45 namespace sw {
46 
48  : public ::cppu::WeakImplHelper<container::XNamed,container::XIndexReplace>
49 {
50 private:
51  // TODO in case this ever becomes accessible via API need an invalidate
53  sal_uInt16 const m_nIndex;
54 
56  {
57  SwNumRulesWithName const* pRules(m_rNumRules.GetRules(m_nIndex));
58  if (!pRules)
59  {
60  m_rNumRules.CreateEmptyNumRule(m_nIndex);
61  pRules = m_rNumRules.GetRules(m_nIndex);
62  assert(pRules);
63  }
64  return const_cast<SwNumRulesWithName*>(pRules);
65  }
66 
67 public:
69  SwChapterNumRules & rNumRules, sal_uInt16 const nIndex)
70  : m_rNumRules(rNumRules)
71  , m_nIndex(nIndex)
72  {
73  assert(m_nIndex < SwChapterNumRules::nMaxRules);
74  }
75 
76  // XNamed
77  virtual OUString SAL_CALL getName() override
78  {
80  SwNumRulesWithName const* pRules(m_rNumRules.GetRules(m_nIndex));
81  if (!pRules)
82  {
83  return OUString();
84  }
85  return pRules->GetName();
86  }
87 
88  virtual void SAL_CALL setName(OUString const& rName) override
89  {
91  SwNumRulesWithName *const pRules(GetOrCreateRules());
92  pRules->SetName(rName);
93  }
94 
95  // XElementAccess
96  virtual uno::Type SAL_CALL getElementType() override
97  {
98  return ::cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get();
99  }
100 
101  virtual ::sal_Bool SAL_CALL hasElements() override
102  {
103  return true;
104  }
105 
106  // XIndexAccess
107  virtual sal_Int32 SAL_CALL getCount() override
108  {
109  return MAXLEVEL;
110  }
111 
112  virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override
113  {
114  if (nIndex < 0 || MAXLEVEL <= nIndex)
115  throw lang::IndexOutOfBoundsException();
116 
117  SolarMutexGuard g;
118  SwNumRulesWithName const* pRules(m_rNumRules.GetRules(m_nIndex));
119  if (!pRules)
120  {
121  return uno::Any();
122  }
123  SwNumFormat const* pNumFormat(nullptr);
124  OUString const* pCharStyleName(nullptr);
125  pRules->GetNumFormat(nIndex, pNumFormat, pCharStyleName);
126  if (!pNumFormat)
127  { // the dialog only fills in those levels that are non-default
128  return uno::Any(); // the export will ignore this level, yay
129  }
130  assert(pCharStyleName);
131  OUString dummy; // pass in empty HeadingStyleName - can't import anyway
132  uno::Sequence<beans::PropertyValue> const ret(
134  *pNumFormat, *pCharStyleName, &dummy, ""));
135  return uno::makeAny(ret);
136  }
137 
138  // XIndexReplace
139  virtual void SAL_CALL replaceByIndex(
140  sal_Int32 nIndex, uno::Any const& rElement) override
141  {
142  if (nIndex < 0 || MAXLEVEL <= nIndex)
143  throw lang::IndexOutOfBoundsException();
144  uno::Sequence<beans::PropertyValue> props;
145  if (!(rElement >>= props))
146  throw lang::IllegalArgumentException("invalid type",
147  static_cast< ::cppu::OWeakObject*>(this), 1);
148 
149  SolarMutexGuard g;
150  SwNumFormat aNumberFormat;
151  OUString charStyleName;
153  aNumberFormat,
154  charStyleName,
155  nullptr, nullptr, nullptr, nullptr, nullptr,
156  props);
157  SwNumRulesWithName *const pRules(GetOrCreateRules());
158  pRules->SetNumFormat(nIndex, aNumberFormat, charStyleName);
159  }
160 };
161 
163  : public SvXMLExport
164 {
165 public:
167  uno::Reference<uno::XComponentContext> const& xContext,
168  OUString const& rFileName,
169  uno::Reference<xml::sax::XDocumentHandler> const& xHandler)
170  : SvXMLExport(xContext, "sw::StoredChapterNumberingExport", rFileName,
171  util::MeasureUnit::CM, xHandler)
172  {
174  GetXMLToken(XML_N_OFFICE), XML_NAMESPACE_OFFICE);
176  GetXMLToken(XML_N_TEXT), XML_NAMESPACE_TEXT);
178  GetXMLToken(XML_N_STYLE), XML_NAMESPACE_STYLE);
180  GetXMLToken(XML_N_FO), XML_NAMESPACE_FO);
182  GetXMLToken(XML_N_SVG), XML_NAMESPACE_SVG);
183  }
184 
185  virtual void ExportAutoStyles_() override {}
186  virtual void ExportMasterStyles_() override {}
187  virtual void ExportContent_() override {}
188 
190  uno::Reference<container::XIndexReplace> const& xRule)
191  {
192  uno::Reference<container::XNamed> const xNamed(xRule, uno::UNO_QUERY);
193  OUString const name(xNamed->getName());
194  bool bEncoded(false);
195  AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
196  EncodeStyleName(name, &bEncoded) );
197  if (bEncoded)
198  {
199  AddAttribute(XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, name);
200  }
201 
202  SvXMLElementExport aElem( *this, XML_NAMESPACE_TEXT,
203  XML_OUTLINE_STYLE, true, true );
204  rExport.exportLevelStyles(xRule, true);
205  }
206 
208  std::set<OUString> const& rCharStyles,
209  std::vector<uno::Reference<container::XIndexReplace>> const& rRules)
210  {
211  GetDocHandler()->startDocument();
212 
214  GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_OFFICE),
215  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_OFFICE));
217  GetNamespaceMap_().GetAttrNameByKey (XML_NAMESPACE_TEXT),
218  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_TEXT));
220  GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_STYLE),
221  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_STYLE));
223  GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_FO),
224  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_FO));
226  GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_SVG),
227  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_SVG));
228 
229  {
230  // let's just have an office:styles as a dummy root
232  XML_NAMESPACE_OFFICE, XML_STYLES, true, true);
233 
234  // horrible hack for char styles to get display-name mapping
235  for (const auto& rCharStyle : rCharStyles)
236  {
237  AddAttribute( XML_NAMESPACE_STYLE, XML_FAMILY, XML_TEXT );
238  bool bEncoded(false);
239  AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
240  EncodeStyleName(rCharStyle, &bEncoded) );
241  if (bEncoded)
242  {
243  AddAttribute(XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, rCharStyle);
244  }
245 
246  SvXMLElementExport style(*this,
247  XML_NAMESPACE_STYLE, XML_STYLE, true, true);
248  }
249 
250  SvxXMLNumRuleExport numRuleExport(*this);
251 
252  for (const auto& rRule : rRules)
253  {
254  ExportRule(numRuleExport, rRule);
255  }
256  }
257 
258  GetDocHandler()->endDocument();
259  }
260 };
261 
269  : public SvXMLImportContext
270 {
271 public:
273  SvXMLImport & rImport,
274  sal_uInt16 const nPrefix, OUString const& rLocalName,
275  uno::Reference<xml::sax::XAttributeList> const& xAttrList)
276  : SvXMLImportContext(rImport, nPrefix, rLocalName)
277  {
278  OUString name;
279  OUString displayName;
280  sal_uInt16 nFamily(0);
281  for (sal_Int32 i = 0; i < xAttrList->getLength(); ++i)
282  {
283  OUString localName;
284  sal_uInt16 const prefix(rImport.GetNamespaceMap().GetKeyByAttrName(
285  xAttrList->getNameByIndex(i), &localName));
286  OUString const& rValue = xAttrList->getValueByIndex(i);
287 
288  if (XML_NAMESPACE_STYLE == prefix)
289  {
290  if (IsXMLToken(localName, XML_FAMILY))
291  {
292  if (IsXMLToken(rValue, XML_TEXT))
293  {
294  nFamily = XML_STYLE_FAMILY_TEXT_TEXT;
295  }
296  }
297  else if (IsXMLToken(localName, XML_NAME))
298  {
299  name = rValue;
300  }
301  else if (IsXMLToken(localName, XML_DISPLAY_NAME))
302  {
303  displayName = rValue;
304  }
305  }
306  }
307  if (nFamily && !name.isEmpty() && !displayName.isEmpty())
308  {
309  rImport.AddStyleDisplayName(nFamily, name, displayName);
310  }
311  }
312 };
313 
314 class StoredChapterNumberingImport;
315 
317  : public SvXMLImportContext
318 {
319 private:
321  size_t m_nCounter;
322  std::vector<rtl::Reference<SvxXMLListStyleContext>> m_Contexts;
323 
324 public:
326  SwChapterNumRules & rNumRules, SvXMLImport & rImport,
327  sal_uInt16 const nPrefix, OUString const& rLocalName)
328  : SvXMLImportContext(rImport, nPrefix, rLocalName)
329  , m_rNumRules(rNumRules)
330  , m_nCounter(0)
331  {
332  }
333 
334  virtual void EndElement() override
335  {
336  assert(m_Contexts.size() < SwChapterNumRules::nMaxRules);
337  for (auto iter = m_Contexts.begin(); iter != m_Contexts.end(); ++iter)
338  {
339  uno::Reference<container::XIndexReplace> const xRule(
340  new sw::StoredChapterNumberingRules(m_rNumRules,
341  iter - m_Contexts.begin()));
342  (*iter)->FillUnoNumRule(xRule);
343  // TODO: xmloff's outline-style import seems to ignore this???
344  uno::Reference<container::XNamed> const xNamed(xRule, uno::UNO_QUERY);
345  xNamed->setName((*iter)->GetDisplayName());
346  }
347  }
348 
350  sal_uInt16 const nPrefix, OUString const& rLocalName,
351  uno::Reference<xml::sax::XAttributeList> const& xAttrList) override
352  {
353  if (XML_NAMESPACE_TEXT == nPrefix && IsXMLToken(rLocalName, XML_OUTLINE_STYLE))
354  {
355  ++m_nCounter;
356  if (m_nCounter <= SwChapterNumRules::nMaxRules)
357  {
358  SvxXMLListStyleContext *const pContext(
360  nPrefix, rLocalName, xAttrList, true));
361  m_Contexts.emplace_back(pContext);
362  return pContext;
363  }
364  }
365  else if (XML_NAMESPACE_STYLE == nPrefix && IsXMLToken(rLocalName, XML_STYLE))
366  {
368  GetImport(), nPrefix, rLocalName, xAttrList);
369  }
370 
372  nPrefix, rLocalName, xAttrList);
373  }
374 };
375 
377  : public SvXMLImport
378 {
379 private:
381 
382 public:
384  uno::Reference<uno::XComponentContext> const& xContext,
385  SwChapterNumRules & rNumRules)
386  : SvXMLImport(xContext, "sw::StoredChapterNumberingImport", SvXMLImportFlags::ALL)
387  , m_rNumRules(rNumRules)
388  {
389  }
390 
392  sal_uInt16 const nPrefix, OUString const& rLocalName,
393  uno::Reference<xml::sax::XAttributeList> const& xAttrList) override
394  {
395  if (XML_NAMESPACE_OFFICE == nPrefix && IsXMLToken(rLocalName, XML_STYLES))
396  {
397  return new StoredChapterNumberingRootContext(m_rNumRules,
398  *this, nPrefix, rLocalName);
399  }
400  return SvXMLImport::CreateDocumentContext(nPrefix, rLocalName, xAttrList);
401  }
402 };
403 
405  SvStream & rStream, OUString const& rFileName)
406 {
407  uno::Reference<uno::XComponentContext> const xContext(
409 
410  uno::Reference<io::XOutputStream> const xOutStream(
411  new ::utl::OOutputStreamWrapper(rStream));
412 
413  uno::Reference<xml::sax::XWriter> const xWriter(
414  xml::sax::Writer::create(xContext));
415 
416  xWriter->setOutputStream(xOutStream);
417 
418  rtl::Reference<StoredChapterNumberingExport> exp(new StoredChapterNumberingExport(xContext, rFileName, xWriter));
419 
420  // if style name contains a space then name != display-name
421  // ... and the import needs to map from name to display-name then!
422  std::set<OUString> charStyles;
423  std::vector<uno::Reference<container::XIndexReplace>> numRules;
424  for (size_t i = 0; i < SwChapterNumRules::nMaxRules; ++i)
425  {
426  if (SwNumRulesWithName const* pRule = rRules.GetRules(i))
427  {
428  for (size_t j = 0; j < MAXLEVEL; ++j)
429  {
430  SwNumFormat const* pDummy(nullptr);
431  OUString const* pCharStyleName(nullptr);
432  pRule->GetNumFormat(j, pDummy, pCharStyleName);
433  if (pCharStyleName && !pCharStyleName->isEmpty())
434  {
435  charStyles.insert(*pCharStyleName);
436  }
437  }
438  numRules.push_back(new StoredChapterNumberingRules(rRules, i));
439  }
440  }
441 
442  try
443  {
444  exp->ExportRules(charStyles, numRules);
445  }
446  catch (uno::Exception const&)
447  {
448  TOOLS_WARN_EXCEPTION("sw.ui", "ExportStoredChapterNumberingRules");
449  }
450 }
451 
453  SvStream & rStream, OUString const& rFileName)
454 {
455  uno::Reference<uno::XComponentContext> const xContext(
457 
458  uno::Reference<io::XInputStream> const xInStream(
459  new ::utl::OInputStreamWrapper(rStream));
460 
461  uno::Reference<xml::sax::XParser> const xParser(
462  xml::sax::Parser::create(xContext));
463 
464  uno::Reference<xml::sax::XDocumentHandler> const xHandler(
465  new StoredChapterNumberingImport(xContext, rRules));
466 
467  xParser->setDocumentHandler(xHandler);
468 
469  xml::sax::InputSource const source(xInStream, "", "", rFileName);
470 
471  try
472  {
473  xParser->parseStream(source);
474  }
475  catch (uno::Exception const&)
476  {
477  TOOLS_WARN_EXCEPTION("sw.ui", "ImportStoredChapterNumberingRules");
478  }
479 }
480 
481 } // namespace sw
482 
483 /* 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:172
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
XML_DISPLAY_NAME
XML_STYLES
XML_NP_FO
void CreateEmptyNumRule(sal_uInt16 nIdx)
Definition: uinums.cxx:93
XML_NAME
void ImportStoredChapterNumberingRules(SwChapterNumRules &rRules, SvStream &rStream, OUString const &rFileName)
SvXMLImport & GetImport()
Dummy import context for style:style element that can just read the attributes needed to map name to ...
const sal_uInt16 XML_NAMESPACE_NONE
SvXMLNamespaceMap & GetNamespaceMap()
XML_N_FO
void ExportRules(std::set< OUString > const &rCharStyles, std::vector< uno::Reference< container::XIndexReplace >> const &rRules)
Dialog to specify the properties of date form field.
void ExportStoredChapterNumberingRules(SwChapterNumRules &rRules, SvStream &rStream, OUString const &rFileName)
const css::uno::Reference< css::xml::sax::XDocumentHandler > & GetDocHandler() const
virtual SvXMLImportContext * CreateDocumentContext(sal_uInt16 const nPrefix, OUString const &rLocalName, uno::Reference< xml::sax::XAttributeList > const &xAttrList) override
sal_uInt16 GetKeyByAttrName(const OUString &rAttrName, OUString *pPrefix, OUString *pLocalName, OUString *pNamespace) const
virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override
std::vector< rtl::Reference< SvxXMLListStyleContext > > m_Contexts
void AddAttribute(sal_uInt16 nPrefix, const sal_Char *pName, const OUString &rValue)
void SetName(const OUString &rSet)
Definition: uinums.hxx:63
virtual OUString SAL_CALL getName() override
XML_STYLE
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 const nPrefix, OUString const &rLocalName, uno::Reference< xml::sax::XAttributeList > const &xAttrList) override
SvXMLImportFlags
virtual SvXMLImportContext * CreateDocumentContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList)
XML_N_STYLE
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
XML_NP_OFFICE
XML_N_TEXT
XML_N_OFFICE
StoredChapterNumberingImport(uno::Reference< uno::XComponentContext > const &xContext, SwChapterNumRules &rNumRules)
#define TOOLS_WARN_EXCEPTION(area, stream)
int i
void AddStyleDisplayName(sal_uInt16 nFamily, const OUString &rName, const OUString &rDisplayName)
XML_NP_TEXT
virtual sal_Int32 SAL_CALL getCount() override
XML_N_SVG
StoredChapterNumberingRootContext(SwChapterNumRules &rNumRules, SvXMLImport &rImport, sal_uInt16 const nPrefix, OUString const &rLocalName)
static css::uno::Sequence< css::beans::PropertyValue > GetPropertiesForNumFormat(const SwNumFormat &rFormat, OUString const &rCharFormatName, OUString const *pHeadingStyleName, OUString const &referer)
Definition: unosett.cxx:1318
XML_TEXT
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:1543
void ExportRule(SvxXMLNumRuleExport &rExport, uno::Reference< container::XIndexReplace > const &xRule)
StoredChapterNumberingRules(SwChapterNumRules &rNumRules, sal_uInt16 const nIndex)
OUString EncodeStyleName(const OUString &rName, bool *pEncoded=nullptr) const
XML_OUTLINE_STYLE
SvXMLNamespaceMap & GetNamespaceMap_()
PointerStyles const styles[]
XML_NP_STYLE
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
XML_NP_SVG
void exportLevelStyles(const css::uno::Reference< css::container::XIndexReplace > &xNumRule, bool bOutline=false)
virtual uno::Type SAL_CALL getElementType() override
sal_uInt16 Add(const OUString &rPrefix, const OUString &rName, sal_uInt16 nKey=XML_NAMESPACE_UNKNOWN)
virtual void SAL_CALL replaceByIndex(sal_Int32 nIndex, uno::Any const &rElement) override
Reference< XComponentContext > getProcessComponentContext()
const char * name
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList)
virtual void SAL_CALL setName(OUString const &rName) override
XML_FAMILY
StoredChapterNumberingDummyStyleContext(SvXMLImport &rImport, sal_uInt16 const nPrefix, OUString const &rLocalName, uno::Reference< xml::sax::XAttributeList > const &xAttrList)
StoredChapterNumberingExport(uno::Reference< uno::XComponentContext > const &xContext, OUString const &rFileName, uno::Reference< xml::sax::XDocumentHandler > const &xHandler)
#define XML_STYLE_FAMILY_TEXT_TEXT