Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/framework/source/fwe/helper/documentundoguard.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 <framework/documentundoguard.hxx>
21
22
#include <com/sun/star/document/XUndoManagerSupplier.hpp>
23
24
#include <cppuhelper/implbase.hxx>
25
#include <rtl/ref.hxx>
26
#include <comphelper/diagnose_ex.hxx>
27
28
namespace framework
29
{
30
31
    using ::com::sun::star::uno::Reference;
32
    using ::com::sun::star::uno::XInterface;
33
    using ::com::sun::star::uno::UNO_QUERY;
34
    using ::com::sun::star::uno::Exception;
35
    using ::com::sun::star::document::XUndoManagerSupplier;
36
    using ::com::sun::star::document::XUndoManager;
37
    using ::com::sun::star::document::XUndoManagerListener;
38
    using ::com::sun::star::document::UndoManagerEvent;
39
    using ::com::sun::star::lang::EventObject;
40
41
    //= UndoManagerContextListener
42
43
    typedef ::cppu::WeakImplHelper <   XUndoManagerListener
44
                                    >   UndoManagerContextListener_Base;
45
46
    class UndoManagerContextListener : public UndoManagerContextListener_Base
47
    {
48
    public:
49
        explicit UndoManagerContextListener( const Reference< XUndoManager >& i_undoManager )
50
0
            :m_xUndoManager( i_undoManager )
51
0
            ,m_nRelativeContextDepth( 0 )
52
0
            ,m_documentDisposed( false )
53
0
        {
54
0
            osl_atomic_increment( &m_refCount );
55
0
            {
56
0
                m_xUndoManager->addUndoManagerListener( this );
57
0
            }
58
0
            osl_atomic_decrement( &m_refCount );
59
0
        }
60
61
        void finish()
62
0
        {
63
0
            OSL_ENSURE( m_nRelativeContextDepth >= 0, "UndoManagerContextListener: more contexts left than entered?" );
64
65
0
            if ( m_documentDisposed )
66
0
                return;
67
68
            // work with a copy of m_nRelativeContextDepth, to be independent from possible bugs in the
69
            // listener notifications (where it would be decremented with every leaveUndoContext)
70
0
            sal_Int32 nDepth = m_nRelativeContextDepth;
71
0
            while ( nDepth-- > 0 )
72
0
            {
73
0
                m_xUndoManager->leaveUndoContext();
74
0
            }
75
0
            m_xUndoManager->removeUndoManagerListener( this );
76
0
        }
77
78
        // XUndoManagerListener
79
        virtual void SAL_CALL undoActionAdded( const UndoManagerEvent& i_event ) override;
80
        virtual void SAL_CALL actionUndone( const UndoManagerEvent& i_event ) override;
81
        virtual void SAL_CALL actionRedone( const UndoManagerEvent& i_event ) override;
82
        virtual void SAL_CALL allActionsCleared( const EventObject& i_event ) override;
83
        virtual void SAL_CALL redoActionsCleared( const EventObject& i_event ) override;
84
        virtual void SAL_CALL resetAll( const EventObject& i_event ) override;
85
        virtual void SAL_CALL enteredContext( const UndoManagerEvent& i_event ) override;
86
        virtual void SAL_CALL enteredHiddenContext( const UndoManagerEvent& i_event ) override;
87
        virtual void SAL_CALL leftContext( const UndoManagerEvent& i_event ) override;
88
        virtual void SAL_CALL leftHiddenContext( const UndoManagerEvent& i_event ) override;
89
        virtual void SAL_CALL cancelledContext( const UndoManagerEvent& i_event ) override;
90
91
        // XEventListener
92
        virtual void SAL_CALL disposing( const EventObject& i_event ) override;
93
94
    private:
95
        Reference< XUndoManager > const m_xUndoManager;
96
        oslInterlockedCount             m_nRelativeContextDepth;
97
        bool                            m_documentDisposed;
98
    };
99
100
    void SAL_CALL UndoManagerContextListener::undoActionAdded( const UndoManagerEvent& )
101
0
    {
102
        // not interested in
103
0
    }
104
105
    void SAL_CALL UndoManagerContextListener::actionUndone( const UndoManagerEvent& )
106
0
    {
107
        // not interested in
108
0
    }
109
110
    void SAL_CALL UndoManagerContextListener::actionRedone( const UndoManagerEvent& )
111
0
    {
112
        // not interested in
113
0
    }
114
115
    void SAL_CALL UndoManagerContextListener::allActionsCleared( const EventObject& )
116
0
    {
117
        // not interested in
118
0
    }
119
120
    void SAL_CALL UndoManagerContextListener::redoActionsCleared( const EventObject& )
121
0
    {
122
        // not interested in
123
0
    }
124
125
    void SAL_CALL UndoManagerContextListener::resetAll( const EventObject& )
126
0
    {
127
0
        m_nRelativeContextDepth = 0;
128
0
    }
129
130
    void SAL_CALL UndoManagerContextListener::enteredContext( const UndoManagerEvent& )
131
0
    {
132
0
        osl_atomic_increment( &m_nRelativeContextDepth );
133
0
    }
134
135
    void SAL_CALL UndoManagerContextListener::enteredHiddenContext( const UndoManagerEvent& )
136
0
    {
137
0
        osl_atomic_increment( &m_nRelativeContextDepth );
138
0
    }
139
140
    void SAL_CALL UndoManagerContextListener::leftContext( const UndoManagerEvent& )
141
0
    {
142
0
        osl_atomic_decrement( &m_nRelativeContextDepth );
143
0
    }
144
145
    void SAL_CALL UndoManagerContextListener::leftHiddenContext( const UndoManagerEvent& )
146
0
    {
147
0
        osl_atomic_decrement( &m_nRelativeContextDepth );
148
0
    }
149
150
    void SAL_CALL UndoManagerContextListener::cancelledContext( const UndoManagerEvent& )
151
0
    {
152
0
        osl_atomic_decrement( &m_nRelativeContextDepth );
153
0
    }
154
155
    void SAL_CALL UndoManagerContextListener::disposing( const EventObject& )
156
0
    {
157
0
        m_documentDisposed = true;
158
0
    }
159
160
    //= DocumentUndoGuard
161
162
    DocumentUndoGuard::DocumentUndoGuard( const Reference< XInterface >& i_undoSupplierComponent )
163
0
    {
164
0
        try
165
0
        {
166
0
            Reference< XUndoManagerSupplier > xUndoSupplier( i_undoSupplierComponent, UNO_QUERY );
167
0
            if ( xUndoSupplier.is() )
168
0
                mxUndoManager.set( xUndoSupplier->getUndoManager(), css::uno::UNO_SET_THROW );
169
170
0
            if ( mxUndoManager.is() )
171
0
                mxContextListener.set( new UndoManagerContextListener( mxUndoManager ) );
172
0
        }
173
0
        catch( const Exception& )
174
0
        {
175
0
            DBG_UNHANDLED_EXCEPTION("fwk");
176
0
        }
177
0
    }
178
179
    DocumentUndoGuard::~DocumentUndoGuard()
180
0
    {
181
0
        try
182
0
        {
183
0
            if ( mxContextListener.is() )
184
0
                mxContextListener->finish();
185
0
            mxContextListener.clear();
186
0
        }
187
0
        catch( const Exception& )
188
0
        {
189
0
            DBG_UNHANDLED_EXCEPTION("fwk");
190
0
        }
191
0
    }
192
193
} // namespace framework
194
195
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */