330 lines
14 KiB
C++
330 lines
14 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <memory>
|
|
#include <string_view>
|
|
#include <config_folders.h>
|
|
|
|
#include <swtypes.hxx>
|
|
#include <labelcfg.hxx>
|
|
#include <rtl/bootstrap.hxx>
|
|
#include <tools/UnitConversion.hxx>
|
|
#include <unotools/configpaths.hxx>
|
|
#include <xmlreader/xmlreader.hxx>
|
|
#include <comphelper/sequence.hxx>
|
|
#include <osl/diagnose.h>
|
|
#include <o3tl/string_view.hxx>
|
|
|
|
#include <com/sun/star/beans/PropertyValue.hpp>
|
|
|
|
using namespace utl;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::beans;
|
|
|
|
static void lcl_assertEndingItem(xmlreader::XmlReader& reader)
|
|
{
|
|
int nsId;
|
|
xmlreader::Span name;
|
|
xmlreader::XmlReader::Result res;
|
|
res = reader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);
|
|
assert(res == xmlreader::XmlReader::Result::End);
|
|
(void) res;
|
|
}
|
|
|
|
static OUString lcl_getValue(xmlreader::XmlReader& reader,
|
|
const xmlreader::Span& span)
|
|
{
|
|
int nsId;
|
|
xmlreader::Span name;
|
|
xmlreader::XmlReader::Result res;
|
|
res = reader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);
|
|
assert(res == xmlreader::XmlReader::Result::Begin && name == span);
|
|
res = reader.nextItem(xmlreader::XmlReader::Text::Raw, &name, &nsId);
|
|
assert(res == xmlreader::XmlReader::Result::Text);
|
|
(void) res; (void) span;
|
|
OUString sTmp = name.convertFromUtf8();
|
|
lcl_assertEndingItem(reader);
|
|
return sTmp;
|
|
}
|
|
|
|
static Sequence<OUString> lcl_CreatePropertyNames(const OUString& rPrefix)
|
|
{
|
|
return { OUString::Concat(rPrefix) + "Name", OUString::Concat(rPrefix) + "Measure" };
|
|
}
|
|
|
|
SwLabelConfig::SwLabelConfig() :
|
|
ConfigItem(u"Office.Labels/Manufacturer"_ustr)
|
|
{
|
|
OUString uri(u"$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/labels/labels.xml"_ustr);
|
|
rtl::Bootstrap::expandMacros(uri);
|
|
xmlreader::XmlReader reader(uri);
|
|
int nsId;
|
|
xmlreader::Span name;
|
|
xmlreader::XmlReader::Result res;
|
|
OUString sManufacturer;
|
|
OUString sName;
|
|
OUString sMeasure;
|
|
|
|
// fill m_aLabels and m_aManufacturers with the predefined labels
|
|
res = reader.nextItem(
|
|
xmlreader::XmlReader::Text::NONE, &name, &nsId);
|
|
assert(
|
|
res == xmlreader::XmlReader::Result::Begin
|
|
&& name == "manufacturers");
|
|
res = reader.nextItem(
|
|
xmlreader::XmlReader::Text::NONE, &name, &nsId);
|
|
while (res != xmlreader::XmlReader::Result::End)
|
|
{
|
|
// Opening manufacturer
|
|
assert(
|
|
res == xmlreader::XmlReader::Result::Begin
|
|
&& name == "manufacturer");
|
|
// Get the name
|
|
(void)reader.nextAttribute(&nsId, &name);
|
|
assert(
|
|
nsId == xmlreader::XmlReader::NAMESPACE_NONE
|
|
&& name == "name");
|
|
sManufacturer = reader.getAttributeValue(false).convertFromUtf8();
|
|
|
|
for(;;) {
|
|
// Opening label or ending manufacturer
|
|
res = reader.nextItem(
|
|
xmlreader::XmlReader::Text::NONE, &name, &nsId);
|
|
if (res == xmlreader::XmlReader::Result::End)
|
|
break;
|
|
assert(
|
|
res == xmlreader::XmlReader::Result::Begin
|
|
&& name == "label");
|
|
// Get name value
|
|
sName = lcl_getValue(reader, xmlreader::Span("name"));
|
|
// Get measure value
|
|
sMeasure = lcl_getValue(reader, xmlreader::Span("measure"));
|
|
// Ending label mark
|
|
lcl_assertEndingItem(reader);
|
|
if ( m_aLabels.find( sManufacturer ) == m_aLabels.end() )
|
|
m_aManufacturers.push_back( sManufacturer );
|
|
m_aLabels[sManufacturer][sName].m_aMeasure = sMeasure;
|
|
m_aLabels[sManufacturer][sName].m_bPredefined = true;
|
|
}
|
|
// Get next manufacturer or end
|
|
res = reader.nextItem(
|
|
xmlreader::XmlReader::Text::NONE, &name, &nsId);
|
|
};
|
|
res = reader.nextItem(
|
|
xmlreader::XmlReader::Text::NONE, &name, &nsId);
|
|
assert(res == xmlreader::XmlReader::Result::Done);
|
|
|
|
// add to m_aLabels and m_aManufacturers the custom labels
|
|
const Sequence<OUString> aMan = GetNodeNames( OUString() );
|
|
for ( const OUString& rManufacturer : aMan )
|
|
{
|
|
const Sequence<OUString> aLabels = GetNodeNames( rManufacturer );
|
|
for( const OUString& rLabel : aLabels )
|
|
{
|
|
OUString sPrefix = rManufacturer + "/" + rLabel + "/";
|
|
Sequence<OUString> aPropNames = lcl_CreatePropertyNames( sPrefix );
|
|
Sequence<Any> aValues = GetProperties( aPropNames );
|
|
const Any* pValues = aValues.getConstArray();
|
|
if (aValues.getLength() >= 1)
|
|
if(pValues[0].hasValue())
|
|
pValues[0] >>= sName;
|
|
if (aValues.getLength() >= 2)
|
|
if(pValues[1].hasValue())
|
|
pValues[1] >>= sMeasure;
|
|
if ( m_aLabels.find( rManufacturer ) == m_aLabels.end() )
|
|
m_aManufacturers.push_back( rManufacturer );
|
|
m_aLabels[rManufacturer][sName].m_aMeasure = sMeasure;
|
|
m_aLabels[rManufacturer][sName].m_bPredefined = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
SwLabelConfig::~SwLabelConfig()
|
|
{
|
|
}
|
|
|
|
// the config item is not writable ?:
|
|
void SwLabelConfig::ImplCommit() {}
|
|
|
|
void SwLabelConfig::Notify( const css::uno::Sequence< OUString >& ) {}
|
|
|
|
static std::unique_ptr<SwLabRec> lcl_CreateSwLabRec(const OUString& rType, std::u16string_view rMeasure, const OUString& rManufacturer)
|
|
{
|
|
std::unique_ptr<SwLabRec> pNewRec(new SwLabRec);
|
|
pNewRec->m_aMake = rManufacturer;
|
|
pNewRec->m_nPWidth = 0;
|
|
pNewRec->m_nPHeight = 0;
|
|
pNewRec->m_aType = rType;
|
|
//all values are contained as colon-separated 1/100 mm values
|
|
//except for the continuous flag ('C'/'S') and nCols, nRows (sal_Int32)
|
|
sal_Int32 nTok{0};
|
|
sal_Int32 nIdx{rMeasure.empty() ? -1 : 0};
|
|
while (nIdx>=0)
|
|
{
|
|
const std::u16string_view sToken(o3tl::getToken(rMeasure, 0, ';', nIdx));
|
|
int nVal = o3tl::toInt32(sToken);
|
|
switch(nTok++)
|
|
{
|
|
case 0 : pNewRec->m_bCont = sToken[0] == 'C'; break;
|
|
case 1 : pNewRec->m_nHDist = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
|
|
case 2 : pNewRec->m_nVDist = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
|
|
case 3 : pNewRec->m_nWidth = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
|
|
case 4 : pNewRec->m_nHeight = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
|
|
case 5 : pNewRec->m_nLeft = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
|
|
case 6 : pNewRec->m_nUpper = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
|
|
case 7 : pNewRec->m_nCols = nVal; break;
|
|
case 8 : pNewRec->m_nRows = nVal; break;
|
|
case 9 : pNewRec->m_nPWidth = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
|
|
case 10 : pNewRec->m_nPHeight = o3tl::toTwips(nVal, o3tl::Length::mm100); break;
|
|
}
|
|
}
|
|
// lines added for compatibility with custom label definitions saved before patch fdo#44516
|
|
if (pNewRec->m_nPWidth == 0 || pNewRec->m_nPHeight == 0)
|
|
{
|
|
// old style definition (no paper dimensions), calculate probable values
|
|
pNewRec->m_nPWidth = 2 * pNewRec->m_nLeft + (pNewRec->m_nCols - 1) * pNewRec->m_nHDist + pNewRec->m_nWidth;
|
|
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 );
|
|
}
|
|
return pNewRec;
|
|
}
|
|
|
|
static Sequence<PropertyValue> lcl_CreateProperties(
|
|
Sequence<OUString> const & rPropNames, OUString& rMeasure, const SwLabRec& rRec)
|
|
{
|
|
const OUString* pNames = rPropNames.getConstArray();
|
|
Sequence<PropertyValue> aRet(rPropNames.getLength());
|
|
PropertyValue* pValues = aRet.getArray();
|
|
OUString sColon(u";"_ustr);
|
|
|
|
for(sal_Int32 nProp = 0; nProp < rPropNames.getLength(); nProp++)
|
|
{
|
|
pValues[nProp].Name = pNames[nProp];
|
|
switch(nProp)
|
|
{
|
|
case 0: pValues[nProp].Value <<= rRec.m_aType; break;
|
|
case 1:
|
|
{
|
|
rMeasure.clear();
|
|
rMeasure += rRec.m_bCont ? std::u16string_view( u"C" ) : std::u16string_view( u"S" ); rMeasure += sColon;
|
|
rMeasure += OUString::number( convertTwipToMm100( rRec.m_nHDist ) ); rMeasure += sColon;
|
|
rMeasure += OUString::number( convertTwipToMm100( rRec.m_nVDist ) ); rMeasure += sColon;
|
|
rMeasure += OUString::number( convertTwipToMm100( rRec.m_nWidth ) ); rMeasure += sColon;
|
|
rMeasure += OUString::number( convertTwipToMm100( rRec.m_nHeight ) ); rMeasure += sColon;
|
|
rMeasure += OUString::number( convertTwipToMm100( rRec.m_nLeft ) ); rMeasure += sColon;
|
|
rMeasure += OUString::number( convertTwipToMm100( rRec.m_nUpper ) ); rMeasure += sColon;
|
|
rMeasure += OUString::number( rRec.m_nCols ); rMeasure += sColon;
|
|
rMeasure += OUString::number( rRec.m_nRows ); rMeasure += sColon;
|
|
rMeasure += OUString::number( convertTwipToMm100( rRec.m_nPWidth ) ); rMeasure += sColon;
|
|
rMeasure += OUString::number( convertTwipToMm100( rRec.m_nPHeight ) );
|
|
pValues[nProp].Value <<= rMeasure;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return aRet;
|
|
}
|
|
|
|
// function fills SwLabDlg with label definitions for manufacturer rManufacturer
|
|
void SwLabelConfig::FillLabels(const OUString& rManufacturer, SwLabRecs& rLabArr)
|
|
{
|
|
if (m_aLabels.find(rManufacturer) == m_aLabels.end())
|
|
return;
|
|
for (const auto& rEntry : m_aLabels[rManufacturer])
|
|
rLabArr.push_back( lcl_CreateSwLabRec(rEntry.first, rEntry.second.m_aMeasure, rManufacturer) );
|
|
}
|
|
|
|
bool SwLabelConfig::HasLabel(const OUString& rManufacturer, const OUString& rType)
|
|
{
|
|
auto it = m_aLabels.find(rManufacturer);
|
|
return ( it != m_aLabels.end() ) && ( it->second.find(rType) != it->second.end() );
|
|
}
|
|
|
|
// label is always saved as a custom label
|
|
// predefined labels can NOT be overwritten by custom labels with same manufacturer/name
|
|
void SwLabelConfig::SaveLabel( const OUString& rManufacturer,
|
|
const OUString& rType, const SwLabRec& rRec )
|
|
{
|
|
OUString sFoundNode;
|
|
bool bManufacturerNodeFound;
|
|
if ( m_aLabels.find( rManufacturer ) == m_aLabels.end() ||
|
|
!GetNodeNames( rManufacturer ).hasElements() )
|
|
{
|
|
bManufacturerNodeFound = false;
|
|
// manufacturer node does not exist, add (and also to m_aManufacturers)
|
|
if ( !AddNode( OUString(), rManufacturer ) )
|
|
{
|
|
OSL_FAIL("New configuration node could not be created");
|
|
return ;
|
|
}
|
|
m_aManufacturers.push_back( rManufacturer );
|
|
}
|
|
else
|
|
bManufacturerNodeFound = true;
|
|
|
|
if ( !bManufacturerNodeFound ||
|
|
m_aLabels[rManufacturer].find( rType ) == m_aLabels[rManufacturer].end() )
|
|
{
|
|
// type does not yet exist, add to config
|
|
const Sequence<OUString> aLabels = GetNodeNames( rManufacturer );
|
|
sal_Int32 nIndex = aLabels.getLength();
|
|
OUString sPrefix( u"Label"_ustr );
|
|
sFoundNode = sPrefix + OUString::number( nIndex );
|
|
while ( comphelper::findValue(aLabels, sFoundNode) != -1 )
|
|
{
|
|
sFoundNode = sPrefix + OUString::number(nIndex++);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// get the appropriate node
|
|
OUString sManufacturer( wrapConfigurationElementName( rManufacturer ) );
|
|
const Sequence<OUString> aLabels = GetNodeNames( sManufacturer );
|
|
for (const OUString& rLabel : aLabels)
|
|
{
|
|
OUString sPrefix = sManufacturer + "/" + rLabel + "/";
|
|
Sequence<OUString> aProperties { sPrefix };
|
|
aProperties.getArray()[0] += "Name";
|
|
Sequence<Any> aValues = GetProperties( aProperties );
|
|
const Any* pValues = aValues.getConstArray();
|
|
if ( pValues[0].hasValue() )
|
|
{
|
|
OUString sTmp;
|
|
pValues[0] >>= sTmp;
|
|
if ( rType == sTmp )
|
|
{
|
|
sFoundNode = rLabel;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
OUString sPrefix = wrapConfigurationElementName( rManufacturer ) +
|
|
"/" + sFoundNode + "/";
|
|
Sequence<OUString> aPropNames = lcl_CreatePropertyNames( sPrefix );
|
|
OUString sMeasure;
|
|
Sequence<PropertyValue> aPropValues = lcl_CreateProperties( aPropNames, sMeasure, rRec );
|
|
SetSetProperties( wrapConfigurationElementName( rManufacturer ), aPropValues );
|
|
|
|
//update m_aLabels
|
|
m_aLabels[rManufacturer][rType].m_aMeasure = sMeasure;
|
|
m_aLabels[rManufacturer][rType].m_bPredefined = false;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|