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 <cppuhelper/compbase.hxx>
32 #include <cppuhelper/implbase.hxx>
34 #include <toolkit/helper/vclunohelper.hxx>
35 #include <vcl/wrkwin.hxx>
36 #include <vcl/svapp.hxx>
38 namespace com::sun::star::uno
{
39 class XComponentContext
;
44 inline void closedialogs(SystemWindow
& rTopLevel
, bool bCloseRoot
)
46 for (vcl::Window
*pChild
= rTopLevel
.GetWindow(GetWindowType::FirstTopWindowChild
); pChild
; pChild
= rTopLevel
.GetWindow(GetWindowType::NextTopWindowSibling
))
47 closedialogs(dynamic_cast<SystemWindow
&>(*pChild
), true);
52 // This is intended to be the parent for any warning dialogs launched
53 // during the load of a document so that those dialogs are modal to
54 // this window and don't block any existing windows.
56 // If there are dialog children open on exit then veto termination,
57 // close the topmost dialog and retry termination.
58 class WarningDialogsParent final
:
59 public cppu::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(dynamic_cast<SystemWindow
&>(*m_xWin
), false);
80 using cppu::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()
99 : cppu::WeakComponentImplHelper
<css::frame::XTerminateListener
>(m_aLock
)
101 SolarMutexGuard aSolarGuard
;
102 m_xWin
= VclPtr
<WorkWindow
>::Create(nullptr, WB_STDWORK
);
103 m_xWin
->SetText("dialog parent for warning dialogs during load");
104 m_xInterface
= VCLUnoHelper::GetInterface(m_xWin
);
107 virtual ~WarningDialogsParent() override
109 closewarningdialogs();
110 m_xWin
.disposeAndClear();
113 const css::uno::Reference
<css::awt::XWindow
>& GetDialogParent() const
119 class WarningDialogsParentScope
122 css::uno::Reference
<css::frame::XDesktop
> m_xDesktop
;
123 rtl::Reference
<WarningDialogsParent
> m_xListener
;
126 WarningDialogsParentScope(const css::uno::Reference
<css::uno::XComponentContext
>& rContext
)
127 : m_xDesktop(css::frame::Desktop::create(rContext
), css::uno::UNO_QUERY_THROW
)
128 , m_xListener(new WarningDialogsParent
)
130 m_xDesktop
->addTerminateListener(m_xListener
);
133 const css::uno::Reference
<css::awt::XWindow
>& GetDialogParent() const
135 return m_xListener
->GetDialogParent();
138 ~WarningDialogsParentScope()
140 m_xDesktop
->removeTerminateListener(m_xListener
);
145 @short Prevent us from showing the same interaction more than once during
146 the same transaction.
148 @descr Every interaction provided to this helper will be safed ... handled by the internal
149 used UUIInteractionHandler (!) and never be handled a second time!
151 On the other side there exists some interactions, which allow a retry.
152 So this helper allow to set a list of interactions combined with a retry value.
154 class PreventDuplicateInteraction final
:
155 public ::cppu::WeakImplHelper
<css::lang::XInitialization
, css::task::XInteractionHandler2
>
157 mutable ::osl::Mutex m_aLock
;
159 // structs, types etc.
162 struct InteractionInfo
165 /// describe the interaction.
166 css::uno::Type m_aInteraction
;
167 /// after max count was reached this interaction will be blocked.
168 sal_Int32 m_nMaxCount
;
169 /// count how often this interaction was called.
170 sal_Int32 m_nCallCount
;
171 /** hold the last intercepted request (matching the set interaction type) alive
172 so it can be used for further checks */
173 css::uno::Reference
< css::task::XInteractionRequest
> m_xRequest
;
177 InteractionInfo(const css::uno::Type
& aInteraction
)
178 : m_aInteraction(aInteraction
)
187 /// Used to create needed uno services at runtime.
188 css::uno::Reference
< css::uno::XComponentContext
> m_xContext
;
190 /** The outside interaction handler, which is used to handle every incoming interaction,
191 if it's not blocked. */
192 css::uno::Reference
< css::task::XInteractionHandler
> m_xHandler
;
194 std::unique_ptr
<WarningDialogsParentScope
> m_xWarningDialogsParent
;
196 /** This list describe which and how incoming interactions must be handled.
197 Further it contains all collected information after this interaction
199 std::vector
< InteractionInfo
> m_lInteractionRules
;
205 virtual void SAL_CALL
initialize(const css::uno::Sequence
<css::uno::Any
>& rArguments
) override
;
208 @interface XInteractionHandler
209 @short called from outside to handle a problem
210 @descr We filter the incoming interactions. some of them
211 will be forwarded to the generic UI interaction handler.
212 So we must not implement it twice. Some other ones
213 will be aborted only.
217 virtual void SAL_CALL
handle(const css::uno::Reference
< css::task::XInteractionRequest
>& xRequest
) override
;
221 @interface XInteractionHandler2
222 @short called from outside to handle a problem
223 @descr We filter the incoming interactions. some of them
224 will be forwarded to the generic UI interaction handler.
225 So we must not implement it twice. Some other ones
226 will be aborted only.
230 virtual sal_Bool SAL_CALL
handleInteractionRequest( const css::uno::Reference
< css::task::XInteractionRequest
>& xRequest
) override
;
234 @interface XInterface
235 @short called to query another interface of the component
236 @descr Will allow to query for XInteractionHandler2 if and only if m_xHandler supports this interface, too.
240 virtual css::uno::Any SAL_CALL
queryInterface( const css::uno::Type
& aType
) override
;
247 @short ctor to guarantee right initialized instances of this class
248 @descr It uses the given uno service manager to create the global
249 generic UI interaction handler for later internal using.
252 uno service manager for creating services internally
254 @threadsafe not necessary
256 PreventDuplicateInteraction(const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
);
260 @short dtor to free used memory.
262 virtual ~PreventDuplicateInteraction() override
;
266 @short set the outside interaction handler, which must be used internally
267 if the interaction will not be blocked by the set list of rules.
269 @note This overwrites the settings of e.g. useDefaultUUIHandler()!
272 the new interaction handler
274 void setHandler(const css::uno::Reference
< css::task::XInteractionHandler
>& xHandler
);
278 @short instead of setting an outside interaction handler, this method
279 make sure the default UUI interaction handler of the office is used.
281 @note This overwrites the settings of e.g. setHandler()!
283 void useDefaultUUIHandler();
287 @short add a new interaction to the list of interactions, which
288 must be handled by this helper.
290 @descr This method must be called immediately after a new instance of this helper was
291 created. Without such list of InteractionRules, this instances does nothing!
292 On the other side there is no possibility to remove rules.
293 So the same instance can't be used within different transactions.
294 It's a OneWay-object .-)
296 @param aInteractionInfo
297 describe the type of interaction, hos often it can be called etcpp.
301 void addInteractionRule(const PreventDuplicateInteraction::InteractionInfo
& aInteractionInfo
);
305 @short return the info struct for the specified interaction.
308 specify the interaction.
311 provides information about:
312 - the count how often this interaction was handled during the
313 lifetime of this helper.
314 - the interaction itself, so it can be analyzed further
317 true if the queried interaction could be found.
322 bool getInteractionInfo(const css::uno::Type
& aInteraction
,
323 PreventDuplicateInteraction::InteractionInfo
* pReturn
) const;
328 #endif // INCLUDED_FRAMEWORK_PREVENTDUPLICATEINTERACTION_HXX
330 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */