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 //------------------------------------------------------------------------ 32 // includes 33 //------------------------------------------------------------------------ 34 35 #include "VistaFilePickerEventHandler.hxx" 36 #include "asyncrequests.hxx" 37 38 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 39 #include <com/sun/star/embed/XStorage.hpp> 40 #include <com/sun/star/document/XDocumentRevisionListPersistence.hpp> 41 #include <com/sun/star/util/RevisionTag.hpp> 42 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> 43 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> 44 45 #include <comphelper/processfactory.hxx> 46 #include <comphelper/storagehelper.hxx> 47 //#include <tools/urlobj.hxx> 48 //#include <unotools/ucbhelper.hxx> 49 50 #include <osl/file.hxx> 51 52 //------------------------------------------------------------------------ 53 // namespace directives 54 //------------------------------------------------------------------------ 55 56 namespace css = ::com::sun::star; 57 58 namespace fpicker{ 59 namespace win32{ 60 namespace vista{ 61 62 //------------------------------------------------------------------------ 63 // defines 64 //------------------------------------------------------------------------ 65 66 //----------------------------------------------------------------------------------------- 67 VistaFilePickerEventHandler::VistaFilePickerEventHandler(IVistaFilePickerInternalNotify* pInternalNotify) 68 : m_nRefCount (0 ) 69 , m_nListenerHandle (0 ) 70 , m_pDialog ( ) 71 , m_lListener (m_aMutex) 72 , m_pInternalNotify (pInternalNotify) 73 { 74 } 75 76 //----------------------------------------------------------------------------------------- 77 VistaFilePickerEventHandler::~VistaFilePickerEventHandler() 78 { 79 } 80 81 //----------------------------------------------------------------------------------------- 82 HRESULT STDMETHODCALLTYPE VistaFilePickerEventHandler::QueryInterface(REFIID rIID , 83 void** ppObject) 84 { 85 *ppObject=NULL; 86 87 if ( rIID == IID_IUnknown ) 88 *ppObject = (IUnknown*)(IFileDialogEvents*)this; 89 90 if ( rIID == IID_IFileDialogEvents ) 91 *ppObject = (IFileDialogEvents*)this; 92 93 if ( rIID == IID_IFileDialogControlEvents ) 94 *ppObject = (IFileDialogControlEvents*)this; 95 96 if ( *ppObject != NULL ) 97 { 98 ((IUnknown*)*ppObject)->AddRef(); 99 return S_OK; 100 } 101 102 return E_NOINTERFACE; 103 } 104 105 //----------------------------------------------------------------------------------------- 106 ULONG STDMETHODCALLTYPE VistaFilePickerEventHandler::AddRef() 107 { 108 return osl_incrementInterlockedCount(&m_nRefCount); 109 } 110 111 //----------------------------------------------------------------------------------------- 112 ULONG STDMETHODCALLTYPE VistaFilePickerEventHandler::Release() 113 { 114 ULONG nReturn = --m_nRefCount; 115 if ( m_nRefCount == 0 ) 116 delete this; 117 118 return nReturn; 119 } 120 121 //----------------------------------------------------------------------------------------- 122 STDMETHODIMP VistaFilePickerEventHandler::OnFileOk(IFileDialog* /*pDialog*/) 123 { 124 return E_NOTIMPL; 125 } 126 127 //----------------------------------------------------------------------------------------- 128 STDMETHODIMP VistaFilePickerEventHandler::OnFolderChanging(IFileDialog* /*pDialog*/, 129 IShellItem* /*pFolder*/) 130 { 131 return E_NOTIMPL; 132 } 133 134 //----------------------------------------------------------------------------------------- 135 STDMETHODIMP VistaFilePickerEventHandler::OnFolderChange(IFileDialog* /*pDialog*/) 136 { 137 impl_sendEvent(E_DIRECTORY_CHANGED, 0); 138 return S_OK; 139 } 140 141 //----------------------------------------------------------------------------- 142 ::rtl::OUString lcl_getURLFromShellItem2 (IShellItem* pItem) 143 { 144 LPOLESTR pStr = NULL; 145 ::rtl::OUString sURL; 146 147 SIGDN eConversion = SIGDN_FILESYSPATH; 148 HRESULT hr = pItem->GetDisplayName ( eConversion, &pStr ); 149 150 if ( FAILED(hr) ) 151 { 152 eConversion = SIGDN_URL; 153 hr = pItem->GetDisplayName ( eConversion, &pStr ); 154 155 if ( FAILED(hr) ) 156 return ::rtl::OUString(); 157 158 sURL = ::rtl::OUString(reinterpret_cast<sal_Unicode*>(pStr)); 159 } 160 else 161 { 162 ::osl::FileBase::getFileURLFromSystemPath( reinterpret_cast<sal_Unicode*>(pStr), sURL ); 163 } 164 165 CoTaskMemFree (pStr); 166 return sURL; 167 } 168 169 //----------------------------------------------------------------------------------------- 170 void lcl_updateVersionListDirectly(IFileDialog* pDialog) 171 { 172 static const ::rtl::OUString SERVICENAME_REVISIONPERSISTENCE = ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence"); 173 static const ::sal_Int16 CONTROL_VERSIONLIST = css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION; 174 175 TFileDialog iDialog (pDialog); 176 TFileOpenDialog iOpen ; 177 TFileDialogCustomize iCustomize; 178 179 #ifdef __MINGW32__ 180 iDialog->QueryInterface(IID_IFileOpenDialog, (void**)(&iOpen)); 181 iDialog->QueryInterface(IID_IFileDialogCustomize, (void**)(&iCustomize)); 182 #else 183 iDialog.query(&iOpen ); 184 iDialog.query(&iCustomize); 185 #endif 186 187 // make sure version list match to the current selection always ... 188 // at least an empty version list will be better then the wrong one .-) 189 iCustomize->RemoveAllControlItems(CONTROL_VERSIONLIST); 190 191 HRESULT hResult = E_FAIL; 192 ComPtr< IShellItemArray > iItems; 193 ComPtr< IShellItem > iItem; 194 195 if (iOpen.is()) 196 { 197 hResult = iOpen->GetSelectedItems(&iItems); 198 if (FAILED(hResult)) 199 return; 200 201 DWORD nCount; 202 hResult = iItems->GetCount(&nCount); 203 if ( FAILED(hResult) ) 204 return; 205 206 // we can show one version list only within control 207 if (nCount != 1) 208 return; 209 210 hResult = iItems->GetItemAt(0, &iItem); 211 } 212 else 213 if (iDialog.is()) 214 hResult = iDialog->GetCurrentSelection(&iItem); 215 216 if ( FAILED(hResult) ) 217 return; 218 219 const ::rtl::OUString sURL = lcl_getURLFromShellItem2(iItem); 220 if (sURL.getLength() < 1) 221 return; 222 /* 223 INetURLObject aURL(sURL); 224 if (aURL.GetProtocol() != INET_PROT_FILE) 225 return; 226 227 ::rtl::OUString sMain = aURL.GetMainURL(INetURLObject::NO_DECODE); 228 if ( ! ::utl::UCBContentHelper::IsDocument(sURL)) 229 return; 230 */ 231 try 232 { 233 css::uno::Reference< css::embed::XStorage > xStorage = ::comphelper::OStorageHelper::GetStorageFromURL(sURL, css::embed::ElementModes::READ); 234 if ( ! xStorage.is() ) 235 return; 236 237 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); 238 css::uno::Reference< css::document::XDocumentRevisionListPersistence > xReader (xSMGR->createInstance(SERVICENAME_REVISIONPERSISTENCE), css::uno::UNO_QUERY_THROW); 239 css::uno::Sequence< css::util::RevisionTag > lVersions = xReader->load(xStorage); 240 241 for (::sal_Int32 i=0; i<lVersions.getLength(); ++i) 242 { 243 const css::util::RevisionTag& aTag = lVersions[i]; 244 iCustomize->AddControlItem(CONTROL_VERSIONLIST, i, reinterpret_cast<LPCTSTR>(aTag.Identifier.getStr())); 245 } 246 iCustomize->SetSelectedControlItem(CONTROL_VERSIONLIST, 0); 247 } 248 catch(const css::uno::Exception&) 249 {} 250 } 251 252 //----------------------------------------------------------------------------------------- 253 STDMETHODIMP VistaFilePickerEventHandler::OnSelectionChange(IFileDialog* /*pDialog*/) 254 { 255 impl_sendEvent(E_FILE_SELECTION_CHANGED, 0); 256 //lcl_updateVersionListDirectly(pDialog); 257 return S_OK; 258 } 259 260 //----------------------------------------------------------------------------------------- 261 STDMETHODIMP VistaFilePickerEventHandler::OnShareViolation(IFileDialog* /*pDialog*/ , 262 263 IShellItem* /*pItem*/ , 264 265 FDE_SHAREVIOLATION_RESPONSE* /*pResponse*/) 266 { 267 impl_sendEvent(E_CONTROL_STATE_CHANGED, css::ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER); 268 return S_OK; 269 } 270 271 //----------------------------------------------------------------------------------------- 272 STDMETHODIMP VistaFilePickerEventHandler::OnTypeChange(IFileDialog* pDialog) 273 { 274 UINT nFileTypeIndex; 275 HRESULT hResult = pDialog->GetFileTypeIndex( &nFileTypeIndex ); 276 277 if ( hResult == S_OK ) 278 { 279 if ( m_pInternalNotify->onFileTypeChanged( nFileTypeIndex )) 280 impl_sendEvent(E_CONTROL_STATE_CHANGED, css::ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER); 281 } 282 283 return S_OK; 284 } 285 286 //----------------------------------------------------------------------------------------- 287 STDMETHODIMP VistaFilePickerEventHandler::OnOverwrite(IFileDialog* /*pDialog*/ , 288 IShellItem* /*pItem*/ , 289 FDE_OVERWRITE_RESPONSE* /*pResponse*/) 290 { 291 return E_NOTIMPL; 292 } 293 294 //----------------------------------------------------------------------------------------- 295 STDMETHODIMP VistaFilePickerEventHandler::OnItemSelected(IFileDialogCustomize* /*pCustomize*/, 296 297 DWORD nIDCtl , 298 299 DWORD /*nIDItem*/ ) 300 { 301 302 impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl )); 303 return S_OK; 304 } 305 306 //----------------------------------------------------------------------------------------- 307 STDMETHODIMP VistaFilePickerEventHandler::OnButtonClicked(IFileDialogCustomize* /*pCustomize*/, 308 DWORD nIDCtl ) 309 { 310 311 impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl)); 312 return S_OK; 313 } 314 315 //----------------------------------------------------------------------------------------- 316 STDMETHODIMP VistaFilePickerEventHandler::OnCheckButtonToggled(IFileDialogCustomize* /*pCustomize*/, 317 DWORD nIDCtl , 318 BOOL bChecked ) 319 { 320 if (nIDCtl == css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION) 321 m_pInternalNotify->onAutoExtensionChanged(bChecked); 322 323 impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl)); 324 325 return S_OK; 326 } 327 328 //----------------------------------------------------------------------------------------- 329 STDMETHODIMP VistaFilePickerEventHandler::OnControlActivating(IFileDialogCustomize* /*pCustomize*/, 330 DWORD nIDCtl ) 331 { 332 impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl)); 333 return S_OK; 334 } 335 336 //----------------------------------------------------------------------------------------- 337 void SAL_CALL VistaFilePickerEventHandler::addFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) 338 throw( css::uno::RuntimeException ) 339 { 340 m_lListener.addInterface(::getCppuType( (const css::uno::Reference< css::ui::dialogs::XFilePickerListener >*)NULL ), xListener); 341 } 342 343 //----------------------------------------------------------------------------------------- 344 void SAL_CALL VistaFilePickerEventHandler::removeFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) 345 throw( css::uno::RuntimeException ) 346 { 347 m_lListener.removeInterface(::getCppuType( (const css::uno::Reference< css::ui::dialogs::XFilePickerListener >*)NULL ), xListener); 348 } 349 350 //----------------------------------------------------------------------------------------- 351 void VistaFilePickerEventHandler::startListening( const TFileDialog& pBroadcaster ) 352 { 353 static const sal_Bool STARTUP_SUSPENDED = sal_True; 354 static const sal_Bool STARTUP_WORKING = sal_False; 355 356 if (m_pDialog.is()) 357 return; 358 359 m_pDialog = pBroadcaster; 360 m_pDialog->Advise(this, &m_nListenerHandle); 361 } 362 363 //----------------------------------------------------------------------------------------- 364 void VistaFilePickerEventHandler::stopListening() 365 { 366 if (m_pDialog.is()) 367 { 368 m_pDialog->Unadvise(m_nListenerHandle); 369 m_pDialog.release(); 370 } 371 } 372 373 static const ::rtl::OUString PROP_CONTROL_ID = ::rtl::OUString::createFromAscii("control_id"); 374 static const ::rtl::OUString PROP_PICKER_LISTENER = ::rtl::OUString::createFromAscii("picker_listener"); 375 376 //----------------------------------------------------------------------------------------- 377 class AsyncPickerEvents : public RequestHandler 378 { 379 public: 380 381 AsyncPickerEvents() 382 {} 383 384 virtual ~AsyncPickerEvents() 385 {} 386 387 virtual void before() 388 {} 389 390 virtual void doRequest(const RequestRef& rRequest) 391 { 392 const ::sal_Int32 nEventID = rRequest->getRequest(); 393 const ::sal_Int16 nControlID = rRequest->getArgumentOrDefault(PROP_CONTROL_ID, (::sal_Int16)0); 394 const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest->getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >()); 395 396 if ( ! xListener.is()) 397 return; 398 399 css::ui::dialogs::FilePickerEvent aEvent; 400 aEvent.ElementId = nControlID; 401 402 switch (nEventID) 403 { 404 case VistaFilePickerEventHandler::E_FILE_SELECTION_CHANGED : 405 xListener->fileSelectionChanged(aEvent); 406 break; 407 408 case VistaFilePickerEventHandler::E_DIRECTORY_CHANGED : 409 xListener->directoryChanged(aEvent); 410 break; 411 412 case VistaFilePickerEventHandler::E_HELP_REQUESTED : 413 xListener->helpRequested(aEvent); 414 break; 415 416 case VistaFilePickerEventHandler::E_CONTROL_STATE_CHANGED : 417 xListener->controlStateChanged(aEvent); 418 break; 419 420 case VistaFilePickerEventHandler::E_DIALOG_SIZE_CHANGED : 421 xListener->dialogSizeChanged(); 422 break; 423 424 // no default here. Let compiler detect changes on enum set ! 425 } 426 } 427 428 virtual void after() 429 {} 430 }; 431 432 //----------------------------------------------------------------------------------------- 433 void VistaFilePickerEventHandler::impl_sendEvent( EEventType eEventType, 434 ::sal_Int16 nControlID) 435 { 436 static AsyncRequests aNotify(RequestHandlerRef(new AsyncPickerEvents())); 437 438 ::cppu::OInterfaceContainerHelper* pContainer = m_lListener.getContainer( ::getCppuType( ( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >*) NULL ) ); 439 if ( ! pContainer) 440 return; 441 442 ::cppu::OInterfaceIteratorHelper pIterator(*pContainer); 443 while (pIterator.hasMoreElements()) 444 { 445 try 446 { 447 css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener (pIterator.next(), css::uno::UNO_QUERY); 448 449 RequestRef rRequest(new Request()); 450 rRequest->setRequest (eEventType); 451 rRequest->setArgument(PROP_PICKER_LISTENER, xListener); 452 if ( nControlID ) 453 rRequest->setArgument(PROP_CONTROL_ID, nControlID); 454 455 aNotify.triggerRequestDirectly(rRequest); 456 //aNotify.triggerRequestNonBlocked(rRequest); 457 } 458 catch(const css::uno::RuntimeException&) 459 { 460 pIterator.remove(); 461 } 462 } 463 } 464 465 } // namespace vista 466 } // namespace win32 467 } // namespace fpicker 468