Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/view/gridwin5.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 <editeng/flditem.hxx>
21
22
#include <svx/fmpage.hxx>
23
#include <svx/svdobj.hxx>
24
#include <svx/svdpagv.hxx>
25
#include <svx/ImageMapInfo.hxx>
26
#include <vcl/imapobj.hxx>
27
#include <vcl/help.hxx>
28
#include <tools/urlobj.hxx>
29
#include <sfx2/sfxhelp.hxx>
30
31
#include <AccessibleDocument.hxx>
32
#include <com/sun/star/accessibility/XAccessible.hpp>
33
34
#include <gridwin.hxx>
35
#include <viewdata.hxx>
36
#include <drawview.hxx>
37
#include <drwlayer.hxx>
38
#include <document.hxx>
39
#include <notemark.hxx>
40
#include <chgtrack.hxx>
41
#include <chgviset.hxx>
42
#include <dbfunc.hxx>
43
#include <postit.hxx>
44
#include <global.hxx>
45
46
bool ScGridWindow::ShowNoteMarker( SCCOL nPosX, SCROW nPosY, bool bKeyboard )
47
0
{
48
0
    bool bDone = false;
49
50
0
    ScDocument& rDoc = mrViewData.GetDocument();
51
0
    SCTAB nTab = mrViewData.CurrentTabForData();
52
0
    ScAddress   aCellPos( nPosX, nPosY, nTab );
53
54
0
    OUString aTrackText;
55
0
    bool bLeftEdge = false;
56
57
    // change tracking
58
59
0
    ScChangeTrack* pTrack = rDoc.GetChangeTrack();
60
0
    ScChangeViewSettings* pSettings = rDoc.GetChangeViewSettings();
61
0
    if ( pTrack && pTrack->GetFirst() && pSettings && pSettings->ShowChanges())
62
0
    {
63
0
        const ScChangeAction* pFound = nullptr;
64
0
        const ScChangeAction* pFoundContent = nullptr;
65
0
        const ScChangeAction* pFoundMove = nullptr;
66
0
        const ScChangeAction* pAction = pTrack->GetFirst();
67
0
        while (pAction)
68
0
        {
69
0
            if ( pAction->IsVisible() &&
70
0
                 ScViewUtil::IsActionShown( *pAction, *pSettings, rDoc ) )
71
0
            {
72
0
                ScChangeActionType eType = pAction->GetType();
73
0
                const ScBigRange& rBig = pAction->GetBigRange();
74
0
                if ( rBig.aStart.Tab() == nTab )
75
0
                {
76
0
                    ScRange aRange = rBig.MakeRange( rDoc );
77
78
0
                    if ( eType == SC_CAT_DELETE_ROWS )
79
0
                        aRange.aEnd.SetRow( aRange.aStart.Row() );
80
0
                    else if ( eType == SC_CAT_DELETE_COLS )
81
0
                        aRange.aEnd.SetCol( aRange.aStart.Col() );
82
83
0
                    if ( aRange.Contains( aCellPos ) )
84
0
                    {
85
0
                        pFound = pAction;       // the last one wins
86
0
                        switch ( eType )
87
0
                        {
88
0
                            case SC_CAT_CONTENT :
89
0
                                pFoundContent = pAction;
90
0
                            break;
91
0
                            case SC_CAT_MOVE :
92
0
                                pFoundMove = pAction;
93
0
                            break;
94
0
                            default:
95
0
                            {
96
                                // added to avoid warnings
97
0
                            }
98
0
                        }
99
0
                    }
100
0
                }
101
0
                if ( eType == SC_CAT_MOVE )
102
0
                {
103
0
                    ScRange aRange =
104
0
                        static_cast<const ScChangeActionMove*>(pAction)->
105
0
                        GetFromRange().MakeRange( rDoc );
106
0
                    if ( aRange.Contains( aCellPos ) )
107
0
                    {
108
0
                        pFound = pAction;
109
0
                    }
110
0
                }
111
0
            }
112
0
            pAction = pAction->GetNext();
113
0
        }
114
115
0
        if ( pFound )
116
0
        {
117
0
            if ( pFoundContent && pFound->GetType() != SC_CAT_CONTENT )
118
0
                pFound = pFoundContent;     // content wins
119
0
            if ( pFoundMove && pFound->GetType() != SC_CAT_MOVE &&
120
0
                    pFoundMove->GetActionNumber() >
121
0
                    pFound->GetActionNumber() )
122
0
                pFound = pFoundMove;        // move wins
123
124
            // for deleted columns: Arrow on the left side of the cell
125
0
            if ( pFound->GetType() == SC_CAT_DELETE_COLS )
126
0
                bLeftEdge = true;
127
128
0
            DateTime aDT = pFound->GetDateTime();
129
0
            aTrackText  = pFound->GetUser()
130
0
                        + ", "
131
0
                        + ScGlobal::getLocaleData().getDate(aDT)
132
0
                        + " "
133
0
                        + ScGlobal::getLocaleData().getTime(aDT)
134
0
                        + ":\n";
135
0
            OUString aComStr=pFound->GetComment();
136
0
            if(!aComStr.isEmpty())
137
0
            {
138
0
                aTrackText += aComStr + "\n( ";
139
0
            }
140
0
            OUString aTmp = pFound->GetDescription(rDoc);
141
0
            aTrackText += aTmp;
142
0
            if(!aComStr.isEmpty())
143
0
            {
144
0
                aTrackText += ")";
145
0
            }
146
0
        }
147
0
    }
148
149
    // Note, only if it is not already displayed on the Drawing Layer:
150
0
    const ScPostIt* pNote = rDoc.GetNote( aCellPos );
151
0
    if ( (!aTrackText.isEmpty()) || (pNote && !pNote->IsCaptionShown()) )
152
0
    {
153
0
        bool bNew = true;
154
0
        bool bFast = false;
155
0
        if (mpNoteOverlay) // A note already shown
156
0
        {
157
0
            if (mpNoteOverlay->GetDocPos() == aCellPos)
158
0
                bNew = false; // then stop
159
0
            else
160
0
                bFast = true; // otherwise, at once
161
162
            //  marker which was shown for ctrl-F1 isn't removed by mouse events
163
0
            if (mpNoteOverlay->IsByKeyboard() && !bKeyboard)
164
0
                bNew = false;
165
0
        }
166
0
        if (bNew)
167
0
        {
168
0
            if (bKeyboard)
169
0
                bFast = true; // keyboard also shows the marker immediately
170
171
0
            mpNoteOverlay.reset(new ScNoteOverlay(*this, aCellPos, aTrackText, bLeftEdge, bFast, bKeyboard));
172
0
        }
173
174
0
        bDone = true;       // something is shown (old or new)
175
0
    }
176
177
0
    return bDone;
178
0
}
179
180
void ScGridWindow::RequestHelp(const HelpEvent& rHEvt)
181
0
{
182
0
    bool bDone = false;
183
0
    OUString aFormulaText;
184
0
    tools::Rectangle aFormulaPixRect;
185
0
    bool bHelpEnabled = bool(rHEvt.GetMode() & ( HelpEventMode::BALLOON | HelpEventMode::QUICK ));
186
0
    SdrView* pDrView = mrViewData.GetScDrawView();
187
0
    bool bDrawTextEdit = false;
188
0
    if (pDrView)
189
0
        bDrawTextEdit = pDrView->IsTextEdit();
190
    //  notes or change tracking
191
0
    if ( bHelpEnabled && !bDrawTextEdit )
192
0
    {
193
0
        Point       aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
194
0
        SCCOL nPosX;
195
0
        SCROW nPosY;
196
0
        ScDocument& rDoc = mrViewData.GetDocument();
197
0
        SCTAB       nTab = mrViewData.CurrentTabForData();
198
0
        const ScViewOptions& rOpts = mrViewData.GetOptions();
199
0
        mrViewData.GetPosFromPixel( aPosPixel.X(), aPosPixel.Y(), eWhich, nPosX, nPosY );
200
201
0
        if ( ShowNoteMarker( nPosX, nPosY, false ) )
202
0
        {
203
0
            Window::RequestHelp( rHEvt );   // turn off old Tip/Balloon
204
0
            bDone = true;
205
0
        }
206
207
0
        if ( rOpts.GetOption(sc::ViewOption::FORMULAS_MARKS) )
208
0
        {
209
0
            aFormulaText = rDoc.GetFormula( nPosX, nPosY, nTab );
210
0
            if ( !aFormulaText.isEmpty() ) {
211
0
                const ScPatternAttr* pPattern = rDoc.GetPattern( nPosX, nPosY, nTab );
212
0
                aFormulaPixRect = mrViewData.GetEditArea( eWhich, nPosX, nPosY, this, pPattern, true );
213
0
            }
214
0
        }
215
0
    }
216
217
0
    if (!bDone && mpNoteOverlay)
218
0
    {
219
0
        if (mpNoteOverlay->IsByKeyboard())
220
0
        {
221
            //  marker which was shown for ctrl-F1 isn't removed by mouse events
222
0
        }
223
0
        else
224
0
        {
225
0
            mpNoteOverlay.reset();
226
0
        }
227
0
    }
228
229
0
    if ( !aFormulaText.isEmpty() )
230
0
    {
231
0
        tools::Rectangle aScreenRect(OutputToScreenPixel(aFormulaPixRect.TopLeft()),
232
0
                                     OutputToScreenPixel(aFormulaPixRect.BottomRight()));
233
0
        if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
234
0
            Help::ShowBalloon(this, rHEvt.GetMousePosPixel(), aScreenRect, aFormulaText);
235
0
        else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
236
0
            Help::ShowQuickHelp(this, aScreenRect, aFormulaText);
237
0
        bDone = true;
238
0
    }
239
240
    //  Image-Map / Text-URL
241
242
0
    if ( bHelpEnabled && !bDone && !nButtonDown )       // only without pressed button
243
0
    {
244
0
        OUString aHelpText;
245
0
        tools::Rectangle aPixRect;
246
0
        Point aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
247
248
0
        if ( pDrView )                                      // URL / Image-Map
249
0
        {
250
0
            SdrViewEvent aVEvt;
251
0
            MouseEvent aMEvt( aPosPixel, 1, MouseEventModifiers::NONE, MOUSE_LEFT );
252
0
            SdrHitKind eHit = pDrView->PickAnything( aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt );
253
254
0
            if ( eHit != SdrHitKind::NONE && aVEvt.mpObj != nullptr )
255
0
            {
256
                // URL for IMapObject below Pointer is help text
257
0
                if (SvxIMapInfo::GetIMapInfo(aVEvt.mpObj))
258
0
                {
259
0
                    Point aLogicPos = PixelToLogic( aPosPixel );
260
0
                    IMapObject* pIMapObj = SvxIMapInfo::GetHitIMapObject(
261
0
                                                    aVEvt.mpObj, aLogicPos, GetOutDev() );
262
263
0
                    if ( pIMapObj )
264
0
                    {
265
                        // For image maps show the description, if available
266
0
                        aHelpText = pIMapObj->GetAltText();
267
0
                        if (aHelpText.isEmpty())
268
0
                            aHelpText = SfxHelp::GetURLHelpText(pIMapObj->GetURL());
269
0
                        aPixRect = LogicToPixel(aVEvt.mpObj->GetLogicRect());
270
0
                    }
271
0
                }
272
                // URL in shape text or at shape itself (URL in text overrides object URL)
273
0
                if ( aHelpText.isEmpty() )
274
0
                {
275
0
                    if( aVEvt.meEvent == SdrEventKind::ExecuteUrl )
276
0
                    {
277
0
                        if (aVEvt.mpURLField && !aVEvt.mpURLField->GetURL().startsWith("#"))
278
0
                        {
279
0
                            aHelpText = SfxHelp::GetURLHelpText(aVEvt.mpURLField->GetURL());
280
0
                            aPixRect = LogicToPixel(aVEvt.mpObj->GetLogicRect());
281
0
                        }
282
0
                    }
283
0
                    else
284
0
                    {
285
0
                        SdrPageView* pPV = nullptr;
286
0
                        Point aMDPos = PixelToLogic( aPosPixel );
287
0
                        SdrObject* pObj = pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER);
288
0
                        if (pObj)
289
0
                        {
290
0
                            if ( pObj->IsGroupObject() )
291
0
                            {
292
0
                                    SdrObject* pHit = pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pPV, SdrSearchOptions::DEEP);
293
0
                                    if (pHit)
294
0
                                        pObj = pHit;
295
0
                            }
296
                            // Fragments pointing into the current document need no tooltip
297
                            // describing the ctrl-click functionality.
298
0
                            if ( !pObj->getHyperlink().isEmpty() && !pObj->getHyperlink().startsWith("#") )
299
0
                            {
300
0
                                aPixRect = LogicToPixel(aVEvt.mpObj->GetLogicRect());
301
0
                                aHelpText = SfxHelp::GetURLHelpText(pObj->getHyperlink());
302
0
                            }
303
0
                        }
304
0
                    }
305
0
                }
306
0
            }
307
0
        }
308
309
0
        if ( aHelpText.isEmpty() )                                 // Text-URL
310
0
        {
311
0
            OUString aUrl;
312
0
            if ( GetEditUrl( aPosPixel, nullptr, &aUrl ) )
313
0
            {
314
0
                aHelpText = SfxHelp::GetURLHelpText(
315
0
                    INetURLObject::decode(aUrl, INetURLObject::DecodeMechanism::Unambiguous));
316
317
0
                ScDocument& rDoc = mrViewData.GetDocument();
318
0
                SCCOL nPosX;
319
0
                SCROW nPosY;
320
0
                SCTAB nTab = mrViewData.CurrentTabForData();
321
0
                mrViewData.GetPosFromPixel( aPosPixel.X(), aPosPixel.Y(), eWhich, nPosX, nPosY );
322
0
                const ScPatternAttr* pPattern = rDoc.GetPattern( nPosX, nPosY, nTab );
323
324
                // bForceToTop = sal_False, use the cell's real position
325
0
                aPixRect = mrViewData.GetEditArea( eWhich, nPosX, nPosY, this, pPattern, false );
326
0
            }
327
0
        }
328
329
0
        if ( !aHelpText.isEmpty() )
330
0
        {
331
0
            tools::Rectangle aScreenRect(OutputToScreenPixel(aPixRect.TopLeft()),
332
0
                                         OutputToScreenPixel(aPixRect.BottomRight()));
333
334
0
            if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
335
0
                Help::ShowBalloon(this,rHEvt.GetMousePosPixel(), aScreenRect, aHelpText);
336
0
            else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
337
0
                Help::ShowQuickHelp(this,aScreenRect, aHelpText);
338
339
0
            bDone = true;
340
0
        }
341
0
    }
342
343
    // basic controls
344
345
0
    if ( pDrView && bHelpEnabled && !bDone )
346
0
    {
347
0
        SdrPageView* pPV = pDrView->GetSdrPageView();
348
0
        OSL_ENSURE( pPV, "SdrPageView* is NULL" );
349
0
        if (pPV)
350
0
            bDone = FmFormPage::RequestHelp( this, pDrView, rHEvt );
351
0
    }
352
353
    // If QuickHelp for AutoFill is shown, do not allow it to be removed
354
355
0
    if ( nMouseStatus == SC_GM_TABDOWN && mrViewData.GetRefType() == SC_REFTYPE_FILL &&
356
0
            Help::IsQuickHelpEnabled() )
357
0
        bDone = true;
358
359
0
    if (!bDone)
360
0
        Window::RequestHelp( rHEvt );
361
0
}
362
363
bool ScGridWindow::IsMyModel(const SdrEditView* pSdrView)
364
0
{
365
0
    return pSdrView &&
366
0
            &pSdrView->GetModel() == mrViewData.GetDocument().GetDrawLayer();
367
0
}
368
369
void ScGridWindow::HideNoteOverlay()
370
0
{
371
0
    mpNoteOverlay.reset();
372
0
}
373
374
rtl::Reference<comphelper::OAccessible> ScGridWindow::CreateAccessible()
375
0
{
376
0
    rtl::Reference<ScAccessibleDocument> pAccessibleDocument =
377
0
        new ScAccessibleDocument(GetAccessibleParent(),
378
0
            mrViewData.GetViewShell(), eWhich);
379
0
    pAccessibleDocument->PreInit();
380
381
0
    SetAccessible(pAccessibleDocument);
382
383
0
    pAccessibleDocument->Init();
384
385
0
    return pAccessibleDocument;
386
0
}
387
388
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */