LibreOffice Module sw (master)  1
labelcfg.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  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <memory>
21 #include <string_view>
22 #include <config_folders.h>
23 
24 #include <swtypes.hxx>
25 #include <labelcfg.hxx>
26 #include <rtl/bootstrap.hxx>
27 #include <tools/UnitConversion.hxx>
28 #include <unotools/configpaths.hxx>
29 #include <xmlreader/xmlreader.hxx>
30 #include <comphelper/sequence.hxx>
31 #include <osl/diagnose.h>
32 #include <o3tl/string_view.hxx>
33 
34 #include <com/sun/star/beans/PropertyValue.hpp>
35 
36 using namespace utl;
37 using namespace ::com::sun::star::uno;
38 using namespace ::com::sun::star::beans;
39 
41 {
42  int nsId;
45  res = reader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);
46  assert(res == xmlreader::XmlReader::Result::End);
47  (void) res;
48 }
49 
50 static OUString lcl_getValue(xmlreader::XmlReader& reader,
51  const xmlreader::Span& span)
52 {
53  int nsId;
56  res = reader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);
57  assert(res == xmlreader::XmlReader::Result::Begin && name == span);
58  res = reader.nextItem(xmlreader::XmlReader::Text::Raw, &name, &nsId);
60  (void) res; (void) span;
61  OUString sTmp = name.convertFromUtf8();
62  lcl_assertEndingItem(reader);
63  return sTmp;
64 }
65 
66 static Sequence<OUString> lcl_CreatePropertyNames(const OUString& rPrefix)
67 {
68  return { OUString::Concat(rPrefix) + "Name", OUString::Concat(rPrefix) + "Measure" };
69 }
70 
72  ConfigItem("Office.Labels/Manufacturer")
73 {
74  OUString uri("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/labels/labels.xml");
75  rtl::Bootstrap::expandMacros(uri);
76  xmlreader::XmlReader reader(uri);
77  int nsId;
80  OUString sManufacturer;
81  OUString sName;
82  OUString sMeasure;
83 
84  // fill m_aLabels and m_aManufacturers with the predefined labels
85  res = reader.nextItem(
86  xmlreader::XmlReader::Text::NONE, &name, &nsId);
87  assert(
89  && name == "manufacturers");
90  res = reader.nextItem(
91  xmlreader::XmlReader::Text::NONE, &name, &nsId);
93  {
94  // Opening manufacturer
95  assert(
97  && name == "manufacturer");
98  // Get the name
99  (void)reader.nextAttribute(&nsId, &name);
100  assert(
102  && name == "name");
103  sManufacturer = reader.getAttributeValue(false).convertFromUtf8();
104 
105  for(;;) {
106  // Opening label or ending manufacturer
107  res = reader.nextItem(
108  xmlreader::XmlReader::Text::NONE, &name, &nsId);
110  break;
111  assert(
113  && name == "label");
114  // Get name value
115  sName = lcl_getValue(reader, xmlreader::Span("name"));
116  // Get measure value
117  sMeasure = lcl_getValue(reader, xmlreader::Span("measure"));
118  // Ending label mark
119  lcl_assertEndingItem(reader);
120  if ( m_aLabels.find( sManufacturer ) == m_aLabels.end() )
121  m_aManufacturers.push_back( sManufacturer );
122  m_aLabels[sManufacturer][sName].m_aMeasure = sMeasure;
123  m_aLabels[sManufacturer][sName].m_bPredefined = true;
124  }
125  // Get next manufacturer or end
126  res = reader.nextItem(
127  xmlreader::XmlReader::Text::NONE, &name, &nsId);
128  };
129  res = reader.nextItem(
130  xmlreader::XmlReader::Text::NONE, &name, &nsId);
131  assert(res == xmlreader::XmlReader::Result::Done);
132 
133  // add to m_aLabels and m_aManufacturers the custom labels
134  const Sequence<OUString>& rMan = GetNodeNames( OUString() );
135  for ( const OUString& rManufacturer : rMan )
136  {
137  const Sequence<OUString> aLabels = GetNodeNames( rManufacturer );
138  for( const OUString& rLabel : aLabels )
139  {
140  OUString sPrefix = rManufacturer + "/" + rLabel + "/";
142  Sequence<Any> aValues = GetProperties( aPropNames );
143  const Any* pValues = aValues.getConstArray();
144  if (aValues.getLength() >= 1)
145  if(pValues[0].hasValue())
146  pValues[0] >>= sName;
147  if (aValues.getLength() >= 2)
148  if(pValues[1].hasValue())
149  pValues[1] >>= sMeasure;
150  if ( m_aLabels.find( rManufacturer ) == m_aLabels.end() )
151  m_aManufacturers.push_back( rManufacturer );
152  m_aLabels[rManufacturer][sName].m_aMeasure = sMeasure;
153  m_aLabels[rManufacturer][sName].m_bPredefined = false;
154  }
155  }
156 }
157 
159 {
160 }
161 
162 // the config item is not writable ?:
164 
165 void SwLabelConfig::Notify( const css::uno::Sequence< OUString >& ) {}
166 
167 static std::unique_ptr<SwLabRec> lcl_CreateSwLabRec(const OUString& rType, std::u16string_view rMeasure, const OUString& rManufacturer)
168 {
169  std::unique_ptr<SwLabRec> pNewRec(new SwLabRec);
170  pNewRec->m_aMake = rManufacturer;
171  pNewRec->m_nPWidth = 0;
172  pNewRec->m_nPHeight = 0;
173  pNewRec->m_aType = rType;
174  //all values are contained as colon-separated 1/100 mm values
175  //except for the continuous flag ('C'/'S') and nCols, nRows (sal_Int32)
176  sal_Int32 nTok{0};
177  sal_Int32 nIdx{rMeasure.empty() ? -1 : 0};
178  while (nIdx>=0)
179  {
180  const std::u16string_view sToken(o3tl::getToken(rMeasure, 0, ';', nIdx));
181  int nVal = o3tl::toInt32(sToken);
182  switch(nTok++)
183  {
184  case 0 : pNewRec->m_bCont = sToken[0] == 'C'; break;
185  case 1 : pNewRec->m_nHDist = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
186  case 2 : pNewRec->m_nVDist = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
187  case 3 : pNewRec->m_nWidth = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
188  case 4 : pNewRec->m_nHeight = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
189  case 5 : pNewRec->m_nLeft = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
190  case 6 : pNewRec->m_nUpper = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
191  case 7 : pNewRec->m_nCols = nVal; break;
192  case 8 : pNewRec->m_nRows = nVal; break;
193  case 9 : pNewRec->m_nPWidth = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
194  case 10 : pNewRec->m_nPHeight = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
195  }
196  }
197  // lines added for compatibility with custom label definitions saved before patch fdo#44516
198  if (pNewRec->m_nPWidth == 0 || pNewRec->m_nPHeight == 0)
199  {
200  // old style definition (no paper dimensions), calculate probable values
201  pNewRec->m_nPWidth = 2 * pNewRec->m_nLeft + (pNewRec->m_nCols - 1) * pNewRec->m_nHDist + pNewRec->m_nWidth;
202  pNewRec->m_nPHeight = ( pNewRec->m_bCont ? pNewRec->m_nRows * pNewRec->m_nVDist : 2 * pNewRec->m_nUpper + (pNewRec->m_nRows - 1) * pNewRec->m_nVDist + pNewRec->m_nHeight );
203  }
204  return pNewRec;
205 }
206 
207 static Sequence<PropertyValue> lcl_CreateProperties(
208  Sequence<OUString> const & rPropNames, OUString& rMeasure, const SwLabRec& rRec)
209 {
210  const OUString* pNames = rPropNames.getConstArray();
211  Sequence<PropertyValue> aRet(rPropNames.getLength());
212  PropertyValue* pValues = aRet.getArray();
213  OUString sColon(";");
214 
215  for(sal_Int32 nProp = 0; nProp < rPropNames.getLength(); nProp++)
216  {
217  pValues[nProp].Name = pNames[nProp];
218  switch(nProp)
219  {
220  case 0: pValues[nProp].Value <<= rRec.m_aType; break;
221  case 1:
222  {
223  rMeasure.clear();
224  rMeasure += rRec.m_bCont ? std::u16string_view( u"C" ) : std::u16string_view( u"S" ); rMeasure += sColon;
225  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nHDist ) ); rMeasure += sColon;
226  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nVDist ) ); rMeasure += sColon;
227  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nWidth ) ); rMeasure += sColon;
228  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nHeight ) ); rMeasure += sColon;
229  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nLeft ) ); rMeasure += sColon;
230  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nUpper ) ); rMeasure += sColon;
231  rMeasure += OUString::number( rRec.m_nCols ); rMeasure += sColon;
232  rMeasure += OUString::number( rRec.m_nRows ); rMeasure += sColon;
233  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nPWidth ) ); rMeasure += sColon;
234  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nPHeight ) );
235  pValues[nProp].Value <<= rMeasure;
236  }
237  break;
238  }
239  }
240  return aRet;
241 }
242 
243 // function fills SwLabDlg with label definitions for manufacturer rManufacturer
244 void SwLabelConfig::FillLabels(const OUString& rManufacturer, SwLabRecs& rLabArr)
245 {
246  if (m_aLabels.find(rManufacturer) == m_aLabels.end())
247  return;
248  for (const auto& rEntry : m_aLabels[rManufacturer])
249  rLabArr.push_back( lcl_CreateSwLabRec(rEntry.first, rEntry.second.m_aMeasure, rManufacturer) );
250 }
251 
252 bool SwLabelConfig::HasLabel(const OUString& rManufacturer, const OUString& rType)
253 {
254  return ( ( m_aLabels.find(rManufacturer) != m_aLabels.end() ) &&
255  ( m_aLabels[rManufacturer].find(rType) != m_aLabels[rManufacturer].end() ) );
256 }
257 
258 // label is always saved as a custom label
259 // predefined labels can NOT be overwritten by custom labels with same manufacturer/name
260 void SwLabelConfig::SaveLabel( const OUString& rManufacturer,
261  const OUString& rType, const SwLabRec& rRec )
262 {
263  OUString sFoundNode;
264  bool bManufacturerNodeFound;
265  if ( m_aLabels.find( rManufacturer ) == m_aLabels.end() ||
266  !GetNodeNames( rManufacturer ).hasElements() )
267  {
268  bManufacturerNodeFound = false;
269  // manufacturer node does not exist, add (and also to m_aManufacturers)
270  if ( !AddNode( OUString(), rManufacturer ) )
271  {
272  OSL_FAIL("New configuration node could not be created");
273  return ;
274  }
275  m_aManufacturers.push_back( rManufacturer );
276  }
277  else
278  bManufacturerNodeFound = true;
279 
280  if ( !bManufacturerNodeFound ||
281  m_aLabels[rManufacturer].find( rType ) == m_aLabels[rManufacturer].end() )
282  {
283  // type does not yet exist, add to config
284  const Sequence<OUString> aLabels = GetNodeNames( rManufacturer );
285  sal_Int32 nIndex = aLabels.getLength();
286  OUString sPrefix( "Label" );
287  sFoundNode = sPrefix + OUString::number( nIndex );
288  while ( comphelper::findValue(aLabels, sFoundNode) != -1 )
289  {
290  sFoundNode = sPrefix + OUString::number(nIndex++);
291  }
292  }
293  else
294  {
295  // get the appropriate node
296  OUString sManufacturer( wrapConfigurationElementName( rManufacturer ) );
297  const Sequence<OUString> aLabels = GetNodeNames( sManufacturer );
298  for (const OUString& rLabel : aLabels)
299  {
300  OUString sPrefix = sManufacturer + "/" + rLabel + "/";
301  Sequence<OUString> aProperties { sPrefix };
302  aProperties.getArray()[0] += "Name";
303  Sequence<Any> aValues = GetProperties( aProperties );
304  const Any* pValues = aValues.getConstArray();
305  if ( pValues[0].hasValue() )
306  {
307  OUString sTmp;
308  pValues[0] >>= sTmp;
309  if ( rType == sTmp )
310  {
311  sFoundNode = rLabel;
312  break;
313  }
314  }
315  }
316  }
317 
318  OUString sPrefix = wrapConfigurationElementName( rManufacturer ) +
319  "/" + sFoundNode + "/";
321  OUString sMeasure;
322  Sequence<PropertyValue> aPropValues = lcl_CreateProperties( aPropNames, sMeasure, rRec );
323  SetSetProperties( wrapConfigurationElementName( rManufacturer ), aPropValues );
324 
325  //update m_aLabels
326  m_aLabels[rManufacturer][rType].m_aMeasure = sMeasure;
327  m_aLabels[rManufacturer][rType].m_bPredefined = false;
328 }
329 
330 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static std::unique_ptr< SwLabRec > lcl_CreateSwLabRec(const OUString &rType, std::u16string_view rMeasure, const OUString &rManufacturer)
Definition: labelcfg.cxx:167
sal_Int32 nIndex
static bool SetSetProperties(css::uno::Reference< css::container::XHierarchicalNameAccess > const &xHierarchyAccess, const OUString &rNode, const css::uno::Sequence< css::beans::PropertyValue > &rValues)
static css::uno::Sequence< OUString > GetNodeNames(css::uno::Reference< css::container::XHierarchicalNameAccess > const &xHierarchyAccess, const OUString &rNode, ConfigNameFormat eFormat)
sal_Int32 m_nRows
Definition: labrec.hxx:50
constexpr auto toTwips(N number, Length from)
sal_Int32 findValue(const css::uno::Sequence< T1 > &_rList, const T2 &_rValue)
tools::Long m_nPWidth
Definition: labrec.hxx:47
bool HasLabel(const OUString &rManufacturer, const OUString &rType)
Definition: labelcfg.cxx:252
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
tools::Long m_nHDist
Definition: labrec.hxx:41
virtual void Notify(const css::uno::Sequence< OUString > &aPropertyNames) override
Definition: labelcfg.cxx:165
std::vector< OUString > m_aManufacturers
Definition: labelcfg.hxx:38
static void lcl_assertEndingItem(xmlreader::XmlReader &reader)
Definition: labelcfg.cxx:40
constexpr auto convertTwipToMm100(N n)
std::map< OUString, std::map< OUString, SwLabelMeasure > > m_aLabels
Definition: labelcfg.hxx:39
OSQLColumns::const_iterator find(const OSQLColumns::const_iterator &first, const OSQLColumns::const_iterator &last, std::u16string_view _rVal, const ::comphelper::UStringMixEqual &_rCase)
constexpr OStringLiteral sColon
PropertiesInfo aProperties
bool m_bCont
Definition: labrec.hxx:51
tools::Long m_nPHeight
Definition: labrec.hxx:48
virtual void ImplCommit() override
Definition: labelcfg.cxx:163
const char * sName
static css::uno::Sequence< css::uno::Any > GetProperties(css::uno::Reference< css::container::XHierarchicalNameAccess > const &xHierarchyAccess, const css::uno::Sequence< OUString > &rNames, bool bAllLocales)
static Sequence< OUString > lcl_CreatePropertyNames(const OUString &rPrefix)
Definition: labelcfg.cxx:66
tools::Long m_nHeight
Definition: labrec.hxx:44
tools::Long m_nUpper
Definition: labrec.hxx:46
float u
const PropertyStruct aPropNames[]
static Sequence< PropertyValue > lcl_CreateProperties(Sequence< OUString > const &rPropNames, OUString &rMeasure, const SwLabRec &rRec)
Definition: labelcfg.cxx:207
OUString wrapConfigurationElementName(std::u16string_view _sElementName)
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
OUString sPrefix
static OUString lcl_getValue(xmlreader::XmlReader &reader, const xmlreader::Span &span)
Definition: labelcfg.cxx:50
void FillLabels(const OUString &rManufacturer, SwLabRecs &rLabArr)
Definition: labelcfg.cxx:244
enumrange< T >::Iterator end(enumrange< T >)
sal_Int32 m_nCols
Definition: labrec.hxx:49
OUString m_aType
Definition: labrec.hxx:40
tools::Long m_nVDist
Definition: labrec.hxx:42
const PropertyValue * pValues
bool AddNode(const OUString &rNode, const OUString &rNewNode)
tools::Long m_nWidth
Definition: labrec.hxx:43
Span getAttributeValue(bool fullyNormalize)
rtl::OUString convertFromUtf8() const
const char * name
tools::Long m_nLeft
Definition: labrec.hxx:45
std::vector< std::unique_ptr< SwLabRec > > SwLabRecs
Definition: labrec.hxx:54
void SaveLabel(const OUString &rManufacturer, const OUString &rType, const SwLabRec &rRec)
Definition: labelcfg.cxx:260
bool nextAttribute(int *nsId, Span *localName)
Result nextItem(Text reportText, Span *data, int *nsId)
virtual ~SwLabelConfig() override
Definition: labelcfg.cxx:158
exports com.sun.star. uri
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo