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_svtools.hxx" 26 27 #include <svtools/fileview.hxx> 28 #include <svtools/svtdata.hxx> 29 #include <svtools/imagemgr.hxx> 30 #include <svtools/headbar.hxx> 31 #include <svtools/svtabbx.hxx> 32 #include <svtools/svtools.hrc> 33 #include "fileview.hrc" 34 #include "contentenumeration.hxx" 35 #include <svtools/AccessibleBrowseBoxObjType.hxx> 36 #include <com/sun/star/util/DateTime.hpp> 37 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 38 #include <com/sun/star/task/XInteractionHandler.hpp> 39 #include <com/sun/star/ucb/XProgressHandler.hpp> 40 #include <com/sun/star/sdbc/XResultSet.hpp> 41 #include <com/sun/star/ucb/XAnyCompareFactory.hpp> 42 #include <com/sun/star/ucb/XContentAccess.hpp> 43 #include <com/sun/star/ucb/XDynamicResultSet.hpp> 44 #include <com/sun/star/ucb/XSortedDynamicResultSetFactory.hpp> 45 #include <com/sun/star/sdbc/XRow.hpp> 46 #include <com/sun/star/container/XChild.hpp> 47 #include <com/sun/star/ucb/CommandAbortedException.hpp> 48 #include <com/sun/star/ucb/ContentCreationException.hpp> 49 #include <vcl/waitobj.hxx> 50 #include <com/sun/star/io/XPersist.hpp> 51 #include <com/sun/star/beans/XPropertySet.hpp> 52 #include <com/sun/star/ucb/XCommandInfo.hpp> 53 #include <com/sun/star/beans/XPropertySetInfo.hpp> 54 #include <com/sun/star/beans/PropertyAttribute.hpp> 55 56 #include <algorithm> 57 #include <memory> 58 #include <tools/urlobj.hxx> 59 #include <tools/datetime.hxx> 60 #include <comphelper/processfactory.hxx> 61 #include <unotools/localfilehelper.hxx> 62 #include <ucbhelper/content.hxx> 63 #include <ucbhelper/commandenvironment.hxx> 64 #include <vcl/msgbox.hxx> 65 #ifndef INCLUDED_RTL_MATH_H 66 #include <rtl/math.hxx> 67 #endif 68 #include <tools/config.hxx> 69 #include <osl/mutex.hxx> 70 #include <osl/conditn.hxx> 71 #include <vos/timer.hxx> 72 #include <vcl/svapp.hxx> 73 #include <vcl/sound.hxx> 74 #include <unotools/ucbhelper.hxx> 75 #include <unotools/intlwrapper.hxx> 76 #include <unotools/syslocale.hxx> 77 #include <svl/urlfilter.hxx> 78 79 using namespace ::com::sun::star::lang; 80 using namespace ::com::sun::star::sdbc; 81 using namespace ::com::sun::star::task; 82 using namespace ::com::sun::star::ucb; 83 using namespace ::com::sun::star::uno; 84 using namespace ::com::sun::star::io; 85 using namespace ::com::sun::star::beans; 86 using namespace ::comphelper; 87 using ::svt::SortingData_Impl; 88 using ::svt::FolderDescriptor; 89 using ::vos::TTimeValue; 90 using ::rtl::OUString; 91 92 #define ALL_FILES_FILTER "*.*" 93 94 #define COLUMN_TITLE 1 95 #define COLUMN_TYPE 2 96 #define COLUMN_SIZE 3 97 #define COLUMN_DATE 4 98 99 DECLARE_LIST( StringList_Impl, OUString* ) 100 101 #define ROW_HEIGHT 17 // the height of a row has to be a little higher than the bitmap 102 #define QUICK_SEARCH_TIMEOUT 1500 // time in mSec before the quicksearch string will be reseted 103 104 namespace 105 { 106 //==================================================================== 107 //= ReleaseSolarMutex 108 //==================================================================== 109 struct ReleaseSolarMutex 110 { 111 private: 112 sal_uLong m_nCount; 113 114 public: 115 inline ReleaseSolarMutex() 116 { 117 m_nCount = Application::ReleaseSolarMutex(); 118 } 119 inline ~ReleaseSolarMutex() 120 { 121 Application::AcquireSolarMutex( m_nCount ); 122 } 123 }; 124 125 //==================================================================== 126 //= ITimeoutHandler 127 //==================================================================== 128 class CallbackTimer; 129 class ITimeoutHandler 130 { 131 public: 132 virtual void onTimeout( CallbackTimer* _pInstigator ) = 0; 133 }; 134 135 //==================================================================== 136 //= CallbackTimer 137 //==================================================================== 138 class CallbackTimer : public ::vos::OTimer 139 { 140 protected: 141 ITimeoutHandler* m_pTimeoutHandler; 142 143 public: 144 CallbackTimer( ITimeoutHandler* _pHandler ) : m_pTimeoutHandler( _pHandler ) { } 145 146 protected: 147 virtual void SAL_CALL onShot(); 148 }; 149 150 //-------------------------------------------------------------------- 151 void SAL_CALL CallbackTimer::onShot() 152 { 153 OSL_ENSURE( m_pTimeoutHandler, "CallbackTimer::onShot: nobody interested in?" ); 154 ITimeoutHandler* pHandler( m_pTimeoutHandler ); 155 if ( pHandler ) 156 pHandler->onTimeout( this ); 157 } 158 159 } 160 161 // ----------------------------------------------------------------------- 162 163 static sal_Bool isHighContrast( const Window* _pView ) 164 { 165 return _pView->GetSettings().GetStyleSettings().GetHighContrastMode(); 166 } 167 168 // ----------------------------------------------------------------------- 169 170 void FilterMatch::createWildCardFilterList(const String& _rFilterList,::std::vector< WildCard >& _rFilters) 171 { 172 if( _rFilterList.Len() ) 173 {// filter is given 174 xub_StrLen nCount = _rFilterList.GetTokenCount(); 175 _rFilters.reserve( nCount ); 176 xub_StrLen nIndex = 0; 177 OUString sToken; 178 do 179 { 180 sToken = _rFilterList.GetToken( 0, ';', nIndex ); 181 if ( sToken.getLength() ) 182 { 183 _rFilters.push_back( WildCard( sToken.toAsciiUpperCase() ) ); 184 } 185 } 186 while ( nIndex != STRING_NOTFOUND ); 187 } 188 else 189 // no filter is given -> match all 190 _rFilters.push_back( WildCard( String::CreateFromAscii( "*" ) ) ); 191 } 192 // class ViewTabListBox_Impl --------------------------------------------- 193 194 class ViewTabListBox_Impl : public SvHeaderTabListBox 195 { 196 private: 197 Reference< XCommandEnvironment > mxCmdEnv; 198 199 ::osl::Mutex maMutex; 200 HeaderBar* mpHeaderBar; 201 SvtFileView_Impl* mpParent; 202 Timer maResetQuickSearch; 203 OUString maQuickSearchText; 204 String msAccessibleDescText; 205 String msFolder; 206 String msFile; 207 sal_uInt32 mnSearchIndex; 208 sal_Bool mbResizeDisabled : 1; 209 sal_Bool mbAutoResize : 1; 210 sal_Bool mbEnableDelete : 1; 211 sal_Bool mbEnableRename : 1; 212 213 void DeleteEntries(); 214 void DoQuickSearch( const xub_Unicode& rChar ); 215 sal_Bool Kill( const OUString& rURL ); 216 217 protected: 218 virtual sal_Bool DoubleClickHdl(); 219 virtual ::rtl::OUString GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const; 220 221 public: 222 ViewTabListBox_Impl( Window* pParentWin, SvtFileView_Impl* pParent, sal_Int16 nFlags ); 223 ~ViewTabListBox_Impl(); 224 225 virtual void Resize(); 226 virtual void KeyInput( const KeyEvent& rKEvt ); 227 virtual sal_Bool EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText ); 228 229 void ClearAll(); 230 HeaderBar* GetHeaderBar() const { return mpHeaderBar; } 231 232 void EnableAutoResize() { mbAutoResize = sal_True; } 233 void EnableDelete( sal_Bool bEnable ) { mbEnableDelete = bEnable; } 234 void EnableRename( sal_Bool bEnable ) { mbEnableRename = bEnable; } 235 sal_Bool IsDeleteOrContextMenuEnabled() { return mbEnableDelete || IsContextMenuHandlingEnabled(); } 236 237 Reference< XCommandEnvironment > GetCommandEnvironment() const { return mxCmdEnv; } 238 239 DECL_LINK( ResetQuickSearch_Impl, Timer * ); 240 241 virtual PopupMenu* CreateContextMenu( void ); 242 virtual void ExcecuteContextMenuAction( sal_uInt16 nSelectedPopentry ); 243 }; 244 245 // class HashedEntry -------------------------------------------------- 246 247 class HashedEntry 248 { // just a special String which can be compared on equality much faster 249 protected: 250 OUString maName; 251 sal_Int32 mnHashCode; 252 public: 253 inline HashedEntry( const OUString& rName ); 254 inline HashedEntry( const INetURLObject& rURL ); 255 inline HashedEntry( const HashedEntry& rCopy ); 256 virtual ~HashedEntry(); 257 258 inline sal_Bool operator ==( const HashedEntry& rRef ) const; 259 inline sal_Bool operator !=( const HashedEntry& rRef ) const; 260 261 inline const OUString& GetName() const; 262 }; 263 264 inline HashedEntry::HashedEntry( const OUString& rName ): maName( rName ), mnHashCode( rName.hashCode() ) 265 { 266 } 267 268 inline HashedEntry::HashedEntry( const INetURLObject& rURL ): 269 maName( rURL.GetMainURL( INetURLObject::NO_DECODE ) ), 270 mnHashCode( maName.hashCode() ) 271 { 272 } 273 274 inline HashedEntry::HashedEntry( const HashedEntry& r ): maName( r.maName ), mnHashCode( r.mnHashCode ) 275 { 276 } 277 278 HashedEntry::~HashedEntry() 279 { 280 } 281 282 inline sal_Bool HashedEntry::operator ==( const HashedEntry& rRef ) const 283 { 284 return mnHashCode == rRef.mnHashCode && maName.reverseCompareTo( rRef.maName ) == 0; 285 } 286 287 inline sal_Bool HashedEntry::operator !=( const HashedEntry& rRef ) const 288 { 289 return mnHashCode != rRef.mnHashCode || maName.reverseCompareTo( rRef.maName ) != 0; 290 } 291 292 inline const OUString& HashedEntry::GetName() const 293 { 294 return maName; 295 } 296 297 // class HashedEntryList ---------------------------------------------- 298 299 class HashedEntryList : protected List 300 {// provides a list of _unique_ Entries 301 protected: 302 inline HashedEntry* First(); 303 inline HashedEntry* Next(); 304 inline void Append( HashedEntry* pNewEntry ); 305 public: 306 virtual ~HashedEntryList(); 307 308 const HashedEntry* Find( const OUString& rNameToSearchFor ); 309 const HashedEntry* Find( const HashedEntry& rToSearchFor ); 310 // not const, because First()/Next() is used 311 using List::Insert; 312 const HashedEntry& Insert( HashedEntry* pInsertOrDelete ); 313 // don't care about pInsertOrDelete after this any more and handle it as invalid! 314 // returns the Entry, which is effectively inserted 315 316 void Clear(); 317 }; 318 319 inline HashedEntry* HashedEntryList::First() 320 { 321 return ( HashedEntry* ) List::First(); 322 } 323 324 inline HashedEntry* HashedEntryList::Next() 325 { 326 return ( HashedEntry* ) List::Next(); 327 } 328 329 inline void HashedEntryList::Append( HashedEntry* pNew ) 330 { 331 List::Insert( pNew, LIST_APPEND ); 332 } 333 334 HashedEntryList::~HashedEntryList() 335 { 336 Clear(); 337 } 338 339 const HashedEntry* HashedEntryList::Find( const OUString& rRefName ) 340 { // simple linear search, which should be fast enough for this purpose 341 HashedEntry aRef( rRefName ); 342 HashedEntry* pIter = First(); 343 while( pIter && *pIter != aRef ) 344 pIter = Next(); 345 346 return pIter; 347 } 348 349 const HashedEntry* HashedEntryList::Find( const HashedEntry& rRef ) 350 { // simple linear search, which should be fast enough for this purpose 351 HashedEntry* pIter = First(); 352 while( pIter && *pIter != rRef ) 353 pIter = Next(); 354 355 return pIter; 356 } 357 358 const HashedEntry& HashedEntryList::Insert( HashedEntry* pNew ) 359 { // inserts (appends) only, if entry doesn't already exists 360 // if it already exists, pNew is deleted, because the caller must not worry about pNew any more 361 362 DBG_ASSERT( pNew, "HashedEntryList::Insert(): NULL-pointer can't be inserted" ); 363 364 const HashedEntry* pSearch = Find( *pNew ); 365 if( pSearch ) 366 { 367 delete pNew; 368 return *pSearch; 369 } 370 371 Append( pNew ); 372 373 return *pNew; 374 } 375 376 void HashedEntryList::Clear() 377 { 378 HashedEntry* p = First(); 379 while( p ) 380 { 381 delete p; 382 p = Next(); 383 } 384 } 385 386 // class NameTranslationEntry ----------------------------------------- 387 388 class NameTranslationEntry : public HashedEntry 389 {// a fast compareble String and another String, which is used to get a substitution for a given String 390 protected: 391 OUString maTranslatedName; 392 public: 393 inline NameTranslationEntry( const OUString& rOriginalName, const OUString& rTranslatedName ); 394 inline NameTranslationEntry( const ByteString& rOriginalName, const ByteString& rTranslatedName ); 395 396 inline const OUString& GetTranslation() const; 397 }; 398 399 inline NameTranslationEntry::NameTranslationEntry( const OUString& rOrg, const OUString& rTrans ): 400 HashedEntry( rOrg ), 401 maTranslatedName( rTrans ) 402 { 403 } 404 405 inline NameTranslationEntry::NameTranslationEntry( const ByteString& rOrg, const ByteString& rTrans ): 406 HashedEntry( OUString( rOrg.GetBuffer(), rOrg.Len(), RTL_TEXTENCODING_ASCII_US ) ), 407 maTranslatedName( OUString( rTrans.GetBuffer(), rTrans.Len(), RTL_TEXTENCODING_UTF8 ) ) 408 { 409 } 410 411 inline const OUString& NameTranslationEntry::GetTranslation() const 412 { 413 return maTranslatedName; 414 } 415 416 // class NameTranslationList ----------------------------------------- 417 418 class NameTranslationList : protected HashedEntryList 419 { // contains a list of substitutes of strings for a given folder (as URL) 420 // explanation of the circumstances see in remarks for Init(); 421 protected: 422 INetURLObject maTransFile; // URL of file with translation entries 423 HashedEntry maHashedURL; // for future purposes when dealing with a set of cached 424 // NameTranslationLists 425 private: 426 const String maTransFileName; 427 void Init(); // reads the translation file and fills the (internal) list 428 429 public: 430 NameTranslationList( const INetURLObject& rBaseURL ); 431 // rBaseURL: path to folder for which the translation of the entries 432 // should be done 433 434 using List::operator==; 435 inline sal_Bool operator ==( const HashedEntry& rRef ) const; 436 using List::operator!=; 437 inline sal_Bool operator !=( const HashedEntry& rRef ) const; 438 439 const OUString* Translate( const OUString& rName ) const; 440 // returns NULL, if rName can't be found 441 442 inline void Update(); // clears list and init 443 444 inline const String& GetTransTableFileName() const; 445 // returns the name for the file, which contains the translation strings 446 }; 447 448 inline const String& NameTranslationList::GetTransTableFileName() const 449 { 450 return maTransFileName; 451 } 452 453 void NameTranslationList::Init() 454 { 455 // Tries to read the file ".nametranslation.table" in the base folder. Complete path/name is in maTransFile. 456 // Further on, the found entries in the section "TRANSLATIONNAMES" are used to replace names in the 457 // base folder by translated ones. The translation must be given in UTF8 458 // See examples of such a files in the samples-folder of an Office installation 459 460 try 461 { 462 ::ucbhelper::Content aTestContent( maTransFile.GetMainURL( INetURLObject::NO_DECODE ), Reference< XCommandEnvironment >() ); 463 464 if( aTestContent.isDocument() ) 465 {// ... also tests the existence of maTransFile by throwing an Exception 466 const sal_Char* pSection = "TRANSLATIONNAMES"; 467 String aFsysName( maTransFile.getFSysPath( INetURLObject::FSYS_DETECT ) ); 468 Config aConfig( aFsysName ); 469 470 aConfig.SetGroup( ByteString( pSection ) ); 471 472 sal_uInt16 nKeyCnt = aConfig.GetKeyCount(); 473 474 for( sal_uInt16 nCnt = 0 ; nCnt < nKeyCnt ; ++nCnt ) 475 Insert( new NameTranslationEntry( aConfig.GetKeyName( nCnt ), aConfig.ReadKey( nCnt ) ) ); 476 } 477 } 478 catch( Exception const & ) {} 479 } 480 481 NameTranslationList::NameTranslationList( const INetURLObject& rBaseURL ): 482 maTransFile( rBaseURL ), 483 maHashedURL( rBaseURL ), 484 maTransFileName( String::CreateFromAscii( ".nametranslation.table" ) ) 485 { 486 maTransFile.insertName( maTransFileName ); 487 Init(); 488 } 489 490 inline sal_Bool NameTranslationList::operator ==( const HashedEntry& rRef ) const 491 { 492 return maHashedURL == rRef; 493 } 494 495 inline sal_Bool NameTranslationList::operator !=( const HashedEntry& rRef ) const 496 { 497 return maHashedURL != rRef; 498 } 499 500 const OUString* NameTranslationList::Translate( const OUString& rName ) const 501 { 502 const NameTranslationEntry* pSearch = static_cast< const NameTranslationEntry* >( 503 ( const_cast< NameTranslationList* >( this ) )->Find( rName ) ); 504 505 return pSearch? &pSearch->GetTranslation() : NULL; 506 } 507 508 inline void NameTranslationList::Update() 509 { 510 Clear(); 511 Init(); 512 } 513 514 // class NameTranslator_Impl ------------------------------------------ 515 516 // enables the user to get string substitutions (translations for the content) for a given folder 517 // see more explanations above in the description for NameTranslationList 518 class NameTranslator_Impl : public ::svt::IContentTitleTranslation 519 { 520 private: 521 NameTranslationList* mpActFolder; 522 public: 523 NameTranslator_Impl( void ); 524 NameTranslator_Impl( const INetURLObject& rActualFolder ); 525 virtual ~NameTranslator_Impl(); 526 527 // IContentTitleTranslation 528 virtual sal_Bool GetTranslation( const OUString& rOriginalName, OUString& rTranslatedName ) const; 529 530 void UpdateTranslationTable(); // reads the translation file again 531 532 void SetActualFolder( const INetURLObject& rActualFolder ); 533 const String* GetTransTableFileName() const; 534 // returns the name for the file, which contains the translation strings 535 }; 536 537 //==================================================================== 538 //= SvtFileView_Impl 539 //==================================================================== 540 541 class SvtFileView_Impl :public ::svt::IEnumerationResultHandler 542 ,public ITimeoutHandler 543 { 544 protected: 545 SvtFileView* mpAntiImpl; 546 Link m_aSelectHandler; 547 548 ::rtl::Reference< ::svt::FileViewContentEnumerator > 549 m_pContentEnumerator; 550 Link m_aCurrentAsyncActionHandler; 551 ::osl::Condition m_aAsyncActionFinished; 552 ::rtl::Reference< ::vos::OTimer > m_pCancelAsyncTimer; 553 ::svt::EnumerationResult m_eAsyncActionResult; 554 bool m_bRunningAsyncAction; 555 bool m_bAsyncActionCancelled; 556 557 558 public: 559 560 ::std::vector< SortingData_Impl* > maContent; 561 ::osl::Mutex maMutex; 562 563 ViewTabListBox_Impl* mpView; 564 NameTranslator_Impl* mpNameTrans; 565 const IUrlFilter* mpUrlFilter; 566 sal_uInt16 mnSortColumn; 567 sal_Bool mbAscending : 1; 568 sal_Bool mbOnlyFolder : 1; 569 sal_Bool mbReplaceNames : 1; // translate folder names or display doc-title instead of file name 570 sal_Int16 mnSuspendSelectCallback : 1; 571 sal_Bool mbIsFirstResort : 1; 572 573 IntlWrapper aIntlWrapper; 574 575 String maViewURL; 576 String maAllFilter; 577 String maCurrentFilter; 578 Image maFolderImage; 579 Link maOpenDoneLink; 580 Reference< XCommandEnvironment > mxCmdEnv; 581 582 SvtFileView_Impl( SvtFileView* pAntiImpl, Reference < XCommandEnvironment > xEnv, 583 sal_Int16 nFlags, 584 sal_Bool bOnlyFolder ); 585 virtual ~SvtFileView_Impl(); 586 587 void Clear(); 588 589 FileViewResult GetFolderContent_Impl( 590 const String& rFolder, 591 const FileViewAsyncAction* pAsyncDescriptor, 592 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList = ::com::sun::star::uno::Sequence< ::rtl::OUString >() ); 593 594 FileViewResult GetFolderContent_Impl( 595 const FolderDescriptor& _rFolder, 596 const FileViewAsyncAction* pAsyncDescriptor, 597 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList = ::com::sun::star::uno::Sequence< ::rtl::OUString >()); 598 void FilterFolderContent_Impl( const OUString &rFilter ); 599 void CancelRunningAsyncAction(); 600 601 void OpenFolder_Impl(); 602 // #83004# ------- 603 void ReplaceTabWithString( OUString& aValue ); 604 void CreateDisplayText_Impl(); 605 void CreateVector_Impl( const Sequence < OUString > &rList ); 606 void SortFolderContent_Impl(); 607 608 void EntryRemoved( const OUString& rURL ); 609 void EntryRenamed( OUString& rURL, 610 const OUString& rName ); 611 String FolderInserted( const OUString& rURL, 612 const OUString& rTitle ); 613 614 sal_uLong GetEntryPos( const OUString& rURL ); 615 616 inline void EnableContextMenu( sal_Bool bEnable ); 617 inline void EnableDelete( sal_Bool bEnable ); 618 619 void Resort_Impl( sal_Int16 nColumn, sal_Bool bAscending ); 620 sal_Bool SearchNextEntry( sal_uInt32 &nIndex, 621 const OUString& rTitle, 622 sal_Bool bWrapAround ); 623 624 inline sal_Bool EnableNameReplacing( sal_Bool bEnable = sal_True ); // returns false, if action wasn't possible 625 void SetActualFolder( const INetURLObject& rActualFolder ); 626 627 sal_Bool GetDocTitle( const OUString& rTargetURL, OUString& rDocTitle ) const; 628 629 void SetSelectHandler( const Link& _rHdl ); 630 631 void InitSelection(); 632 void ResetCursor(); 633 634 inline void EndEditing( bool _bCancel ); 635 636 protected: 637 DECL_LINK( SelectionMultiplexer, void* ); 638 639 protected: 640 // IEnumerationResultHandler overridables 641 virtual void enumerationDone( ::svt::EnumerationResult _eResult ); 642 void implEnumerationSuccess(); 643 644 // ITimeoutHandler 645 virtual void onTimeout( CallbackTimer* _pInstigator ); 646 }; 647 648 inline void SvtFileView_Impl::EnableContextMenu( sal_Bool bEnable ) 649 { 650 mpView->EnableContextMenuHandling( bEnable ); 651 if( bEnable ) 652 mbReplaceNames = sal_False; 653 } 654 655 inline void SvtFileView_Impl::EnableDelete( sal_Bool bEnable ) 656 { 657 mpView->EnableDelete( bEnable ); 658 if( bEnable ) 659 mbReplaceNames = sal_False; 660 } 661 662 inline sal_Bool SvtFileView_Impl::EnableNameReplacing( sal_Bool bEnable ) 663 { 664 mpView->EnableRename( bEnable ); 665 666 sal_Bool bRet; 667 if( mpView->IsDeleteOrContextMenuEnabled() ) 668 { 669 DBG_ASSERT( !mbReplaceNames, "SvtFileView_Impl::EnableNameReplacing(): state should be not possible!" ); 670 bRet = !bEnable; // only for enabling this is an unsuccessful result 671 } 672 else 673 { 674 mbReplaceNames = bEnable; 675 bRet = sal_True; 676 } 677 678 return bRet; 679 } 680 681 inline void SvtFileView_Impl::EndEditing( bool _bCancel ) 682 { 683 if ( mpView->IsEditingActive() ) 684 mpView->EndEditing( _bCancel != false ); 685 } 686 687 // functions ------------------------------------------------------------- 688 689 OUString CreateExactSizeText_Impl( sal_Int64 nSize ) 690 { 691 double fSize( ( double ) nSize ); 692 int nDec; 693 694 long nMega = 1024 * 1024; 695 long nGiga = nMega * 1024; 696 697 String aUnitStr = ' '; 698 699 if ( nSize < 10000 ) 700 { 701 aUnitStr += String( SvtResId( STR_SVT_BYTES ) ); 702 nDec = 0; 703 } 704 else if ( nSize < nMega ) 705 { 706 fSize /= 1024; 707 aUnitStr += String( SvtResId( STR_SVT_KB ) ); 708 nDec = 1; 709 } 710 else if ( nSize < nGiga ) 711 { 712 fSize /= nMega; 713 aUnitStr += String( SvtResId( STR_SVT_MB ) ); 714 nDec = 2; 715 } 716 else 717 { 718 fSize /= nGiga; 719 aUnitStr += String( SvtResId( STR_SVT_GB ) ); 720 nDec = 3; 721 } 722 723 OUString aSizeStr( ::rtl::math::doubleToUString( fSize, 724 rtl_math_StringFormat_F, nDec, 725 SvtSysLocale().GetLocaleData().getNumDecimalSep().GetChar(0))); 726 aSizeStr += aUnitStr; 727 728 return aSizeStr; 729 } 730 731 // ----------------------------------------------------------------------- 732 // class ViewTabListBox_Impl --------------------------------------------- 733 // ----------------------------------------------------------------------- 734 735 ViewTabListBox_Impl::ViewTabListBox_Impl( Window* pParentWin, 736 SvtFileView_Impl* pParent, 737 sal_Int16 nFlags ) : 738 739 SvHeaderTabListBox( pParentWin, WB_TABSTOP ), 740 741 mpHeaderBar ( NULL ), 742 mpParent ( pParent ), 743 msAccessibleDescText( SvtResId( STR_SVT_ACC_DESC_FILEVIEW ) ), 744 msFolder ( SvtResId( STR_SVT_ACC_DESC_FOLDER ) ), 745 msFile ( SvtResId( STR_SVT_ACC_DESC_FILE ) ), 746 mnSearchIndex ( 0 ), 747 mbResizeDisabled ( sal_False ), 748 mbAutoResize ( sal_False ), 749 mbEnableDelete ( sal_True ), 750 mbEnableRename ( sal_True ) 751 752 { 753 Size aBoxSize = pParentWin->GetSizePixel(); 754 mpHeaderBar = new HeaderBar( pParentWin, WB_BUTTONSTYLE | WB_BOTTOMBORDER ); 755 mpHeaderBar->SetPosSizePixel( Point( 0, 0 ), mpHeaderBar->CalcWindowSizePixel() ); 756 757 HeaderBarItemBits nBits = ( HIB_LEFT | HIB_VCENTER | HIB_CLICKABLE ); 758 if ( ( nFlags & FILEVIEW_SHOW_ALL ) == FILEVIEW_SHOW_ALL ) 759 { 760 mpHeaderBar->InsertItem( COLUMN_TITLE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_TITLE ) ), 180, nBits | HIB_UPARROW ); 761 mpHeaderBar->InsertItem( COLUMN_TYPE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_TYPE ) ), 140, nBits ); 762 mpHeaderBar->InsertItem( COLUMN_SIZE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_SIZE ) ), 80, nBits ); 763 mpHeaderBar->InsertItem( COLUMN_DATE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_DATE ) ), 500, nBits ); 764 } 765 else 766 mpHeaderBar->InsertItem( COLUMN_TITLE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_TITLE ) ), 600, nBits ); 767 768 Size aHeadSize = mpHeaderBar->GetSizePixel(); 769 SetPosSizePixel( Point( 0, aHeadSize.Height() ), 770 Size( aBoxSize.Width(), aBoxSize.Height() - aHeadSize.Height() ) ); 771 InitHeaderBar( mpHeaderBar ); 772 SetHighlightRange(); 773 SetEntryHeight( ROW_HEIGHT ); 774 775 Show(); 776 mpHeaderBar->Show(); 777 778 maResetQuickSearch.SetTimeout( QUICK_SEARCH_TIMEOUT ); 779 maResetQuickSearch.SetTimeoutHdl( LINK( this, ViewTabListBox_Impl, ResetQuickSearch_Impl ) ); 780 781 Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); 782 Reference< XInteractionHandler > xInteractionHandler = Reference< XInteractionHandler > ( 783 xFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), UNO_QUERY ); 784 785 mxCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() ); 786 787 EnableContextMenuHandling(); 788 } 789 790 // ----------------------------------------------------------------------- 791 792 ViewTabListBox_Impl::~ViewTabListBox_Impl() 793 { 794 maResetQuickSearch.Stop(); 795 796 delete mpHeaderBar; 797 } 798 799 // ----------------------------------------------------------------------- 800 801 IMPL_LINK( ViewTabListBox_Impl, ResetQuickSearch_Impl, Timer*, EMPTYARG ) 802 { 803 ::osl::MutexGuard aGuard( maMutex ); 804 805 maQuickSearchText = OUString(); 806 mnSearchIndex = 0; 807 808 return 0; 809 } 810 811 // ----------------------------------------------------------------------- 812 813 void ViewTabListBox_Impl::Resize() 814 { 815 SvTabListBox::Resize(); 816 Size aBoxSize = Control::GetParent()->GetOutputSizePixel(); 817 818 if ( mbResizeDisabled || !aBoxSize.Width() ) 819 return; 820 821 Size aBarSize = mpHeaderBar->GetSizePixel(); 822 aBarSize.Width() = mbAutoResize ? aBoxSize.Width() : GetSizePixel().Width(); 823 mpHeaderBar->SetSizePixel( aBarSize ); 824 825 if ( mbAutoResize ) 826 { 827 mbResizeDisabled = sal_True; 828 Point aPos = GetPosPixel(); 829 SetPosSizePixel( Point( 0, aBarSize.Height() ), 830 Size( aBoxSize.Width(), aBoxSize.Height() - aBarSize.Height() ) ); 831 mbResizeDisabled = sal_False; 832 } 833 } 834 835 // ----------------------------------------------------------------------- 836 837 void ViewTabListBox_Impl::KeyInput( const KeyEvent& rKEvt ) 838 { 839 bool bHandled = false; 840 841 const KeyCode& rKeyCode = rKEvt.GetKeyCode(); 842 if ( 0 == rKeyCode.GetModifier() ) 843 { 844 if ( rKeyCode.GetCode() == KEY_RETURN ) 845 { 846 ResetQuickSearch_Impl( NULL ); 847 GetDoubleClickHdl().Call( this ); 848 bHandled = true; 849 } 850 else if ( ( rKeyCode.GetCode() == KEY_DELETE ) && 851 mbEnableDelete ) 852 { 853 ResetQuickSearch_Impl( NULL ); 854 DeleteEntries(); 855 bHandled = true; 856 } 857 else if ( ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_NUM ) || 858 ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_ALPHA ) ) 859 { 860 DoQuickSearch( rKEvt.GetCharCode() ); 861 bHandled = true; 862 } 863 } 864 865 if ( !bHandled ) 866 { 867 ResetQuickSearch_Impl( NULL ); 868 SvHeaderTabListBox::KeyInput( rKEvt ); 869 } 870 } 871 872 // ----------------------------------------------------------------------- 873 874 PopupMenu* ViewTabListBox_Impl::CreateContextMenu( void ) 875 { 876 bool bEnableDelete = mbEnableDelete; 877 bool bEnableRename = mbEnableRename; 878 879 if ( bEnableDelete || bEnableRename ) 880 { 881 sal_Int32 nSelectedEntries = GetSelectionCount(); 882 bEnableDelete &= nSelectedEntries > 0; 883 bEnableRename &= nSelectedEntries == 1; 884 } 885 886 if ( bEnableDelete || bEnableRename ) 887 { 888 SvLBoxEntry* pEntry = FirstSelected(); 889 while ( pEntry ) 890 { 891 ::ucbhelper::Content aCnt; 892 try 893 { 894 OUString aURL( static_cast< SvtContentEntry * >( 895 pEntry->GetUserData() )->maURL ); 896 aCnt = ::ucbhelper::Content( aURL, mxCmdEnv ); 897 } 898 catch( Exception const & ) 899 { 900 bEnableDelete = bEnableRename = false; 901 } 902 903 if ( bEnableDelete ) 904 { 905 try 906 { 907 Reference< XCommandInfo > aCommands = aCnt.getCommands(); 908 if ( aCommands.is() ) 909 bEnableDelete 910 = aCommands->hasCommandByName( 911 OUString::createFromAscii( "delete" ) ); 912 else 913 bEnableDelete = false; 914 } 915 catch( Exception const & ) 916 { 917 bEnableDelete = false; 918 } 919 } 920 921 if ( bEnableRename ) 922 { 923 try 924 { 925 Reference< XPropertySetInfo > aProps = aCnt.getProperties(); 926 if ( aProps.is() ) 927 { 928 Property aProp 929 = aProps->getPropertyByName( 930 OUString::createFromAscii( "Title" ) ); 931 bEnableRename 932 = !( aProp.Attributes & PropertyAttribute::READONLY ); 933 } 934 else 935 bEnableRename = false; 936 } 937 catch( Exception const & ) 938 { 939 bEnableRename = false; 940 } 941 } 942 943 pEntry = ( bEnableDelete || bEnableRename ) 944 ? NextSelected( pEntry ) 945 : 0; 946 } 947 } 948 949 if ( bEnableDelete || bEnableRename ) 950 { 951 PopupMenu * pRet 952 = new PopupMenu( SvtResId( RID_FILEVIEW_CONTEXTMENU ) ); 953 pRet->EnableItem( MID_FILEVIEW_DELETE, bEnableDelete ); 954 pRet->EnableItem( MID_FILEVIEW_RENAME, bEnableRename ); 955 pRet->RemoveDisabledEntries( sal_True, sal_True ); 956 return pRet; 957 } 958 959 return NULL; 960 } 961 962 // ----------------------------------------------------------------------- 963 964 void ViewTabListBox_Impl::ExcecuteContextMenuAction( sal_uInt16 nSelectedPopupEntry ) 965 { 966 switch ( nSelectedPopupEntry ) 967 { 968 case MID_FILEVIEW_DELETE : 969 DeleteEntries(); 970 break; 971 972 case MID_FILEVIEW_RENAME : 973 EditEntry( FirstSelected() ); 974 break; 975 } 976 } 977 978 // ----------------------------------------------------------------------- 979 980 void ViewTabListBox_Impl::ClearAll() 981 { 982 for ( sal_uInt16 i = 0; i < GetEntryCount(); ++i ) 983 delete (SvtContentEntry*)GetEntry(i)->GetUserData(); 984 Clear(); 985 } 986 987 // ----------------------------------------------------------------------- 988 void ViewTabListBox_Impl::DeleteEntries() 989 { 990 svtools::QueryDeleteResult_Impl eResult = svtools::QUERYDELETE_YES; 991 SvLBoxEntry* pEntry = FirstSelected(); 992 String aURL; 993 994 ByteString sDialogPosition; 995 while ( pEntry && ( eResult != svtools::QUERYDELETE_CANCEL ) ) 996 { 997 SvLBoxEntry *pCurEntry = pEntry; 998 pEntry = NextSelected( pEntry ); 999 1000 if ( pCurEntry->GetUserData() ) 1001 aURL = ( (SvtContentEntry*)pCurEntry->GetUserData() )->maURL; 1002 1003 if ( !aURL.Len() ) 1004 continue; 1005 1006 bool canDelete = true; 1007 try 1008 { 1009 ::ucbhelper::Content aCnt( aURL, mxCmdEnv ); 1010 Reference< XCommandInfo > aCommands = aCnt.getCommands(); 1011 if ( aCommands.is() ) 1012 canDelete 1013 = aCommands->hasCommandByName( 1014 OUString::createFromAscii( "delete" ) ); 1015 else 1016 canDelete = false; 1017 } 1018 catch( Exception const & ) 1019 { 1020 canDelete = false; 1021 } 1022 1023 if (!canDelete) 1024 continue; // process next entry 1025 1026 if ( eResult != svtools::QUERYDELETE_ALL ) 1027 { 1028 INetURLObject aObj( aURL ); 1029 svtools::QueryDeleteDlg_Impl aDlg( NULL, aObj.GetName( INetURLObject::DECODE_WITH_CHARSET ) ); 1030 if ( sDialogPosition.Len() ) 1031 aDlg.SetWindowState( sDialogPosition ); 1032 1033 if ( GetSelectionCount() > 1 ) 1034 aDlg.EnableAllButton(); 1035 1036 if ( aDlg.Execute() == RET_OK ) 1037 eResult = aDlg.GetResult(); 1038 else 1039 eResult = svtools::QUERYDELETE_CANCEL; 1040 1041 sDialogPosition = aDlg.GetWindowState( ); 1042 } 1043 1044 if ( ( eResult == svtools::QUERYDELETE_ALL ) || 1045 ( eResult == svtools::QUERYDELETE_YES ) ) 1046 { 1047 if ( Kill( aURL ) ) 1048 { 1049 delete (SvtContentEntry*)pCurEntry->GetUserData(); 1050 GetModel()->Remove( pCurEntry ); 1051 mpParent->EntryRemoved( aURL ); 1052 } 1053 } 1054 } 1055 } 1056 1057 // ----------------------------------------------------------------------- 1058 sal_Bool ViewTabListBox_Impl::EditedEntry( SvLBoxEntry* pEntry, 1059 const XubString& rNewText ) 1060 { 1061 sal_Bool bRet = sal_False; 1062 1063 OUString aURL; 1064 SvtContentEntry* pData = (SvtContentEntry*)pEntry->GetUserData(); 1065 1066 if ( pData ) 1067 aURL = OUString( pData->maURL ); 1068 1069 if ( ! aURL.getLength() ) 1070 return bRet; 1071 1072 try 1073 { 1074 OUString aPropName = OUString::createFromAscii( "Title" ); 1075 bool canRename = true; 1076 ::ucbhelper::Content aContent( aURL, mxCmdEnv ); 1077 1078 try 1079 { 1080 Reference< XPropertySetInfo > aProps = aContent.getProperties(); 1081 if ( aProps.is() ) 1082 { 1083 Property aProp = aProps->getPropertyByName( aPropName ); 1084 canRename = !( aProp.Attributes & PropertyAttribute::READONLY ); 1085 } 1086 else 1087 { 1088 canRename = false; 1089 } 1090 } 1091 catch ( Exception const & ) 1092 { 1093 canRename = false; 1094 } 1095 1096 if ( canRename ) 1097 { 1098 Any aValue; 1099 aValue <<= OUString( rNewText ); 1100 aContent.setPropertyValue( aPropName, aValue ); 1101 mpParent->EntryRenamed( aURL, rNewText ); 1102 1103 pData->maURL = aURL; 1104 pEntry->SetUserData( pData ); 1105 1106 bRet = sal_True; 1107 } 1108 } 1109 catch( Exception const & ) 1110 { 1111 } 1112 1113 return bRet; 1114 } 1115 1116 // ----------------------------------------------------------------------- 1117 void ViewTabListBox_Impl::DoQuickSearch( const xub_Unicode& rChar ) 1118 { 1119 ::osl::MutexGuard aGuard( maMutex ); 1120 1121 maResetQuickSearch.Stop(); 1122 1123 OUString aLastText = maQuickSearchText; 1124 sal_uInt32 aLastPos = mnSearchIndex; 1125 sal_Bool bFound = sal_False; 1126 1127 maQuickSearchText += OUString( String( rChar ) ).toAsciiLowerCase(); 1128 1129 bFound = mpParent->SearchNextEntry( mnSearchIndex, maQuickSearchText, sal_False ); 1130 1131 if ( !bFound && ( aLastText.getLength() == 1 ) && 1132 ( aLastText == OUString( String( rChar ) ) ) ) 1133 { 1134 mnSearchIndex = aLastPos + 1; 1135 maQuickSearchText = aLastText; 1136 bFound = mpParent->SearchNextEntry( mnSearchIndex, maQuickSearchText, sal_True ); 1137 } 1138 1139 if ( bFound ) 1140 { 1141 SvLBoxEntry* pEntry = GetEntry( mnSearchIndex ); 1142 if ( pEntry ) 1143 { 1144 SelectAll( sal_False ); 1145 Select( pEntry ); 1146 SetCurEntry( pEntry ); 1147 MakeVisible( pEntry ); 1148 } 1149 else 1150 bFound = sal_False; 1151 } 1152 1153 if ( !bFound ) 1154 Sound::Beep(); 1155 1156 maResetQuickSearch.Start(); 1157 } 1158 1159 // ----------------------------------------------------------------------- 1160 sal_Bool ViewTabListBox_Impl::DoubleClickHdl() 1161 { 1162 SvHeaderTabListBox::DoubleClickHdl(); 1163 return sal_False; 1164 // this means "do no additional handling". Especially this means that the SvImpLBox does not 1165 // recognize that the entry at the double click position change after the handler call (which is 1166 // the case if in the handler, our content was replaced) 1167 // If it _would_ recognize this change, it would take this as a reason to select the entry, again 1168 // - which is not what in the case of content replace 1169 // (I really doubt that this behaviour of the SvImpLBox does make any sense at all, but 1170 // who knows ...) 1171 // 07.12.2001 - 95727 - fs@openoffice.org 1172 } 1173 1174 ::rtl::OUString ViewTabListBox_Impl::GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const 1175 { 1176 ::rtl::OUString sRet = SvHeaderTabListBox::GetAccessibleObjectDescription( _eType, _nPos ); 1177 if ( ::svt::BBTYPE_TABLECELL == _eType ) 1178 { 1179 sal_Int32 nRow = -1; 1180 const sal_uInt16 nColumnCount = GetColumnCount(); 1181 if (nColumnCount > 0) 1182 nRow = _nPos / nColumnCount; 1183 SvLBoxEntry* pEntry = GetEntry( nRow ); 1184 if ( pEntry ) 1185 { 1186 SvtContentEntry* pData = (SvtContentEntry*)pEntry->GetUserData(); 1187 if ( pData ) 1188 { 1189 static const String sVar1( RTL_CONSTASCII_USTRINGPARAM( "%1" ) ); 1190 static const String sVar2( RTL_CONSTASCII_USTRINGPARAM( "%2" ) ); 1191 String aText( msAccessibleDescText ); 1192 aText.SearchAndReplace( sVar1, pData->mbIsFolder ? msFolder : msFile ); 1193 aText.SearchAndReplace( sVar2, pData->maURL ); 1194 sRet += ::rtl::OUString( aText ); 1195 } 1196 } 1197 } 1198 1199 return sRet; 1200 } 1201 1202 // ----------------------------------------------------------------------- 1203 sal_Bool ViewTabListBox_Impl::Kill( const OUString& rContent ) 1204 { 1205 sal_Bool bRet = sal_True; 1206 1207 try 1208 { 1209 ::ucbhelper::Content aCnt( rContent, mxCmdEnv ); 1210 aCnt.executeCommand( OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) ); 1211 } 1212 catch( ::com::sun::star::ucb::CommandAbortedException const & ) 1213 { 1214 DBG_WARNING( "CommandAbortedException" ); 1215 bRet = sal_False; 1216 } 1217 catch( Exception const & ) 1218 { 1219 DBG_WARNING( "Any other exception" ); 1220 bRet = sal_False; 1221 } 1222 1223 return bRet; 1224 } 1225 1226 1227 1228 1229 // ----------------------------------------------------------------------- 1230 // class SvtFileView ----------------------------------------------------- 1231 // ----------------------------------------------------------------------- 1232 1233 SvtFileView::SvtFileView( Window* pParent, const ResId& rResId, 1234 sal_Bool bOnlyFolder, sal_Bool bMultiSelection ) : 1235 1236 Control( pParent, rResId ) 1237 { 1238 sal_Int8 nFlags = FILEVIEW_SHOW_ALL; 1239 if ( bOnlyFolder ) 1240 nFlags |= FILEVIEW_ONLYFOLDER; 1241 if ( bMultiSelection ) 1242 nFlags |= FILEVIEW_MULTISELECTION; 1243 1244 Reference< XInteractionHandler > xInteractionHandler = Reference< XInteractionHandler > ( 1245 ::comphelper::getProcessServiceFactory()->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), UNO_QUERY ); 1246 Reference < XCommandEnvironment > xCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() ); 1247 1248 mpImp = new SvtFileView_Impl( this, xCmdEnv, nFlags, bOnlyFolder ); 1249 mpImp->mpView->ForbidEmptyText(); 1250 1251 long pTabs[] = { 5, 20, 180, 320, 400, 600 }; 1252 mpImp->mpView->SetTabs( &pTabs[0], MAP_PIXEL ); 1253 mpImp->mpView->SetTabJustify( 2, AdjustRight ); // column "Size" 1254 1255 if ( bMultiSelection ) 1256 mpImp->mpView->SetSelectionMode( MULTIPLE_SELECTION ); 1257 1258 HeaderBar* pHeaderBar = mpImp->mpView->GetHeaderBar(); 1259 pHeaderBar->SetSelectHdl( LINK( this, SvtFileView, HeaderSelect_Impl ) ); 1260 pHeaderBar->SetEndDragHdl( LINK( this, SvtFileView, HeaderEndDrag_Impl ) ); 1261 } 1262 1263 SvtFileView::SvtFileView( Window* pParent, const ResId& rResId, sal_Int8 nFlags ) : 1264 1265 Control( pParent, rResId ) 1266 { 1267 Reference< XInteractionHandler > xInteractionHandler = Reference< XInteractionHandler > ( 1268 ::comphelper::getProcessServiceFactory()->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), UNO_QUERY ); 1269 Reference < XCommandEnvironment > xCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() ); 1270 mpImp = new SvtFileView_Impl( this, xCmdEnv, nFlags, 1271 ( nFlags & FILEVIEW_ONLYFOLDER ) == FILEVIEW_ONLYFOLDER ); 1272 1273 if ( ( nFlags & FILEVIEW_SHOW_ALL ) == FILEVIEW_SHOW_ALL ) 1274 { 1275 long pTabs[] = { 5, 20, 180, 320, 400, 600 }; 1276 mpImp->mpView->SetTabs( &pTabs[0], MAP_PIXEL ); 1277 mpImp->mpView->SetTabJustify( 2, AdjustRight ); // column "Size" 1278 } 1279 else 1280 { 1281 // show only title 1282 long pTabs[] = { 2, 20, 600 }; 1283 mpImp->mpView->SetTabs( &pTabs[0], MAP_PIXEL ); 1284 } 1285 1286 if ( ( nFlags & FILEVIEW_MULTISELECTION ) == FILEVIEW_MULTISELECTION ) 1287 mpImp->mpView->SetSelectionMode( MULTIPLE_SELECTION ); 1288 1289 HeaderBar *pHeaderBar = mpImp->mpView->GetHeaderBar(); 1290 pHeaderBar->SetSelectHdl( LINK( this, SvtFileView, HeaderSelect_Impl ) ); 1291 pHeaderBar->SetEndDragHdl( LINK( this, SvtFileView, HeaderEndDrag_Impl ) ); 1292 } 1293 1294 // ----------------------------------------------------------------------- 1295 1296 SvtFileView::~SvtFileView() 1297 { 1298 // use temp pointer to prevent access of deleted member (GetFocus()) 1299 SvtFileView_Impl* pTemp = mpImp; 1300 mpImp = NULL; 1301 delete pTemp; 1302 } 1303 1304 // ----------------------------------------------------------------------- 1305 1306 void SvtFileView::OpenFolder( const Sequence< OUString >& aContents ) 1307 { 1308 mpImp->mpView->ClearAll(); 1309 const OUString* pFileProperties = aContents.getConstArray(); 1310 sal_uInt32 i, nCount = aContents.getLength(); 1311 for ( i = 0; i < nCount; ++i ) 1312 { 1313 String aRow( pFileProperties[i] ); 1314 // extract columns 1315 // the columns are: title, type, size, date, target url, is folder, image url 1316 String aTitle, aType, aSize, aDate, aURL, aImageURL; 1317 xub_StrLen nIdx = 0; 1318 aTitle = aRow.GetToken( 0, '\t', nIdx ); 1319 aType = aRow.GetToken( 0, '\t', nIdx ); 1320 aSize = aRow.GetToken( 0, '\t', nIdx ); 1321 aDate = aRow.GetToken( 0, '\t', nIdx ); 1322 aURL = aRow.GetToken( 0, '\t', nIdx ); 1323 sal_Unicode cFolder = aRow.GetToken( 0, '\t', nIdx ).GetChar(0); 1324 sal_Bool bIsFolder = ( '1' == cFolder ); 1325 if ( nIdx != STRING_NOTFOUND ) 1326 aImageURL = aRow.GetToken( 0, '\t', nIdx ); 1327 1328 if ( mpImp->mbOnlyFolder && !bIsFolder ) 1329 continue; 1330 1331 // build new row 1332 String aNewRow = aTitle; 1333 aNewRow += '\t'; 1334 aNewRow += aType; 1335 aNewRow += '\t'; 1336 aNewRow += aSize; 1337 aNewRow += '\t'; 1338 aNewRow += aDate; 1339 // detect image 1340 sal_Bool bDoInsert = sal_True; 1341 INetURLObject aObj( aImageURL.Len() > 0 ? aImageURL : aURL ); 1342 Image aImage = SvFileInformationManager::GetImage( aObj, sal_False, isHighContrast( this ) ); 1343 1344 if ( bDoInsert ) 1345 { 1346 // insert entry and set user data 1347 SvLBoxEntry* pEntry = mpImp->mpView->InsertEntry( aNewRow, aImage, aImage, NULL ); 1348 SvtContentEntry* pUserData = new SvtContentEntry( aURL, bIsFolder ); 1349 pEntry->SetUserData( pUserData ); 1350 } 1351 } 1352 1353 mpImp->InitSelection(); 1354 mpImp->ResetCursor(); 1355 } 1356 1357 // ----------------------------------------------------------------------- 1358 1359 String SvtFileView::GetURL( SvLBoxEntry* pEntry ) const 1360 { 1361 String aURL; 1362 if ( pEntry && pEntry->GetUserData() ) 1363 aURL = ( (SvtContentEntry*)pEntry->GetUserData() )->maURL; 1364 return aURL; 1365 } 1366 1367 // ----------------------------------------------------------------------- 1368 1369 String SvtFileView::GetCurrentURL() const 1370 { 1371 String aURL; 1372 SvLBoxEntry* pEntry = mpImp->mpView->FirstSelected(); 1373 if ( pEntry && pEntry->GetUserData() ) 1374 aURL = ( (SvtContentEntry*)pEntry->GetUserData() )->maURL; 1375 return aURL; 1376 } 1377 // ----------------------------------------------------------------------------- 1378 1379 sal_Bool SvtFileView::CreateNewFolder( const String& rNewFolder ) 1380 { 1381 sal_Bool bRet = sal_False; 1382 INetURLObject aObj( mpImp->maViewURL ); 1383 aObj.insertName( rNewFolder, false, INetURLObject::LAST_SEGMENT, true, INetURLObject::ENCODE_ALL ); 1384 String sURL = aObj.GetMainURL( INetURLObject::NO_DECODE ); 1385 if ( ::utl::UCBContentHelper::MakeFolder( sURL, sal_True ) ) 1386 { 1387 String sTitle = aObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); 1388 String sEntry = mpImp->FolderInserted( sURL, sTitle ); 1389 SvLBoxEntry* pEntry = mpImp->mpView->InsertEntry( sEntry, mpImp->maFolderImage, mpImp->maFolderImage ); 1390 SvtContentEntry* pUserData = new SvtContentEntry( sURL, sal_True ); 1391 pEntry->SetUserData( pUserData ); 1392 mpImp->mpView->MakeVisible( pEntry ); 1393 bRet = sal_True; 1394 } 1395 return bRet; 1396 } 1397 1398 // ----------------------------------------------------------------------- 1399 1400 FileViewResult SvtFileView::PreviousLevel( const FileViewAsyncAction* pAsyncDescriptor ) 1401 { 1402 FileViewResult eResult = eFailure; 1403 1404 String sParentURL; 1405 if ( GetParentURL( sParentURL ) ) 1406 eResult = Initialize( sParentURL, mpImp->maCurrentFilter, pAsyncDescriptor, mpBlackList ); 1407 1408 return eResult; 1409 } 1410 1411 // ----------------------------------------------------------------------- 1412 1413 sal_Bool SvtFileView::GetParentURL( String& rParentURL ) const 1414 { 1415 sal_Bool bRet = sal_False; 1416 try 1417 { 1418 ::ucbhelper::Content aCnt( mpImp->maViewURL, mpImp->mxCmdEnv ); 1419 Reference< XContent > xContent( aCnt.get() ); 1420 Reference< com::sun::star::container::XChild > xChild( xContent, UNO_QUERY ); 1421 if ( xChild.is() ) 1422 { 1423 Reference< XContent > xParent( xChild->getParent(), UNO_QUERY ); 1424 if ( xParent.is() ) 1425 { 1426 rParentURL = String( xParent->getIdentifier()->getContentIdentifier() ); 1427 bRet = ( rParentURL.Len() > 0 && rParentURL != mpImp->maViewURL ); 1428 } 1429 } 1430 } 1431 catch( Exception const & ) 1432 { 1433 // perhaps an unkown url protocol (e.g. "private:newdoc") 1434 } 1435 1436 return bRet; 1437 } 1438 1439 // ----------------------------------------------------------------------- 1440 1441 const rtl::OString& SvtFileView::GetHelpId( ) const 1442 { 1443 return mpImp->mpView->GetHelpId( ); 1444 } 1445 1446 // ----------------------------------------------------------------------- 1447 1448 void SvtFileView::SetHelpId( const rtl::OString& rHelpId ) 1449 { 1450 mpImp->mpView->SetHelpId( rHelpId ); 1451 } 1452 1453 // ----------------------------------------------------------------------- 1454 1455 void SvtFileView::SetSizePixel( const Size& rNewSize ) 1456 { 1457 Control::SetSizePixel( rNewSize ); 1458 mpImp->mpView->SetSizePixel( rNewSize ); 1459 } 1460 1461 // ----------------------------------------------------------------------- 1462 1463 void SvtFileView::SetPosSizePixel( const Point& rNewPos, const Size& rNewSize ) 1464 { 1465 SetPosPixel( rNewPos ); 1466 SetSizePixel( rNewSize ); 1467 } 1468 1469 // ----------------------------------------------------------------------------- 1470 sal_Bool SvtFileView::Initialize( const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent>& _xContent, const String& rFilter ) 1471 { 1472 WaitObject aWaitCursor( this ); 1473 1474 mpImp->Clear(); 1475 ::ucbhelper::Content aContent(_xContent, mpImp->mxCmdEnv ); 1476 FileViewResult eResult = mpImp->GetFolderContent_Impl( FolderDescriptor( aContent ), NULL ); 1477 OSL_ENSURE( eResult != eStillRunning, "SvtFileView::Initialize: this was expected to be synchronous!" ); 1478 if ( eResult != eSuccess ) 1479 return sal_False; 1480 1481 mpImp->FilterFolderContent_Impl( rFilter ); 1482 1483 mpImp->SortFolderContent_Impl(); // possibly not necessary!!!!!!!!!! 1484 mpImp->CreateDisplayText_Impl(); 1485 mpImp->OpenFolder_Impl(); 1486 1487 mpImp->maOpenDoneLink.Call( this ); 1488 return sal_True; 1489 } 1490 1491 // ----------------------------------------------------------------------- 1492 FileViewResult SvtFileView::Initialize( 1493 const String& rURL, 1494 const String& rFilter, 1495 const FileViewAsyncAction* pAsyncDescriptor, 1496 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList ) 1497 { 1498 WaitObject aWaitCursor( this ); 1499 mpBlackList = rBlackList; 1500 1501 String sPushURL( mpImp->maViewURL ); 1502 1503 mpImp->maViewURL = rURL; 1504 FileViewResult eResult = ExecuteFilter( rFilter, pAsyncDescriptor ); 1505 switch ( eResult ) 1506 { 1507 case eFailure: 1508 case eTimeout: 1509 mpImp->maViewURL = sPushURL; 1510 return eResult; 1511 1512 case eStillRunning: 1513 OSL_ENSURE( pAsyncDescriptor, "SvtFileView::Initialize: we told it to read synchronously!" ); 1514 case eSuccess: 1515 return eResult; 1516 } 1517 1518 OSL_ENSURE( sal_False, "SvtFileView::Initialize: unreachable!" ); 1519 return eFailure; 1520 } 1521 1522 // ----------------------------------------------------------------------- 1523 FileViewResult SvtFileView::Initialize( 1524 const String& rURL, 1525 const String& rFilter, 1526 const FileViewAsyncAction* pAsyncDescriptor ) 1527 { 1528 return Initialize( rURL, rFilter, pAsyncDescriptor, ::com::sun::star::uno::Sequence< ::rtl::OUString >()); 1529 } 1530 1531 // ----------------------------------------------------------------------- 1532 1533 // ----------------------------------------------------------------------- 1534 sal_Bool SvtFileView::Initialize( const Sequence< OUString >& aContents ) 1535 { 1536 WaitObject aWaitCursor( this ); 1537 1538 mpImp->maViewURL = String(); 1539 mpImp->maCurrentFilter = mpImp->maAllFilter; 1540 1541 mpImp->Clear(); 1542 mpImp->CreateVector_Impl( aContents ); 1543 mpImp->SortFolderContent_Impl(); 1544 1545 mpImp->OpenFolder_Impl(); 1546 1547 mpImp->maOpenDoneLink.Call( this ); 1548 1549 return sal_True; 1550 } 1551 1552 // ----------------------------------------------------------------------- 1553 1554 FileViewResult SvtFileView::ExecuteFilter( const String& rFilter, const FileViewAsyncAction* pAsyncDescriptor ) 1555 { 1556 mpImp->maCurrentFilter = rFilter; 1557 mpImp->maCurrentFilter.ToLowerAscii(); 1558 1559 mpImp->Clear(); 1560 FileViewResult eResult = mpImp->GetFolderContent_Impl( mpImp->maViewURL, pAsyncDescriptor, mpBlackList ); 1561 OSL_ENSURE( ( eResult != eStillRunning ) || pAsyncDescriptor, "SvtFileView::ExecuteFilter: we told it to read synchronously!" ); 1562 return eResult; 1563 } 1564 1565 // ----------------------------------------------------------------------- 1566 1567 void SvtFileView::CancelRunningAsyncAction() 1568 { 1569 mpImp->CancelRunningAsyncAction(); 1570 } 1571 1572 // ----------------------------------------------------------------------- 1573 1574 void SvtFileView::SetNoSelection() 1575 { 1576 mpImp->mpView->SelectAll( sal_False ); 1577 } 1578 1579 // ----------------------------------------------------------------------- 1580 1581 void SvtFileView::GetFocus() 1582 { 1583 Control::GetFocus(); 1584 if ( mpImp && mpImp->mpView ) 1585 mpImp->mpView->GrabFocus(); 1586 } 1587 1588 // ----------------------------------------------------------------------- 1589 1590 void SvtFileView::ResetCursor() 1591 { 1592 mpImp->ResetCursor(); 1593 } 1594 1595 // ----------------------------------------------------------------------- 1596 1597 void SvtFileView::SetSelectHdl( const Link& rHdl ) 1598 { 1599 mpImp->SetSelectHandler( rHdl ); 1600 } 1601 1602 // ----------------------------------------------------------------------- 1603 1604 void SvtFileView::SetDoubleClickHdl( const Link& rHdl ) 1605 { 1606 mpImp->mpView->SetDoubleClickHdl( rHdl ); 1607 } 1608 1609 // ----------------------------------------------------------------------- 1610 1611 sal_uLong SvtFileView::GetSelectionCount() const 1612 { 1613 return mpImp->mpView->GetSelectionCount(); 1614 } 1615 1616 // ----------------------------------------------------------------------- 1617 1618 SvLBoxEntry* SvtFileView::FirstSelected() const 1619 { 1620 return mpImp->mpView->FirstSelected(); 1621 } 1622 1623 // ----------------------------------------------------------------------- 1624 1625 SvLBoxEntry* SvtFileView::NextSelected( SvLBoxEntry* pEntry ) const 1626 { 1627 return mpImp->mpView->NextSelected( pEntry ); 1628 } 1629 1630 // ----------------------------------------------------------------------- 1631 1632 void SvtFileView::EnableAutoResize() 1633 { 1634 mpImp->mpView->EnableAutoResize(); 1635 } 1636 1637 // ----------------------------------------------------------------------- 1638 1639 void SvtFileView::SetFocus() 1640 { 1641 mpImp->mpView->GrabFocus(); 1642 } 1643 1644 // ----------------------------------------------------------------------- 1645 const String& SvtFileView::GetViewURL() const 1646 { 1647 return mpImp->maViewURL; 1648 } 1649 1650 // ----------------------------------------------------------------------- 1651 void SvtFileView::SetOpenDoneHdl( const Link& rHdl ) 1652 { 1653 mpImp->maOpenDoneLink = rHdl; 1654 } 1655 1656 // ----------------------------------------------------------------------- 1657 void SvtFileView::EnableContextMenu( sal_Bool bEnable ) 1658 { 1659 mpImp->EnableContextMenu( bEnable ); 1660 } 1661 1662 // ----------------------------------------------------------------------- 1663 void SvtFileView::EnableDelete( sal_Bool bEnable ) 1664 { 1665 mpImp->EnableDelete( bEnable ); 1666 } 1667 1668 void SvtFileView::EnableNameReplacing( sal_Bool bEnable ) 1669 { 1670 mpImp->EnableNameReplacing( bEnable ); 1671 } 1672 1673 // ----------------------------------------------------------------------- 1674 void SvtFileView::EndInplaceEditing( bool _bCancel ) 1675 { 1676 return mpImp->EndEditing( _bCancel ); 1677 } 1678 1679 // ----------------------------------------------------------------------- 1680 IMPL_LINK( SvtFileView, HeaderSelect_Impl, HeaderBar*, pBar ) 1681 { 1682 DBG_ASSERT( pBar, "no headerbar" ); 1683 sal_uInt16 nItemID = pBar->GetCurItemId(); 1684 1685 HeaderBarItemBits nBits; 1686 1687 // clear the arrow of the recently used column 1688 if ( nItemID != mpImp->mnSortColumn ) 1689 { 1690 if ( !nItemID ) 1691 { 1692 // first call -> remove arrow from title column, 1693 // because another column is the sort column 1694 nItemID = mpImp->mnSortColumn; 1695 mpImp->mnSortColumn = COLUMN_TITLE; 1696 } 1697 nBits = pBar->GetItemBits( mpImp->mnSortColumn ); 1698 nBits &= ~( HIB_UPARROW | HIB_DOWNARROW ); 1699 pBar->SetItemBits( mpImp->mnSortColumn, nBits ); 1700 } 1701 1702 nBits = pBar->GetItemBits( nItemID ); 1703 1704 sal_Bool bUp = ( ( nBits & HIB_UPARROW ) == HIB_UPARROW ); 1705 1706 if ( bUp ) 1707 { 1708 nBits &= ~HIB_UPARROW; 1709 nBits |= HIB_DOWNARROW; 1710 } 1711 else 1712 { 1713 nBits &= ~HIB_DOWNARROW; 1714 nBits |= HIB_UPARROW; 1715 } 1716 1717 pBar->SetItemBits( nItemID, nBits ); 1718 mpImp->Resort_Impl( nItemID, !bUp ); 1719 return 1; 1720 } 1721 1722 // ----------------------------------------------------------------------- 1723 IMPL_LINK( SvtFileView, HeaderEndDrag_Impl, HeaderBar*, pBar ) 1724 { 1725 if ( !pBar->IsItemMode() ) 1726 { 1727 Size aSize; 1728 sal_uInt16 nTabs = pBar->GetItemCount(); 1729 long nTmpSize = 0; 1730 1731 for ( sal_uInt16 i = 1; i <= nTabs; ++i ) 1732 { 1733 long nWidth = pBar->GetItemSize(i); 1734 aSize.Width() = nWidth + nTmpSize; 1735 nTmpSize += nWidth; 1736 mpImp->mpView->SetTab( i, aSize.Width(), MAP_PIXEL ); 1737 } 1738 } 1739 1740 return 0; 1741 } 1742 1743 // ----------------------------------------------------------------------- 1744 String SvtFileView::GetConfigString() const 1745 { 1746 String sRet; 1747 HeaderBar* pBar = mpImp->mpView->GetHeaderBar(); 1748 DBG_ASSERT( pBar, "invalid headerbar" ); 1749 1750 // sort order 1751 sRet += String::CreateFromInt32( mpImp->mnSortColumn ); 1752 sRet += ';'; 1753 HeaderBarItemBits nBits = pBar->GetItemBits( mpImp->mnSortColumn ); 1754 sal_Bool bUp = ( ( nBits & HIB_UPARROW ) == HIB_UPARROW ); 1755 sRet += bUp ? '1' : '0'; 1756 sRet += ';'; 1757 1758 sal_uInt16 nCount = pBar->GetItemCount(); 1759 for ( sal_uInt16 i = 0; i < nCount; ++i ) 1760 { 1761 sal_uInt16 nId = pBar->GetItemId(i); 1762 sRet += String::CreateFromInt32( nId ); 1763 sRet += ';'; 1764 sRet += String::CreateFromInt32( pBar->GetItemSize( nId ) ); 1765 sRet += ';'; 1766 } 1767 1768 sRet.EraseTrailingChars( ';' ); 1769 return sRet; 1770 } 1771 1772 // ----------------------------------------------------------------------- 1773 void SvtFileView::SetConfigString( const String& rCfgStr ) 1774 { 1775 HeaderBar* pBar = mpImp->mpView->GetHeaderBar(); 1776 DBG_ASSERT( pBar, "invalid headerbar" ); 1777 1778 sal_uInt16 nIdx = 0; 1779 mpImp->mnSortColumn = (sal_uInt16)rCfgStr.GetToken( 0, ';', nIdx ).ToInt32(); 1780 sal_Bool bUp = (sal_Bool)(sal_uInt16)rCfgStr.GetToken( 0, ';', nIdx ).ToInt32(); 1781 HeaderBarItemBits nBits = pBar->GetItemBits( mpImp->mnSortColumn ); 1782 1783 if ( bUp ) 1784 { 1785 nBits &= ~HIB_UPARROW; 1786 nBits |= HIB_DOWNARROW; 1787 } 1788 else 1789 { 1790 nBits &= ~HIB_DOWNARROW; 1791 nBits |= HIB_UPARROW; 1792 } 1793 pBar->SetItemBits( mpImp->mnSortColumn, nBits ); 1794 1795 while ( nIdx != STRING_NOTFOUND ) 1796 { 1797 sal_uInt16 nItemId = (sal_uInt16)rCfgStr.GetToken( 0, ';', nIdx ).ToInt32(); 1798 pBar->SetItemSize( nItemId, rCfgStr.GetToken( 0, ';', nIdx ).ToInt32() ); 1799 } 1800 1801 HeaderSelect_Impl( pBar ); 1802 HeaderEndDrag_Impl( pBar ); 1803 } 1804 1805 // ----------------------------------------------------------------------- 1806 void SvtFileView::SetUrlFilter( const IUrlFilter* _pFilter ) 1807 { 1808 mpImp->mpUrlFilter = _pFilter; 1809 } 1810 1811 // ----------------------------------------------------------------------- 1812 const IUrlFilter* SvtFileView::GetUrlFilter( ) const 1813 { 1814 return mpImp->mpUrlFilter; 1815 } 1816 1817 // ----------------------------------------------------------------------- 1818 void SvtFileView::StateChanged( StateChangedType nStateChange ) 1819 { 1820 if ( nStateChange == STATE_CHANGE_ENABLE ) 1821 Invalidate(); 1822 Control::StateChanged( nStateChange ); 1823 } 1824 1825 // ----------------------------------------------------------------------- 1826 // class NameTranslator_Impl 1827 // ----------------------------------------------------------------------- 1828 1829 NameTranslator_Impl::NameTranslator_Impl( void ) : 1830 mpActFolder( NULL ) 1831 { 1832 } 1833 1834 NameTranslator_Impl::NameTranslator_Impl( const INetURLObject& rActualFolder ) 1835 { 1836 mpActFolder = new NameTranslationList( rActualFolder ); 1837 } 1838 1839 NameTranslator_Impl::~NameTranslator_Impl() 1840 { 1841 if( mpActFolder ) 1842 delete mpActFolder; 1843 } 1844 1845 void NameTranslator_Impl::UpdateTranslationTable() 1846 { 1847 if( mpActFolder ) 1848 mpActFolder->Update(); 1849 } 1850 1851 void NameTranslator_Impl::SetActualFolder( const INetURLObject& rActualFolder ) 1852 { 1853 HashedEntry aActFolder( rActualFolder ); 1854 1855 if( mpActFolder ) 1856 { 1857 if( *mpActFolder != aActFolder ) 1858 { 1859 delete mpActFolder; 1860 mpActFolder = new NameTranslationList( rActualFolder ); 1861 } 1862 } 1863 else 1864 mpActFolder = new NameTranslationList( rActualFolder ); 1865 } 1866 1867 sal_Bool NameTranslator_Impl::GetTranslation( const OUString& rOrg, OUString& rTrans ) const 1868 { 1869 sal_Bool bRet = sal_False; 1870 1871 if( mpActFolder ) 1872 { 1873 const OUString* pTrans = mpActFolder->Translate( rOrg ); 1874 if( pTrans ) 1875 { 1876 rTrans = *pTrans; 1877 bRet = sal_True; 1878 } 1879 } 1880 1881 return bRet; 1882 } 1883 1884 const String* NameTranslator_Impl::GetTransTableFileName() const 1885 { 1886 return mpActFolder? &mpActFolder->GetTransTableFileName() : NULL; 1887 } 1888 1889 // ----------------------------------------------------------------------- 1890 // class SvtFileView_Impl 1891 // ----------------------------------------------------------------------- 1892 1893 SvtFileView_Impl::SvtFileView_Impl( SvtFileView* pAntiImpl, Reference < XCommandEnvironment > xEnv, sal_Int16 nFlags, sal_Bool bOnlyFolder ) 1894 1895 :mpAntiImpl ( pAntiImpl ) 1896 ,m_eAsyncActionResult ( ::svt::ERROR ) 1897 ,m_bRunningAsyncAction ( false ) 1898 ,m_bAsyncActionCancelled ( false ) 1899 ,mpNameTrans ( NULL ) 1900 ,mpUrlFilter ( NULL ) 1901 ,mnSortColumn ( COLUMN_TITLE ) 1902 ,mbAscending ( sal_True ) 1903 ,mbOnlyFolder ( bOnlyFolder ) 1904 ,mbReplaceNames ( sal_False ) 1905 ,mnSuspendSelectCallback ( 0 ) 1906 ,mbIsFirstResort ( sal_True ) 1907 ,aIntlWrapper ( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() ) 1908 ,maFolderImage ( SvtResId( IMG_SVT_FOLDER ) ) 1909 ,mxCmdEnv ( xEnv ) 1910 1911 { 1912 maAllFilter = String::CreateFromAscii( "*.*" ); 1913 mpView = new ViewTabListBox_Impl( mpAntiImpl, this, nFlags ); 1914 mpView->EnableCellFocus(); 1915 } 1916 1917 // ----------------------------------------------------------------------- 1918 SvtFileView_Impl::~SvtFileView_Impl() 1919 { 1920 Clear(); 1921 1922 // use temp pointer to prevent access of deleted member (GetFocus()) 1923 ViewTabListBox_Impl* pTemp = mpView; 1924 mpView = NULL; 1925 delete pTemp; 1926 } 1927 1928 // ----------------------------------------------------------------------- 1929 void SvtFileView_Impl::Clear() 1930 { 1931 ::osl::MutexGuard aGuard( maMutex ); 1932 1933 std::vector< SortingData_Impl* >::iterator aIt; 1934 1935 for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ ) 1936 delete (*aIt); 1937 1938 maContent.clear(); 1939 1940 if( mpNameTrans ) 1941 DELETEZ( mpNameTrans ); 1942 } 1943 1944 // ----------------------------------------------------------------------- 1945 FileViewResult SvtFileView_Impl::GetFolderContent_Impl( 1946 const String& rFolder, 1947 const FileViewAsyncAction* pAsyncDescriptor, 1948 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList ) 1949 { 1950 ::osl::ClearableMutexGuard aGuard( maMutex ); 1951 INetURLObject aFolderObj( rFolder ); 1952 DBG_ASSERT( aFolderObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); 1953 1954 // prepare name translation 1955 SetActualFolder( aFolderObj ); 1956 1957 FolderDescriptor aFolder( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ) ); 1958 1959 aGuard.clear(); 1960 return GetFolderContent_Impl( aFolder, pAsyncDescriptor, rBlackList ); 1961 } 1962 1963 // ----------------------------------------------------------------------- 1964 FileViewResult SvtFileView_Impl::GetFolderContent_Impl( 1965 const FolderDescriptor& _rFolder, 1966 const FileViewAsyncAction* pAsyncDescriptor, 1967 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList ) 1968 { 1969 DBG_TESTSOLARMUTEX(); 1970 ::osl::ClearableMutexGuard aGuard( maMutex ); 1971 1972 OSL_ENSURE( !m_pContentEnumerator.is(), "SvtFileView_Impl::GetFolderContent_Impl: still running another enumeration!" ); 1973 m_pContentEnumerator = new ::svt::FileViewContentEnumerator( 1974 mpView->GetCommandEnvironment(), maContent, maMutex, mbReplaceNames ? mpNameTrans : NULL ); 1975 // TODO: should we cache and re-use this thread? 1976 1977 if ( !pAsyncDescriptor ) 1978 { 1979 ::svt::EnumerationResult eResult = m_pContentEnumerator->enumerateFolderContentSync( _rFolder, mpUrlFilter, rBlackList ); 1980 if ( ::svt::SUCCESS == eResult ) 1981 { 1982 implEnumerationSuccess(); 1983 m_pContentEnumerator = NULL; 1984 return eSuccess; 1985 } 1986 m_pContentEnumerator = NULL; 1987 return eFailure; 1988 } 1989 1990 m_bRunningAsyncAction = true; 1991 m_bAsyncActionCancelled = false; 1992 m_eAsyncActionResult = ::svt::ERROR; 1993 m_aAsyncActionFinished.reset(); 1994 1995 // don't (yet) set m_aCurrentAsyncActionHandler to pTimeout->aFinishHandler. 1996 // By definition, this handler *only* get's called when the result cannot be obtained 1997 // during the minimum wait time, so it is only set below, when needed. 1998 m_aCurrentAsyncActionHandler = Link(); 1999 2000 // minimum time to wait 2001 ::std::auto_ptr< TimeValue > pTimeout( new TimeValue ); 2002 sal_Int32 nMinTimeout = pAsyncDescriptor->nMinTimeout; 2003 OSL_ENSURE( nMinTimeout > 0, "SvtFileView_Impl::GetFolderContent_Impl: invalid minimum timeout!" ); 2004 if ( nMinTimeout <= 0 ) 2005 nMinTimeout = sal_Int32( 1000L ); 2006 pTimeout->Seconds = nMinTimeout / 1000L; 2007 pTimeout->Nanosec = ( nMinTimeout % 1000L ) * 1000000L; 2008 2009 m_pContentEnumerator->enumerateFolderContent( _rFolder, mpUrlFilter, this ); 2010 2011 // wait until the enumeration is finished 2012 // for this, release our own mutex (which is used by the enumerator thread) 2013 aGuard.clear(); 2014 2015 ::osl::Condition::Result eResult = ::osl::Condition::result_ok; 2016 { 2017 // also release the SolarMutex. Not all code which is needed during the enumeration 2018 // is Solar-Thread-Safe, in particular there is some code which needs to access 2019 // string resources (and our resource system relies on the SolarMutex :() 2020 ReleaseSolarMutex aSolarRelease; 2021 2022 // now wait. Note that if we didn't get an pAsyncDescriptor, then this is an infinite wait. 2023 eResult = m_aAsyncActionFinished.wait( pTimeout.get() ); 2024 } 2025 2026 ::osl::MutexGuard aGuard2( maMutex ); 2027 if ( ::osl::Condition::result_timeout == eResult ) 2028 { 2029 // maximum time to wait 2030 OSL_ENSURE( !m_pCancelAsyncTimer.get(), "SvtFileView_Impl::GetFolderContent_Impl: there's still a previous timer!" ); 2031 m_pCancelAsyncTimer = new CallbackTimer( this ); 2032 sal_Int32 nMaxTimeout = pAsyncDescriptor->nMaxTimeout; 2033 OSL_ENSURE( nMaxTimeout > nMinTimeout, 2034 "SvtFileView_Impl::GetFolderContent_Impl: invalid maximum timeout!" ); 2035 if ( nMaxTimeout <= nMinTimeout ) 2036 nMaxTimeout = nMinTimeout + 5000; 2037 m_pCancelAsyncTimer->setRemainingTime( TTimeValue( nMaxTimeout - nMinTimeout ) ); 2038 // we already waited for nMinTimeout milliseconds, so take this into account 2039 m_pCancelAsyncTimer->start(); 2040 2041 m_aCurrentAsyncActionHandler = pAsyncDescriptor->aFinishHandler; 2042 DBG_ASSERT( m_aCurrentAsyncActionHandler.IsSet(), "SvtFileView_Impl::GetFolderContent_Impl: nobody interested when it's finished?" ); 2043 mpView->ClearAll(); 2044 return eStillRunning; 2045 } 2046 2047 m_bRunningAsyncAction = false; 2048 switch ( m_eAsyncActionResult ) 2049 { 2050 case ::svt::SUCCESS: 2051 return eSuccess; 2052 2053 case ::svt::ERROR: 2054 return eFailure; 2055 2056 case ::svt::RUNNING: 2057 return eStillRunning; 2058 } 2059 2060 DBG_ERRORFILE( "SvtFileView_Impl::GetFolderContent_Impl: unreachable!" ); 2061 return eFailure; 2062 } 2063 2064 // ----------------------------------------------------------------------- 2065 void SvtFileView_Impl::FilterFolderContent_Impl( const OUString &rFilter ) 2066 { 2067 sal_Bool bHideTransFile = mbReplaceNames && mpNameTrans; 2068 2069 String sHideEntry; 2070 if( bHideTransFile ) 2071 { 2072 const String* pTransTableFileName = mpNameTrans->GetTransTableFileName(); 2073 if( pTransTableFileName ) 2074 { 2075 sHideEntry = *pTransTableFileName; 2076 sHideEntry.ToUpperAscii(); 2077 } 2078 else 2079 bHideTransFile = sal_False; 2080 } 2081 2082 if ( !bHideTransFile && 2083 ( !rFilter.getLength() || ( rFilter.compareToAscii( ALL_FILES_FILTER ) == COMPARE_EQUAL ) ) ) 2084 // when replacing names, there is always something to filter (no view of ".nametranslation.table") 2085 return; 2086 2087 ::osl::MutexGuard aGuard( maMutex ); 2088 2089 if ( maContent.empty() ) 2090 return; 2091 2092 // count (estimate) the number of filter tokens 2093 sal_Int32 nTokens=0; 2094 const sal_Unicode* pStart = rFilter.getStr(); 2095 const sal_Unicode* pEnd = pStart + rFilter.getLength(); 2096 while ( pStart != pEnd ) 2097 if ( *pStart++ == ';' ) 2098 ++nTokens; 2099 2100 // collect the filter tokens 2101 ::std::vector< WildCard > aFilters; 2102 FilterMatch::createWildCardFilterList(rFilter,aFilters); 2103 2104 2105 // do the filtering 2106 ::std::vector< SortingData_Impl* >::iterator aContentLoop = maContent.begin(); 2107 String sCompareString; 2108 do 2109 { 2110 if ( (*aContentLoop)->mbIsFolder ) 2111 ++aContentLoop; 2112 else 2113 { 2114 // normalize the content title (we always match case-insensitive) 2115 // 91872 - 11.09.2001 - frank.schoenheit@sun.com 2116 sCompareString = (*aContentLoop)->GetFileName(); // filter works on file name, not on title! 2117 sal_Bool bDelete; 2118 2119 if( bHideTransFile && sCompareString == sHideEntry ) 2120 bDelete = sal_True; 2121 else 2122 { 2123 // search for the first filter which matches 2124 ::std::vector< WildCard >::const_iterator pMatchingFilter = 2125 ::std::find_if( 2126 aFilters.begin(), 2127 aFilters.end(), 2128 FilterMatch( sCompareString ) 2129 ); 2130 2131 bDelete = aFilters.end() == pMatchingFilter; 2132 } 2133 2134 if( bDelete ) 2135 { 2136 // none of the filters did match 2137 delete (*aContentLoop); 2138 2139 if ( maContent.begin() == aContentLoop ) 2140 { 2141 maContent.erase( aContentLoop ); 2142 aContentLoop = maContent.begin(); 2143 } 2144 else 2145 { 2146 std::vector< SortingData_Impl* >::iterator aDelete = aContentLoop; 2147 --aContentLoop; // move the iterator to a position which is not invalidated by the erase 2148 maContent.erase( aDelete ); 2149 ++aContentLoop; // this is now the next one .... 2150 } 2151 } 2152 else 2153 ++aContentLoop; 2154 } 2155 } 2156 while ( aContentLoop != maContent.end() ); 2157 } 2158 2159 // ----------------------------------------------------------------------- 2160 IMPL_LINK( SvtFileView_Impl, SelectionMultiplexer, void*, _pSource ) 2161 { 2162 return mnSuspendSelectCallback ? 0L : m_aSelectHandler.Call( _pSource ); 2163 } 2164 2165 // ----------------------------------------------------------------------- 2166 void SvtFileView_Impl::SetSelectHandler( const Link& _rHdl ) 2167 { 2168 m_aSelectHandler = _rHdl; 2169 2170 Link aMasterHandler; 2171 if ( m_aSelectHandler.IsSet() ) 2172 aMasterHandler = LINK( this, SvtFileView_Impl, SelectionMultiplexer ); 2173 2174 mpView->SetSelectHdl( aMasterHandler ); 2175 } 2176 2177 // ----------------------------------------------------------------------- 2178 void SvtFileView_Impl::InitSelection() 2179 { 2180 mpView->SelectAll( sal_False ); 2181 SvLBoxEntry* pFirst = mpView->First(); 2182 if ( pFirst ) 2183 mpView->SetCursor( pFirst, sal_True ); 2184 } 2185 2186 // ----------------------------------------------------------------------- 2187 void SvtFileView_Impl::OpenFolder_Impl() 2188 { 2189 ::osl::MutexGuard aGuard( maMutex ); 2190 2191 mpView->SetUpdateMode( sal_False ); 2192 mpView->ClearAll(); 2193 2194 std::vector< SortingData_Impl* >::iterator aIt; 2195 2196 for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ ) 2197 { 2198 if ( mbOnlyFolder && ! (*aIt)->mbIsFolder ) 2199 continue; 2200 2201 // insert entry and set user data 2202 SvLBoxEntry* pEntry = mpView->InsertEntry( (*aIt)->maDisplayText, 2203 (*aIt)->maImage, 2204 (*aIt)->maImage ); 2205 2206 SvtContentEntry* pUserData = new SvtContentEntry( (*aIt)->maTargetURL, 2207 (*aIt)->mbIsFolder ); 2208 pEntry->SetUserData( pUserData ); 2209 } 2210 2211 InitSelection(); 2212 2213 ++mnSuspendSelectCallback; 2214 mpView->SetUpdateMode( sal_True ); 2215 --mnSuspendSelectCallback; 2216 2217 ResetCursor(); 2218 } 2219 2220 // ----------------------------------------------------------------------- 2221 void SvtFileView_Impl::ResetCursor() 2222 { 2223 // deselect 2224 SvLBoxEntry* pEntry = mpView->FirstSelected(); 2225 if ( pEntry ) 2226 mpView->Select( pEntry, sal_False ); 2227 // set cursor to the first entry 2228 mpView->SetCursor( mpView->First(), sal_True ); 2229 mpView->Update(); 2230 } 2231 2232 // ----------------------------------------------------------------------- 2233 void SvtFileView_Impl::CancelRunningAsyncAction() 2234 { 2235 DBG_TESTSOLARMUTEX(); 2236 ::osl::MutexGuard aGuard( maMutex ); 2237 if ( !m_pContentEnumerator.is() ) 2238 return; 2239 2240 m_bAsyncActionCancelled = true; 2241 m_pContentEnumerator->cancel(); 2242 m_bRunningAsyncAction = false; 2243 2244 m_pContentEnumerator = NULL; 2245 if ( m_pCancelAsyncTimer.is() && m_pCancelAsyncTimer->isTicking() ) 2246 m_pCancelAsyncTimer->stop(); 2247 m_pCancelAsyncTimer = NULL; 2248 } 2249 2250 //----------------------------------------------------------------------- 2251 void SvtFileView_Impl::onTimeout( CallbackTimer* ) 2252 { 2253 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 2254 ::osl::MutexGuard aGuard( maMutex ); 2255 if ( !m_bRunningAsyncAction ) 2256 // there might have been a race condition while we waited for the mutex 2257 return; 2258 2259 CancelRunningAsyncAction(); 2260 2261 if ( m_aCurrentAsyncActionHandler.IsSet() ) 2262 { 2263 Application::PostUserEvent( m_aCurrentAsyncActionHandler, reinterpret_cast< void* >( eTimeout ) ); 2264 m_aCurrentAsyncActionHandler = Link(); 2265 } 2266 } 2267 2268 //----------------------------------------------------------------------- 2269 void SvtFileView_Impl::enumerationDone( ::svt::EnumerationResult _eResult ) 2270 { 2271 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 2272 ::osl::MutexGuard aGuard( maMutex ); 2273 2274 m_pContentEnumerator = NULL; 2275 if ( m_pCancelAsyncTimer.is() && m_pCancelAsyncTimer->isTicking() ) 2276 m_pCancelAsyncTimer->stop(); 2277 m_pCancelAsyncTimer = NULL; 2278 2279 if ( m_bAsyncActionCancelled ) 2280 // this is to prevent race conditions 2281 return; 2282 2283 m_eAsyncActionResult = _eResult; 2284 m_bRunningAsyncAction = false; 2285 2286 m_aAsyncActionFinished.set(); 2287 2288 if ( svt::SUCCESS == _eResult ) 2289 implEnumerationSuccess(); 2290 2291 if ( m_aCurrentAsyncActionHandler.IsSet() ) 2292 { 2293 Application::PostUserEvent( m_aCurrentAsyncActionHandler, reinterpret_cast< void* >( m_eAsyncActionResult ) ); 2294 m_aCurrentAsyncActionHandler = Link(); 2295 } 2296 } 2297 2298 //----------------------------------------------------------------------- 2299 void SvtFileView_Impl::implEnumerationSuccess() 2300 { 2301 FilterFolderContent_Impl( maCurrentFilter ); 2302 SortFolderContent_Impl(); 2303 CreateDisplayText_Impl(); 2304 OpenFolder_Impl(); 2305 maOpenDoneLink.Call( mpAntiImpl ); 2306 } 2307 2308 // ----------------------------------------------------------------------- 2309 void SvtFileView_Impl::ReplaceTabWithString( OUString& aValue ) 2310 { 2311 OUString aTab = OUString::createFromAscii( "\t" ); 2312 OUString aTabString = OUString::createFromAscii( "%09" ); 2313 sal_Int32 iPos; 2314 2315 while ( ( iPos = aValue.indexOf( aTab ) ) >= 0 ) 2316 aValue = aValue.replaceAt( iPos, 1, aTabString ); 2317 } 2318 2319 // ----------------------------------------------------------------------- 2320 void SvtFileView_Impl::CreateDisplayText_Impl() 2321 { 2322 ::osl::MutexGuard aGuard( maMutex ); 2323 2324 OUString aValue; 2325 OUString aTab = OUString::createFromAscii( "\t" ); 2326 OUString aDateSep = OUString::createFromAscii( ", " ); 2327 2328 std::vector< SortingData_Impl* >::iterator aIt; 2329 2330 for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ ) 2331 { 2332 // title, type, size, date 2333 aValue = (*aIt)->GetTitle(); 2334 // #83004# -------------------- 2335 ReplaceTabWithString( aValue ); 2336 aValue += aTab; 2337 aValue += (*aIt)->maType; 2338 aValue += aTab; 2339 // folders don't have a size 2340 if ( ! (*aIt)->mbIsFolder ) 2341 aValue += CreateExactSizeText_Impl( (*aIt)->maSize ); 2342 aValue += aTab; 2343 // set the date, but volumes have no date 2344 if ( ! (*aIt)->mbIsFolder || ! (*aIt)->mbIsVolume ) 2345 { 2346 SvtSysLocale aSysLocale; 2347 const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData(); 2348 aValue += rLocaleData.getDate( (*aIt)->maModDate ); 2349 aValue += aDateSep; 2350 aValue += rLocaleData.getTime( (*aIt)->maModDate ); 2351 } 2352 (*aIt)->maDisplayText = aValue; 2353 2354 // detect image 2355 if ( (*aIt)->mbIsFolder ) 2356 { 2357 ::svtools::VolumeInfo aVolInfo( (*aIt)->mbIsVolume, (*aIt)->mbIsRemote, 2358 (*aIt)->mbIsRemoveable, (*aIt)->mbIsFloppy, 2359 (*aIt)->mbIsCompactDisc ); 2360 (*aIt)->maImage = SvFileInformationManager::GetFolderImage( aVolInfo, sal_False, isHighContrast( mpView ) ); 2361 } 2362 else 2363 (*aIt)->maImage = SvFileInformationManager::GetFileImage( INetURLObject( (*aIt)->maTargetURL ), sal_False, isHighContrast( mpView )); 2364 } 2365 } 2366 2367 // ----------------------------------------------------------------------- 2368 // this function converts the sequence of strings into a vector of SortingData 2369 // the string should have the form : 2370 // title \t type \t size \t date \t target url \t is folder \t image url 2371 2372 void SvtFileView_Impl::CreateVector_Impl( const Sequence < OUString > &rList ) 2373 { 2374 ::osl::MutexGuard aGuard( maMutex ); 2375 2376 OUString aTab = OUString::createFromAscii( "\t" ); 2377 2378 sal_uInt32 nCount = (sal_uInt32) rList.getLength(); 2379 2380 for( sal_uInt32 i = 0; i < nCount; i++ ) 2381 { 2382 SortingData_Impl* pEntry = new SortingData_Impl; 2383 OUString aValue = rList[i]; 2384 OUString aDisplayText; 2385 sal_Int32 nIndex = 0; 2386 2387 // get the title 2388 pEntry->SetNewTitle( aValue.getToken( 0, '\t', nIndex ) ); 2389 aDisplayText = pEntry->GetTitle(); 2390 // #83004# -------------------- 2391 ReplaceTabWithString( aDisplayText ); 2392 aDisplayText += aTab; 2393 2394 // get the type 2395 if ( nIndex >= 0 ) 2396 { 2397 pEntry->maType = aValue.getToken( 0, '\t', nIndex ); 2398 aDisplayText += pEntry->maType; 2399 } 2400 aDisplayText += aTab; 2401 2402 // get the size 2403 if ( nIndex >= 0 ) 2404 { 2405 OUString aSize = aValue.getToken( 0, '\t', nIndex ); 2406 aDisplayText += aSize; 2407 2408 if ( aSize.getLength() ) 2409 pEntry->maSize = aSize.toInt64(); 2410 } 2411 aDisplayText += aTab; 2412 2413 // get the date 2414 if ( nIndex >= 0 ) 2415 { 2416 OUString aDate = aValue.getToken( 0, '\t', nIndex ); 2417 aDisplayText += aDate; 2418 2419 if ( aDate.getLength() ) 2420 { 2421 DBG_ERRORFILE( "Don't know, how to convert date" ); 2422 ;// convert date string to date 2423 } 2424 } 2425 // get the target url 2426 if ( nIndex >= 0 ) 2427 { 2428 pEntry->maTargetURL = aValue.getToken( 0, '\t', nIndex ); 2429 } 2430 // get the size 2431 if ( nIndex >= 0 ) 2432 { 2433 OUString aBool = aValue.getToken( 0, '\t', nIndex ); 2434 if ( aBool.getLength() ) 2435 pEntry->mbIsFolder = aBool.toBoolean(); 2436 } 2437 // get the image url 2438 if ( nIndex >= 0 ) 2439 { 2440 pEntry->maImageURL = aValue.getToken( 0, '\t', nIndex ); 2441 } 2442 2443 // set the display text 2444 pEntry->maDisplayText = aDisplayText; 2445 2446 // detect the image 2447 INetURLObject aObj( pEntry->maImageURL.getLength() ? pEntry->maImageURL : pEntry->maTargetURL ); 2448 pEntry->maImage = SvFileInformationManager::GetImage( aObj, sal_False, isHighContrast( mpView ) ); 2449 2450 maContent.push_back( pEntry ); 2451 } 2452 } 2453 2454 // ----------------------------------------------------------------------- 2455 void SvtFileView_Impl::Resort_Impl( sal_Int16 nColumn, sal_Bool bAscending ) 2456 { 2457 ::osl::MutexGuard aGuard( maMutex ); 2458 2459 if ( ( nColumn == mnSortColumn ) && 2460 ( bAscending == mbAscending ) ) 2461 return; 2462 2463 // reset the quick search index 2464 mpView->ResetQuickSearch_Impl( NULL ); 2465 2466 String aEntryURL; 2467 SvLBoxEntry* pEntry = mpView->GetCurEntry(); 2468 if ( pEntry && pEntry->GetUserData() ) 2469 aEntryURL = ( (SvtContentEntry*)pEntry->GetUserData() )->maURL; 2470 2471 mnSortColumn = nColumn; 2472 mbAscending = bAscending; 2473 2474 SortFolderContent_Impl(); 2475 OpenFolder_Impl(); 2476 2477 if ( !mbIsFirstResort ) 2478 { 2479 sal_uLong nPos = GetEntryPos( aEntryURL ); 2480 if ( nPos < mpView->GetEntryCount() ) 2481 { 2482 pEntry = mpView->GetEntry( nPos ); 2483 2484 ++mnSuspendSelectCallback; // #i15668# - 2004-04-25 - fs@openoffice.org 2485 mpView->SetCurEntry( pEntry ); 2486 --mnSuspendSelectCallback; 2487 } 2488 } 2489 else 2490 mbIsFirstResort = sal_False; 2491 } 2492 2493 // ----------------------------------------------------------------------- 2494 static sal_Bool gbAscending = sal_True; 2495 static sal_Int16 gnColumn = COLUMN_TITLE; 2496 static const CollatorWrapper* pCollatorWrapper = NULL; 2497 2498 /* this functions returns true, if aOne is less then aTwo 2499 */ 2500 sal_Bool CompareSortingData_Impl( SortingData_Impl* const aOne, SortingData_Impl* const aTwo ) 2501 { 2502 DBG_ASSERT( pCollatorWrapper, "*CompareSortingData_Impl(): Can't work this way!" ); 2503 2504 sal_Int32 nComp; 2505 sal_Bool bRet = sal_False; 2506 sal_Bool bEqual = sal_False; 2507 2508 if ( aOne->mbIsFolder != aTwo->mbIsFolder ) 2509 { 2510 if ( aOne->mbIsFolder ) 2511 bRet = sal_True; 2512 else 2513 bRet = sal_False; 2514 2515 // !!! pb: #100376# folder always on top 2516 if ( !gbAscending ) 2517 bRet = !bRet; 2518 } 2519 else 2520 { 2521 switch ( gnColumn ) 2522 { 2523 case COLUMN_TITLE: 2524 // compare case insensitiv first 2525 nComp = pCollatorWrapper->compareString( aOne->GetLowerTitle(), aTwo->GetLowerTitle() ); 2526 2527 if ( nComp == 0 ) 2528 nComp = pCollatorWrapper->compareString( aOne->GetTitle(), aTwo->GetTitle() ); 2529 2530 if ( nComp < 0 ) 2531 bRet = sal_True; 2532 else if ( nComp > 0 ) 2533 bRet = sal_False; 2534 else 2535 bEqual = sal_True; 2536 break; 2537 case COLUMN_TYPE: 2538 nComp = pCollatorWrapper->compareString( aOne->maType, aTwo->maType ); 2539 if ( nComp < 0 ) 2540 bRet = sal_True; 2541 else if ( nComp > 0 ) 2542 bRet = sal_False; 2543 else 2544 bEqual = sal_True; 2545 break; 2546 case COLUMN_SIZE: 2547 if ( aOne->maSize < aTwo->maSize ) 2548 bRet = sal_True; 2549 else if ( aOne->maSize > aTwo->maSize ) 2550 bRet = sal_False; 2551 else 2552 bEqual = sal_True; 2553 break; 2554 case COLUMN_DATE: 2555 if ( aOne->maModDate < aTwo->maModDate ) 2556 bRet = sal_True; 2557 else if ( aOne->maModDate > aTwo->maModDate ) 2558 bRet = sal_False; 2559 else 2560 bEqual = sal_True; 2561 break; 2562 default: 2563 DBG_WARNING( "CompareSortingData_Impl: Compare unknown type!" ); 2564 bRet = sal_False; 2565 } 2566 } 2567 2568 // when the two elements are equal, we must not return sal_True (which would 2569 // happen if we just return ! ( a < b ) when not sorting ascending ) 2570 if ( bEqual ) 2571 return sal_False; 2572 2573 return gbAscending ? bRet : !bRet; 2574 } 2575 2576 // ----------------------------------------------------------------------- 2577 void SvtFileView_Impl::SortFolderContent_Impl() 2578 { 2579 ::osl::MutexGuard aGuard( maMutex ); 2580 2581 sal_uInt32 nSize = maContent.size(); 2582 2583 if ( nSize > 1 ) 2584 { 2585 gbAscending = mbAscending; 2586 gnColumn = mnSortColumn; 2587 pCollatorWrapper = aIntlWrapper.getCaseCollator(); 2588 2589 std::stable_sort( maContent.begin(), maContent.end(), CompareSortingData_Impl ); 2590 2591 pCollatorWrapper = NULL; 2592 } 2593 } 2594 2595 // ----------------------------------------------------------------------- 2596 void SvtFileView_Impl::EntryRemoved( const OUString& rURL ) 2597 { 2598 ::osl::MutexGuard aGuard( maMutex ); 2599 2600 std::vector< SortingData_Impl* >::iterator aIt; 2601 2602 for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ ) 2603 { 2604 if ( (*aIt)->maTargetURL == rURL ) 2605 { 2606 maContent.erase( aIt ); 2607 break; 2608 } 2609 } 2610 } 2611 2612 // ----------------------------------------------------------------------- 2613 void SvtFileView_Impl::EntryRenamed( OUString& rURL, 2614 const OUString& rTitle ) 2615 { 2616 ::osl::MutexGuard aGuard( maMutex ); 2617 2618 std::vector< SortingData_Impl* >::iterator aIt; 2619 2620 for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ ) 2621 { 2622 if ( (*aIt)->maTargetURL == rURL ) 2623 { 2624 (*aIt)->SetNewTitle( rTitle ); 2625 OUString aDisplayText = (*aIt)->maDisplayText; 2626 sal_Int32 nIndex = aDisplayText.indexOf( '\t' ); 2627 2628 if ( nIndex > 0 ) 2629 (*aIt)->maDisplayText = aDisplayText.replaceAt( 0, nIndex, rTitle ); 2630 2631 INetURLObject aURLObj( rURL ); 2632 aURLObj.SetName( rTitle, INetURLObject::ENCODE_ALL ); 2633 2634 rURL = aURLObj.GetMainURL( INetURLObject::NO_DECODE ); 2635 2636 (*aIt)->maTargetURL = rURL; 2637 break; 2638 } 2639 } 2640 } 2641 2642 // ----------------------------------------------------------------------- 2643 String SvtFileView_Impl::FolderInserted( const OUString& rURL, const OUString& rTitle ) 2644 { 2645 ::osl::MutexGuard aGuard( maMutex ); 2646 2647 SortingData_Impl* pData = new SortingData_Impl; 2648 2649 pData->SetNewTitle( rTitle ); 2650 pData->maSize = 0; 2651 pData->mbIsFolder = sal_True; 2652 pData->maTargetURL = rURL; 2653 2654 INetURLObject aURLObj( rURL ); 2655 2656 ::svtools::VolumeInfo aVolInfo; 2657 pData->maType = SvFileInformationManager::GetFolderDescription( aVolInfo ); 2658 pData->maImage = SvFileInformationManager::GetFolderImage( aVolInfo, sal_False, isHighContrast( mpView ) ); 2659 2660 OUString aValue; 2661 OUString aTab = OUString::createFromAscii( "\t" ); 2662 OUString aDateSep = OUString::createFromAscii( ", " ); 2663 2664 // title, type, size, date 2665 aValue = pData->GetTitle(); 2666 // #83004# -------------------- 2667 ReplaceTabWithString( aValue ); 2668 aValue += aTab; 2669 aValue += pData->maType; 2670 aValue += aTab; 2671 // folders don't have a size 2672 aValue += aTab; 2673 // set the date 2674 SvtSysLocale aSysLocale; 2675 const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData(); 2676 aValue += rLocaleData.getDate( pData->maModDate ); 2677 aValue += aDateSep; 2678 aValue += rLocaleData.getTime( pData->maModDate ); 2679 2680 pData->maDisplayText = aValue; 2681 maContent.push_back( pData ); 2682 2683 return String( aValue ); 2684 } 2685 2686 // ----------------------------------------------------------------------- 2687 sal_uLong SvtFileView_Impl::GetEntryPos( const OUString& rURL ) 2688 { 2689 ::osl::MutexGuard aGuard( maMutex ); 2690 2691 std::vector< SortingData_Impl* >::iterator aIt; 2692 sal_uLong nPos = 0; 2693 2694 for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ ) 2695 { 2696 if ( (*aIt)->maTargetURL == rURL ) 2697 return nPos; 2698 nPos += 1; 2699 } 2700 2701 return nPos; 2702 } 2703 2704 // ----------------------------------------------------------------------- 2705 sal_Bool SvtFileView_Impl::SearchNextEntry( sal_uInt32& nIndex, const OUString& rTitle, sal_Bool bWrapAround ) 2706 { 2707 ::osl::MutexGuard aGuard( maMutex ); 2708 2709 sal_uInt32 nEnd = maContent.size(); 2710 sal_uInt32 nStart = nIndex; 2711 while ( nIndex < nEnd ) 2712 { 2713 SortingData_Impl* pData = maContent[ nIndex ]; 2714 if ( rTitle.compareTo( pData->GetLowerTitle(), rTitle.getLength() ) == 0 ) 2715 return sal_True; 2716 nIndex += 1; 2717 } 2718 2719 if ( bWrapAround ) 2720 { 2721 nIndex = 0; 2722 while ( nIndex < nEnd && nIndex <= nStart ) 2723 { 2724 SortingData_Impl* pData = maContent[ nIndex ]; 2725 if ( rTitle.compareTo( pData->GetLowerTitle(), rTitle.getLength() ) == 0 ) 2726 return sal_True; 2727 nIndex += 1; 2728 } 2729 } 2730 2731 return sal_False; 2732 } 2733 2734 // ----------------------------------------------------------------------- 2735 void SvtFileView_Impl::SetActualFolder( const INetURLObject& rActualFolder ) 2736 { 2737 if( mbReplaceNames ) 2738 { 2739 if( mpNameTrans ) 2740 mpNameTrans->SetActualFolder( rActualFolder ); 2741 else 2742 mpNameTrans = new NameTranslator_Impl( rActualFolder ); 2743 } 2744 } 2745 2746 namespace svtools { 2747 2748 // ----------------------------------------------------------------------- 2749 // QueryDeleteDlg_Impl 2750 // ----------------------------------------------------------------------- 2751 2752 QueryDeleteDlg_Impl::QueryDeleteDlg_Impl 2753 ( 2754 Window* pParent, 2755 const String& rName // Eintragsname 2756 ) : 2757 2758 ModalDialog( pParent, SvtResId( DLG_SVT_QUERYDELETE ) ), 2759 2760 _aEntryLabel ( this, SvtResId( TXT_ENTRY ) ), 2761 _aEntry ( this, SvtResId( TXT_ENTRYNAME ) ), 2762 _aQueryMsg ( this, SvtResId( TXT_QUERYMSG ) ), 2763 _aYesButton ( this, SvtResId( BTN_YES ) ), 2764 _aAllButton ( this, SvtResId( BTN_ALL ) ), 2765 _aNoButton ( this, SvtResId( BTN_NO ) ), 2766 _aCancelButton( this, SvtResId( BTN_CANCEL ) ) 2767 2768 { 2769 FreeResource(); 2770 2771 // Handler 2772 Link aLink( STATIC_LINK( this, QueryDeleteDlg_Impl, ClickLink ) ); 2773 _aYesButton.SetClickHdl( aLink ); 2774 _aAllButton.SetClickHdl( aLink ); 2775 _aNoButton.SetClickHdl( aLink ); 2776 2777 // Anzeige der spezifizierten Texte 2778 2779 WinBits nTmpStyle = _aEntry.GetStyle(); 2780 nTmpStyle |= WB_PATHELLIPSIS; 2781 _aEntry.SetStyle( nTmpStyle ); 2782 _aEntry.SetText( rName ); 2783 } 2784 2785 // ----------------------------------------------------------------------- 2786 2787 IMPL_STATIC_LINK( QueryDeleteDlg_Impl, ClickLink, PushButton*, pBtn ) 2788 { 2789 if ( pBtn == &pThis->_aYesButton ) 2790 pThis->_eResult = QUERYDELETE_YES; 2791 else if ( pBtn == &pThis->_aNoButton ) 2792 pThis->_eResult = QUERYDELETE_NO; 2793 else if ( pBtn == &pThis->_aAllButton ) 2794 pThis->_eResult = QUERYDELETE_ALL; 2795 else if ( pBtn == &pThis->_aCancelButton ) 2796 pThis->_eResult = QUERYDELETE_CANCEL; 2797 2798 pThis->EndDialog( RET_OK ); 2799 2800 return 0; 2801 } 2802 2803 } 2804 2805