Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / uibase / envelp / labelcfg.cxx
blob8d98c7a9f1eb3a6d9596f05e3a55b728140a3288
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <memory>
21 #include <string_view>
22 #include <config_folders.h>
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>
34 #include <com/sun/star/beans/PropertyValue.hpp>
36 using namespace utl;
37 using namespace ::com::sun::star::uno;
38 using namespace ::com::sun::star::beans;
40 static void lcl_assertEndingItem(xmlreader::XmlReader& reader)
42 int nsId;
43 xmlreader::Span name;
44 xmlreader::XmlReader::Result res;
45 res = reader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);
46 assert(res == xmlreader::XmlReader::Result::End);
47 (void) res;
50 static OUString lcl_getValue(xmlreader::XmlReader& reader,
51 const xmlreader::Span& span)
53 int nsId;
54 xmlreader::Span name;
55 xmlreader::XmlReader::Result res;
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);
59 assert(res == xmlreader::XmlReader::Result::Text);
60 (void) res; (void) span;
61 OUString sTmp = name.convertFromUtf8();
62 lcl_assertEndingItem(reader);
63 return sTmp;
66 static Sequence<OUString> lcl_CreatePropertyNames(const OUString& rPrefix)
68 return { OUString::Concat(rPrefix) + "Name", OUString::Concat(rPrefix) + "Measure" };
71 SwLabelConfig::SwLabelConfig() :
72 ConfigItem("Office.Labels/Manufacturer")
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;
78 xmlreader::Span name;
79 xmlreader::XmlReader::Result res;
80 OUString sManufacturer;
81 OUString sName;
82 OUString sMeasure;
84 // fill m_aLabels and m_aManufacturers with the predefined labels
85 res = reader.nextItem(
86 xmlreader::XmlReader::Text::NONE, &name, &nsId);
87 assert(
88 res == xmlreader::XmlReader::Result::Begin
89 && name == "manufacturers");
90 res = reader.nextItem(
91 xmlreader::XmlReader::Text::NONE, &name, &nsId);
92 while (res != xmlreader::XmlReader::Result::End)
94 // Opening manufacturer
95 assert(
96 res == xmlreader::XmlReader::Result::Begin
97 && name == "manufacturer");
98 // Get the name
99 (void)reader.nextAttribute(&nsId, &name);
100 assert(
101 nsId == xmlreader::XmlReader::NAMESPACE_NONE
102 && name == "name");
103 sManufacturer = reader.getAttributeValue(false).convertFromUtf8();
105 for(;;) {
106 // Opening label or ending manufacturer
107 res = reader.nextItem(
108 xmlreader::XmlReader::Text::NONE, &name, &nsId);
109 if (res == xmlreader::XmlReader::Result::End)
110 break;
111 assert(
112 res == xmlreader::XmlReader::Result::Begin
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;
125 // Get next manufacturer or end
126 res = reader.nextItem(
127 xmlreader::XmlReader::Text::NONE, &name, &nsId);
129 res = reader.nextItem(
130 xmlreader::XmlReader::Text::NONE, &name, &nsId);
131 assert(res == xmlreader::XmlReader::Result::Done);
133 // add to m_aLabels and m_aManufacturers the custom labels
134 const Sequence<OUString>& rMan = GetNodeNames( OUString() );
135 for ( const OUString& rManufacturer : rMan )
137 const Sequence<OUString> aLabels = GetNodeNames( rManufacturer );
138 for( const OUString& rLabel : aLabels )
140 OUString sPrefix = rManufacturer + "/" + rLabel + "/";
141 Sequence<OUString> aPropNames = lcl_CreatePropertyNames( sPrefix );
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;
158 SwLabelConfig::~SwLabelConfig()
162 // the config item is not writable ?:
163 void SwLabelConfig::ImplCommit() {}
165 void SwLabelConfig::Notify( const css::uno::Sequence< OUString >& ) {}
167 static std::unique_ptr<SwLabRec> lcl_CreateSwLabRec(const OUString& rType, std::u16string_view rMeasure, const OUString& rManufacturer)
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)
180 const std::u16string_view sToken(o3tl::getToken(rMeasure, 0, ';', nIdx));
181 int nVal = o3tl::toInt32(sToken);
182 switch(nTok++)
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;
197 // lines added for compatibility with custom label definitions saved before patch fdo#44516
198 if (pNewRec->m_nPWidth == 0 || pNewRec->m_nPHeight == 0)
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 );
204 return pNewRec;
207 static Sequence<PropertyValue> lcl_CreateProperties(
208 Sequence<OUString> const & rPropNames, OUString& rMeasure, const SwLabRec& rRec)
210 const OUString* pNames = rPropNames.getConstArray();
211 Sequence<PropertyValue> aRet(rPropNames.getLength());
212 PropertyValue* pValues = aRet.getArray();
213 OUString sColon(";");
215 for(sal_Int32 nProp = 0; nProp < rPropNames.getLength(); nProp++)
217 pValues[nProp].Name = pNames[nProp];
218 switch(nProp)
220 case 0: pValues[nProp].Value <<= rRec.m_aType; break;
221 case 1:
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;
237 break;
240 return aRet;
243 // function fills SwLabDlg with label definitions for manufacturer rManufacturer
244 void SwLabelConfig::FillLabels(const OUString& rManufacturer, SwLabRecs& rLabArr)
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) );
252 bool SwLabelConfig::HasLabel(const OUString& rManufacturer, const OUString& rType)
254 return ( ( m_aLabels.find(rManufacturer) != m_aLabels.end() ) &&
255 ( m_aLabels[rManufacturer].find(rType) != m_aLabels[rManufacturer].end() ) );
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 )
263 OUString sFoundNode;
264 bool bManufacturerNodeFound;
265 if ( m_aLabels.find( rManufacturer ) == m_aLabels.end() ||
266 !GetNodeNames( rManufacturer ).hasElements() )
268 bManufacturerNodeFound = false;
269 // manufacturer node does not exist, add (and also to m_aManufacturers)
270 if ( !AddNode( OUString(), rManufacturer ) )
272 OSL_FAIL("New configuration node could not be created");
273 return ;
275 m_aManufacturers.push_back( rManufacturer );
277 else
278 bManufacturerNodeFound = true;
280 if ( !bManufacturerNodeFound ||
281 m_aLabels[rManufacturer].find( rType ) == m_aLabels[rManufacturer].end() )
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 )
290 sFoundNode = sPrefix + OUString::number(nIndex++);
293 else
295 // get the appropriate node
296 OUString sManufacturer( wrapConfigurationElementName( rManufacturer ) );
297 const Sequence<OUString> aLabels = GetNodeNames( sManufacturer );
298 for (const OUString& rLabel : aLabels)
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() )
307 OUString sTmp;
308 pValues[0] >>= sTmp;
309 if ( rType == sTmp )
311 sFoundNode = rLabel;
312 break;
318 OUString sPrefix = wrapConfigurationElementName( rManufacturer ) +
319 "/" + sFoundNode + "/";
320 Sequence<OUString> aPropNames = lcl_CreatePropertyNames( sPrefix );
321 OUString sMeasure;
322 Sequence<PropertyValue> aPropValues = lcl_CreateProperties( aPropNames, sMeasure, rRec );
323 SetSetProperties( wrapConfigurationElementName( rManufacturer ), aPropValues );
325 //update m_aLabels
326 m_aLabels[rManufacturer][rType].m_aMeasure = sMeasure;
327 m_aLabels[rManufacturer][rType].m_bPredefined = false;
330 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */