LibreOffice Module sfx2 (master) 1
preventduplicateinteraction.cxx
Go to the documentation of this file.
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
21
23#include <osl/diagnose.h>
24
25#include <com/sun/star/task/InteractionHandler.hpp>
26#include <com/sun/star/task/XInteractionAbort.hpp>
27#include <utility>
28
29namespace sfx2 {
30
31PreventDuplicateInteraction::PreventDuplicateInteraction(css::uno::Reference< css::uno::XComponentContext > xContext)
32 : m_xContext(std::move(xContext))
33{
34}
35
37{
38}
39
40void PreventDuplicateInteraction::setHandler(const css::uno::Reference< css::task::XInteractionHandler >& xHandler)
41{
42 // SAFE ->
43 std::unique_lock aLock(m_aLock);
45 m_xHandler = xHandler;
46 // <- SAFE
47}
48
50{
51 //if we use the default handler, set the parent to a window belonging to this object so that the dialogs
52 //don't block unrelated windows.
54 css::uno::Reference<css::task::XInteractionHandler> xHandler(css::task::InteractionHandler::createWithParent(
55 m_xContext, m_xWarningDialogsParent->GetDialogParent()), css::uno::UNO_QUERY_THROW);
56
57 // SAFE ->
58 std::unique_lock aLock(m_aLock);
59 m_xHandler = xHandler;
60 // <- SAFE
61}
62
63css::uno::Any SAL_CALL PreventDuplicateInteraction::queryInterface( const css::uno::Type& aType )
64{
65 if ( aType.equals( cppu::UnoType<XInteractionHandler2>::get() ) )
66 {
67 std::unique_lock aLock(m_aLock);
68 css::uno::Reference< css::task::XInteractionHandler2 > xHandler( m_xHandler, css::uno::UNO_QUERY );
69 if ( !xHandler.is() )
70 return css::uno::Any();
71 }
72 return ::cppu::WeakImplHelper<css::lang::XInitialization, css::task::XInteractionHandler2>::queryInterface(aType);
73}
74
75void SAL_CALL PreventDuplicateInteraction::handle(const css::uno::Reference< css::task::XInteractionRequest >& xRequest)
76{
77 css::uno::Any aRequest = xRequest->getRequest();
78 bool bHandleIt = true;
79
80 // SAFE ->
81 std::unique_lock aLock(m_aLock);
82
83 auto pIt = std::find_if(m_lInteractionRules.begin(), m_lInteractionRules.end(),
84 [&aRequest](const InteractionInfo& rInfo) { return aRequest.isExtractableTo(rInfo.m_aInteraction); });
85 if (pIt != m_lInteractionRules.end())
86 {
87 InteractionInfo& rInfo = *pIt;
88
89 ++rInfo.m_nCallCount;
90 rInfo.m_xRequest = xRequest;
91 bHandleIt = (rInfo.m_nCallCount <= rInfo.m_nMaxCount);
92 }
93
94 css::uno::Reference< css::task::XInteractionHandler > xHandler = m_xHandler;
95
96 aLock.unlock();
97 // <- SAFE
98
99 if ( bHandleIt && xHandler.is() )
100 {
101 xHandler->handle(xRequest);
102 }
103 else
104 {
105 const css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations = xRequest->getContinuations();
106 for (const auto& rContinuation : lContinuations)
107 {
108 css::uno::Reference< css::task::XInteractionAbort > xAbort(rContinuation, css::uno::UNO_QUERY);
109 if (xAbort.is())
110 {
111 xAbort->select();
112 break;
113 }
114 }
115 }
116}
117
118sal_Bool SAL_CALL PreventDuplicateInteraction::handleInteractionRequest( const css::uno::Reference< css::task::XInteractionRequest >& xRequest )
119{
120 css::uno::Any aRequest = xRequest->getRequest();
121 bool bHandleIt = true;
122
123 // SAFE ->
124 std::unique_lock aLock(m_aLock);
125
126 auto pIt = std::find_if(m_lInteractionRules.begin(), m_lInteractionRules.end(),
127 [&aRequest](const InteractionInfo& rInfo) { return aRequest.isExtractableTo(rInfo.m_aInteraction); });
128 if (pIt != m_lInteractionRules.end())
129 {
130 InteractionInfo& rInfo = *pIt;
131
132 ++rInfo.m_nCallCount;
133 rInfo.m_xRequest = xRequest;
134 bHandleIt = (rInfo.m_nCallCount <= rInfo.m_nMaxCount);
135 }
136
137 css::uno::Reference< css::task::XInteractionHandler2 > xHandler( m_xHandler, css::uno::UNO_QUERY );
138 OSL_ENSURE( xHandler.is() || !m_xHandler.is(),
139 "PreventDuplicateInteraction::handleInteractionRequest: inconsistency!" );
140
141 aLock.unlock();
142 // <- SAFE
143
144 if ( bHandleIt && xHandler.is() )
145 {
146 return xHandler->handleInteractionRequest(xRequest);
147 }
148 else
149 {
150 const css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations = xRequest->getContinuations();
151 for (const auto& rContinuation : lContinuations)
152 {
153 css::uno::Reference< css::task::XInteractionAbort > xAbort(rContinuation, css::uno::UNO_QUERY);
154 if (xAbort.is())
155 {
156 xAbort->select();
157 break;
158 }
159 }
160 }
161 return false;
162}
163
165{
166 // SAFE ->
167 std::unique_lock aLock(m_aLock);
168
169 auto pIt = std::find_if(m_lInteractionRules.begin(), m_lInteractionRules.end(),
170 [&aInteractionInfo](const InteractionInfo& rInfo) { return rInfo.m_aInteraction == aInteractionInfo.m_aInteraction; });
171 if (pIt != m_lInteractionRules.end())
172 {
173 InteractionInfo& rInfo = *pIt;
174 rInfo.m_nMaxCount = aInteractionInfo.m_nMaxCount;
175 rInfo.m_nCallCount = aInteractionInfo.m_nCallCount;
176 return;
177 }
178
179 m_lInteractionRules.push_back(aInteractionInfo);
180 // <- SAFE
181}
182
183bool PreventDuplicateInteraction::getInteractionInfo(const css::uno::Type& aInteraction,
185{
186 // SAFE ->
187 std::unique_lock aLock(m_aLock);
188
189 auto pIt = std::find_if(m_lInteractionRules.begin(), m_lInteractionRules.end(),
190 [&aInteraction](const InteractionInfo& rInfo) { return rInfo.m_aInteraction == aInteraction; });
191 if (pIt != m_lInteractionRules.end())
192 {
193 *pReturn = *pIt;
194 return true;
195 }
196 // <- SAFE
197
198 return false;
199}
200
201void SAL_CALL PreventDuplicateInteraction::initialize(const css::uno::Sequence<css::uno::Any>& rArguments)
202{
203 // If we're re-initialized to set a specific new window as a parent then drop our temporary
204 // dialog parent
205 css::uno::Reference<css::lang::XInitialization> xHandler(m_xHandler, css::uno::UNO_QUERY);
206 if (xHandler.is())
207 {
209 xHandler->initialize(rArguments);
210 }
211}
212
213IMPL_STATIC_LINK_NOARG(WarningDialogsParent, TerminateDesktop, void*, void)
214{
215 css::frame::Desktop::create(comphelper::getProcessComponentContext())->terminate();
216}
217
218} // namespace sfx2
219
220/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XComponentContext > m_xContext
std::vector< InteractionInfo > m_lInteractionRules
This list describe which and how incoming interactions must be handled.
std::unique_ptr< WarningDialogsParentScope > m_xWarningDialogsParent
css::uno::Reference< css::uno::XComponentContext > m_xContext
Used to create needed uno services at runtime.
bool getInteractionInfo(const css::uno::Type &aInteraction, PreventDuplicateInteraction::InteractionInfo *pReturn) const
return the info struct for the specified interaction.
virtual ~PreventDuplicateInteraction() override
dtor to free used memory.
virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &rArguments) override
virtual sal_Bool SAL_CALL handleInteractionRequest(const css::uno::Reference< css::task::XInteractionRequest > &xRequest) override
css::uno::Reference< css::task::XInteractionHandler > m_xHandler
The outside interaction handler, which is used to handle every incoming interaction,...
void useDefaultUUIHandler()
instead of setting an outside interaction handler, this method make sure the default UUI interaction ...
void addInteractionRule(const PreventDuplicateInteraction::InteractionInfo &aInteractionInfo)
add a new interaction to the list of interactions, which must be handled by this helper.
virtual void SAL_CALL handle(const css::uno::Reference< css::task::XInteractionRequest > &xRequest) override
void setHandler(const css::uno::Reference< css::task::XInteractionHandler > &xHandler)
set the outside interaction handler, which must be used internally if the interaction will not be blo...
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &aType) override
PreventDuplicateInteraction(css::uno::Reference< css::uno::XComponentContext > xContext)
ctor to guarantee right initialized instances of this class @descr It uses the given uno service mana...
Reference< XComponentContext > getProcessComponentContext()
IMPL_STATIC_LINK_NOARG(WarningDialogsParent, TerminateDesktop, void *, void)
sal_Int32 m_nCallCount
count how often this interaction was called.
sal_Int32 m_nMaxCount
after max count was reached this interaction will be blocked.
css::uno::Reference< css::task::XInteractionRequest > m_xRequest
hold the last intercepted request (matching the set interaction type) alive so it can be used for fur...
unsigned char sal_Bool