1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <swtypes.hxx>
21 #include <labelcfg.hxx>
23 #include <comphelper/string.hxx>
24 #include <rtl/bootstrap.hxx>
25 #include <unotools/configpaths.hxx>
26 #include <xmlreader/xmlreader.hxx>
31 using namespace ::com::sun::star::uno
;
32 using namespace ::com::sun::star::beans
;
34 static inline void lcl_assertEndingItem(xmlreader::XmlReader
& reader
)
38 xmlreader::XmlReader::Result res
;
39 res
= reader
.nextItem(xmlreader::XmlReader::TEXT_NONE
, &name
, &nsId
);
40 assert(res
== xmlreader::XmlReader::RESULT_END
);
44 static inline OUString
lcl_getValue(xmlreader::XmlReader
& reader
,
45 const xmlreader::Span
& span
)
49 xmlreader::XmlReader::Result res
;
50 res
= reader
.nextItem(xmlreader::XmlReader::TEXT_NONE
, &name
, &nsId
);
51 assert(res
== xmlreader::XmlReader::RESULT_BEGIN
&& name
.equals(span
));
52 res
= reader
.nextItem(xmlreader::XmlReader::TEXT_RAW
, &name
, &nsId
);
53 assert(res
== xmlreader::XmlReader::RESULT_TEXT
);
54 (void) res
; (void) span
;
55 OUString sTmp
= name
.convertFromUtf8();
56 lcl_assertEndingItem(reader
);
60 static Sequence
<OUString
> lcl_CreatePropertyNames(const OUString
& rPrefix
)
62 Sequence
<OUString
> aProperties(2);
63 OUString
* pProperties
= aProperties
.getArray();
64 for(sal_Int32 nProp
= 0; nProp
< 2; nProp
++)
65 pProperties
[nProp
] = rPrefix
;
67 pProperties
[ 0] += "Name";
68 pProperties
[ 1] += "Measure";
72 SwLabelConfig::SwLabelConfig() :
73 ConfigItem("Office.Labels/Manufacturer")
75 OUString
uri("$BRAND_BASE_DIR/share/labels/labels.xml");
76 rtl::Bootstrap::expandMacros(uri
);
77 xmlreader::XmlReader
reader(uri
);
80 xmlreader::XmlReader::Result res
;
81 OUString sManufacturer
;
85 // fill m_aLabels and m_aManufacturers with the predefined labels
86 res
= reader
.nextItem(
87 xmlreader::XmlReader::TEXT_NONE
, &name
, &nsId
);
89 res
== xmlreader::XmlReader::RESULT_BEGIN
90 && name
.equals("manufacturers"));
91 res
= reader
.nextItem(
92 xmlreader::XmlReader::TEXT_NONE
, &name
, &nsId
);
93 while (res
!= xmlreader::XmlReader::RESULT_END
)
95 // Opening manufacturer
97 res
== xmlreader::XmlReader::RESULT_BEGIN
98 && name
.equals("manufacturer"));
100 reader
.nextAttribute(&nsId
, &name
);
102 nsId
== xmlreader::XmlReader::NAMESPACE_NONE
103 && name
.equals("name"));
104 sManufacturer
= reader
.getAttributeValue(false).convertFromUtf8();
107 // Opening label or ending manufacturer
108 res
= reader
.nextItem(
109 xmlreader::XmlReader::TEXT_NONE
, &name
, &nsId
);
110 if (res
== xmlreader::XmlReader::RESULT_END
)
113 res
== xmlreader::XmlReader::RESULT_BEGIN
114 && name
.equals("label"));
116 sName
= lcl_getValue(reader
, xmlreader::Span("name"));
118 sMeasure
= lcl_getValue(reader
, xmlreader::Span("measure"));
120 lcl_assertEndingItem(reader
);
121 if ( m_aLabels
.find( sManufacturer
) == m_aLabels
.end() )
122 m_aManufacturers
.push_back( sManufacturer
);
123 m_aLabels
[sManufacturer
][sName
].m_aMeasure
= sMeasure
;
124 m_aLabels
[sManufacturer
][sName
].m_bPredefined
= true;
126 // Get next manufacturer or end
127 res
= reader
.nextItem(
128 xmlreader::XmlReader::TEXT_NONE
, &name
, &nsId
);
130 res
= reader
.nextItem(
131 xmlreader::XmlReader::TEXT_NONE
, &name
, &nsId
);
132 assert(res
== xmlreader::XmlReader::RESULT_DONE
);
134 // add to m_aLabels and m_aManufacturers the custom labels
135 const Sequence
<OUString
>& rMan
= GetNodeNames( OUString() );
136 const OUString
* pMan
= rMan
.getConstArray();
137 for ( sal_Int32 nMan
= 0; nMan
< rMan
.getLength(); nMan
++ )
139 sManufacturer
= pMan
[nMan
];
140 const Sequence
<OUString
> aLabels
= GetNodeNames( sManufacturer
);
141 const OUString
* pLabels
= aLabels
.getConstArray();
142 for( sal_Int32 nLabel
= 0; nLabel
< aLabels
.getLength(); nLabel
++ )
144 OUString
sPrefix( sManufacturer
);
146 sPrefix
+= pLabels
[nLabel
];
148 Sequence
<OUString
> aPropNames
= lcl_CreatePropertyNames( sPrefix
);
149 Sequence
<Any
> aValues
= GetProperties( aPropNames
);
150 const Any
* pValues
= aValues
.getConstArray();
151 if (aValues
.getLength() >= 1)
152 if(pValues
[0].hasValue())
153 pValues
[0] >>= sName
;
154 if (aValues
.getLength() >= 2)
155 if(pValues
[1].hasValue())
156 pValues
[1] >>= sMeasure
;
157 if ( m_aLabels
.find( sManufacturer
) == m_aLabels
.end() )
158 m_aManufacturers
.push_back( sManufacturer
);
159 m_aLabels
[sManufacturer
][sName
].m_aMeasure
= sMeasure
;
160 m_aLabels
[sManufacturer
][sName
].m_bPredefined
= false;
165 SwLabelConfig::~SwLabelConfig()
169 // the config item is not writable ?:
170 void SwLabelConfig::Commit() {}
172 void SwLabelConfig::Notify( const ::com::sun::star::uno::Sequence
< OUString
>& ) {}
174 static SwLabRec
* lcl_CreateSwLabRec(const OUString
& rType
, const OUString
& rMeasure
, const OUString
& rManufacturer
)
176 SwLabRec
* pNewRec
= new SwLabRec
;
177 pNewRec
->aMake
= rManufacturer
;
178 pNewRec
->lPWidth
= 0;
179 pNewRec
->lPHeight
= 0;
180 pNewRec
->aType
= rType
;
181 //all values are contained as colon-separated 1/100 mm values
182 //except for the continuous flag ('C'/'S') and nCols, nRows (sal_Int32)
183 String
sMeasure(rMeasure
);
184 sal_uInt16 nTokenCount
= comphelper::string::getTokenCount(sMeasure
, ';');
185 for(sal_uInt16 i
= 0; i
< nTokenCount
; i
++)
187 String
sToken(sMeasure
.GetToken(i
, ';' ));
188 int nVal
= sToken
.ToInt32();
191 case 0 : pNewRec
->bCont
= sToken
.GetChar(0) == 'C'; break;
192 case 1 : pNewRec
->lHDist
= MM100_TO_TWIP(nVal
); break;
193 case 2 : pNewRec
->lVDist
= MM100_TO_TWIP(nVal
); break;
194 case 3 : pNewRec
->lWidth
= MM100_TO_TWIP(nVal
); break;
195 case 4 : pNewRec
->lHeight
= MM100_TO_TWIP(nVal
); break;
196 case 5 : pNewRec
->lLeft
= MM100_TO_TWIP(nVal
); break;
197 case 6 : pNewRec
->lUpper
= MM100_TO_TWIP(nVal
); break;
198 case 7 : pNewRec
->nCols
= nVal
; break;
199 case 8 : pNewRec
->nRows
= nVal
; break;
200 case 9 : pNewRec
->lPWidth
= MM100_TO_TWIP(nVal
); break;
201 case 10 : pNewRec
->lPHeight
= MM100_TO_TWIP(nVal
); break;
204 // lines added for compatibility with custom label definitions saved before patch fdo#44516
205 if (pNewRec
->lPWidth
== 0 || pNewRec
->lPHeight
== 0)
207 // old style definition (no paper dimensions), calculate probable values
208 pNewRec
->lPWidth
= 2 * pNewRec
->lLeft
+ (pNewRec
->nCols
- 1) * pNewRec
->lHDist
+ pNewRec
->lWidth
;
209 pNewRec
->lPHeight
= ( pNewRec
->bCont
? pNewRec
->nRows
* pNewRec
->lVDist
: 2 * pNewRec
->lUpper
+ (pNewRec
->nRows
- 1) * pNewRec
->lVDist
+ pNewRec
->lHeight
);
214 static Sequence
<PropertyValue
> lcl_CreateProperties(
215 Sequence
<OUString
>& rPropNames
, OUString
& rMeasure
, const SwLabRec
& rRec
)
217 const OUString
* pNames
= rPropNames
.getConstArray();
218 Sequence
<PropertyValue
> aRet(rPropNames
.getLength());
219 PropertyValue
* pValues
= aRet
.getArray();
220 OUString
sColon(";");
222 for(sal_Int32 nProp
= 0; nProp
< rPropNames
.getLength(); nProp
++)
224 pValues
[nProp
].Name
= pNames
[nProp
];
227 case 0: pValues
[nProp
].Value
<<= OUString(rRec
.aType
); break;
231 rMeasure
+= rRec
.bCont
? OUString( "C" ) : OUString( "S" ); rMeasure
+= sColon
;
232 rMeasure
+= OUString::valueOf( TWIP_TO_MM100( rRec
.lHDist
) ); rMeasure
+= sColon
;
233 rMeasure
+= OUString::valueOf( TWIP_TO_MM100( rRec
.lVDist
) ); rMeasure
+= sColon
;
234 rMeasure
+= OUString::valueOf( TWIP_TO_MM100( rRec
.lWidth
) ); rMeasure
+= sColon
;
235 rMeasure
+= OUString::valueOf( TWIP_TO_MM100( rRec
.lHeight
) ); rMeasure
+= sColon
;
236 rMeasure
+= OUString::valueOf( TWIP_TO_MM100( rRec
.lLeft
) ); rMeasure
+= sColon
;
237 rMeasure
+= OUString::valueOf( TWIP_TO_MM100( rRec
.lUpper
) ); rMeasure
+= sColon
;
238 rMeasure
+= OUString::valueOf( rRec
.nCols
); rMeasure
+= sColon
;
239 rMeasure
+= OUString::valueOf( rRec
.nRows
); rMeasure
+= sColon
;
240 rMeasure
+= OUString::valueOf( TWIP_TO_MM100( rRec
.lPWidth
) ); rMeasure
+= sColon
;
241 rMeasure
+= OUString::valueOf( TWIP_TO_MM100( rRec
.lPHeight
) );
242 pValues
[nProp
].Value
<<= rMeasure
;
250 // function fills SwLabDlg with label definitions for manufacturer rManufacturer
251 void SwLabelConfig::FillLabels(const OUString
& rManufacturer
, SwLabRecs
& rLabArr
)
253 if (m_aLabels
.find(rManufacturer
) == m_aLabels
.end())
255 for (std::map
<OUString
, SwLabelMeasure
>::iterator it
= m_aLabels
[rManufacturer
].begin();
256 it
!= m_aLabels
[rManufacturer
].end(); ++it
)
257 rLabArr
.push_back( lcl_CreateSwLabRec(it
->first
, it
->second
.m_aMeasure
, rManufacturer
) );
260 sal_Bool
SwLabelConfig::HasLabel(const OUString
& rManufacturer
, const OUString
& rType
)
262 return ( ( m_aLabels
.find(rManufacturer
) != m_aLabels
.end() ) &&
263 ( m_aLabels
[rManufacturer
].find(rType
) != m_aLabels
[rManufacturer
].end() ) );
266 static bool lcl_Exists(const OUString
& rNode
, const Sequence
<OUString
>& rLabels
)
268 const OUString
* pLabels
= rLabels
.getConstArray();
269 for(sal_Int32 i
= 0; i
< rLabels
.getLength(); i
++)
270 if(pLabels
[i
] == rNode
)
275 // label is always saved as a custom label
276 // predefined labels can NOT be overwritten by custom labels with same manufacturer/name
277 void SwLabelConfig::SaveLabel( const OUString
& rManufacturer
,
278 const OUString
& rType
, const SwLabRec
& rRec
)
281 bool bManufacturerNodeFound
;
282 if ( m_aLabels
.find( rManufacturer
) == m_aLabels
.end() ||
283 GetNodeNames( rManufacturer
).getLength() == 0 )
285 bManufacturerNodeFound
= false;
286 // manufacturer node does not exist, add (and also to m_aManufacturers)
287 if ( !AddNode( OUString(), rManufacturer
) )
289 OSL_FAIL("New configuration node could not be created");
292 m_aManufacturers
.push_back( rManufacturer
);
295 bManufacturerNodeFound
= true;
297 if ( !bManufacturerNodeFound
||
298 m_aLabels
[rManufacturer
].find( rType
) == m_aLabels
[rManufacturer
].end() )
300 // type does not yet exist, add to config
301 const Sequence
<OUString
> aLabels
= GetNodeNames( rManufacturer
);
302 sal_Int32 nIndex
= aLabels
.getLength();
303 OUString
sPrefix( "Label" );
304 sFoundNode
= sPrefix
;
305 sFoundNode
+= OUString::valueOf( nIndex
);
306 while ( lcl_Exists( sFoundNode
, aLabels
) )
308 sFoundNode
= sPrefix
;
309 sFoundNode
+= OUString::valueOf(nIndex
++);
314 // get the appropiate node
315 OUString
sManufacturer( wrapConfigurationElementName( rManufacturer
) );
316 const Sequence
<OUString
> aLabels
= GetNodeNames( sManufacturer
);
317 const OUString
* pLabels
= aLabels
.getConstArray();
318 for (sal_Int32 nLabel
= 0; nLabel
< aLabels
.getLength(); nLabel
++)
320 OUString
sPrefix( sManufacturer
);
322 sPrefix
+= pLabels
[nLabel
];
324 Sequence
<OUString
> aProperties(1);
325 aProperties
.getArray()[0] = sPrefix
;
326 aProperties
.getArray()[0] += "Name";
327 Sequence
<Any
> aValues
= GetProperties( aProperties
);
328 const Any
* pValues
= aValues
.getConstArray();
329 if ( pValues
[0].hasValue() )
335 sFoundNode
= pLabels
[nLabel
];
342 OUString
sPrefix( wrapConfigurationElementName( rManufacturer
) );
344 sPrefix
+= sFoundNode
;
346 Sequence
<OUString
> aPropNames
= lcl_CreatePropertyNames( sPrefix
);
348 Sequence
<PropertyValue
> aPropValues
= lcl_CreateProperties( aPropNames
, sMeasure
, rRec
);
349 SetSetProperties( wrapConfigurationElementName( rManufacturer
), aPropValues
);
352 m_aLabels
[rManufacturer
][rType
].m_aMeasure
= sMeasure
;
353 m_aLabels
[rManufacturer
][rType
].m_bPredefined
= false;
357 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */