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) throw( ::com::sun::star::uno::RuntimeException );
66 
67         // XStatusListener
68 	    virtual void SAL_CALL statusChanged(const ::com::sun::star::frame::FeatureStateEvent& Event) throw( ::com::sun::star::uno::RuntimeException );
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 throw( RuntimeException )
109 {
110     ::vos::OGuard aGuard( Application::GetSolarMutex() );
111     m_xDispatch.clear();
112 }
113 
statusChanged(const FeatureStateEvent & rEvent)114 void SAL_CALL SfxQueryStatus_Impl::statusChanged( const FeatureStateEvent& rEvent)
115 throw( RuntimeException )
116 {
117     ::vos::OGuard aGuard( Application::GetSolarMutex() );
118 
119     m_pItem  = NULL;
120     m_eState = SFX_ITEM_DISABLED;
121 
122     if ( rEvent.IsEnabled )
123 	{
124 		m_eState = SFX_ITEM_AVAILABLE;
125 		::com::sun::star::uno::Type pType =	rEvent.State.getValueType();
126 
127 		if ( pType == ::getBooleanCppuType() )
128 		{
129 			sal_Bool bTemp = false;
130 			rEvent.State >>= bTemp ;
131 			m_pItem = new SfxBoolItem( m_nSlotID, bTemp );
132 		}
133 		else if ( pType == ::getCppuType((const sal_uInt16*)0) )
134 		{
135 			sal_uInt16 nTemp = 0;
136 			rEvent.State >>= nTemp ;
137 			m_pItem = new SfxUInt16Item( m_nSlotID, nTemp );
138 		}
139 		else if ( pType == ::getCppuType((const sal_uInt32*)0) )
140 		{
141 			sal_uInt32 nTemp = 0;
142 			rEvent.State >>= nTemp ;
143 			m_pItem = new SfxUInt32Item( m_nSlotID, nTemp );
144 		}
145 		else if ( pType == ::getCppuType((const ::rtl::OUString*)0) )
146 		{
147 			::rtl::OUString sTemp ;
148 			rEvent.State >>= sTemp ;
149 			m_pItem = new SfxStringItem( m_nSlotID, sTemp );
150 		}
151         else if ( pType == ::getCppuType((const ::com::sun::star::frame::status::ItemStatus*)0) )
152         {
153             ItemStatus aItemStatus;
154             rEvent.State >>= aItemStatus;
155             m_eState = aItemStatus.State;
156             m_pItem = new SfxVoidItem( m_nSlotID );
157         }
158         else if ( pType == ::getCppuType((const ::com::sun::star::frame::status::Visibility*)0) )
159         {
160             Visibility aVisibilityStatus;
161             rEvent.State >>= aVisibilityStatus;
162             m_pItem = new SfxVisibilityItem( m_nSlotID, aVisibilityStatus.bVisible );
163         }
164 		else
165         {
166             m_eState = SFX_ITEM_UNKNOWN;
167 			m_pItem  = new SfxVoidItem( m_nSlotID );
168         }
169 	}
170 
171 	if ( m_pItem )
172         DeleteItemOnIdle( m_pItem );
173 
174     try
175     {
176         m_aCondition.set();
177         m_xDispatch->removeStatusListener( Reference< XStatusListener >( static_cast< cppu::OWeakObject* >( this ), UNO_QUERY ),
178                                            m_aCommand );
179     }
180     catch ( Exception& )
181     {
182     }
183 }
184 
185 // Query method
QueryState(SfxPoolItem * & rpPoolItem)186 SfxItemState SfxQueryStatus_Impl::QueryState( SfxPoolItem*& rpPoolItem )
187 {
188     ::vos::OGuard aGuard( Application::GetSolarMutex() );
189     if ( !m_bQueryInProgress )
190     {
191         m_pItem  = NULL;
192         m_eState = SFX_ITEM_DISABLED;
193 
194         if ( m_xDispatch.is() )
195         {
196             try
197             {
198                 m_aCondition.reset();
199                 m_bQueryInProgress = sal_True;
200                 m_xDispatch->addStatusListener( Reference< XStatusListener >( static_cast< cppu::OWeakObject* >( this ), UNO_QUERY ),
201                                                 m_aCommand );
202             }
203             catch ( Exception& )
204             {
205                 m_aCondition.set();
206             }
207         }
208         else
209             m_aCondition.set();
210     }
211 
212     m_aCondition.wait();
213 
214     m_bQueryInProgress = sal_False;
215     rpPoolItem = m_pItem;
216     return m_eState;
217 }
218 
219 //*************************************************************************
220 
SfxQueryStatus(const Reference<XDispatchProvider> & rDispatchProvider,sal_uInt16 nSlotId,const OUString & rCommand)221 SfxQueryStatus::SfxQueryStatus( const Reference< XDispatchProvider >& rDispatchProvider, sal_uInt16 nSlotId, const OUString& rCommand )
222 {
223     m_pSfxQueryStatusImpl = new SfxQueryStatus_Impl( rDispatchProvider, nSlotId, rCommand );
224     m_xStatusListener     = Reference< XStatusListener >(
225                                 static_cast< cppu::OWeakObject* >( m_pSfxQueryStatusImpl ),
226                                 UNO_QUERY );
227 }
228 
~SfxQueryStatus()229 SfxQueryStatus::~SfxQueryStatus()
230 {
231 }
232 
QueryState(SfxPoolItem * & rpPoolItem)233 SfxItemState SfxQueryStatus::QueryState( SfxPoolItem*& rpPoolItem )
234 {
235     ::vos::OGuard aGuard( Application::GetSolarMutex() );
236     return m_pSfxQueryStatusImpl->QueryState( rpPoolItem );
237 }
238