From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- svtools/source/table/cellvalueconversion.cxx | 376 +++++++++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 svtools/source/table/cellvalueconversion.cxx (limited to 'svtools/source/table/cellvalueconversion.cxx') diff --git a/svtools/source/table/cellvalueconversion.cxx b/svtools/source/table/cellvalueconversion.cxx new file mode 100644 index 000000000..53177af0d --- /dev/null +++ b/svtools/source/table/cellvalueconversion.cxx @@ -0,0 +1,376 @@ +/* -*- 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 "cellvalueconversion.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace svt +{ +using namespace ::com::sun::star::uno; +using ::com::sun::star::util::XNumberFormatter; +using ::com::sun::star::util::NumberFormatter; +using ::com::sun::star::util::XNumberFormatsSupplier; +using ::com::sun::star::util::NumberFormatsSupplier; +using ::com::sun::star::beans::XPropertySet; +using ::com::sun::star::lang::Locale; +using ::com::sun::star::util::DateTime; +using ::com::sun::star::util::XNumberFormatTypes; + +namespace NumberFormat = ::com::sun::star::util::NumberFormat; + +//= helper + +namespace +{ +double lcl_convertDateToDays(sal_uInt16 const i_day, sal_uInt16 const i_month, + sal_Int16 const i_year) +{ + tools::Long const nNullDateDays = ::Date::DateToDays(1, 1, 1900); + tools::Long const nValueDateDays = ::Date::DateToDays(i_day, i_month, i_year); + + return nValueDateDays - nNullDateDays; +} + +double lcl_convertTimeToDays(tools::Long const i_hours, tools::Long const i_minutes, + tools::Long const i_seconds, tools::Long const i_100thSeconds) +{ + return tools::Time(i_hours, i_minutes, i_seconds, i_100thSeconds).GetTimeInDays(); +} +} + +//= StandardFormatNormalizer + +StandardFormatNormalizer::StandardFormatNormalizer(Reference const& i_formatter, + ::sal_Int32 const i_numberFormatType) + : m_nFormatKey(0) +{ + try + { + ENSURE_OR_THROW(i_formatter.is(), "StandardFormatNormalizer: no formatter!"); + Reference const xSupplier(i_formatter->getNumberFormatsSupplier(), + UNO_SET_THROW); + Reference const xTypes(xSupplier->getNumberFormats(), UNO_QUERY_THROW); + m_nFormatKey = xTypes->getStandardFormat(i_numberFormatType, + SvtSysLocale().GetLanguageTag().getLocale()); + } + catch (const Exception&) + { + DBG_UNHANDLED_EXCEPTION("svtools.table"); + } +} + +//= DoubleNormalization + +namespace +{ +class DoubleNormalization : public StandardFormatNormalizer +{ +public: + explicit DoubleNormalization(Reference const& i_formatter) + : StandardFormatNormalizer(i_formatter, NumberFormat::NUMBER) + { + } + + virtual double convertToDouble(Any const& i_value) const override + { + double returnValue = std::numeric_limits::quiet_NaN(); + OSL_VERIFY(i_value >>= returnValue); + return returnValue; + } +}; + +//= IntegerNormalization + +class IntegerNormalization : public StandardFormatNormalizer +{ +public: + explicit IntegerNormalization(Reference const& i_formatter) + : StandardFormatNormalizer(i_formatter, NumberFormat::NUMBER) + { + } + + virtual double convertToDouble(Any const& i_value) const override + { + sal_Int64 value(0); + OSL_VERIFY(i_value >>= value); + return value; + } +}; + +//= BooleanNormalization + +class BooleanNormalization : public StandardFormatNormalizer +{ +public: + explicit BooleanNormalization(Reference const& i_formatter) + : StandardFormatNormalizer(i_formatter, NumberFormat::LOGICAL) + { + } + + virtual double convertToDouble(Any const& i_value) const override + { + bool value(false); + OSL_VERIFY(i_value >>= value); + return value ? 1 : 0; + } +}; + +//= DateTimeNormalization + +class DateTimeNormalization : public StandardFormatNormalizer +{ +public: + explicit DateTimeNormalization(Reference const& i_formatter) + : StandardFormatNormalizer(i_formatter, NumberFormat::DATETIME) + { + } + + virtual double convertToDouble(Any const& i_value) const override + { + double returnValue = std::numeric_limits::quiet_NaN(); + + // extract actual UNO value + DateTime aDateTimeValue; + ENSURE_OR_RETURN(i_value >>= aDateTimeValue, "allowed for DateTime values only", + returnValue); + + // date part + returnValue + = lcl_convertDateToDays(aDateTimeValue.Day, aDateTimeValue.Month, aDateTimeValue.Year); + + // time part + returnValue += lcl_convertTimeToDays(aDateTimeValue.Hours, aDateTimeValue.Minutes, + aDateTimeValue.Seconds, aDateTimeValue.NanoSeconds); + + // done + return returnValue; + } +}; + +//= DateNormalization + +class DateNormalization : public StandardFormatNormalizer +{ +public: + explicit DateNormalization(Reference const& i_formatter) + : StandardFormatNormalizer(i_formatter, NumberFormat::DATE) + { + } + + virtual double convertToDouble(Any const& i_value) const override + { + double returnValue = std::numeric_limits::quiet_NaN(); + + // extract + css::util::Date aDateValue; + ENSURE_OR_RETURN(i_value >>= aDateValue, "allowed for Date values only", returnValue); + + // convert + returnValue = lcl_convertDateToDays(aDateValue.Day, aDateValue.Month, aDateValue.Year); + + // done + return returnValue; + } +}; + +//= TimeNormalization + +class TimeNormalization : public StandardFormatNormalizer +{ +public: + explicit TimeNormalization(Reference const& i_formatter) + : StandardFormatNormalizer(i_formatter, NumberFormat::TIME) + { + } + + virtual double convertToDouble(Any const& i_value) const override + { + double returnValue = std::numeric_limits::quiet_NaN(); + + // extract + css::util::Time aTimeValue; + ENSURE_OR_RETURN(i_value >>= aTimeValue, "allowed for tools::Time values only", + returnValue); + + // convert + returnValue += lcl_convertTimeToDays(aTimeValue.Hours, aTimeValue.Minutes, + aTimeValue.Seconds, aTimeValue.NanoSeconds); + + // done + return returnValue; + } +}; +} + +//= operations + +bool CellValueConversion::ensureNumberFormatter() +{ + if (bAttemptedFormatterCreation) + return xNumberFormatter.is(); + bAttemptedFormatterCreation = true; + + try + { + Reference xContext = ::comphelper::getProcessComponentContext(); + // a number formatter + Reference const xFormatter(NumberFormatter::create(xContext), + UNO_QUERY_THROW); + + // a supplier of number formats + Locale aLocale = SvtSysLocale().GetLanguageTag().getLocale(); + + Reference const xSupplier + = NumberFormatsSupplier::createWithLocale(xContext, aLocale); + + // ensure a NullDate we will assume later on + css::util::Date const aNullDate(1, 1, 1900); + Reference const xFormatSettings(xSupplier->getNumberFormatSettings(), + UNO_SET_THROW); + xFormatSettings->setPropertyValue("NullDate", Any(aNullDate)); + + // knit + xFormatter->attachNumberFormatsSupplier(xSupplier); + + // done + xNumberFormatter = xFormatter; + } + catch (const Exception&) + { + DBG_UNHANDLED_EXCEPTION("svtools.table"); + } + + return xNumberFormatter.is(); +} + +bool CellValueConversion::getValueNormalizer(Type const& i_valueType, + std::shared_ptr& o_formatter) +{ + auto pos = aNormalizers.find(i_valueType.getTypeName()); + if (pos == aNormalizers.end()) + { + // never encountered this type before + o_formatter.reset(); + + OUString const sTypeName(i_valueType.getTypeName()); + TypeClass const eTypeClass = i_valueType.getTypeClass(); + + if (sTypeName == ::cppu::UnoType::get().getTypeName()) + { + o_formatter = std::make_shared(xNumberFormatter); + } + else if (sTypeName == ::cppu::UnoType::get().getTypeName()) + { + o_formatter = std::make_shared(xNumberFormatter); + } + else if (sTypeName == ::cppu::UnoType::get().getTypeName()) + { + o_formatter = std::make_shared(xNumberFormatter); + } + else if (sTypeName == ::cppu::UnoType::get().getTypeName()) + { + o_formatter = std::make_shared(xNumberFormatter); + } + else if (sTypeName == ::cppu::UnoType::get().getTypeName() + || sTypeName == ::cppu::UnoType::get().getTypeName()) + { + o_formatter = std::make_shared(xNumberFormatter); + } + else if ((eTypeClass == TypeClass_BYTE) || (eTypeClass == TypeClass_SHORT) + || (eTypeClass == TypeClass_UNSIGNED_SHORT) || (eTypeClass == TypeClass_LONG) + || (eTypeClass == TypeClass_UNSIGNED_LONG) || (eTypeClass == TypeClass_HYPER)) + { + o_formatter = std::make_shared(xNumberFormatter); + } + else + { + SAL_WARN("svtools.table", "unsupported type '" << sTypeName << "'!"); + } + aNormalizers[sTypeName] = o_formatter; + } + else + o_formatter = pos->second; + + return bool(o_formatter); +} + +//= CellValueConversion + +CellValueConversion::CellValueConversion() + : xNumberFormatter() + , bAttemptedFormatterCreation(false) + , aNormalizers() +{ +} + +CellValueConversion::~CellValueConversion() {} + +OUString CellValueConversion::convertToString(const Any& i_value) +{ + OUString sStringValue; + if (!i_value.hasValue()) + return sStringValue; + + if (!(i_value >>= sStringValue)) + { + if (ensureNumberFormatter()) + { + std::shared_ptr pNormalizer; + if (getValueNormalizer(i_value.getValueType(), pNormalizer)) + { + try + { + double const formatterCompliantValue = pNormalizer->convertToDouble(i_value); + sal_Int32 const formatKey = pNormalizer->getFormatKey(); + sStringValue = xNumberFormatter->convertNumberToString(formatKey, + formatterCompliantValue); + } + catch (const Exception&) + { + DBG_UNHANDLED_EXCEPTION("svtools.table"); + } + } + } + } + + return sStringValue; +} + +} // namespace svt + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3