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/Writer.hpp>
20 
22 
23 #include <unotools/streamwrap.hxx>
24 
25 #include <xmloff/xmlnmspe.hxx>
26 #include <xmloff/xmltoken.hxx>
27 #include <xmloff/nmspmap.hxx>
28 #include <xmloff/xmlexp.hxx>
29 #include <xmloff/xmlnume.hxx>
30 #include <xmloff/xmlimp.hxx>
31 #include <xmloff/xmlictxt.hxx>
32 #include <xmloff/xmlnumi.hxx>
33 
34 #include <vcl/svapp.hxx>
35 #include <sal/log.hxx>
36 #include <tools/diagnose_ex.h>
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 an 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 
161 namespace {
162 
163 class StoredChapterNumberingExport
164  : public SvXMLExport
165 {
166 public:
167  StoredChapterNumberingExport(
168  uno::Reference<uno::XComponentContext> const& xContext,
169  OUString const& rFileName,
170  uno::Reference<xml::sax::XDocumentHandler> const& xHandler)
171  : SvXMLExport(xContext, "sw::StoredChapterNumberingExport", rFileName,
172  util::MeasureUnit::CM, xHandler)
173  {
174  GetNamespaceMap_().Add(GetXMLToken(XML_NP_OFFICE),
175  GetXMLToken(XML_N_OFFICE), XML_NAMESPACE_OFFICE);
176  GetNamespaceMap_().Add(GetXMLToken(XML_NP_TEXT),
177  GetXMLToken(XML_N_TEXT), XML_NAMESPACE_TEXT);
178  GetNamespaceMap_().Add(GetXMLToken(XML_NP_STYLE),
179  GetXMLToken(XML_N_STYLE), XML_NAMESPACE_STYLE);
180  GetNamespaceMap_().Add(GetXMLToken(XML_NP_FO),
181  GetXMLToken(XML_N_FO), XML_NAMESPACE_FO);
182  GetNamespaceMap_().Add(GetXMLToken(XML_NP_SVG),
183  GetXMLToken(XML_N_SVG), XML_NAMESPACE_SVG);
184  }
185 
186  virtual void ExportAutoStyles_() override {}
187  virtual void ExportMasterStyles_() override {}
188  virtual void ExportContent_() override {}
189 
190  void ExportRule(SvxXMLNumRuleExport & rExport,
191  uno::Reference<container::XIndexReplace> const& xRule)
192  {
193  uno::Reference<container::XNamed> const xNamed(xRule, uno::UNO_QUERY);
194  OUString const name(xNamed->getName());
195  bool bEncoded(false);
196  AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
197  EncodeStyleName(name, &bEncoded) );
198  if (bEncoded)
199  {
200  AddAttribute(XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, name);
201  }
202 
203  SvXMLElementExport aElem( *this, XML_NAMESPACE_TEXT,
204  XML_OUTLINE_STYLE, true, true );
205  rExport.exportLevelStyles(xRule, true);
206  }
207 
208  void ExportRules(
209  std::set<OUString> const& rCharStyles,
210  std::vector<uno::Reference<container::XIndexReplace>> const& rRules)
211  {
212  GetDocHandler()->startDocument();
213 
214  AddAttribute(XML_NAMESPACE_NONE,
215  GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_OFFICE),
216  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_OFFICE));
217  AddAttribute(XML_NAMESPACE_NONE,
218  GetNamespaceMap_().GetAttrNameByKey (XML_NAMESPACE_TEXT),
219  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_TEXT));
220  AddAttribute(XML_NAMESPACE_NONE,
221  GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_STYLE),
222  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_STYLE));
223  AddAttribute(XML_NAMESPACE_NONE,
224  GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_FO),
225  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_FO));
226  AddAttribute(XML_NAMESPACE_NONE,
227  GetNamespaceMap_().GetAttrNameByKey(XML_NAMESPACE_SVG),
228  GetNamespaceMap_().GetNameByKey(XML_NAMESPACE_SVG));
229 
230  {
231  // let's just have an office:styles as a dummy root
233  XML_NAMESPACE_OFFICE, XML_STYLES, true, true);
234 
235  // horrible hack for char styles to get display-name mapping
236  for (const auto& rCharStyle : rCharStyles)
237  {
238  AddAttribute( XML_NAMESPACE_STYLE, XML_FAMILY, XML_TEXT );
239  bool bEncoded(false);
240  AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
241  EncodeStyleName(rCharStyle, &bEncoded) );
242  if (bEncoded)
243  {
244  AddAttribute(XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, rCharStyle);
245  }
246 
247  SvXMLElementExport style(*this,
248  XML_NAMESPACE_STYLE, XML_STYLE, true, true);
249  }
250 
251  SvxXMLNumRuleExport numRuleExport(*this);
252 
253  for (const auto& rRule : rRules)
254  {
255  ExportRule(numRuleExport, rRule);
256  }
257  }
258 
259  GetDocHandler()->endDocument();
260  }
261 };
262 
269 class StoredChapterNumberingDummyStyleContext
270  : public SvXMLImportContext
271 {
272 public:
273  StoredChapterNumberingDummyStyleContext(
274  SvXMLImport & rImport,
275  uno::Reference<xml::sax::XFastAttributeList> const& xAttrList)
276  : SvXMLImportContext(rImport)
277  {
278  OUString name;
279  OUString displayName;
280  sal_uInt16 nFamily(0);
281 
282  sax_fastparser::FastAttributeList *pAttribList =
284 
285  for (auto &aIter : *pAttribList)
286  if (aIter.getToken() == (XML_NAMESPACE_STYLE | XML_FAMILY))
287  {
288  if (IsXMLToken(aIter.toString(), XML_TEXT))
289  nFamily = XML_STYLE_FAMILY_TEXT_TEXT;
290  else if (IsXMLToken(aIter.toString(), XML_NAME))
291  name = aIter.toString();
292  else if (IsXMLToken(aIter.toString(), XML_DISPLAY_NAME))
293  displayName = aIter.toString();
294  }
295 
296  if (nFamily && !name.isEmpty() && !displayName.isEmpty())
297  {
298  rImport.AddStyleDisplayName(nFamily, name, displayName);
299  }
300  }
301 };
302 
303 class StoredChapterNumberingImport;
304 
305 class StoredChapterNumberingRootContext
306  : public SvXMLImportContext
307 {
308 private:
309  SwChapterNumRules & m_rNumRules;
310  size_t m_nCounter;
311  std::vector<rtl::Reference<SvxXMLListStyleContext>> m_Contexts;
312 
313 public:
314  StoredChapterNumberingRootContext(
315  SwChapterNumRules & rNumRules, SvXMLImport & rImport)
316  : SvXMLImportContext(rImport)
317  , m_rNumRules(rNumRules)
318  , m_nCounter(0)
319  {
320  }
321 
322  virtual void SAL_CALL endFastElement(sal_Int32 /*Element*/) override
323  {
324  assert(m_Contexts.size() < SwChapterNumRules::nMaxRules);
325  for (auto iter = m_Contexts.begin(); iter != m_Contexts.end(); ++iter)
326  {
327  uno::Reference<container::XIndexReplace> const xRule(
328  new sw::StoredChapterNumberingRules(m_rNumRules,
329  iter - m_Contexts.begin()));
330  (*iter)->FillUnoNumRule(xRule);
331  // TODO: xmloff's outline-style import seems to ignore this???
332  uno::Reference<container::XNamed> const xNamed(xRule, uno::UNO_QUERY);
333  xNamed->setName((*iter)->GetDisplayName());
334  }
335  }
336 
337  virtual css::uno::Reference<XFastContextHandler> SAL_CALL createFastChildContext(
338  sal_Int32 Element,
339  const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override
340  {
341  if (Element == XML_ELEMENT(TEXT, XML_OUTLINE_STYLE))
342  {
343  ++m_nCounter;
344  if (m_nCounter <= SwChapterNumRules::nMaxRules)
345  {
346  SvxXMLListStyleContext *const pContext(
347  new SvxXMLListStyleContext(GetImport(), Element, xAttrList, true));
348  m_Contexts.emplace_back(pContext);
349  return pContext;
350  }
351  }
352  else if (Element == XML_ELEMENT(STYLE, XML_STYLE))
353  {
354  return new StoredChapterNumberingDummyStyleContext(GetImport(), xAttrList);
355  }
356 
357  return SvXMLImportContext::createFastChildContext(Element, xAttrList);
358  }
359 };
360 
361 class StoredChapterNumberingImport
362  : public SvXMLImport
363 {
364 private:
365  SwChapterNumRules & m_rNumRules;
366 
367 public:
368  StoredChapterNumberingImport(
369  uno::Reference<uno::XComponentContext> const& xContext,
370  SwChapterNumRules & rNumRules)
371  : SvXMLImport(xContext, "sw::StoredChapterNumberingImport", SvXMLImportFlags::ALL)
372  , m_rNumRules(rNumRules)
373  {
374  }
375 
376  virtual SvXMLImportContext *CreateFastContext( sal_Int32 Element,
377  const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override
378  {
379  if (Element == XML_ELEMENT(OFFICE, XML_STYLES))
380  {
381  return new StoredChapterNumberingRootContext(m_rNumRules, *this);
382  }
383  return SvXMLImport::CreateFastContext(Element, xAttrList);
384  }
385 };
386 
387 }
388 
390  SvStream & rStream, OUString const& rFileName)
391 {
392  uno::Reference<uno::XComponentContext> const xContext(
394 
395  uno::Reference<io::XOutputStream> const xOutStream(
396  new ::utl::OOutputStreamWrapper(rStream));
397 
398  uno::Reference<xml::sax::XWriter> const xWriter(
399  xml::sax::Writer::create(xContext));
400 
401  xWriter->setOutputStream(xOutStream);
402 
403  rtl::Reference<StoredChapterNumberingExport> exp(new StoredChapterNumberingExport(xContext, rFileName, xWriter));
404 
405  // if style name contains a space then name != display-name
406  // ... and the import needs to map from name to display-name then!
407  std::set<OUString> charStyles;
408  std::vector<uno::Reference<container::XIndexReplace>> numRules;
409  for (size_t i = 0; i < SwChapterNumRules::nMaxRules; ++i)
410  {
411  if (SwNumRulesWithName const* pRule = rRules.GetRules(i))
412  {
413  for (size_t j = 0; j < MAXLEVEL; ++j)
414  {
415  SwNumFormat const* pDummy(nullptr);
416  OUString const* pCharStyleName(nullptr);
417  pRule->GetNumFormat(j, pDummy, pCharStyleName);
418  if (pCharStyleName && !pCharStyleName->isEmpty())
419  {
420  charStyles.insert(*pCharStyleName);
421  }
422  }
423  numRules.push_back(new StoredChapterNumberingRules(rRules, i));
424  }
425  }
426 
427  try
428  {
429  exp->ExportRules(charStyles, numRules);
430  }
431  catch (uno::Exception const&)
432  {
433  TOOLS_WARN_EXCEPTION("sw.ui", "ExportStoredChapterNumberingRules");
434  }
435 }
436 
438  SvStream & rStream, OUString const& rFileName)
439 {
440  uno::Reference<uno::XComponentContext> const xContext(
442 
443  uno::Reference<io::XInputStream> const xInStream(
444  new ::utl::OInputStreamWrapper(rStream));
445 
446  rtl::Reference<StoredChapterNumberingImport> const xImport(new StoredChapterNumberingImport(xContext, rRules));
447 
448  xml::sax::InputSource const source(xInStream, "", "", rFileName);
449 
450  try
451  {
452  xImport->parseStream(source);
453  }
454  catch (uno::Exception const&)
455  {
456  TOOLS_WARN_EXCEPTION("sw.ui", "ImportStoredChapterNumberingRules");
457  }
458 }
459 
460 } // namespace sw
461 
462 /* 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
void CreateEmptyNumRule(sal_uInt16 nIdx)
Definition: uinums.cxx:93
XML_NAME
void ImportStoredChapterNumberingRules(SwChapterNumRules &rRules, SvStream &rStream, OUString const &rFileName)
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
virtual OUString SAL_CALL getName() override
SvXMLImportFlags
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)
sal_Int32 & m_nCounter
int i
void AddStyleDisplayName(sal_uInt16 nFamily, const OUString &rName, const OUString &rDisplayName)
static FastAttributeList * castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
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:1311
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:1536
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)
virtual uno::Type SAL_CALL getElementType() override
virtual css::uno::Reference< XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual SvXMLImportContext * CreateFastContext(sal_Int32 Element, const ::css::uno::Reference< ::css::xml::sax::XFastAttributeList > &xAttrList)
#define XML_ELEMENT(prefix, name)
virtual void SAL_CALL replaceByIndex(sal_Int32 nIndex, uno::Any const &rElement) override
Reference< XComponentContext > getProcessComponentContext()
const char * name
virtual void SAL_CALL setName(OUString const &rName) override
XML_FAMILY
#define XML_STYLE_FAMILY_TEXT_TEXT