Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/unoobj/addruno.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
20
#include <com/sun/star/table/CellAddress.hpp>
21
#include <com/sun/star/table/CellRangeAddress.hpp>
22
#include <cppuhelper/supportsservice.hxx>
23
24
#include <svl/itemprop.hxx>
25
#include <vcl/svapp.hxx>
26
27
#include <docsh.hxx>
28
#include <unonames.hxx>
29
#include <miscuno.hxx>
30
#include <convuno.hxx>
31
#include <addruno.hxx>
32
33
using namespace com::sun::star;
34
35
ScAddressConversionObj::ScAddressConversionObj(ScDocShell* pDocSh, bool _bIsRange) :
36
0
    pDocShell( pDocSh ),
37
0
    nRefSheet( 0 ),
38
0
    bIsRange( _bIsRange )
39
0
{
40
0
    pDocShell->GetDocument().AddUnoObject(*this);
41
0
}
42
43
ScAddressConversionObj::~ScAddressConversionObj()
44
0
{
45
0
    SolarMutexGuard g;
46
47
0
    if (pDocShell)
48
0
        pDocShell->GetDocument().RemoveUnoObject(*this);
49
0
}
50
51
void ScAddressConversionObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
52
0
{
53
0
    if ( rHint.GetId() == SfxHintId::Dying )
54
0
    {
55
0
        pDocShell = nullptr;       // invalid
56
0
    }
57
0
}
58
59
bool ScAddressConversionObj::ParseUIString( const OUString& rUIString, ::formula::FormulaGrammar::AddressConvention eConv )
60
0
{
61
0
    if (!pDocShell)
62
0
        return false;
63
64
0
    ScDocument& rDoc = pDocShell->GetDocument();
65
0
    bool bSuccess = false;
66
0
    if ( bIsRange )
67
0
    {
68
0
        ScRefFlags nResult = aRange.ParseAny( rUIString, rDoc, eConv );
69
0
        if ( nResult & ScRefFlags::VALID )
70
0
        {
71
0
            if ( ( nResult & ScRefFlags::TAB_3D ) == ScRefFlags::ZERO )
72
0
                aRange.aStart.SetTab( static_cast<SCTAB>(nRefSheet) );
73
0
            if ( ( nResult & ScRefFlags::TAB2_3D ) == ScRefFlags::ZERO )
74
0
                aRange.aEnd.SetTab( aRange.aStart.Tab() );
75
            // different sheets are not supported in CellRangeAddress
76
0
            if ( aRange.aStart.Tab() == aRange.aEnd.Tab() )
77
0
                bSuccess = true;
78
0
        }
79
0
    }
80
0
    else
81
0
    {
82
0
        ScRefFlags nResult = aRange.aStart.Parse( rUIString, rDoc, eConv );
83
0
        if ( nResult & ScRefFlags::VALID )
84
0
        {
85
0
            if ( ( nResult & ScRefFlags::TAB_3D ) == ScRefFlags::ZERO )
86
0
                aRange.aStart.SetTab( static_cast<SCTAB>(nRefSheet) );
87
0
            bSuccess = true;
88
0
        }
89
0
    }
90
0
    return bSuccess;
91
0
}
92
93
// XPropertySet
94
95
uno::Reference<beans::XPropertySetInfo> SAL_CALL ScAddressConversionObj::getPropertySetInfo()
96
0
{
97
0
    SolarMutexGuard aGuard;
98
99
0
    if ( bIsRange )
100
0
    {
101
0
        static const SfxItemPropertyMapEntry aPropertyMap[] =
102
0
        {
103
0
            { SC_UNONAME_ADDRESS,  0,  cppu::UnoType<table::CellRangeAddress>::get(), 0, 0 },
104
0
            { SC_UNONAME_PERSREPR, 0,  cppu::UnoType<OUString>::get(),    0, 0 },
105
0
            { SC_UNONAME_XLA1REPR, 0,  cppu::UnoType<OUString>::get(),    0, 0 },
106
0
            { SC_UNONAME_REFSHEET, 0,  cppu::UnoType<sal_Int32>::get(),        0, 0 },
107
0
            { SC_UNONAME_UIREPR,   0,  cppu::UnoType<OUString>::get(),    0, 0 },
108
0
            { SC_UNONAME_XLA1REPR, 0,  cppu::UnoType<OUString>::get(),    0, 0 },
109
0
        };
110
0
        static uno::Reference<beans::XPropertySetInfo> aRef(new SfxItemPropertySetInfo( aPropertyMap ));
111
0
        return aRef;
112
0
    }
113
0
    else
114
0
    {
115
0
        static const SfxItemPropertyMapEntry aPropertyMap[] =
116
0
        {
117
0
            { SC_UNONAME_ADDRESS,  0,  cppu::UnoType<table::CellAddress>::get(), 0, 0 },
118
0
            { SC_UNONAME_PERSREPR, 0,  cppu::UnoType<OUString>::get(),    0, 0 },
119
0
            { SC_UNONAME_XLA1REPR, 0,  cppu::UnoType<OUString>::get(),    0, 0 },
120
0
            { SC_UNONAME_REFSHEET, 0,  cppu::UnoType<sal_Int32>::get(),        0, 0 },
121
0
            { SC_UNONAME_UIREPR,   0,  cppu::UnoType<OUString>::get(),    0, 0 },
122
0
            { SC_UNONAME_XLA1REPR, 0,  cppu::UnoType<OUString>::get(),    0, 0 },
123
0
        };
124
0
        static uno::Reference<beans::XPropertySetInfo> aRef(new SfxItemPropertySetInfo( aPropertyMap ));
125
0
        return aRef;
126
0
    }
127
0
}
128
129
void SAL_CALL ScAddressConversionObj::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
130
0
{
131
0
    if ( !pDocShell )
132
0
        throw uno::RuntimeException();
133
134
0
    bool bSuccess = false;
135
0
    if ( aPropertyName == SC_UNONAME_ADDRESS )
136
0
    {
137
        //  read the cell/range address from API struct
138
0
        if ( bIsRange )
139
0
        {
140
0
            table::CellRangeAddress aRangeAddress;
141
0
            if ( aValue >>= aRangeAddress )
142
0
            {
143
0
                ScUnoConversion::FillScRange( aRange, aRangeAddress );
144
0
                bSuccess = true;
145
0
            }
146
0
        }
147
0
        else
148
0
        {
149
0
            table::CellAddress aCellAddress;
150
0
            if ( aValue >>= aCellAddress )
151
0
            {
152
0
                ScUnoConversion::FillScAddress( aRange.aStart, aCellAddress );
153
0
                bSuccess = true;
154
0
            }
155
0
        }
156
0
    }
157
0
    else if ( aPropertyName == SC_UNONAME_REFSHEET )
158
0
    {
159
        //  set the reference sheet
160
0
        sal_Int32 nIntVal = 0;
161
0
        if ( aValue >>= nIntVal )
162
0
        {
163
0
            nRefSheet = nIntVal;
164
0
            bSuccess = true;
165
0
        }
166
0
    }
167
0
    else if ( aPropertyName == SC_UNONAME_UIREPR )
168
0
    {
169
        //  parse the UI representation string
170
0
        OUString sRepresentation;
171
0
        if (aValue >>= sRepresentation)
172
0
        {
173
0
            bSuccess = ParseUIString( sRepresentation );
174
0
        }
175
0
    }
176
0
    else if ( aPropertyName == SC_UNONAME_PERSREPR || aPropertyName == SC_UNONAME_XLA1REPR )
177
0
    {
178
0
        ::formula::FormulaGrammar::AddressConvention eConv = aPropertyName == SC_UNONAME_XLA1REPR ?
179
0
            ::formula::FormulaGrammar::CONV_XL_A1 : ::formula::FormulaGrammar::CONV_OOO;
180
181
        //  parse the file format string
182
0
        OUString sRepresentation;
183
0
        if (aValue >>= sRepresentation)
184
0
        {
185
0
            OUString aUIString(sRepresentation);
186
187
            //  cell or range: strip a single "." at the start
188
0
            if ( aUIString[0]== '.' )
189
0
                aUIString = aUIString.copy( 1 );
190
191
0
            if ( bIsRange )
192
0
            {
193
                //  range: also strip a "." after the last colon
194
0
                sal_Int32 nColon = aUIString.lastIndexOf( ':' );
195
0
                if ( nColon >= 0 && nColon < aUIString.getLength() - 1 &&
196
0
                     aUIString[nColon+1] == '.' )
197
0
                    aUIString = aUIString.replaceAt( nColon+1, 1, u"" );
198
0
            }
199
200
            //  parse the rest like a UI string
201
0
            bSuccess = ParseUIString( aUIString, eConv );
202
0
        }
203
0
    }
204
0
    else
205
0
        throw beans::UnknownPropertyException(aPropertyName);
206
207
0
    if ( !bSuccess )
208
0
        throw lang::IllegalArgumentException();
209
0
}
210
211
uno::Any SAL_CALL ScAddressConversionObj::getPropertyValue( const OUString& aPropertyName )
212
0
{
213
0
    if ( !pDocShell )
214
0
        throw uno::RuntimeException();
215
216
0
    ScDocument& rDoc = pDocShell->GetDocument();
217
0
    uno::Any aRet;
218
219
0
    if ( aPropertyName == SC_UNONAME_ADDRESS )
220
0
    {
221
0
        if ( bIsRange )
222
0
        {
223
0
            table::CellRangeAddress aRangeAddress;
224
0
            ScUnoConversion::FillApiRange( aRangeAddress, aRange );
225
0
            aRet <<= aRangeAddress;
226
0
        }
227
0
        else
228
0
        {
229
0
            table::CellAddress aCellAddress;
230
0
            ScUnoConversion::FillApiAddress( aCellAddress, aRange.aStart );
231
0
            aRet <<= aCellAddress;
232
0
        }
233
0
    }
234
0
    else if ( aPropertyName == SC_UNONAME_REFSHEET )
235
0
    {
236
0
        aRet <<= nRefSheet;
237
0
    }
238
0
    else if ( aPropertyName == SC_UNONAME_UIREPR )
239
0
    {
240
        //  generate UI representation string - include sheet only if different from ref sheet
241
0
        OUString aFormatStr;
242
0
        ScRefFlags nFlags = ScRefFlags::VALID;
243
0
        if ( aRange.aStart.Tab() != nRefSheet )
244
0
            nFlags |= ScRefFlags::TAB_3D;
245
0
        if ( bIsRange )
246
0
            aFormatStr = aRange.Format(rDoc, nFlags);
247
0
        else
248
0
            aFormatStr = aRange.aStart.Format(nFlags, &rDoc);
249
0
        aRet <<= aFormatStr;
250
0
    }
251
0
    else if ( aPropertyName == SC_UNONAME_PERSREPR || aPropertyName == SC_UNONAME_XLA1REPR )
252
0
    {
253
0
        ::formula::FormulaGrammar::AddressConvention eConv = aPropertyName == SC_UNONAME_XLA1REPR ?
254
0
            ::formula::FormulaGrammar::CONV_XL_A1 : ::formula::FormulaGrammar::CONV_OOO;
255
256
        //  generate file format string - always include sheet
257
0
        OUString aFormatStr(aRange.aStart.Format(ScRefFlags::VALID | ScRefFlags::TAB_3D, &rDoc, eConv));
258
0
        if ( bIsRange )
259
0
        {
260
            //  manually concatenate range so both parts always have the sheet name
261
0
            aFormatStr += ":";
262
0
            ScRefFlags nFlags = ScRefFlags::VALID;
263
0
            if( eConv != ::formula::FormulaGrammar::CONV_XL_A1 )
264
0
                nFlags |= ScRefFlags::TAB_3D;
265
0
            OUString aSecond(aRange.aEnd.Format(nFlags, &rDoc, eConv));
266
0
            aFormatStr += aSecond ;
267
0
        }
268
0
        aRet <<= aFormatStr;
269
0
    }
270
0
    else
271
0
        throw beans::UnknownPropertyException(aPropertyName);
272
273
0
    return aRet;
274
0
}
275
276
SC_IMPL_DUMMY_PROPERTY_LISTENER( ScAddressConversionObj )
277
278
// lang::XServiceInfo
279
280
OUString SAL_CALL ScAddressConversionObj::getImplementationName()
281
0
{
282
0
    return u"ScAddressConversionObj"_ustr;
283
0
}
284
285
sal_Bool SAL_CALL ScAddressConversionObj::supportsService( const OUString& rServiceName )
286
0
{
287
0
    return cppu::supportsService(this, rServiceName);
288
0
}
289
290
uno::Sequence<OUString> SAL_CALL ScAddressConversionObj::getSupportedServiceNames()
291
0
{
292
0
    if (bIsRange)
293
0
        return {SC_SERVICENAME_RANGEADDRESS};
294
0
    else
295
0
        return {SC_SERVICENAME_CELLADDRESS};
296
0
}
297
298
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */