1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef INCLUDED_FRAMEWORK_PREVENTDUPLICATEINTERACTION_HXX
21 #define INCLUDED_FRAMEWORK_PREVENTDUPLICATEINTERACTION_HXX
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>
31 #include <comphelper/compbase.hxx>
32 #include <cppuhelper/implbase.hxx>
34 #include <toolkit/helper/vclunohelper.hxx>
35 #include <vcl/wrkwin.hxx>
36 #include <vcl/svapp.hxx>
39 namespace com::sun::star::uno
{
40 class XComponentContext
;
45 inline void closedialogs(SystemWindow
& rTopLevel
, bool bCloseRoot
)
47 for (vcl::Window
*pChild
= rTopLevel
.GetWindow(GetWindowType::FirstTopWindowChild
); pChild
; pChild
= rTopLevel
.GetWindow(GetWindowType::NextTopWindowSibling
))
48 closedialogs(dynamic_cast<SystemWindow
&>(*pChild
), true);
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.
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
>
63 VclPtr
<WorkWindow
> m_xWin
;
64 css::uno::Reference
<css::awt::XWindow
> m_xInterface
;
68 DECL_STATIC_LINK(WarningDialogsParent
, TerminateDesktop
, void*, void);
70 void closewarningdialogs()
74 SolarMutexGuard aSolarGuard
;
75 closedialogs(*m_xWin
, false);
80 using comphelper::WeakComponentImplHelperBase::disposing
;
81 virtual void SAL_CALL
disposing(const css::lang::EventObject
&) override
86 virtual void SAL_CALL
queryTermination(const css::lang::EventObject
&) override
88 closewarningdialogs();
89 Application::PostUserEvent(LINK(this, WarningDialogsParent
, TerminateDesktop
));
90 throw css::frame::TerminationVetoException();
93 virtual void SAL_CALL
notifyTermination(const css::lang::EventObject
&) override
98 WarningDialogsParent()
100 SolarMutexGuard aSolarGuard
;
101 m_xWin
= VclPtr
<WorkWindow
>::Create(nullptr, WB_STDWORK
);
102 m_xWin
->SetText(u
"dialog parent for warning dialogs during load"_ustr
);
103 m_xInterface
= VCLUnoHelper::GetInterface(m_xWin
);
106 virtual ~WarningDialogsParent() override
108 closewarningdialogs();
109 m_xWin
.disposeAndClear();
112 const css::uno::Reference
<css::awt::XWindow
>& GetDialogParent() const
118 class WarningDialogsParentScope
121 css::uno::Reference
<css::frame::XDesktop
> m_xDesktop
;
122 rtl::Reference
<WarningDialogsParent
> m_xListener
;
125 WarningDialogsParentScope(const css::uno::Reference
<css::uno::XComponentContext
>& rContext
)
126 : m_xDesktop(css::frame::Desktop::create(rContext
), css::uno::UNO_QUERY_THROW
)
127 , m_xListener(new WarningDialogsParent
)
129 m_xDesktop
->addTerminateListener(m_xListener
);
132 const css::uno::Reference
<css::awt::XWindow
>& GetDialogParent() const
134 return m_xListener
->GetDialogParent();
137 ~WarningDialogsParentScope()
139 m_xDesktop
->removeTerminateListener(m_xListener
);
144 @short Prevent us from showing the same interaction more than once during
145 the same transaction.
147 @descr Every interaction provided to this helper will be safed ... handled by the internal
148 used UUIInteractionHandler (!) and never be handled a second time!
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.
153 class PreventDuplicateInteraction final
:
154 public ::cppu::WeakImplHelper
<css::lang::XInitialization
, css::task::XInteractionHandler2
>
156 mutable std::mutex m_aLock
;
158 // structs, types etc.
161 struct InteractionInfo
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
;
176 InteractionInfo(const css::uno::Type
& aInteraction
)
177 : m_aInteraction(aInteraction
)
186 /// Used to create needed uno services at runtime.
187 css::uno::Reference
< css::uno::XComponentContext
> m_xContext
;
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
;
193 std::unique_ptr
<WarningDialogsParentScope
> m_xWarningDialogsParent
;
195 /** This list describe which and how incoming interactions must be handled.
196 Further it contains all collected information after this interaction
198 std::vector
< InteractionInfo
> m_lInteractionRules
;
204 virtual void SAL_CALL
initialize(const css::uno::Sequence
<css::uno::Any
>& rArguments
) override
;
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.
216 virtual void SAL_CALL
handle(const css::uno::Reference
< css::task::XInteractionRequest
>& xRequest
) override
;
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.
229 virtual sal_Bool SAL_CALL
handleInteractionRequest( const css::uno::Reference
< css::task::XInteractionRequest
>& xRequest
) override
;
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.
239 virtual css::uno::Any SAL_CALL
queryInterface( const css::uno::Type
& aType
) override
;
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.
251 uno service manager for creating services internally
253 @threadsafe not necessary
255 PreventDuplicateInteraction(css::uno::Reference
< css::uno::XComponentContext
> xContext
);
259 @short dtor to free used memory.
261 virtual ~PreventDuplicateInteraction() override
;
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.
268 @note This overwrites the settings of e.g. useDefaultUUIHandler()!
271 the new interaction handler
273 void setHandler(const css::uno::Reference
< css::task::XInteractionHandler
>& xHandler
);
277 @short instead of setting an outside interaction handler, this method
278 make sure the default UUI interaction handler of the office is used.
280 @note This overwrites the settings of e.g. setHandler()!
282 void useDefaultUUIHandler();
286 @short add a new interaction to the list of interactions, which
287 must be handled by this helper.
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 .-)
295 @param aInteractionInfo
296 describe the type of interaction, hos often it can be called etcpp.
300 void addInteractionRule(const PreventDuplicateInteraction::InteractionInfo
& aInteractionInfo
);
304 @short return the info struct for the specified interaction.
307 specify the interaction.
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
316 true if the queried interaction could be found.
321 bool getInteractionInfo(const css::uno::Type
& aInteraction
,
322 PreventDuplicateInteraction::InteractionInfo
* pReturn
) const;
327 #endif // INCLUDED_FRAMEWORK_PREVENTDUPLICATEINTERACTION_HXX
329 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */