Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sfx2/inc/preventduplicateinteraction.hxx
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
#ifndef INCLUDED_FRAMEWORK_PREVENTDUPLICATEINTERACTION_HXX
21
#define INCLUDED_FRAMEWORK_PREVENTDUPLICATEINTERACTION_HXX
22
23
#include <vector>
24
25
#include <com/sun/star/frame/Desktop.hpp>
26
#include <com/sun/star/frame/TerminationVetoException.hpp>
27
#include <com/sun/star/lang/XInitialization.hpp>
28
#include <com/sun/star/task/XInteractionHandler2.hpp>
29
#include <com/sun/star/task/XInteractionRequest.hpp>
30
31
#include <comphelper/compbase.hxx>
32
#include <cppuhelper/implbase.hxx>
33
34
#include <toolkit/helper/vclunohelper.hxx>
35
#include <vcl/wrkwin.hxx>
36
#include <vcl/svapp.hxx>
37
#include <mutex>
38
39
namespace com::sun::star::uno {
40
    class XComponentContext;
41
}
42
43
namespace sfx2 {
44
45
inline void closedialogs(SystemWindow& rTopLevel, bool bCloseRoot)
46
0
{
47
0
    for (vcl::Window *pChild = rTopLevel.GetWindow(GetWindowType::FirstTopWindowChild); pChild; pChild = rTopLevel.GetWindow(GetWindowType::NextTopWindowSibling))
48
0
        closedialogs(dynamic_cast<SystemWindow&>(*pChild), true);
49
0
    if (bCloseRoot)
50
0
        rTopLevel.Close();
51
0
}
52
53
// This is intended to be the parent for any warning dialogs launched
54
// during the load of a document so that those dialogs are modal to
55
// this window and don't block any existing windows.
56
//
57
// If there are dialog children open on exit then veto termination,
58
// close the topmost dialog and retry termination.
59
class WarningDialogsParent final :
60
    public comphelper::WeakComponentImplHelper<css::frame::XTerminateListener>
61
{
62
private:
63
    VclPtr<WorkWindow> m_xWin;
64
    css::uno::Reference<css::awt::XWindow> m_xInterface;
65
66
private:
67
68
    DECL_STATIC_LINK(WarningDialogsParent, TerminateDesktop, void*, void);
69
70
    void closewarningdialogs()
71
0
    {
72
0
        if (!m_xWin)
73
0
            return;
74
0
        SolarMutexGuard aSolarGuard;
75
0
        closedialogs(*m_xWin, false);
76
0
    }
77
78
public:
79
80
    using comphelper::WeakComponentImplHelperBase::disposing;
81
    virtual void SAL_CALL disposing(const css::lang::EventObject&) override
82
0
    {
83
0
    }
84
85
    // XTerminateListener
86
    virtual void SAL_CALL queryTermination(const css::lang::EventObject&) override
87
0
    {
88
0
        closewarningdialogs();
89
0
        Application::PostUserEvent(LINK(this, WarningDialogsParent, TerminateDesktop));
90
0
        throw css::frame::TerminationVetoException();
91
0
    }
92
93
    virtual void SAL_CALL notifyTermination(const css::lang::EventObject&) override
94
0
    {
95
0
    }
96
97
public:
98
    WarningDialogsParent()
99
0
    {
100
0
        SolarMutexGuard aSolarGuard;
101
0
        m_xWin = VclPtr<WorkWindow>::Create(nullptr, WB_STDWORK);
102
0
        m_xWin->SetText(u"dialog parent for warning dialogs during load"_ustr);
103
0
        m_xInterface = VCLUnoHelper::GetInterface(m_xWin);
104
0
    }
Unexecuted instantiation: sfx2::WarningDialogsParent::WarningDialogsParent()
Unexecuted instantiation: sfx2::WarningDialogsParent::WarningDialogsParent()
105
106
    virtual ~WarningDialogsParent() override
107
0
    {
108
0
        closewarningdialogs();
109
0
        m_xWin.disposeAndClear();
110
0
    }
111
112
    const css::uno::Reference<css::awt::XWindow>& GetDialogParent() const
113
0
    {
114
0
        return m_xInterface;
115
0
    }
116
};
117
118
class WarningDialogsParentScope
119
{
120
private:
121
    css::uno::Reference<css::frame::XDesktop> m_xDesktop;
122
    rtl::Reference<WarningDialogsParent> m_xListener;
123
124
public:
125
    WarningDialogsParentScope(const css::uno::Reference<css::uno::XComponentContext>& rContext)
126
0
        : m_xDesktop(css::frame::Desktop::create(rContext), css::uno::UNO_QUERY_THROW)
127
0
        , m_xListener(new WarningDialogsParent)
128
0
    {
129
0
        m_xDesktop->addTerminateListener(m_xListener);
130
0
    }
131
132
    const css::uno::Reference<css::awt::XWindow>& GetDialogParent() const
133
0
    {
134
0
        return m_xListener->GetDialogParent();
135
0
    }
136
137
    ~WarningDialogsParentScope()
138
0
    {
139
0
        m_xDesktop->removeTerminateListener(m_xListener);
140
0
    }
141
};
142
143
/**
144
    @short      Prevent us from showing the same interaction more than once during
145
                the same transaction.
146
147
    @descr      Every interaction provided to this helper will be saved... handled by the internal
148
                used UUIInteractionHandler (!) and never be handled a second time!
149
150
                On the other side there exists some interactions, which allow a retry.
151
                So this helper allow to set a list of interactions combined with a retry value.
152
 */
153
class PreventDuplicateInteraction final :
154
                                  public ::cppu::WeakImplHelper<css::lang::XInitialization, css::task::XInteractionHandler2>
155
{
156
    mutable std::mutex m_aLock;
157
158
    // structs, types etc.
159
    public:
160
161
        struct InteractionInfo
162
        {
163
            public:
164
                /// describe the interaction.
165
                css::uno::Type m_aInteraction;
166
                /// after max count was reached this interaction will be blocked.
167
                sal_Int32 m_nMaxCount;
168
                /// count how often this interaction was called.
169
                sal_Int32 m_nCallCount;
170
                /** hold the last intercepted request (matching the set interaction type) alive
171
                so it can be used for further checks */
172
                css::uno::Reference< css::task::XInteractionRequest > m_xRequest;
173
174
            public:
175
176
                InteractionInfo(const css::uno::Type& aInteraction)
177
0
                    : m_aInteraction(aInteraction)
178
0
                    , m_nMaxCount   (1   )
179
0
                    , m_nCallCount  (0           )
180
0
                {}
181
        };
182
183
    // member
184
    private:
185
186
        /// Used to create needed uno services at runtime.
187
        css::uno::Reference< css::uno::XComponentContext > m_xContext;
188
189
        /** The outside interaction handler, which is used to handle every incoming interaction,
190
            if it's not blocked. */
191
        css::uno::Reference< css::task::XInteractionHandler > m_xHandler;
192
193
        std::unique_ptr<WarningDialogsParentScope> m_xWarningDialogsParent;
194
195
        /** This list describe which and how incoming interactions must be handled.
196
            Further it contains all collected information after this interaction
197
            object was used.*/
198
        std::vector< InteractionInfo > m_lInteractionRules;
199
200
201
    // uno interface
202
    public:
203
204
        virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArguments) override;
205
206
        /**
207
            @interface  XInteractionHandler
208
            @short      called from outside to handle a problem
209
            @descr      We filter the incoming interactions. some of them
210
                        will be forwarded to the generic UI interaction handler.
211
                        So we must not implement it twice. Some other ones
212
                        will be aborted only.
213
214
            @threadsafe yes
215
        */
216
        virtual void SAL_CALL handle(const css::uno::Reference< css::task::XInteractionRequest >& xRequest) override;
217
218
219
        /**
220
            @interface  XInteractionHandler2
221
            @short      called from outside to handle a problem
222
            @descr      We filter the incoming interactions. some of them
223
                        will be forwarded to the generic UI interaction handler.
224
                        So we must not implement it twice. Some other ones
225
                        will be aborted only.
226
227
            @threadsafe yes
228
        */
229
        virtual sal_Bool SAL_CALL handleInteractionRequest( const css::uno::Reference< css::task::XInteractionRequest >& xRequest ) override;
230
231
232
        /**
233
            @interface  XInterface
234
            @short      called to query another interface of the component
235
            @descr      Will allow to query for XInteractionHandler2 if and only if m_xHandler supports this interface, too.
236
237
            @threadsafe yes
238
        */
239
        virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
240
241
    // c++ interface
242
    public:
243
244
245
        /**
246
            @short      ctor to guarantee right initialized instances of this class
247
            @descr      It uses the given uno service manager to create the global
248
                        generic UI interaction handler for later internal using.
249
250
            @param      xSMGR
251
                            uno service manager for creating services internally
252
253
            @threadsafe not necessary
254
        */
255
        PreventDuplicateInteraction(css::uno::Reference< css::uno::XComponentContext > xContext);
256
257
258
        /**
259
            @short      dtor to free used memory.
260
         */
261
        virtual ~PreventDuplicateInteraction() override;
262
263
264
        /**
265
            @short      set the outside interaction handler, which must be used internally
266
                        if the interaction will not be blocked by the set list of rules.
267
268
            @note       This overwrites the settings of e.g. useDefaultUUIHandler()!
269
270
            @param      xHandler
271
                        the new interaction handler
272
         */
273
        void setHandler(const css::uno::Reference< css::task::XInteractionHandler >& xHandler);
274
275
276
        /**
277
            @short      instead of setting an outside interaction handler, this method
278
                        make sure the default UUI interaction handler of the office is used.
279
280
            @note       This overwrites the settings of e.g. setHandler()!
281
         */
282
        void useDefaultUUIHandler();
283
284
285
        /**
286
            @short      add a new interaction to the list of interactions, which
287
                        must be handled by this helper.
288
289
            @descr      This method must be called immediately after a new instance of this helper was
290
                        created. Without such list of InteractionRules, this instances does nothing!
291
                        On the other side there is no possibility to remove rules.
292
                        So the same instance can't be used within different transactions.
293
                        It's a OneWay-object .-)
294
295
            @param      aInteractionInfo
296
                        describe the type of interaction, hos often it can be called etcpp.
297
298
            @threadsafe yes
299
        */
300
        void addInteractionRule(const PreventDuplicateInteraction::InteractionInfo& aInteractionInfo);
301
302
303
        /**
304
            @short      return the info struct for the specified interaction.
305
306
            @param      aInteraction
307
                        specify the interaction.
308
309
            @param      pReturn
310
                        provides information about:
311
                        - the count how often this interaction was handled during the
312
                          lifetime of this helper.
313
                        - the interaction itself, so it can be analyzed further
314
315
            @return     [boolean]
316
                        true if the queried interaction could be found.
317
                        false otherwise.
318
319
            @threadsafe yes
320
        */
321
        bool getInteractionInfo(const css::uno::Type&                               aInteraction,
322
                                                  PreventDuplicateInteraction::InteractionInfo* pReturn     ) const;
323
};
324
325
} // namespace sfx2
326
327
#endif // INCLUDED_FRAMEWORK_PREVENTDUPLICATEINTERACTION_HXX
328
329
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */