1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sfx2.hxx"
26 #include <sfx2/querystatus.hxx>
27 #include <svl/poolitem.hxx>
28 #include <svl/eitem.hxx>
29 #include <svl/stritem.hxx>
30 #include <svl/intitem.hxx>
31 #include <svl/itemset.hxx>
32 #include <svtools/itemdel.hxx>
33 #include <svl/visitem.hxx>
34 #include <cppuhelper/weak.hxx>
35 #include <comphelper/processfactory.hxx>
36 #include <vos/mutex.hxx>
37 #include <vcl/svapp.hxx>
38 #include <com/sun/star/util/XURLTransformer.hpp>
39 #include <com/sun/star/frame/status/ItemStatus.hpp>
40 #include <com/sun/star/frame/status/ItemState.hpp>
41 #include <com/sun/star/frame/status/Visibility.hpp>
42
43 using ::rtl::OUString;
44 using namespace ::cppu;
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::frame;
47 using namespace ::com::sun::star::frame::status;
48 using namespace ::com::sun::star::lang;
49 using namespace ::com::sun::star::util;
50
51 class SfxQueryStatus_Impl : public ::com::sun::star::frame::XStatusListener ,
52 public ::com::sun::star::lang::XTypeProvider ,
53 public ::cppu::OWeakObject
54 {
55 public:
56 SFX_DECL_XINTERFACE_XTYPEPROVIDER
57
58 SfxQueryStatus_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >& rDispatchProvider, sal_uInt16 nSlotId, const rtl::OUString& aCommand );
59 virtual ~SfxQueryStatus_Impl();
60
61 // Query method
62 SfxItemState QueryState( SfxPoolItem*& pPoolItem );
63
64 // XEventListener
65 virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source);
66
67 // XStatusListener
68 virtual void SAL_CALL statusChanged(const ::com::sun::star::frame::FeatureStateEvent& Event);
69
70 private:
71 SfxQueryStatus_Impl( const SfxQueryStatus& );
72 SfxQueryStatus_Impl();
73 SfxQueryStatus_Impl& operator=( const SfxQueryStatus& );
74
75 sal_Bool m_bQueryInProgress;
76 SfxItemState m_eState;
77 SfxPoolItem* m_pItem;
78 sal_uInt16 m_nSlotID;
79 osl::Condition m_aCondition;
80 ::com::sun::star::util::URL m_aCommand;
81 com::sun::star::uno::Reference< com::sun::star::frame::XDispatch > m_xDispatch;
82 };
83
SFX_IMPL_XINTERFACE_2(SfxQueryStatus_Impl,OWeakObject,::com::sun::star::frame::XStatusListener,::com::sun::star::lang::XEventListener)84 SFX_IMPL_XINTERFACE_2( SfxQueryStatus_Impl, OWeakObject, ::com::sun::star::frame::XStatusListener, ::com::sun::star::lang::XEventListener )
85 SFX_IMPL_XTYPEPROVIDER_2( SfxQueryStatus_Impl, ::com::sun::star::frame::XStatusListener, ::com::sun::star::lang::XEventListener )
86
87 SfxQueryStatus_Impl::SfxQueryStatus_Impl( const Reference< XDispatchProvider >& rDispatchProvider, sal_uInt16 nSlotId, const OUString& rCommand ) :
88 cppu::OWeakObject(),
89 m_bQueryInProgress( sal_False ),
90 m_eState( SFX_ITEM_DISABLED ),
91 m_pItem( 0 ),
92 m_nSlotID( nSlotId )
93 {
94 m_aCommand.Complete = rCommand;
95 Reference < XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance(
96 rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY );
97 xTrans->parseStrict( m_aCommand );
98 if ( rDispatchProvider.is() )
99 m_xDispatch = rDispatchProvider->queryDispatch( m_aCommand, rtl::OUString(), 0 );
100 m_aCondition.reset();
101 }
102
~SfxQueryStatus_Impl()103 SfxQueryStatus_Impl::~SfxQueryStatus_Impl()
104 {
105 }
106
disposing(const EventObject &)107 void SAL_CALL SfxQueryStatus_Impl::disposing( const EventObject& )
108 {
109 ::vos::OGuard aGuard( Application::GetSolarMutex() );
110 m_xDispatch.clear();
111 }
112
statusChanged(const FeatureStateEvent & rEvent)113 void SAL_CALL SfxQueryStatus_Impl::statusChanged( const FeatureStateEvent& rEvent)
114 {
115 ::vos::OGuard aGuard( Application::GetSolarMutex() );
116
117 m_pItem = NULL;
118 m_eState = SFX_ITEM_DISABLED;
119
120 if ( rEvent.IsEnabled )
121 {
122 m_eState = SFX_ITEM_AVAILABLE;
123 ::com::sun::star::uno::Type pType = rEvent.State.getValueType();
124
125 if ( pType == ::getBooleanCppuType() )
126 {
127 sal_Bool bTemp = false;
128 rEvent.State >>= bTemp ;
129 m_pItem = new SfxBoolItem( m_nSlotID, bTemp );
130 }
131 else if ( pType == ::getCppuType((const sal_uInt16*)0) )
132 {
133 sal_uInt16 nTemp = 0;
134 rEvent.State >>= nTemp ;
135 m_pItem = new SfxUInt16Item( m_nSlotID, nTemp );
136 }
137 else if ( pType == ::getCppuType((const sal_uInt32*)0) )
138 {
139 sal_uInt32 nTemp = 0;
140 rEvent.State >>= nTemp ;
141 m_pItem = new SfxUInt32Item( m_nSlotID, nTemp );
142 }
143 else if ( pType == ::getCppuType((const ::rtl::OUString*)0) )
144 {
145 ::rtl::OUString sTemp ;
146 rEvent.State >>= sTemp ;
147 m_pItem = new SfxStringItem( m_nSlotID, sTemp );
148 }
149 else if ( pType == ::getCppuType((const ::com::sun::star::frame::status::ItemStatus*)0) )
150 {
151 ItemStatus aItemStatus;
152 rEvent.State >>= aItemStatus;
153 m_eState = aItemStatus.State;
154 m_pItem = new SfxVoidItem( m_nSlotID );
155 }
156 else if ( pType == ::getCppuType((const ::com::sun::star::frame::status::Visibility*)0) )
157 {
158 Visibility aVisibilityStatus;
159 rEvent.State >>= aVisibilityStatus;
160 m_pItem = new SfxVisibilityItem( m_nSlotID, aVisibilityStatus.bVisible );
161 }
162 else
163 {
164 m_eState = SFX_ITEM_UNKNOWN;
165 m_pItem = new SfxVoidItem( m_nSlotID );
166 }
167 }
168
169 if ( m_pItem )
170 DeleteItemOnIdle( m_pItem );
171
172 try
173 {
174 m_aCondition.set();
175 m_xDispatch->removeStatusListener( Reference< XStatusListener >( static_cast< cppu::OWeakObject* >( this ), UNO_QUERY ),
176 m_aCommand );
177 }
178 catch ( Exception& )
179 {
180 }
181 }
182
183 // Query method
QueryState(SfxPoolItem * & rpPoolItem)184 SfxItemState SfxQueryStatus_Impl::QueryState( SfxPoolItem*& rpPoolItem )
185 {
186 ::vos::OGuard aGuard( Application::GetSolarMutex() );
187 if ( !m_bQueryInProgress )
188 {
189 m_pItem = NULL;
190 m_eState = SFX_ITEM_DISABLED;
191
192 if ( m_xDispatch.is() )
193 {
194 try
195 {
196 m_aCondition.reset();
197 m_bQueryInProgress = sal_True;
198 m_xDispatch->addStatusListener( Reference< XStatusListener >( static_cast< cppu::OWeakObject* >( this ), UNO_QUERY ),
199 m_aCommand );
200 }
201 catch ( Exception& )
202 {
203 m_aCondition.set();
204 }
205 }
206 else
207 m_aCondition.set();
208 }
209
210 m_aCondition.wait();
211
212 m_bQueryInProgress = sal_False;
213 rpPoolItem = m_pItem;
214 return m_eState;
215 }
216
217 //*************************************************************************
218
SfxQueryStatus(const Reference<XDispatchProvider> & rDispatchProvider,sal_uInt16 nSlotId,const OUString & rCommand)219 SfxQueryStatus::SfxQueryStatus( const Reference< XDispatchProvider >& rDispatchProvider, sal_uInt16 nSlotId, const OUString& rCommand )
220 {
221 m_pSfxQueryStatusImpl = new SfxQueryStatus_Impl( rDispatchProvider, nSlotId, rCommand );
222 m_xStatusListener = Reference< XStatusListener >(
223 static_cast< cppu::OWeakObject* >( m_pSfxQueryStatusImpl ),
224 UNO_QUERY );
225 }
226
~SfxQueryStatus()227 SfxQueryStatus::~SfxQueryStatus()
228 {
229 }
230
QueryState(SfxPoolItem * & rpPoolItem)231 SfxItemState SfxQueryStatus::QueryState( SfxPoolItem*& rpPoolItem )
232 {
233 ::vos::OGuard aGuard( Application::GetSolarMutex() );
234 return m_pSfxQueryStatusImpl->QueryState( rpPoolItem );
235 }
236