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 <config_folders.h>
22 
23 #include <swtypes.hxx>
24 #include <labelcfg.hxx>
25 #include <labimp.hxx>
26 #include <rtl/bootstrap.hxx>
27 #include <unotools/configpaths.hxx>
28 #include <xmlreader/xmlreader.hxx>
29 #include <comphelper/sequence.hxx>
30 #include <osl/diagnose.h>
31 
32 #include <com/sun/star/beans/PropertyValue.hpp>
33 
34 #include <unomid.h>
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.equals(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  Sequence<OUString> aProperties(2);
69  OUString* pProperties = aProperties.getArray();
70  std::fill(aProperties.begin(), aProperties.end(), rPrefix);
71 
72  pProperties[ 0] += "Name";
73  pProperties[ 1] += "Measure";
74  return aProperties;
75 }
76 
78  ConfigItem("Office.Labels/Manufacturer")
79 {
80  OUString uri("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/labels/labels.xml");
81  rtl::Bootstrap::expandMacros(uri);
82  xmlreader::XmlReader reader(uri);
83  int nsId;
86  OUString sManufacturer;
87  OUString sName;
88  OUString sMeasure;
89 
90  // fill m_aLabels and m_aManufacturers with the predefined labels
91  res = reader.nextItem(
92  xmlreader::XmlReader::Text::NONE, &name, &nsId);
93  assert(
95  && name.equals("manufacturers"));
96  res = reader.nextItem(
97  xmlreader::XmlReader::Text::NONE, &name, &nsId);
99  {
100  // Opening manufacturer
101  assert(
103  && name.equals("manufacturer"));
104  // Get the name
105  (void)reader.nextAttribute(&nsId, &name);
106  assert(
108  && name.equals("name"));
109  sManufacturer = reader.getAttributeValue(false).convertFromUtf8();
110 
111  for(;;) {
112  // Opening label or ending manufacturer
113  res = reader.nextItem(
114  xmlreader::XmlReader::Text::NONE, &name, &nsId);
116  break;
117  assert(
119  && name.equals("label"));
120  // Get name value
121  sName = lcl_getValue(reader, xmlreader::Span("name"));
122  // Get measure value
123  sMeasure = lcl_getValue(reader, xmlreader::Span("measure"));
124  // Ending label mark
125  lcl_assertEndingItem(reader);
126  if ( m_aLabels.find( sManufacturer ) == m_aLabels.end() )
127  m_aManufacturers.push_back( sManufacturer );
128  m_aLabels[sManufacturer][sName].m_aMeasure = sMeasure;
129  m_aLabels[sManufacturer][sName].m_bPredefined = true;
130  }
131  // Get next manufacturer or end
132  res = reader.nextItem(
133  xmlreader::XmlReader::Text::NONE, &name, &nsId);
134  };
135  res = reader.nextItem(
136  xmlreader::XmlReader::Text::NONE, &name, &nsId);
137  assert(res == xmlreader::XmlReader::Result::Done);
138 
139  // add to m_aLabels and m_aManufacturers the custom labels
140  const Sequence<OUString>& rMan = GetNodeNames( OUString() );
141  for ( const OUString& rManufacturer : rMan )
142  {
143  const Sequence<OUString> aLabels = GetNodeNames( rManufacturer );
144  for( const OUString& rLabel : aLabels )
145  {
146  OUString sPrefix( rManufacturer );
147  sPrefix += "/";
148  sPrefix += rLabel;
149  sPrefix += "/";
150  Sequence<OUString> aPropNames = lcl_CreatePropertyNames( sPrefix );
151  Sequence<Any> aValues = GetProperties( aPropNames );
152  const Any* pValues = aValues.getConstArray();
153  if (aValues.getLength() >= 1)
154  if(pValues[0].hasValue())
155  pValues[0] >>= sName;
156  if (aValues.getLength() >= 2)
157  if(pValues[1].hasValue())
158  pValues[1] >>= sMeasure;
159  if ( m_aLabels.find( rManufacturer ) == m_aLabels.end() )
160  m_aManufacturers.push_back( rManufacturer );
161  m_aLabels[rManufacturer][sName].m_aMeasure = sMeasure;
162  m_aLabels[rManufacturer][sName].m_bPredefined = false;
163  }
164  }
165 }
166 
168 {
169 }
170 
171 // the config item is not writable ?:
173 
174 void SwLabelConfig::Notify( const css::uno::Sequence< OUString >& ) {}
175 
176 static std::unique_ptr<SwLabRec> lcl_CreateSwLabRec(const OUString& rType, const OUString& rMeasure, const OUString& rManufacturer)
177 {
178  std::unique_ptr<SwLabRec> pNewRec(new SwLabRec);
179  pNewRec->m_aMake = rManufacturer;
180  pNewRec->m_nPWidth = 0;
181  pNewRec->m_nPHeight = 0;
182  pNewRec->m_aType = rType;
183  //all values are contained as colon-separated 1/100 mm values
184  //except for the continuous flag ('C'/'S') and nCols, nRows (sal_Int32)
185  sal_Int32 nTok{0};
186  sal_Int32 nIdx{rMeasure.isEmpty() ? -1 : 0};
187  while (nIdx>=0)
188  {
189  const OUString sToken(rMeasure.getToken(0, ';', nIdx));
190  int nVal = sToken.toInt32();
191  switch(nTok++)
192  {
193  case 0 : pNewRec->m_bCont = sToken[0] == 'C'; break;
194  case 1 : pNewRec->m_nHDist = convertMm100ToTwip(nVal); break;
195  case 2 : pNewRec->m_nVDist = convertMm100ToTwip(nVal); break;
196  case 3 : pNewRec->m_nWidth = convertMm100ToTwip(nVal); break;
197  case 4 : pNewRec->m_nHeight = convertMm100ToTwip(nVal); break;
198  case 5 : pNewRec->m_nLeft = convertMm100ToTwip(nVal); break;
199  case 6 : pNewRec->m_nUpper = convertMm100ToTwip(nVal); break;
200  case 7 : pNewRec->m_nCols = nVal; break;
201  case 8 : pNewRec->m_nRows = nVal; break;
202  case 9 : pNewRec->m_nPWidth = convertMm100ToTwip(nVal); break;
203  case 10 : pNewRec->m_nPHeight = convertMm100ToTwip(nVal); break;
204  }
205  }
206  // lines added for compatibility with custom label definitions saved before patch fdo#44516
207  if (pNewRec->m_nPWidth == 0 || pNewRec->m_nPHeight == 0)
208  {
209  // old style definition (no paper dimensions), calculate probable values
210  pNewRec->m_nPWidth = 2 * pNewRec->m_nLeft + (pNewRec->m_nCols - 1) * pNewRec->m_nHDist + pNewRec->m_nWidth;
211  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 );
212  }
213  return pNewRec;
214 }
215 
217  Sequence<OUString> const & rPropNames, OUString& rMeasure, const SwLabRec& rRec)
218 {
219  const OUString* pNames = rPropNames.getConstArray();
220  Sequence<PropertyValue> aRet(rPropNames.getLength());
221  PropertyValue* pValues = aRet.getArray();
222  OUString sColon(";");
223 
224  for(sal_Int32 nProp = 0; nProp < rPropNames.getLength(); nProp++)
225  {
226  pValues[nProp].Name = pNames[nProp];
227  switch(nProp)
228  {
229  case 0: pValues[nProp].Value <<= rRec.m_aType; break;
230  case 1:
231  {
232  rMeasure.clear();
233  rMeasure += rRec.m_bCont ? OUString( "C" ) : OUString( "S" ); rMeasure += sColon;
234  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nHDist ) ); rMeasure += sColon;
235  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nVDist ) ); rMeasure += sColon;
236  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nWidth ) ); rMeasure += sColon;
237  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nHeight ) ); rMeasure += sColon;
238  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nLeft ) ); rMeasure += sColon;
239  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nUpper ) ); rMeasure += sColon;
240  rMeasure += OUString::number( rRec.m_nCols ); rMeasure += sColon;
241  rMeasure += OUString::number( rRec.m_nRows ); rMeasure += sColon;
242  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nPWidth ) ); rMeasure += sColon;
243  rMeasure += OUString::number( convertTwipToMm100( rRec.m_nPHeight ) );
244  pValues[nProp].Value <<= rMeasure;
245  }
246  break;
247  }
248  }
249  return aRet;
250 }
251 
252 // function fills SwLabDlg with label definitions for manufacturer rManufacturer
253 void SwLabelConfig::FillLabels(const OUString& rManufacturer, SwLabRecs& rLabArr)
254 {
255  if (m_aLabels.find(rManufacturer) == m_aLabels.end())
256  return;
257  for (const auto& rEntry : m_aLabels[rManufacturer])
258  rLabArr.push_back( lcl_CreateSwLabRec(rEntry.first, rEntry.second.m_aMeasure, rManufacturer) );
259 }
260 
261 bool SwLabelConfig::HasLabel(const OUString& rManufacturer, const OUString& rType)
262 {
263  return ( ( m_aLabels.find(rManufacturer) != m_aLabels.end() ) &&
264  ( m_aLabels[rManufacturer].find(rType) != m_aLabels[rManufacturer].end() ) );
265 }
266 
267 // label is always saved as a custom label
268 // predefined labels can NOT be overwritten by custom labels with same manufacturer/name
269 void SwLabelConfig::SaveLabel( const OUString& rManufacturer,
270  const OUString& rType, const SwLabRec& rRec )
271 {
272  OUString sFoundNode;
273  bool bManufacturerNodeFound;
274  if ( m_aLabels.find( rManufacturer ) == m_aLabels.end() ||
275  !GetNodeNames( rManufacturer ).hasElements() )
276  {
277  bManufacturerNodeFound = false;
278  // manufacturer node does not exist, add (and also to m_aManufacturers)
279  if ( !AddNode( OUString(), rManufacturer ) )
280  {
281  OSL_FAIL("New configuration node could not be created");
282  return ;
283  }
284  m_aManufacturers.push_back( rManufacturer );
285  }
286  else
287  bManufacturerNodeFound = true;
288 
289  if ( !bManufacturerNodeFound ||
290  m_aLabels[rManufacturer].find( rType ) == m_aLabels[rManufacturer].end() )
291  {
292  // type does not yet exist, add to config
293  const Sequence<OUString> aLabels = GetNodeNames( rManufacturer );
294  sal_Int32 nIndex = aLabels.getLength();
295  OUString sPrefix( "Label" );
296  sFoundNode = sPrefix;
297  sFoundNode += OUString::number( nIndex );
298  while ( comphelper::findValue(aLabels, sFoundNode) != -1 )
299  {
300  sFoundNode = sPrefix + OUString::number(nIndex++);
301  }
302  }
303  else
304  {
305  // get the appropriate node
306  OUString sManufacturer( wrapConfigurationElementName( rManufacturer ) );
307  const Sequence<OUString> aLabels = GetNodeNames( sManufacturer );
308  for (const OUString& rLabel : aLabels)
309  {
310  OUString sPrefix( sManufacturer );
311  sPrefix += "/";
312  sPrefix += rLabel;
313  sPrefix += "/";
314  Sequence<OUString> aProperties { sPrefix };
315  aProperties.getArray()[0] += "Name";
316  Sequence<Any> aValues = GetProperties( aProperties );
317  const Any* pValues = aValues.getConstArray();
318  if ( pValues[0].hasValue() )
319  {
320  OUString sTmp;
321  pValues[0] >>= sTmp;
322  if ( rType == sTmp )
323  {
324  sFoundNode = rLabel;
325  break;
326  }
327  }
328  }
329  }
330 
331  OUString sPrefix( wrapConfigurationElementName( rManufacturer ) );
332  sPrefix += "/";
333  sPrefix += sFoundNode;
334  sPrefix += "/";
335  Sequence<OUString> aPropNames = lcl_CreatePropertyNames( sPrefix );
336  OUString sMeasure;
337  Sequence<PropertyValue> aPropValues = lcl_CreateProperties( aPropNames, sMeasure, rRec );
338  SetSetProperties( wrapConfigurationElementName( rManufacturer ), aPropValues );
339 
340  //update m_aLabels
341  m_aLabels[rManufacturer][rType].m_aMeasure = sMeasure;
342  m_aLabels[rManufacturer][rType].m_bPredefined = false;
343 }
344 
345 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long m_nHDist
Definition: labrec.hxx:40
long m_nHeight
Definition: labrec.hxx:43
sal_Int32 m_nRows
Definition: labrec.hxx:49
sal_Int32 findValue(const css::uno::Sequence< OUString > &_rList, const OUString &_rValue)
bool HasLabel(const OUString &rManufacturer, const OUString &rType)
Definition: labelcfg.cxx:261
long m_nWidth
Definition: labrec.hxx:42
virtual void Notify(const css::uno::Sequence< OUString > &aPropertyNames) override
Definition: labelcfg.cxx:174
std::vector< OUString > m_aManufacturers
Definition: labelcfg.hxx:38
static void lcl_assertEndingItem(xmlreader::XmlReader &reader)
Definition: labelcfg.cxx:40
OSQLColumns::Vector::const_iterator find(const OSQLColumns::Vector::const_iterator &first, const OSQLColumns::Vector::const_iterator &last, const OUString &_rVal, const ::comphelper::UStringMixEqual &_rCase)
std::map< OUString, std::map< OUString, SwLabelMeasure > > m_aLabels
Definition: labelcfg.hxx:39
long m_nLeft
Definition: labrec.hxx:44
bool m_bCont
Definition: labrec.hxx:50
bool SetSetProperties(const OUString &rNode, const css::uno::Sequence< css::beans::PropertyValue > &rValues)
virtual void ImplCommit() override
Definition: labelcfg.cxx:172
long m_nVDist
Definition: labrec.hxx:41
static Sequence< OUString > lcl_CreatePropertyNames(const OUString &rPrefix)
Definition: labelcfg.cxx:66
long m_nPWidth
Definition: labrec.hxx:46
OUString sName
OUString wrapConfigurationElementName(OUString const &_sElementName)
css::uno::Sequence< css::uno::Any > GetProperties(const css::uno::Sequence< OUString > &rNames)
static Sequence< PropertyValue > lcl_CreateProperties(Sequence< OUString > const &rPropNames, OUString &rMeasure, const SwLabRec &rRec)
Definition: labelcfg.cxx:216
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:253
enumrange< T >::Iterator end(enumrange< T >)
sal_Int32 m_nCols
Definition: labrec.hxx:48
OUString m_aType
Definition: labrec.hxx:39
bool AddNode(const OUString &rNode, const OUString &rNewNode)
Span getAttributeValue(bool fullyNormalize)
rtl::OUString convertFromUtf8() const
static std::unique_ptr< SwLabRec > lcl_CreateSwLabRec(const OUString &rType, const OUString &rMeasure, const OUString &rManufacturer)
Definition: labelcfg.cxx:176
const char * name
css::uno::Sequence< OUString > GetNodeNames(const OUString &rNode)
std::vector< std::unique_ptr< SwLabRec > > SwLabRecs
Definition: labrec.hxx:53
constexpr sal_Int64 convertTwipToMm100(sal_Int64 n)
long m_nPHeight
Definition: labrec.hxx:47
void SaveLabel(const OUString &rManufacturer, const OUString &rType, const SwLabRec &rRec)
Definition: labelcfg.cxx:269
bool equals(Span const &text) const
bool nextAttribute(int *nsId, Span *localName)
Result nextItem(Text reportText, Span *data, int *nsId)
constexpr sal_Int64 convertMm100ToTwip(sal_Int64 n)
virtual ~SwLabelConfig() override
Definition: labelcfg.cxx:167
long m_nUpper
Definition: labrec.hxx:45
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo