1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_fpicker.hxx"
30 
31 #include "asyncfilepicker.hxx"
32 #include "iodlg.hxx"
33 #include "svtools/fileview.hxx"
34 #include <tools/debug.hxx>
35 
36 #include <memory>
37 
38 //........................................................................
39 namespace svt
40 {
41 //........................................................................
42 
43 	//====================================================================
44 	//= AsyncPickerAction
45 	//====================================================================
46     DBG_NAME( AsyncPickerAction )
47 	//--------------------------------------------------------------------
48     AsyncPickerAction::AsyncPickerAction( SvtFileDialog* _pDialog, SvtFileView* _pView, const Action _eAction )
49         :m_refCount ( 0        )
50         ,m_eAction  ( _eAction )
51         ,m_pView    ( _pView   )
52         ,m_pDialog  ( _pDialog )
53         ,m_bRunning ( false    )
54     {
55         DBG_CTOR( AsyncPickerAction, NULL );
56         DBG_ASSERT( m_pDialog, "AsyncPickerAction::AsyncPickerAction: invalid dialog!" );
57         DBG_ASSERT( m_pView, "AsyncPickerAction::AsyncPickerAction: invalid view!" );
58     }
59 
60     //--------------------------------------------------------------------
61     AsyncPickerAction::~AsyncPickerAction()
62     {
63         DBG_DTOR( AsyncPickerAction, NULL );
64     }
65 
66     //--------------------------------------------------------------------
67     oslInterlockedCount SAL_CALL AsyncPickerAction::acquire()
68     {
69         return osl_incrementInterlockedCount( &m_refCount );
70     }
71 
72     //--------------------------------------------------------------------
73     oslInterlockedCount SAL_CALL AsyncPickerAction::release()
74     {
75         if ( 0 == osl_decrementInterlockedCount( &m_refCount ) )
76         {
77             delete this;
78             return 0;
79         }
80         return m_refCount;
81     }
82 
83 	//--------------------------------------------------------------------
84     void AsyncPickerAction::cancel()
85     {
86         DBG_TESTSOLARMUTEX();
87             // if this asserts, we'd need to have an own mutex per instance
88 
89         OSL_ENSURE( m_bRunning, "AsyncPickerAction::cancel: not running" );
90         if ( m_pView )
91             m_pView->CancelRunningAsyncAction();
92     }
93 
94 	//--------------------------------------------------------------------
95     void AsyncPickerAction::execute(
96 		const String& _rURL,
97 		const String& _rFilter,
98 		sal_Int32 _nMinTimeout,
99 		sal_Int32 _nMaxTimeout,
100 		const OUStringList& rBlackList )
101     {
102         DBG_TESTSOLARMUTEX();
103             // if this asserts, we'd need to have an own mutex per instance
104 
105         sal_Int32 nMinTimeout = _nMinTimeout;
106         sal_Int32 nMaxTimeout = _nMaxTimeout;
107         // normalizations
108         if ( nMinTimeout < 0 )
109             // if negative, this is considered as "do it synchronously"
110             nMinTimeout = 0;
111         else if ( nMinTimeout < 1000 )
112             nMinTimeout = 1000;
113         if ( nMaxTimeout <= nMinTimeout )
114             nMaxTimeout = nMinTimeout + 30000;
115 
116         ::std::auto_ptr< FileViewAsyncAction > pActionDescriptor;
117         if ( nMinTimeout )
118         {
119             pActionDescriptor.reset( new FileViewAsyncAction );
120             pActionDescriptor->nMinTimeout = nMinTimeout;
121             pActionDescriptor->nMaxTimeout = nMaxTimeout;
122             pActionDescriptor->aFinishHandler = LINK( this, AsyncPickerAction, OnActionDone );
123         }
124 
125         FileViewResult eResult = eFailure;
126         m_sURL = _rURL;
127         switch ( m_eAction )
128         {
129         case ePrevLevel:
130             eResult = m_pView->PreviousLevel( pActionDescriptor.get() );
131             break;
132 
133         case eOpenURL:
134             eResult = m_pView->Initialize( _rURL, _rFilter, pActionDescriptor.get(), rBlackList );
135             break;
136 
137         case eExecuteFilter:
138             // preserve the filename (FS: why?)
139             m_sFileName = m_pDialog->getCurrentFileText();
140             // execute the new filter
141             eResult = m_pView->ExecuteFilter( _rFilter, pActionDescriptor.get() );
142             break;
143 
144         default:
145             DBG_ERROR( "AsyncPickerAction::execute: unknown action!" );
146             break;
147         }
148 
149         acquire();
150         if ( ( eResult == eSuccess ) || ( eResult == eFailure ) )
151         {
152             // the handler is only called if the action could not be finished within
153             // the given minimum time period. In case of success, we need to call it
154             // explicitly
155             OnActionDone( reinterpret_cast< void* >( eResult ) );
156         }
157         else if ( eResult == eStillRunning )
158         {
159             m_bRunning = true;
160             m_pDialog->onAsyncOperationStarted();
161         }
162     }
163 
164 	//--------------------------------------------------------------------
165 	IMPL_LINK( AsyncPickerAction, OnActionDone, void*, pEmptyArg )
166     {
167         DBG_TESTSOLARMUTEX();
168             // if this asserts, we'd need to have an own mutex per instance
169 
170         FileViewResult eResult = static_cast< FileViewResult >( reinterpret_cast< sal_IntPtr >( pEmptyArg ) );
171         OSL_ENSURE( eStillRunning != eResult, "AsyncPickerAction::OnActionDone: invalid result!" );
172 
173         // release once (since we acquired in |execute|), but keep alive until the
174         // end of the method
175         ::rtl::Reference< AsyncPickerAction > xKeepAlive( this );
176         release();
177 
178         m_pDialog->onAsyncOperationFinished();
179         m_bRunning = true;
180 
181         if ( eFailure == eResult )
182             // TODO: do we need some kind of cleanup here?
183             return 0L;
184 
185         if ( eTimeout == eResult )
186         {
187             m_pDialog->displayIOException( m_sURL, ::com::sun::star::ucb::IOErrorCode_CANT_READ );
188             return 0L;
189         }
190 
191         OSL_ENSURE( eSuccess == eResult, "AsyncPickerAction::OnActionDone: what else valid results are there?" );
192 
193         switch ( m_eAction )
194         {
195         case ePrevLevel:
196         case eOpenURL:
197             m_pDialog->UpdateControls( m_pView->GetViewURL() );
198             break;
199 
200         case eExecuteFilter:
201 	        // restore the filename
202 	        m_pView->SetNoSelection();
203             m_pDialog->setCurrentFileText( m_sFileName, true );
204 
205 	        // notify listeners
206 	        m_pDialog->FilterSelect();
207             break;
208 
209         default:
210             DBG_ERROR( "AsyncPickerAction::OnActionDone: unknown action!" );
211             break;
212         }
213 
214         return 1L;
215     }
216 
217 //........................................................................
218 } // namespace svt
219 //........................................................................
220 
221