/* -*- 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 . */ /** @#file * * export of all variable related text fields (and database display field) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // service names constexpr char16_t sAPI_fieldmaster_prefix[] = u"com.sun.star.text.FieldMaster."; constexpr OUString sAPI_get_expression = u"GetExpression"_ustr; constexpr OUString sAPI_set_expression = u"SetExpression"_ustr; constexpr OUString sAPI_user = u"User"_ustr; constexpr OUString sAPI_database = u"com.sun.star.text.TextField.Database"_ustr; // property names constexpr OUString sAPI_content = u"Content"_ustr; constexpr OUString sAPI_sub_type = u"SubType"_ustr; constexpr OUString sAPI_number_format = u"NumberFormat"_ustr; constexpr OUString sAPI_is_visible = u"IsVisible"_ustr; constexpr OUString sAPI_current_presentation = u"CurrentPresentation"_ustr; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::text; using namespace ::com::sun::star::style; using namespace ::xmloff::token; // XMLVarFieldImportContext: superclass for all variable related fields XMLVarFieldImportContext::XMLVarFieldImportContext( SvXMLImport& rImport, XMLTextImportHelper& rHlp, const OUString& pServiceName, bool bFormula, bool bFormulaDefault, bool bDescription, bool bHelp, bool bHint, bool bVisible, bool bIsDisplayFormula, bool bType, bool bStyle, bool bValue, bool bPresentation) : XMLTextFieldImportContext(rImport, rHlp, pServiceName), aValueHelper(rImport, rHlp, bType, bStyle, bValue, false), bDisplayFormula(false), bDisplayNone(false), bFormulaOK(false), bDescriptionOK(false), bHelpOK(false), bHintOK(false), bDisplayOK(false), bSetFormula(bFormula), bSetFormulaDefault(bFormulaDefault), bSetDescription(bDescription), bSetHelp(bHelp), bSetHint(bHint), bSetVisible(bVisible), bSetDisplayFormula(bIsDisplayFormula), bSetPresentation(bPresentation) { } void XMLVarFieldImportContext::ProcessAttribute( sal_Int32 nAttrToken, std::string_view sAttrValue ) { switch (nAttrToken) { case XML_ELEMENT(TEXT, XML_NAME): sName = OUString::fromUtf8(sAttrValue); bValid = true; // we assume: field with name is valid! break; case XML_ELEMENT(TEXT, XML_DESCRIPTION): sDescription = OUString::fromUtf8(sAttrValue); bDescriptionOK = true; break; case XML_ELEMENT(TEXT, XML_HELP): sHelp = OUString::fromUtf8(sAttrValue); bHelpOK = true; break; case XML_ELEMENT(TEXT, XML_HINT): sHint = OUString::fromUtf8(sAttrValue); bHintOK = true; break; case XML_ELEMENT(TEXT, XML_FORMULA): { OUString sTmp; sal_uInt16 nPrefix = GetImport().GetNamespaceMap(). GetKeyByAttrValueQName(OUString::fromUtf8(sAttrValue), &sTmp); if( XML_NAMESPACE_OOOW == nPrefix ) { sFormula = sTmp; bFormulaOK = true; } else sFormula = OUString::fromUtf8(sAttrValue); } break; case XML_ELEMENT(TEXT, XML_DISPLAY): if (IsXMLToken(sAttrValue, XML_FORMULA)) { bDisplayFormula = true; bDisplayNone = false; bDisplayOK = true; } else if (IsXMLToken(sAttrValue, XML_VALUE)) { bDisplayFormula = false; bDisplayNone = false; bDisplayOK = true; } else if (IsXMLToken(sAttrValue, XML_NONE)) { bDisplayFormula = false; bDisplayNone = true; bDisplayOK = true; } // else: no change DBG_ASSERT(!(bDisplayFormula && bDisplayNone), "illegal display values"); break; default: // delegate all others to value helper aValueHelper.ProcessAttribute(nAttrToken, sAttrValue); break; } } void XMLVarFieldImportContext::PrepareField( const Reference & xPropertySet) { // bSetName: not implemented if (bSetFormula) { if (!bFormulaOK && bSetFormulaDefault) { sFormula = GetContent(); bFormulaOK = true; } if (bFormulaOK) { xPropertySet->setPropertyValue(sAPI_content, Any(sFormula)); } } if (bSetDescription && bDescriptionOK) { xPropertySet->setPropertyValue(u"Hint"_ustr, Any(sDescription)); } if (bSetHelp && bHelpOK) { xPropertySet->setPropertyValue(u"Help"_ustr, Any(sHelp)); } if (bSetHint && bHintOK) { xPropertySet->setPropertyValue(u"Tooltip"_ustr, Any(sHint)); } if (bSetVisible && bDisplayOK) { bool bTmp = !bDisplayNone; xPropertySet->setPropertyValue(sAPI_is_visible, Any(bTmp)); } // workaround for #no-bug#: display formula by default if (xPropertySet->getPropertySetInfo()-> hasPropertyByName(u"IsShowFormula"_ustr) && !bSetDisplayFormula) { bDisplayFormula = false; bSetDisplayFormula = true; } if (bSetDisplayFormula) { bool bTmp = bDisplayFormula && bDisplayOK; xPropertySet->setPropertyValue(u"IsShowFormula"_ustr, Any(bTmp)); } // delegate to value helper aValueHelper.SetDefault(GetContent()); aValueHelper.PrepareField(xPropertySet); // finally, set the current presentation if (bSetPresentation) { Any aAny; aAny <<= GetContent(); xPropertySet->setPropertyValue(sAPI_current_presentation, aAny); } } // variable set fields XMLSetVarFieldImportContext::XMLSetVarFieldImportContext( SvXMLImport& rImport, XMLTextImportHelper& rHlp, const OUString& pServiceName, VarType eVarType, bool bFormula, bool bFormulaDefault, bool bDescription, bool bHelp, bool bHint, bool bVisible, bool bIsDisplayFormula, bool bType, bool bStyle, bool bValue, bool bPresentation) : XMLVarFieldImportContext(rImport, rHlp, pServiceName, bFormula, bFormulaDefault, bDescription, bHelp, bHint, bVisible, bIsDisplayFormula, bType, bStyle, bValue, bPresentation), eFieldType(eVarType) { } void XMLSetVarFieldImportContext::endFastElement(sal_Int32 ) { // should we call PrepareField on the field, or rather on it's master? // currently: call on field (just like superclass) // possible alternatives: call on master // call field or master depending on variable // PrepareMaster() in addition to PrepareField() DBG_ASSERT(!GetServiceName().isEmpty(), "no service name for element!"); if (bValid) { DBG_ASSERT(!GetName().isEmpty(), "variable name needed!"); // find field master Reference xMaster; if (FindFieldMaster(xMaster)) { // create field/Service Reference xPropSet; if (CreateField(xPropSet, "com.sun.star.text.TextField." + GetServiceName())) { Reference xDepTextField(xPropSet, UNO_QUERY); if (xDepTextField.is()) { // attach field to field master xDepTextField->attachTextFieldMaster(xMaster); // attach field to document Reference xTextContent(xPropSet, UNO_QUERY); if (xTextContent.is()) { try { // insert, set field properties and exit! GetImportHelper().InsertTextContent(xTextContent); PrepareField(xPropSet); } catch (lang::IllegalArgumentException & /*e*/) { // ignore e: #i54023# }; return; } } } } } // above: exit on success; so for all error cases we end up here! // write element content GetImportHelper().InsertString(GetContent()); } bool XMLSetVarFieldImportContext::FindFieldMaster( Reference & xMaster) { // currently: delegate to XMLVariableDeclImportContext; // should eventually go here return XMLVariableDeclImportContext::FindFieldMaster(xMaster, GetImport(), GetImportHelper(), GetName(), eFieldType); } // sequence field XMLSequenceFieldImportContext::XMLSequenceFieldImportContext( SvXMLImport& rImport, XMLTextImportHelper& rHlp) : XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression, VarTypeSequence, // formula true, true, false, false, false, false, false, false, false, false, true), sNumFormat(OUString('1')), sNumFormatSync(GetXMLToken(XML_FALSE)), bRefNameOK(false) { } void XMLSequenceFieldImportContext::ProcessAttribute( sal_Int32 nAttrToken, std::string_view sAttrValue ) { switch (nAttrToken) { case XML_ELEMENT(STYLE, XML_NUM_FORMAT): sNumFormat = OUString::fromUtf8(sAttrValue); break; case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC): sNumFormatSync = OUString::fromUtf8(sAttrValue); break; case XML_ELEMENT(TEXT, XML_REF_NAME): sRefName = OUString::fromUtf8(sAttrValue); bRefNameOK = true; break; default: // delegate to super class (name, formula) XMLSetVarFieldImportContext::ProcessAttribute(nAttrToken, sAttrValue); break; } // switch } void XMLSequenceFieldImportContext::PrepareField( const Reference & xPropertySet) { // delegate to super class (formula) XMLSetVarFieldImportContext::PrepareField(xPropertySet); // set format sal_Int16 nNumType = NumberingType::ARABIC; GetImport().GetMM100UnitConverter().convertNumFormat( nNumType, sNumFormat, sNumFormatSync ); xPropertySet->setPropertyValue(sAPI_number_format, Any(nNumType)); // handle reference name if (bRefNameOK) { Any aAny = xPropertySet->getPropertyValue(u"SequenceValue"_ustr); sal_Int16 nValue = 0; aAny >>= nValue; GetImportHelper().InsertSequenceID(sRefName, GetName(), nValue); } } // variable set field XMLVariableSetFieldImportContext::XMLVariableSetFieldImportContext( SvXMLImport& rImport, XMLTextImportHelper& rHlp) : XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression, VarTypeSimple, // formula, value&type, style, // display none true, true, false, false, false, true, false, true, true, true, true) { } void XMLVariableSetFieldImportContext::PrepareField( const Reference & xPropertySet) { // set type Any aAny; aAny <<= (IsStringValue()? SetVariableType::STRING : SetVariableType::VAR); xPropertySet->setPropertyValue(sAPI_sub_type, aAny); // the remainder is handled by super class XMLSetVarFieldImportContext::PrepareField(xPropertySet); } // variable input field XMLVariableInputFieldImportContext::XMLVariableInputFieldImportContext( SvXMLImport& rImport, XMLTextImportHelper& rHlp) : XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression, VarTypeSimple, // description, display none/formula, // value&type, style, formula true, true, true, true, true, true, false, true, true, true, true) { } void XMLVariableInputFieldImportContext::PrepareField( const Reference & xPropertySet) { // set type (input field) Any aAny; xPropertySet->setPropertyValue(u"Input"_ustr, Any(true)); // set type aAny <<= (IsStringValue()? SetVariableType::STRING : SetVariableType::VAR); xPropertySet->setPropertyValue(sAPI_sub_type, aAny); // the remainder is handled by super class XMLSetVarFieldImportContext::PrepareField(xPropertySet); } // user field XMLUserFieldImportContext::XMLUserFieldImportContext( SvXMLImport& rImport, XMLTextImportHelper& rHlp) : XMLSetVarFieldImportContext(rImport, rHlp, sAPI_user, VarTypeUserField, // display none/formula, style false, false, false, false, false, true, true, false, true, false, false) { } // user input field // bug: doesn't work (SO API lacking) XMLUserFieldInputImportContext::XMLUserFieldInputImportContext( SvXMLImport& rImport, XMLTextImportHelper& rHlp) : XMLVarFieldImportContext(rImport, rHlp, u"InputUser"_ustr, // description, style false, false, true, false, false, false, false, false /*???*/, true, false, false) { } void XMLUserFieldInputImportContext::PrepareField( const Reference & xPropertySet) { xPropertySet->setPropertyValue(sAPI_content, Any(GetName())); // delegate to super class XMLVarFieldImportContext::PrepareField(xPropertySet); } // variable get field XMLVariableGetFieldImportContext::XMLVariableGetFieldImportContext( SvXMLImport& rImport, XMLTextImportHelper& rHlp) : XMLVarFieldImportContext(rImport, rHlp, sAPI_get_expression, // style, display formula false, false, false, false, false, false, true, true, true, false, true) { } void XMLVariableGetFieldImportContext::PrepareField( const Reference & xPropertySet) { // set name xPropertySet->setPropertyValue(sAPI_content, Any(GetName())); // the remainder is handled by super class XMLVarFieldImportContext::PrepareField(xPropertySet); } // expression field XMLExpressionFieldImportContext::XMLExpressionFieldImportContext( SvXMLImport& rImport, XMLTextImportHelper& rHlp) : XMLVarFieldImportContext(rImport, rHlp, sAPI_get_expression, // formula, type, style, display formula true, true, false, false, false, false, true, true, true, false, true) { bValid = true; // always valid } void XMLExpressionFieldImportContext::PrepareField( const Reference & xPropertySet) { xPropertySet->setPropertyValue(sAPI_sub_type, Any(sal_Int16(SetVariableType::FORMULA))); // delegate to super class XMLVarFieldImportContext::PrepareField(xPropertySet); } // text input field XMLTextInputFieldImportContext::XMLTextInputFieldImportContext( SvXMLImport& rImport, XMLTextImportHelper& rHlp) : XMLVarFieldImportContext(rImport, rHlp, u"Input"_ustr, // description false, false, true, true, true, false, false, false, false, false, false) { bValid = true; // always valid } void XMLTextInputFieldImportContext::PrepareField( const Reference & xPropertySet) { XMLVarFieldImportContext::PrepareField(xPropertySet); xPropertySet->setPropertyValue(sAPI_content, Any(GetContent())); } // table formula field XMLTableFormulaImportContext::XMLTableFormulaImportContext( SvXMLImport& rImport, XMLTextImportHelper& rHlp) : XMLTextFieldImportContext(rImport, rHlp, u"TableFormula"_ustr), aValueHelper(rImport, rHlp, false, true, false, true), bIsShowFormula(false) { } void XMLTableFormulaImportContext::ProcessAttribute( sal_Int32 nAttrToken, std::string_view sAttrValue ) { switch (nAttrToken) { case XML_ELEMENT(TEXT, XML_FORMULA): aValueHelper.ProcessAttribute( nAttrToken, sAttrValue ); bValid = true; // we need a formula! break; case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME): aValueHelper.ProcessAttribute( nAttrToken, sAttrValue ); break; case XML_ELEMENT(TEXT, XML_DISPLAY): if ( sAttrValue == "formula" ) bIsShowFormula = true; break; default: // unknown attribute -> ignore XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue); break; } } void XMLTableFormulaImportContext::PrepareField( const Reference & xPropertySet) { // set format and formula aValueHelper.PrepareField( xPropertySet ); Any aAny; // set 'show formula' and presentation xPropertySet->setPropertyValue( u"IsShowFormula"_ustr, Any(bIsShowFormula) ); aAny <<= GetContent(); xPropertySet->setPropertyValue( u"CurrentPresentation"_ustr, aAny ); } // variable declarations // Should be adapted to XMLVarField-/XMLSetVarFieldImportContext scheme! // declaration container import () XMLVariableDeclsImportContext::XMLVariableDeclsImportContext( SvXMLImport& rImport, XMLTextImportHelper& rHlp, enum VarType eVarType) : SvXMLImportContext(rImport), eVarDeclsContextType(eVarType), rImportHelper(rHlp) { } css::uno::Reference< css::xml::sax::XFastContextHandler > XMLVariableDeclsImportContext::createFastChildContext( sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) { if( IsTokenInNamespace(nElement, XML_NAMESPACE_TEXT) ) { enum XMLTokenEnum eElementName; switch (eVarDeclsContextType) { case VarTypeSequence: eElementName = XML_SEQUENCE_DECL; break; case VarTypeSimple: eElementName = XML_VARIABLE_DECL; break; case VarTypeUserField: eElementName = XML_USER_FIELD_DECL; break; default: OSL_FAIL("unknown field type!"); eElementName = XML_SEQUENCE_DECL; break; } if( nElement == XML_ELEMENT(TEXT, eElementName) ) { return new XMLVariableDeclImportContext( GetImport(), rImportHelper, nElement, xAttrList, eVarDeclsContextType); } } // if no context was created, use default context return nullptr; } // declaration import ( elements) XMLVariableDeclImportContext::XMLVariableDeclImportContext( SvXMLImport& rImport, XMLTextImportHelper& rHlp, sal_Int32 nElement, const Reference & xAttrList, enum VarType eVarType) : SvXMLImportContext(rImport) { // bug?? which properties for userfield/userfieldmaster XMLValueImportHelper aValueHelper(rImport, rHlp, true, false, true, false); sal_Unicode cSeparationChar('.'); sal_Int8 nNumLevel(-1); OUString sName; if (nElement != XML_ELEMENT(TEXT, XML_SEQUENCE_DECL) && nElement != XML_ELEMENT(TEXT, XML_VARIABLE_DECL) && nElement != XML_ELEMENT(TEXT, XML_USER_FIELD_DECL) ) return; // TODO: check validity (need name!) // parse attributes for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList )) { switch (aIter.getToken()) { case XML_ELEMENT(TEXT, XML_NAME): sName = aIter.toString(); break; case XML_ELEMENT(TEXT, XML_DISPLAY_OUTLINE_LEVEL): { sal_Int32 nLevel; bool const bRet = ::sax::Converter::convertNumber( nLevel, aIter.toView(), 0, GetImport().GetTextImport()->GetChapterNumbering()-> getCount()); if (bRet) { nNumLevel = static_cast< sal_Int8 >( nLevel-1 ); // API numbers -1..9 } break; } case XML_ELEMENT(TEXT, XML_SEPARATION_CHARACTER): cSeparationChar = static_cast(aIter.toString().toChar()); break; default: // delegate to value helper aValueHelper.ProcessAttribute(aIter.getToken(), aIter.toView()); break; } } Reference xFieldMaster; if (!FindFieldMaster(xFieldMaster, GetImport(), rHlp, sName, eVarType)) return; // now we have a field master: process attributes! Any aAny; switch (eVarType) { case VarTypeSequence: xFieldMaster->setPropertyValue(u"ChapterNumberingLevel"_ustr, Any(nNumLevel)); if (nNumLevel >= 0) { OUString sStr(&cSeparationChar, 1); xFieldMaster->setPropertyValue( u"NumberingSeparator"_ustr, Any(sStr)); } break; case VarTypeSimple: { // set string or non-string SubType (#93192#) // The SubType was already set in the FindFieldMaster // method, but it needs to be adjusted if it's a string. aAny <<= aValueHelper.IsStringValue() ? SetVariableType::STRING : SetVariableType::VAR; xFieldMaster->setPropertyValue(sAPI_sub_type, aAny); } break; case VarTypeUserField: { bool bTmp = !aValueHelper.IsStringValue(); xFieldMaster->setPropertyValue(u"IsExpression"_ustr, Any(bTmp)); aValueHelper.PrepareField(xFieldMaster); break; } default: OSL_FAIL("unknown varfield type"); } // switch } bool XMLVariableDeclImportContext::FindFieldMaster( Reference & xMaster, SvXMLImport& rImport, XMLTextImportHelper& rImportHelper, const OUString& sVarName, enum VarType eVarType) { static sal_Int32 nCollisionCount = 0; // rename field // currently: no family in use! Use 0. OUString sName = rImportHelper.GetRenameMap().Get( sal::static_int_cast< sal_uInt16 >(eVarType), sVarName); // get text fields supplier and field masters Reference xTextFieldsSupp(rImport.GetModel(), UNO_QUERY); Reference xFieldMasterNameAccess = xTextFieldsSupp->getTextFieldMasters(); OUString sVarServiceName = OUString::Concat(sAPI_fieldmaster_prefix) + sAPI_set_expression + "." + sName; OUString sUserServiceName = OUString::Concat(sAPI_fieldmaster_prefix) + sAPI_user + "." + sName; if (xFieldMasterNameAccess->hasByName(sVarServiceName)) { // variable field master already in document Any aAny = xFieldMasterNameAccess->getByName(sVarServiceName); aAny >>= xMaster; aAny = xMaster->getPropertyValue(sAPI_sub_type); sal_Int16 nType = 0; aAny >>= nType; enum VarType eFMVarType = (SetVariableType::SEQUENCE == nType) ? VarTypeSequence : VarTypeSimple; if (eFMVarType != eVarType) { ++nCollisionCount; OUString sNew(sName + "_renamed_" + OUString::number(nCollisionCount)); // FIXME! can't find if name is taken already!!!! rImportHelper.GetRenameMap().Add( sal::static_int_cast< sal_uInt16 >(eVarType), sName, sNew); // call FindFieldMaster recursively to create new master return FindFieldMaster(xMaster, rImport, rImportHelper, sNew, eVarType); } } else if (xFieldMasterNameAccess->hasByName(sUserServiceName)) { // user field: get field master Any aAny = xFieldMasterNameAccess->getByName(sUserServiceName); aAny >>= xMaster; if (VarTypeUserField != eVarType) { ++nCollisionCount; // find new name that is not taken OUString sNew(sName + "_renamed_" + OUString::number(nCollisionCount)); // FIXME! can't find if name is taken already!!!! rImportHelper.GetRenameMap().Add( sal::static_int_cast< sal_uInt16 >(eVarType), sName, sNew); // call FindFieldMaster recursively to create new master return FindFieldMaster(xMaster, rImport, rImportHelper, sNew, eVarType); } } else { // field name not used: create field master // import -> model is MultiServiceFactory -> createInstance Reference xFactory(rImport.GetModel(),UNO_QUERY); if( xFactory.is() ) { OUString sService = sAPI_fieldmaster_prefix + ((eVarType==VarTypeUserField) ? sAPI_user : sAPI_set_expression); Reference xIfc = xFactory->createInstance( sService ); if (xIfc.is()) { xMaster.set(xIfc, UNO_QUERY); // set name xMaster->setPropertyValue(u"Name"_ustr, Any(sName)); if (eVarType != VarTypeUserField) { // set subtype for setexp field Any aAny; aAny <<= ((eVarType == VarTypeSimple) ? SetVariableType::VAR : SetVariableType::SEQUENCE); xMaster->setPropertyValue(sAPI_sub_type, aAny); } // else : user field: no subtype } else { return false; } } else { return false; } } DBG_ASSERT(xMaster.is(), "no field master found!?!"); return true; } // Database Display field import XMLDatabaseDisplayImportContext::XMLDatabaseDisplayImportContext( SvXMLImport& rImport, XMLTextImportHelper& rHlp) : XMLDatabaseFieldImportContext(rImport, rHlp, sAPI_database, false), aValueHelper(rImport, rHlp, false, true, false, false), bColumnOK(false), bDisplay( true ), bDisplayOK( false ) { } void XMLDatabaseDisplayImportContext::ProcessAttribute( sal_Int32 nAttrToken, std::string_view sAttrValue ) { switch (nAttrToken) { case XML_ELEMENT(TEXT, XML_COLUMN_NAME): sColumnName = OUString::fromUtf8(sAttrValue); bColumnOK = true; break; case XML_ELEMENT(TEXT, XML_DISPLAY): { bool bNone = IsXMLToken( sAttrValue, XML_NONE ); bool bValue = IsXMLToken( sAttrValue, XML_VALUE ); bDisplay = bValue; bDisplayOK = bNone || bValue; } break; case XML_ELEMENT(TEXT, XML_DATABASE_NAME): case XML_ELEMENT(TEXT, XML_TABLE_NAME): case XML_ELEMENT(TEXT, XML_TABLE_TYPE): // handled by super class XMLDatabaseFieldImportContext::ProcessAttribute(nAttrToken, sAttrValue); break; default: // remainder handled by value helper aValueHelper.ProcessAttribute(nAttrToken, sAttrValue); break; } bValid = m_bTableOK && m_bDatabaseOK && bColumnOK; } void XMLDatabaseDisplayImportContext::endFastElement(sal_Int32 ) { // we have an EndElement of our own, because database fields need // to be attached to a field master before they can be inserted into // the document. Database stuff (database, table, column) all goes // to the field master, value & style go to the field. if (bValid) { // so here goes: we start with the master Reference xMaster; // create and prepare field master first if (CreateField(xMaster, u"com.sun.star.text.FieldMaster.Database"_ustr)) { Any aAny; xMaster->setPropertyValue(u"DataColumnName"_ustr, Any(sColumnName)); // fieldmaster takes database, table and column name XMLDatabaseFieldImportContext::PrepareField(xMaster); // create field Reference xField; if (CreateField(xField, sAPI_database)) { // attach field master Reference xDepField(xField, UNO_QUERY); if (xDepField.is()) { // attach field to field master xDepField->attachTextFieldMaster(xMaster); // attach field to document Reference xTextContent(xField, UNO_QUERY); if (xTextContent.is()) { // insert, set field properties and exit! try { GetImportHelper().InsertTextContent(xTextContent); // prepare field: format from database? bool bTmp = !aValueHelper.IsFormatOK(); xField->setPropertyValue(u"DataBaseFormat"_ustr, Any(bTmp)); // value, value-type and format done by value helper aValueHelper.PrepareField(xField); // visibility if( bDisplayOK ) { xField->setPropertyValue(sAPI_is_visible, Any(bDisplay)); } // set presentation aAny <<= GetContent(); xField->setPropertyValue(sAPI_current_presentation, aAny); // success! return; } catch (const lang::IllegalArgumentException&) { TOOLS_WARN_EXCEPTION("xmloff.text", "Failed to insert text content"); } } } } } } // above: exit on success; so for all error cases we end up here! // write element content GetImportHelper().InsertString(GetContent()); } // value import helper namespace { enum ValueType { XML_VALUE_TYPE_STRING, XML_VALUE_TYPE_FLOAT, XML_VALUE_TYPE_CURRENCY, XML_VALUE_TYPE_PERCENTAGE, XML_VALUE_TYPE_DATE, XML_VALUE_TYPE_TIME, XML_VALUE_TYPE_BOOLEAN }; } SvXMLEnumMapEntry const aValueTypeMap[] = { { XML_FLOAT, XML_VALUE_TYPE_FLOAT }, { XML_CURRENCY, XML_VALUE_TYPE_CURRENCY }, { XML_PERCENTAGE, XML_VALUE_TYPE_PERCENTAGE }, { XML_DATE, XML_VALUE_TYPE_DATE }, { XML_TIME, XML_VALUE_TYPE_TIME }, { XML_BOOLEAN, XML_VALUE_TYPE_BOOLEAN }, { XML_STRING, XML_VALUE_TYPE_STRING }, { XML_TOKEN_INVALID, ValueType(0) } }; XMLValueImportHelper::XMLValueImportHelper( SvXMLImport& rImprt, XMLTextImportHelper& rHlp, bool bType, bool bStyle, bool bValue, bool bFormula) : rImport(rImprt), rHelper(rHlp), fValue(0.0), nFormatKey(0), bIsDefaultLanguage(true), bStringType(false), bFormatOK(false), bStringValueOK(false), bFormulaOK(false), bSetType(bType), bSetValue(bValue), bSetStyle(bStyle), bSetFormula(bFormula) { } void XMLValueImportHelper::ProcessAttribute( sal_Int32 nAttrToken, std::string_view sAttrValue ) { switch (nAttrToken) { case XML_ELEMENT(TEXT, XML_VALUE_TYPE): // #i32362#: src680m48++ saves text:value-type case XML_ELEMENT(OFFICE, XML_VALUE_TYPE): { // convert enum ValueType eValueType = XML_VALUE_TYPE_STRING; bool bRet = SvXMLUnitConverter::convertEnum( eValueType, sAttrValue, aValueTypeMap); if (bRet) { switch (eValueType) { case XML_VALUE_TYPE_STRING: bStringType = true; break; case XML_VALUE_TYPE_FLOAT: case XML_VALUE_TYPE_CURRENCY: case XML_VALUE_TYPE_PERCENTAGE: case XML_VALUE_TYPE_DATE: case XML_VALUE_TYPE_TIME: case XML_VALUE_TYPE_BOOLEAN: bStringType = false; break; default: OSL_FAIL("unknown value type"); } } break; } case XML_ELEMENT(TEXT, XML_VALUE): case XML_ELEMENT(OFFICE, XML_VALUE): { double fTmp; bool const bRet = ::sax::Converter::convertDouble(fTmp,sAttrValue); if (bRet) { fValue = fTmp; } break; } case XML_ELEMENT(TEXT, XML_TIME_VALUE): case XML_ELEMENT(OFFICE, XML_TIME_VALUE): { double fTmp; bool const bRet = ::sax::Converter::convertDuration(fTmp, sAttrValue); if (bRet) { fValue = fTmp; } break; } case XML_ELEMENT(TEXT, XML_DATE_VALUE): case XML_ELEMENT(OFFICE, XML_DATE_VALUE): { double fTmp; bool bRet = rImport.GetMM100UnitConverter(). convertDateTime(fTmp,sAttrValue); if (bRet) { fValue = fTmp; } break; } case XML_ELEMENT(OFFICE, XML_BOOLEAN_VALUE): { bool bTmp(false); bool bRet = ::sax::Converter::convertBool(bTmp, sAttrValue); if (bRet) { fValue = (bTmp ? 1.0 : 0.0); } else { double fTmp; bRet = ::sax::Converter::convertDouble(fTmp, sAttrValue); if (bRet) { fValue = fTmp; } } break; } case XML_ELEMENT(TEXT, XML_STRING_VALUE): case XML_ELEMENT(OFFICE, XML_STRING_VALUE): sValue = OUString::fromUtf8(sAttrValue); bStringValueOK = true; break; case XML_ELEMENT(TEXT, XML_FORMULA): { OUString sTmp; sal_uInt16 nPrefix = rImport.GetNamespaceMap(). GetKeyByAttrValueQName(OUString::fromUtf8(sAttrValue), &sTmp); if( XML_NAMESPACE_OOOW == nPrefix ) { sFormula = sTmp; bFormulaOK = true; } else sFormula = OUString::fromUtf8(sAttrValue); } break; case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME): { sal_Int32 nKey = rHelper.GetDataStyleKey( OUString::fromUtf8(sAttrValue), &bIsDefaultLanguage); if (-1 != nKey) { nFormatKey = nKey; bFormatOK = true; } break; } default: XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue); } // switch } void XMLValueImportHelper::PrepareField( const Reference & xPropertySet) { Any aAny; if (bSetType) { // ??? how to set type? } if (bSetFormula) { aAny <<= !bFormulaOK ? sDefault : sFormula; xPropertySet->setPropertyValue(sAPI_content, aAny); } // format/style if (bSetStyle && bFormatOK) { xPropertySet->setPropertyValue(sAPI_number_format, Any(nFormatKey)); if( xPropertySet->getPropertySetInfo()-> hasPropertyByName( u"IsFixedLanguage"_ustr ) ) { bool bIsFixedLanguage = ! bIsDefaultLanguage; xPropertySet->setPropertyValue( u"IsFixedLanguage"_ustr, Any(bIsFixedLanguage) ); } } // value: string or float if (bSetValue) { if (bStringType) { aAny <<= !bStringValueOK ? sDefault : sValue; xPropertySet->setPropertyValue(sAPI_content, aAny); } else { xPropertySet->setPropertyValue(u"Value"_ustr, Any(fValue)); } } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */