Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/uitest/uiobject.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
10
#include <memory>
11
#include <uiobject.hxx>
12
#include <drawview.hxx>
13
14
#include <rangeutl.hxx>
15
#include <gridwin.hxx>
16
17
#include <viewdata.hxx>
18
#include <viewfunc.hxx>
19
#include <dbfunc.hxx>
20
#include <tabvwsh.hxx>
21
#include <drwlayer.hxx>
22
#include <sfx2/sidebar/Sidebar.hxx>
23
#include <sfx2/viewfrm.hxx>
24
#include <sfx2/dispatch.hxx>
25
#include <appoptio.hxx>
26
#include <scmod.hxx>
27
#include <fudraw.hxx>
28
#include <postit.hxx>
29
30
#include <com/sun/star/embed/EmbedVerbs.hpp>
31
32
#include <svx/svditer.hxx>
33
#include <svx/svdobj.hxx>
34
#include <svx/svdoole2.hxx>
35
#include <sal/log.hxx>
36
37
namespace {
38
39
ScAddress get_address_from_string(const ScDocument& rDoc, std::u16string_view aStr)
40
0
{
41
0
    ScAddress aAddr;
42
0
    sal_Int32 nOffset = 0;
43
0
    ScRangeStringConverter::GetAddressFromString(aAddr, aStr, rDoc, formula::FormulaGrammar::CONV_OOO, nOffset);
44
0
    return aAddr;
45
0
}
46
47
ScRange get_range_from_string(const ScDocument& rDoc, std::u16string_view aStr)
48
0
{
49
0
    ScRange aRange;
50
0
    sal_Int32 nOffset = 0;
51
0
    ScRangeStringConverter::GetRangeFromString(aRange, aStr, rDoc, formula::FormulaGrammar::CONV_OOO, nOffset);
52
53
0
    return aRange;
54
0
}
55
56
}
57
58
ScGridWinUIObject::ScGridWinUIObject(const VclPtr<ScGridWindow>& xGridWin):
59
0
    WindowUIObject(xGridWin),
60
0
    mxGridWindow(xGridWin)
61
0
{
62
0
}
63
64
StringMap ScGridWinUIObject::get_state()
65
0
{
66
0
    StringMap aMap = WindowUIObject::get_state();
67
68
0
    aMap[u"SelectedTable"_ustr] = OUString::number(mxGridWindow->getViewData().CurrentTabForData());
69
0
    aMap[u"CurrentColumn"_ustr] = OUString::number(mxGridWindow->getViewData().GetCurX());
70
0
    aMap[u"CurrentRow"_ustr] = OUString::number(mxGridWindow->getViewData().GetCurY());
71
72
0
    ScSplitPos eAlign = mxGridWindow->getViewData().GetActivePart();
73
0
    ScHSplitPos eAlignX = WhichH(eAlign);
74
0
    ScVSplitPos eAlignY = WhichV(eAlign);
75
0
    aMap[u"TopVisibleRow"_ustr] = OUString::number(mxGridWindow->getViewData().GetPosY(eAlignY));
76
0
    aMap[u"TopVisibleColumn"_ustr] = OUString::number(mxGridWindow->getViewData().GetPosX(eAlignX));
77
78
0
    ScRangeList aMarkedArea = mxGridWindow->getViewData().GetMarkData().GetMarkedRanges();
79
0
    OUString aMarkedAreaString;
80
0
    ScRangeStringConverter::GetStringFromRangeList(aMarkedAreaString, &aMarkedArea, &mxGridWindow->getViewData().GetDocument(), formula::FormulaGrammar::CONV_OOO);
81
82
0
    aMap[u"MarkedArea"_ustr] = aMarkedAreaString;
83
84
0
    ScDocument& rDoc = mxGridWindow->getViewData().GetDocument();
85
0
    ScAddress aPos( mxGridWindow->getViewData().GetCurX() , mxGridWindow->getViewData().GetCurY() , mxGridWindow->getViewData().CurrentTabForData() );
86
0
    if ( rDoc.HasNote( aPos ) )
87
0
    {
88
0
        ScPostIt* pNote = rDoc.GetNote(aPos);
89
0
        assert(pNote);
90
0
        aMap[u"CurrentCellCommentText"_ustr] = pNote->GetText();
91
0
    }
92
93
0
    SCCOL nCol;
94
0
    SCROW nRow;
95
0
    aMap[u"CurrentTableHasData"_ustr] = OUString::boolean( rDoc.GetDataStart( mxGridWindow->getViewData().CurrentTabForData(), nCol, nRow ) );
96
0
    nCol = mxGridWindow->getViewData().GetCurX();
97
0
    nRow = 0;
98
0
    aMap[u"CurrentColumnHasData"_ustr] = OUString::boolean( rDoc.GetPrintAreaVer( mxGridWindow->getViewData().CurrentTabForData(), nCol, nCol, nRow, true ) );
99
0
    nRow = mxGridWindow->getViewData().GetCurY();
100
0
    nCol = 0;
101
0
    aMap[u"CurrentRowHasData"_ustr] = OUString::boolean( rDoc.GetPrintAreaHor( mxGridWindow->getViewData().CurrentTabForData(), nRow, nRow, nCol ) );
102
103
0
    ScAppOptions aOpt = ScModule::get()->GetAppOptions();
104
0
    aMap[u"Zoom"_ustr] = OUString::number( aOpt.GetZoom() );
105
0
    return aMap;
106
0
}
107
108
ScDBFunc* ScGridWinUIObject::getDBFunc()
109
0
{
110
0
    ScViewData& rViewData = mxGridWindow->getViewData();
111
0
    ScDBFunc* pFunc = rViewData.GetView();
112
113
0
    return pFunc;
114
0
}
115
116
ScDrawView* ScGridWinUIObject::getDrawView()
117
0
{
118
0
    ScViewData& rViewData = mxGridWindow->getViewData();
119
0
    ScDrawView* pDrawView = rViewData.GetScDrawView();
120
121
0
    return pDrawView;
122
0
}
123
124
ScTabViewShell* ScGridWinUIObject::getViewShell()
125
0
{
126
0
    ScViewData& rViewData = mxGridWindow->getViewData();
127
0
    ScTabViewShell* pViewShell = rViewData.GetViewShell();
128
129
0
    return pViewShell;
130
0
}
131
132
ScViewFunc* ScGridWinUIObject::getViewFunc()
133
0
{
134
0
    ScViewData& rViewData = mxGridWindow->getViewData();
135
0
    ScViewFunc* pViewFunc = rViewData.GetView();
136
137
0
    return pViewFunc;
138
0
}
139
140
void ScGridWinUIObject::execute(const OUString& rAction,
141
        const StringMap& rParameters)
142
0
{
143
0
    if (rAction == "SELECT")
144
0
    {
145
0
        bool bExtend = false;
146
0
        if (auto itr = rParameters.find(u"EXTEND"_ustr); itr != rParameters.end())
147
0
        {
148
0
            if (itr->second.equalsIgnoreAsciiCase("true") || itr->second == "1")
149
0
                bExtend = true;
150
0
        }
151
152
0
        if (auto itrCell = rParameters.find(u"CELL"_ustr); itrCell != rParameters.end())
153
0
        {
154
0
            const OUString& rStr = itrCell->second;
155
0
            ScAddress aAddr = get_address_from_string(mxGridWindow->getViewData().GetDocument(), rStr);
156
0
            ScDBFunc* pFunc = getDBFunc();
157
0
            pFunc->MarkRange(ScRange(aAddr), true, bExtend);
158
0
            mxGridWindow->CursorChanged();
159
0
        }
160
0
        else if (auto itrRange = rParameters.find(u"RANGE"_ustr); itrRange != rParameters.end())
161
0
        {
162
0
            const OUString rStr = itrRange->second;
163
0
            ScRange aRange = get_range_from_string(mxGridWindow->getViewData().GetDocument(), rStr);
164
0
            ScDBFunc* pFunc = getDBFunc();
165
0
            pFunc->MarkRange(aRange, true, bExtend);
166
0
            mxGridWindow->CursorChanged();
167
0
        }
168
0
        else if (auto itrTable = rParameters.find(u"TABLE"_ustr); itrTable != rParameters.end())
169
0
        {
170
0
            const OUString rStr = itrTable->second;
171
0
            sal_Int32 nTab = rStr.toUInt32();
172
0
            ScTabView* pTabView = mxGridWindow->getViewData().GetView();
173
0
            if (pTabView)
174
0
            {
175
0
                ScDocument& rDoc = mxGridWindow->getViewData().GetDocument();
176
0
                if( nTab < rDoc.GetTableCount() )
177
0
                    pTabView->SetTabNo(nTab);
178
0
                else
179
0
                {
180
0
                    SAL_WARN("sc.uitest", "incorrect table number");
181
0
                }
182
0
            }
183
0
        }
184
0
        else if (auto itrObject = rParameters.find(u"OBJECT"_ustr); itrObject != rParameters.end())
185
0
        {
186
0
            const OUString rStr = itrObject->second;
187
188
0
            ScDrawView* pDrawView = getDrawView();
189
0
            pDrawView->SelectObject(rStr);
190
0
        }
191
0
        else
192
0
        {
193
0
            SAL_WARN("sc.uitest", "unknown selection method");
194
0
        }
195
0
    }
196
0
    else if (rAction == "DESELECT")
197
0
    {
198
0
        if ( rParameters.contains(u"OBJECT"_ustr) )
199
0
        {
200
0
            ScDrawView* pDrawView = getDrawView();
201
0
            pDrawView->UnmarkAll();
202
203
0
            ScTabViewShell* pViewShell = getViewShell();
204
0
            pViewShell->SetDrawShell(false);
205
0
        }
206
0
    }
207
0
    else if (rAction == "ACTIVATE")
208
0
    {
209
0
        ScDrawView* pDrawView = getDrawView();
210
0
        const SdrMarkList& rMarkList = pDrawView->GetMarkedObjectList();
211
0
        if (rMarkList.GetMarkCount() == 1)
212
0
        {
213
0
            SdrMark* pMark = rMarkList.GetMark(0);
214
0
            SdrObject* pObj = pMark->GetMarkedSdrObj();
215
0
            SdrObjKind nSdrObjKind = pObj->GetObjIdentifier();
216
0
            if (nSdrObjKind == SdrObjKind::OLE2)
217
0
            {
218
0
                ScTabViewShell* pViewShell = getViewShell();
219
0
                pViewShell->ActivateObject(static_cast<SdrOle2Obj*>(pObj), css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY);
220
0
            }
221
0
            else
222
0
            {
223
0
                SAL_WARN("sc.uitest", "can't activate non-ole objects");
224
0
            }
225
0
        }
226
0
        else
227
0
            SAL_WARN("sc.uitest", "can't activate the current selection");
228
0
    }
229
0
    else if (rAction == "LAUNCH")
230
0
    {
231
0
        if ( rParameters.contains(u"AUTOFILTER"_ustr) )
232
0
        {
233
0
            auto itrCol = rParameters.find(u"COL"_ustr);
234
0
            if (itrCol == rParameters.end())
235
0
            {
236
0
                SAL_WARN("sc.uitest", "missing COL parameter");
237
0
                return;
238
0
            }
239
240
0
            auto itrRow = rParameters.find(u"ROW"_ustr);
241
0
            if (itrRow == rParameters.end())
242
0
            {
243
0
                SAL_WARN("sc.uitest", "missing ROW parameter");
244
0
                return;
245
0
            }
246
0
            SCROW nRow = itrRow->second.toUInt32();
247
0
            SCCOL nCol = itrCol->second.toUInt32();
248
0
            mxGridWindow->LaunchAutoFilterMenu(nCol, nRow);
249
0
        }
250
0
        else if ( rParameters.contains(u"PIVOTTABLE"_ustr) )
251
0
        {
252
0
            auto itrCol = rParameters.find(u"COL"_ustr);
253
0
            if (itrCol == rParameters.end())
254
0
            {
255
0
                SAL_WARN("sc.uitest", "missing COL parameter");
256
0
                return;
257
0
            }
258
259
0
            auto itrRow = rParameters.find(u"ROW"_ustr);
260
0
            if (itrRow == rParameters.end())
261
0
            {
262
0
                SAL_WARN("sc.uitest", "missing ROW parameter");
263
0
                return;
264
0
            }
265
0
            SCROW nRow = itrRow->second.toUInt32();
266
0
            SCCOL nCol = itrCol->second.toUInt32();
267
0
            mxGridWindow->LaunchDPFieldMenu(nCol, nRow);
268
0
        }
269
0
        else if ( rParameters.contains(u"SELECTMENU"_ustr) )
270
0
        {
271
0
            auto itrCol = rParameters.find(u"COL"_ustr);
272
0
            if (itrCol == rParameters.end())
273
0
            {
274
0
                SAL_WARN("sc.uitest", "missing COL parameter");
275
0
                return;
276
0
            }
277
278
0
            auto itrRow = rParameters.find(u"ROW"_ustr);
279
0
            if (itrRow == rParameters.end())
280
0
            {
281
0
                SAL_WARN("sc.uitest", "missing ROW parameter");
282
0
                return;
283
0
            }
284
0
            SCROW nRow = itrRow->second.toUInt32();
285
0
            SCCOL nCol = itrCol->second.toUInt32();
286
0
            mxGridWindow->LaunchDataSelectMenu(nCol, nRow);
287
0
        }
288
0
    }
289
0
    else if (rAction == "COMMENT")
290
0
    {
291
0
        if ( rParameters.contains(u"OPEN"_ustr) )
292
0
        {
293
0
            ScViewFunc* pViewFunc = getViewFunc();
294
0
            pViewFunc->EditNote();
295
0
        }
296
0
        else if ( rParameters.contains(u"CLOSE"_ustr) )
297
0
        {
298
0
            FuDraw* pDraw = dynamic_cast<FuDraw*>(getViewFunc()->GetDrawFuncPtr());
299
0
            assert(pDraw);
300
0
            ScViewData& rViewData = mxGridWindow->getViewData();
301
0
            rViewData.GetDispatcher().Execute( pDraw->GetSlotID() , SfxCallMode::SLOT | SfxCallMode::RECORD );
302
0
        }
303
0
        else if (auto itr = rParameters.find(u"SETTEXT"_ustr); itr != rParameters.end())
304
0
        {
305
0
            const OUString rStr = itr->second;
306
0
            ScDocument& rDoc = mxGridWindow->getViewData().GetDocument();
307
0
            ScAddress aPos( mxGridWindow->getViewData().GetCurX() , mxGridWindow->getViewData().GetCurY() , mxGridWindow->getViewData().CurrentTabForData() );
308
0
            rDoc.GetOrCreateNote( aPos )->SetText( aPos , rStr );
309
0
        }
310
0
    }
311
0
    else if (rAction == "SIDEBAR")
312
0
    {
313
0
        SfxViewFrame* pViewFrm = SfxViewFrame::Current();
314
0
        assert(pViewFrm && "ScGridWinUIObject::execute: no viewframe");
315
0
        pViewFrm->ShowChildWindow(SID_SIDEBAR);
316
317
0
        auto itr = rParameters.find(u"PANEL"_ustr);
318
0
        if (itr != rParameters.end())
319
0
        {
320
0
            OUString aVal = itr->second;
321
0
            ::sfx2::sidebar::Sidebar::ShowPanel(aVal, pViewFrm->GetFrame().GetFrameInterface());
322
0
        }
323
0
    }
324
0
    else if (rAction == "SET")
325
0
    {
326
0
        if (auto itr = rParameters.find(u"ZOOM"_ustr); itr != rParameters.end())
327
0
        {
328
0
            OUString aVal = itr->second;
329
0
            sal_Int32 nVal = aVal.toInt32();
330
0
            ScTabViewShell* pViewShell = getViewShell();
331
0
            if( nVal )
332
0
            {
333
0
                ScModule* pScMod = ScModule::get();
334
0
                ScAppOptions aNewOpt = pScMod->GetAppOptions();
335
0
                aNewOpt.SetZoom( nVal );
336
0
                pScMod->SetAppOptions( aNewOpt );
337
0
                double aFract = double(nVal) / 100;
338
0
                pViewShell->SetZoom( aFract, aFract, true );
339
0
                pViewShell->PaintGrid();
340
0
                pViewShell->PaintTop();
341
0
                pViewShell->PaintLeft();
342
0
            }
343
0
        }
344
0
    }
345
0
    else
346
0
    {
347
0
        WindowUIObject::execute(rAction, rParameters);
348
0
    }
349
0
}
350
351
namespace {
352
353
ScDrawLayer* get_draw_layer(VclPtr<ScGridWindow> const & xGridWindow)
354
0
{
355
0
    return xGridWindow->getViewData().GetDocument().GetDrawLayer();
356
0
}
357
358
SdrPage* get_draw_page(VclPtr<ScGridWindow> const & xGridWindow, SCTAB nTab)
359
0
{
360
0
    ScDrawLayer* pDrawLayer = get_draw_layer(xGridWindow);
361
362
0
    return pDrawLayer->GetPage(nTab);
363
0
}
364
365
std::set<OUString> collect_charts(VclPtr<ScGridWindow> const & xGridWindow)
366
0
{
367
0
    SCTAB nTab = xGridWindow->getViewData().CurrentTabForData();
368
0
    SdrPage* pPage = get_draw_page(xGridWindow, nTab);
369
370
0
    std::set<OUString> aRet;
371
372
0
    if (!pPage)
373
0
        return aRet;
374
375
0
    SdrObjListIter aIter( pPage, SdrIterMode::Flat );
376
0
    SdrObject* pObject = aIter.Next();
377
0
    while (pObject)
378
0
    {
379
0
        if (pObject->GetObjIdentifier() == SdrObjKind::OLE2)
380
0
        {
381
0
            aRet.insert(static_cast<SdrOle2Obj*>(pObject)->GetPersistName());
382
0
        }
383
0
        pObject = aIter.Next();
384
0
    }
385
386
0
    return aRet;
387
0
}
388
389
}
390
391
std::set<OUString> ScGridWinUIObject::get_children() const
392
0
{
393
0
    std::set<OUString> aChildren = collect_charts(mxGridWindow);
394
0
    return aChildren;
395
0
}
396
397
std::unique_ptr<UIObject> ScGridWinUIObject::get_child(const OUString& /*rID*/)
398
0
{
399
0
    return nullptr;
400
0
}
401
402
std::unique_ptr<UIObject> ScGridWinUIObject::create(vcl::Window* pWindow)
403
0
{
404
0
    ScGridWindow* pGridWin = dynamic_cast<ScGridWindow*>(pWindow);
405
0
    assert(pGridWin);
406
0
    return std::unique_ptr<UIObject>(new ScGridWinUIObject(pGridWin));
407
0
}
408
409
OUString ScGridWinUIObject::get_name() const
410
0
{
411
0
    return u"ScGridWinUIObject"_ustr;
412
0
}
413
414
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */