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 
38 #include <unosett.hxx>
39 
40 
41 using namespace ::com::sun::star;
42 using namespace ::xmloff::token;
43 
44 namespace sw {
45 
47  : public ::cppu::WeakImplHelper<container::XNamed,container::XIndexReplace>
48 {
49 private:
50  // TODO in case this ever becomes accessible via api need a invalidate
52  sal_uInt16 const m_nIndex;
53 
55  {
56  SwNumRulesWithName const* pRules(m_rNumRules.GetRules(m_nIndex));
57  if (!pRules)
58  {
59  m_rNumRules.CreateEmptyNumRule(m_nIndex);
60  pRules = m_rNumRules.GetRules(m_nIndex);
61  assert(pRules);
62  }
63  return const_cast<SwNumRulesWithName*>(pRules);
64  }
65 
66 public:
68  SwChapterNumRules & rNumRules, sal_uInt16 const nIndex)
69  : m_rNumRules(rNumRules)
70  , m_nIndex(nIndex)
71  {
72  assert(m_nIndex < SwChapterNumRules::nMaxRules);
73  }
74 
75  // XNamed
76  virtual OUString SAL_CALL getName() override
77  {
79  SwNumRulesWithName const* pRules(m_rNumRules.GetRules(m_nIndex));
80  if (!pRules)
81  {
82  return OUString();
83  }
84  return pRules->GetName();
85  }
86 
87  virtual void SAL_CALL setName(OUString const& rName) override
88  {
90  SwNumRulesWithName *const pRules(GetOrCreateRules());
91  pRules->SetName(rName);
92  }
93 
94  // XElementAccess
95  virtual uno::Type SAL_CALL getElementType() override
96  {
97  return ::cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get();
98  }
99 
100  virtual ::sal_Bool SAL_CALL hasElements() override
101  {
102  return true;
103  }
104 
105  // XIndexAccess
106  virtual sal_Int32 SAL_CALL getCount() override
107  {
108  return MAXLEVEL;
109  }
110 
111  virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex) override
112  {
113  if (nIndex < 0 || MAXLEVEL <= nIndex)
114  throw lang::IndexOutOfBoundsException();
115 
116  SolarMutexGuard g;
117  SwNumRulesWithName const* pRules(m_rNumRules.GetRules(m_nIndex));
118  if (!pRules)
119  {
120  return uno::Any();
121  }
122  SwNumFormat const* pNumFormat(nullptr);
123  OUString const* pCharStyleName(nullptr);
124  pRules->GetNumFormat(nIndex, pNumFormat, pCharStyleName);
125  if (!pNumFormat)
126  { // the dialog only fills in those levels that are non-default
127  return uno::Any(); // the export will ignore this level, yay
128  }
129  assert(pCharStyleName);
130  OUString dummy; // pass in empty HeadingStyleName - can't import anyway
131  uno::Sequence<beans::PropertyValue> const ret(
133  *pNumFormat, *pCharStyleName, &dummy, ""));
134  return uno::makeAny(ret);
135  }
136 
137  // XIndexReplace
138  virtual void SAL_CALL replaceByIndex(
139  sal_Int32 nIndex, uno::Any const& rElement) override
140  {
141  if (nIndex < 0 || MAXLEVEL <= nIndex)
142  throw lang::IndexOutOfBoundsException();
143  uno::Sequence<beans::PropertyValue> props;
144  if (!(rElement >>= props))
145  throw lang::IllegalArgumentException("invalid type",
146  static_cast< ::cppu::OWeakObject*>(this), 1);
147 
148  SolarMutexGuard g;
149  SwNumFormat aNumberFormat;
150  OUString charStyleName;
152  aNumberFormat,
153  charStyleName,
154  nullptr, nullptr, nullptr, nullptr, nullptr,
155  props);
156  SwNumRulesWithName *const pRules(GetOrCreateRules());
157  pRules->SetNumFormat(nIndex, aNumberFormat, charStyleName);
158  }
159 };
160 
162  : public SvXMLExport
163 {
164 public:
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  {
173  GetXMLToken(XML_N_OFFICE), XML_NAMESPACE_OFFICE);
175  GetXMLToken(XML_N_TEXT), XML_NAMESPACE_TEXT);
177  GetXMLToken(XML_N_STYLE), XML_NAMESPACE_STYLE);
179  GetXMLToken(XML_N_FO), XML_NAMESPACE_FO);
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 
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 
207  std::set<OUString> const& rCharStyles,
208  std::vector<uno::Reference<container::XIndexReplace>> const& rRules)
209  {
210  GetDocHandler()->startDocument();
211 
213  GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_OFFICE),
214  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_OFFICE));
216  GetNamespaceMap_().GetAttrNameByKey (XML_NAMESPACE_TEXT),
217  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_TEXT));
219  GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_STYLE),
220  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_STYLE));
222  GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_FO),
223  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_FO));
225  GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_SVG),
226  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_SVG));
227 
228  {
229  // let's just have a 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 
268  : public SvXMLImportContext
269 {
270 public:
272  SvXMLImport & rImport,
273  sal_uInt16 const nPrefix, OUString const& rLocalName,
274  uno::Reference<xml::sax::XAttributeList> const& xAttrList)
275  : SvXMLImportContext(rImport, nPrefix, rLocalName)
276  {
277  OUString name;
278  OUString displayName;
279  sal_uInt16 nFamily(0);
280  for (sal_Int32 i = 0; i < xAttrList->getLength(); ++i)
281  {
282  OUString localName;
283  sal_uInt16 const prefix(rImport.GetNamespaceMap().GetKeyByAttrName(
284  xAttrList->getNameByIndex(i), &localName));
285  OUString const& rValue = xAttrList->getValueByIndex(i);
286 
287  if (XML_NAMESPACE_STYLE == prefix)
288  {
289  if (IsXMLToken(localName, XML_FAMILY))
290  {
291  if (IsXMLToken(rValue, XML_TEXT))
292  {
293  nFamily = XML_STYLE_FAMILY_TEXT_TEXT;
294  }
295  }
296  else if (IsXMLToken(localName, XML_NAME))
297  {
298  name = rValue;
299  }
300  else if (IsXMLToken(localName, XML_DISPLAY_NAME))
301  {
302  displayName = rValue;
303  }
304  }
305  }
306  if (nFamily && !name.isEmpty() && !displayName.isEmpty())
307  {
308  rImport.AddStyleDisplayName(nFamily, name, displayName);
309  }
310  }
311 };
312 
313 class StoredChapterNumberingImport;
314 
316  : public SvXMLImportContext
317 {
318 private:
320  size_t m_nCounter;
321  std::vector<rtl::Reference<SvxXMLListStyleContext>> m_Contexts;
322 
323 public:
325  SwChapterNumRules & rNumRules, SvXMLImport & rImport,
326  sal_uInt16 const nPrefix, OUString const& rLocalName)
327  : SvXMLImportContext(rImport, nPrefix, rLocalName)
328  , m_rNumRules(rNumRules)
329  , m_nCounter(0)
330  {
331  }
332 
333  virtual void EndElement() override
334  {
335  assert(m_Contexts.size() < SwChapterNumRules::nMaxRules);
336  for (auto iter = m_Contexts.begin(); iter != m_Contexts.end(); ++iter)
337  {
338  uno::Reference<container::XIndexReplace> const xRule(
339  new sw::StoredChapterNumberingRules(m_rNumRules,
340  iter - m_Contexts.begin()));
341  (*iter)->FillUnoNumRule(xRule);
342  // TODO: xmloff's outline-style import seems to ignore this???
343  uno::Reference<container::XNamed> const xNamed(xRule, uno::UNO_QUERY);
344  xNamed->setName((*iter)->GetDisplayName());
345  }
346  }
347 
349  sal_uInt16 const nPrefix, OUString const& rLocalName,
350  uno::Reference<xml::sax::XAttributeList> const& xAttrList) override
351  {
352  if (XML_NAMESPACE_TEXT == nPrefix && IsXMLToken(rLocalName, XML_OUTLINE_STYLE))
353  {
354  ++m_nCounter;
355  if (m_nCounter <= SwChapterNumRules::nMaxRules)
356  {
357  SvxXMLListStyleContext *const pContext(
359  nPrefix, rLocalName, xAttrList, true));
360  m_Contexts.emplace_back(pContext);
361  return pContext;
362  }
363  }
364  else if (XML_NAMESPACE_STYLE == nPrefix && IsXMLToken(rLocalName, XML_STYLE))
365  {
367  GetImport(), nPrefix, rLocalName, xAttrList);
368  }
369 
371  nPrefix, rLocalName, xAttrList);
372  }
373 };
374 
376  : public SvXMLImport
377 {
378 private:
380 
381 public:
383  uno::Reference<uno::XComponentContext> const& xContext,
384  SwChapterNumRules & rNumRules)
385  : SvXMLImport(xContext, "sw::StoredChapterNumberingImport", SvXMLImportFlags::ALL)
386  , m_rNumRules(rNumRules)
387  {
388  }
389 
391  sal_uInt16 const nPrefix, OUString const& rLocalName,
392  uno::Reference<xml::sax::XAttributeList> const& xAttrList) override
393  {
394  if (XML_NAMESPACE_OFFICE == nPrefix && IsXMLToken(rLocalName, XML_STYLES))
395  {
396  return new StoredChapterNumberingRootContext(m_rNumRules,
397  *this, nPrefix, rLocalName);
398  }
399  return SvXMLImport::CreateDocumentContext(nPrefix, rLocalName, xAttrList);
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  uno::Reference<io::XActiveDataSource> const xADS(xWriter, uno::UNO_QUERY);
416  xADS->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& e)
447  {
448  SAL_WARN("sw.ui", "ExportStoredChapterNumberingRules: " << e);
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& e)
476  {
477  SAL_WARN("sw.ui", "ImportStoredChapterNumberingRules: " << e);
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:178
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 drop-down form field.
Definition: accfrmobj.cxx:40
void ExportStoredChapterNumberingRules(SwChapterNumRules &rRules, SvStream &rStream, OUString const &rFileName)
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
const css::uno::Reference< css::xml::sax::XDocumentHandler > & GetDocHandler()
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)
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)
OString const name
static css::uno::Sequence< css::beans::PropertyValue > GetPropertiesForNumFormat(const SwNumFormat &rFormat, OUString const &rCharFormatName, OUString const *pHeadingStyleName, OUString const &referer)
Definition: unosett.cxx:1319
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:1544
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()
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList)
#define SAL_WARN(area, stream)
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