Update ooo320-m1
[ooovba.git] / svtools / source / contnr / fileview.cxx
blobba6be963e9461a6e1bb465faa382e5623a000290
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fileview.cxx,v $
10 * $Revision: 1.73.104.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include "fileview.hxx"
35 #include <svtools/svtdata.hxx>
36 #include "imagemgr.hxx"
37 #include <svtools/headbar.hxx>
38 #include <svtools/svtabbx.hxx>
40 #include <svtools/svtools.hrc>
41 #include "fileview.hrc"
42 #include "contentenumeration.hxx"
43 #include <svtools/AccessibleBrowseBoxObjType.hxx>
44 #include <com/sun/star/util/DateTime.hpp>
45 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
46 #include <com/sun/star/task/XInteractionHandler.hpp>
47 #include <com/sun/star/ucb/XProgressHandler.hpp>
48 #include <com/sun/star/sdbc/XResultSet.hpp>
49 #include <com/sun/star/ucb/XAnyCompareFactory.hpp>
50 #include <com/sun/star/ucb/XContentAccess.hpp>
51 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
52 #include <com/sun/star/ucb/XSortedDynamicResultSetFactory.hpp>
53 #include <com/sun/star/sdbc/XRow.hpp>
54 #include <com/sun/star/container/XChild.hpp>
55 #include <com/sun/star/ucb/CommandAbortedException.hpp>
56 #include <com/sun/star/ucb/ContentCreationException.hpp>
57 #include <vcl/waitobj.hxx>
58 #include <com/sun/star/io/XPersist.hpp>
59 #include <com/sun/star/beans/XPropertySet.hpp>
61 #include <algorithm>
62 #include <memory>
63 #include <tools/urlobj.hxx>
64 #include <tools/datetime.hxx>
65 #include <comphelper/processfactory.hxx>
66 #include <unotools/localfilehelper.hxx>
67 #include <ucbhelper/content.hxx>
68 #include <ucbhelper/commandenvironment.hxx>
69 #include <vcl/msgbox.hxx>
70 #ifndef INCLUDED_RTL_MATH_H
71 #include <rtl/math.hxx>
72 #endif
73 #include <tools/config.hxx>
74 #include <osl/mutex.hxx>
75 #include <osl/conditn.hxx>
76 #include <vos/timer.hxx>
77 #include <vcl/svapp.hxx>
78 #include <vcl/sound.hxx>
79 #include <unotools/ucbhelper.hxx>
80 #include <unotools/intlwrapper.hxx>
81 #include <svtools/syslocale.hxx>
82 #include <svtools/urlfilter.hxx>
84 using namespace ::com::sun::star::lang;
85 using namespace ::com::sun::star::sdbc;
86 using namespace ::com::sun::star::task;
87 using namespace ::com::sun::star::ucb;
88 using namespace ::com::sun::star::uno;
89 using namespace ::com::sun::star::io;
90 using namespace ::com::sun::star::beans;
91 using namespace ::comphelper;
92 using ::svt::SortingData_Impl;
93 using ::svt::FolderDescriptor;
94 using ::vos::TTimeValue;
95 using ::rtl::OUString;
97 #define ALL_FILES_FILTER "*.*"
99 #define COLUMN_TITLE 1
100 #define COLUMN_TYPE 2
101 #define COLUMN_SIZE 3
102 #define COLUMN_DATE 4
104 DECLARE_LIST( StringList_Impl, OUString* )
106 #define aSeparatorStr "----------------------------------"
108 #define ROW_HEIGHT 17 // the height of a row has to be a little higher than the bitmap
109 #define QUICK_SEARCH_TIMEOUT 1500 // time in mSec before the quicksearch string will be reseted
111 namespace
113 //====================================================================
114 //= ReleaseSolarMutex
115 //====================================================================
116 struct ReleaseSolarMutex
118 private:
119 ULONG m_nCount;
121 public:
122 inline ReleaseSolarMutex()
124 m_nCount = Application::ReleaseSolarMutex();
126 inline ~ReleaseSolarMutex()
128 Application::AcquireSolarMutex( m_nCount );
132 //====================================================================
133 //= ITimeoutHandler
134 //====================================================================
135 class CallbackTimer;
136 class ITimeoutHandler
138 public:
139 virtual void onTimeout( CallbackTimer* _pInstigator ) = 0;
142 //====================================================================
143 //= CallbackTimer
144 //====================================================================
145 class CallbackTimer : public ::vos::OTimer
147 protected:
148 ITimeoutHandler* m_pTimeoutHandler;
150 public:
151 CallbackTimer( ITimeoutHandler* _pHandler ) : m_pTimeoutHandler( _pHandler ) { }
153 protected:
154 virtual void SAL_CALL onShot();
157 //--------------------------------------------------------------------
158 void SAL_CALL CallbackTimer::onShot()
160 OSL_ENSURE( m_pTimeoutHandler, "CallbackTimer::onShot: nobody interested in?" );
161 ITimeoutHandler* pHandler( m_pTimeoutHandler );
162 if ( pHandler )
163 pHandler->onTimeout( this );
168 // -----------------------------------------------------------------------
170 static sal_Bool isHighContrast( const Window* _pView )
172 return _pView->GetDisplayBackground().GetColor().IsDark();
175 // -----------------------------------------------------------------------
177 void FilterMatch::createWildCardFilterList(const String& _rFilterList,::std::vector< WildCard >& _rFilters)
179 if( _rFilterList.Len() )
180 {// filter is given
181 xub_StrLen nCount = _rFilterList.GetTokenCount();
182 _rFilters.reserve( nCount );
183 xub_StrLen nIndex = 0;
184 OUString sToken;
187 sToken = _rFilterList.GetToken( 0, ';', nIndex );
188 if ( sToken.getLength() )
190 _rFilters.push_back( WildCard( sToken.toAsciiUpperCase() ) );
193 while ( nIndex != STRING_NOTFOUND );
195 else
196 // no filter is given -> match all
197 _rFilters.push_back( WildCard( String::CreateFromAscii( "*" ) ) );
199 // class ViewTabListBox_Impl ---------------------------------------------
201 class ViewTabListBox_Impl : public SvHeaderTabListBox
203 private:
204 Reference< XCommandEnvironment > mxCmdEnv;
206 ::osl::Mutex maMutex;
207 HeaderBar* mpHeaderBar;
208 SvtFileView_Impl* mpParent;
209 Timer maResetQuickSearch;
210 OUString maQuickSearchText;
211 String msAccessibleDescText;
212 String msFolder;
213 String msFile;
214 sal_uInt32 mnSearchIndex;
215 sal_Bool mbResizeDisabled : 1;
216 sal_Bool mbAutoResize : 1;
217 sal_Bool mbEnableDelete : 1;
219 void DeleteEntries();
220 void DoQuickSearch( const xub_Unicode& rChar );
221 sal_Bool Kill( const OUString& rURL );
223 protected:
224 virtual BOOL DoubleClickHdl();
225 virtual ::rtl::OUString GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const;
227 public:
228 ViewTabListBox_Impl( Window* pParentWin, SvtFileView_Impl* pParent, sal_Int16 nFlags );
229 ~ViewTabListBox_Impl();
231 virtual void Resize();
232 virtual void KeyInput( const KeyEvent& rKEvt );
233 virtual BOOL EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText );
235 void ClearAll();
236 HeaderBar* GetHeaderBar() const { return mpHeaderBar; }
238 void EnableAutoResize() { mbAutoResize = sal_True; }
239 void EnableDelete( sal_Bool bEnable ) { mbEnableDelete = bEnable; }
240 sal_Bool IsDeleteOrContextMenuEnabled() { return mbEnableDelete || IsContextMenuHandlingEnabled(); }
242 Reference< XCommandEnvironment > GetCommandEnvironment() const { return mxCmdEnv; }
244 DECL_LINK( ResetQuickSearch_Impl, Timer * );
246 virtual PopupMenu* CreateContextMenu( void );
247 virtual void ExcecuteContextMenuAction( USHORT nSelectedPopentry );
250 // class HashedEntry --------------------------------------------------
252 class HashedEntry
253 { // just a special String which can be compared on equality much faster
254 protected:
255 OUString maName;
256 sal_Int32 mnHashCode;
257 public:
258 inline HashedEntry( const OUString& rName );
259 inline HashedEntry( const INetURLObject& rURL );
260 inline HashedEntry( const HashedEntry& rCopy );
261 virtual ~HashedEntry();
263 inline sal_Bool operator ==( const HashedEntry& rRef ) const;
264 inline sal_Bool operator !=( const HashedEntry& rRef ) const;
266 inline const OUString& GetName() const;
269 inline HashedEntry::HashedEntry( const OUString& rName ): maName( rName ), mnHashCode( rName.hashCode() )
273 inline HashedEntry::HashedEntry( const INetURLObject& rURL ):
274 maName( rURL.GetMainURL( INetURLObject::NO_DECODE ) ),
275 mnHashCode( maName.hashCode() )
279 inline HashedEntry::HashedEntry( const HashedEntry& r ): maName( r.maName ), mnHashCode( r.mnHashCode )
283 HashedEntry::~HashedEntry()
287 inline sal_Bool HashedEntry::operator ==( const HashedEntry& rRef ) const
289 return mnHashCode == rRef.mnHashCode && maName.reverseCompareTo( rRef.maName ) == 0;
292 inline sal_Bool HashedEntry::operator !=( const HashedEntry& rRef ) const
294 return mnHashCode != rRef.mnHashCode || maName.reverseCompareTo( rRef.maName ) != 0;
297 inline const OUString& HashedEntry::GetName() const
299 return maName;
302 // class HashedEntryList ----------------------------------------------
304 class HashedEntryList : protected List
305 {// provides a list of _unique_ Entries
306 protected:
307 inline HashedEntry* First();
308 inline HashedEntry* Next();
309 inline void Append( HashedEntry* pNewEntry );
310 public:
311 virtual ~HashedEntryList();
313 const HashedEntry* Find( const OUString& rNameToSearchFor );
314 const HashedEntry* Find( const HashedEntry& rToSearchFor );
315 // not const, because First()/Next() is used
316 using List::Insert;
317 const HashedEntry& Insert( HashedEntry* pInsertOrDelete );
318 // don't care about pInsertOrDelete after this any more and handle it as invalid!
319 // returns the Entry, which is effectively inserted
321 void Clear();
324 inline HashedEntry* HashedEntryList::First()
326 return ( HashedEntry* ) List::First();
329 inline HashedEntry* HashedEntryList::Next()
331 return ( HashedEntry* ) List::Next();
334 inline void HashedEntryList::Append( HashedEntry* pNew )
336 List::Insert( pNew, LIST_APPEND );
339 HashedEntryList::~HashedEntryList()
341 Clear();
344 const HashedEntry* HashedEntryList::Find( const OUString& rRefName )
345 { // simple linear search, which should be fast enough for this purpose
346 HashedEntry aRef( rRefName );
347 HashedEntry* pIter = First();
348 while( pIter && *pIter != aRef )
349 pIter = Next();
351 return pIter;
354 const HashedEntry* HashedEntryList::Find( const HashedEntry& rRef )
355 { // simple linear search, which should be fast enough for this purpose
356 HashedEntry* pIter = First();
357 while( pIter && *pIter != rRef )
358 pIter = Next();
360 return pIter;
363 const HashedEntry& HashedEntryList::Insert( HashedEntry* pNew )
364 { // inserts (appends) only, if entry doesn't already exists
365 // if it already exists, pNew is deleted, because the caller must not worry about pNew any more
367 DBG_ASSERT( pNew, "HashedEntryList::Insert(): NULL-pointer can't be inserted" );
369 const HashedEntry* pSearch = Find( *pNew );
370 if( pSearch )
372 delete pNew;
373 return *pSearch;
376 Append( pNew );
378 return *pNew;
381 void HashedEntryList::Clear()
383 HashedEntry* p = First();
384 while( p )
386 delete p;
387 p = Next();
391 // class NameTranslationEntry -----------------------------------------
393 class NameTranslationEntry : public HashedEntry
394 {// a fast compareble String and another String, which is used to get a substitution for a given String
395 protected:
396 OUString maTranslatedName;
397 public:
398 inline NameTranslationEntry( const OUString& rOriginalName, const OUString& rTranslatedName );
399 inline NameTranslationEntry( const ByteString& rOriginalName, const ByteString& rTranslatedName );
401 inline const OUString& GetTranslation() const;
404 inline NameTranslationEntry::NameTranslationEntry( const OUString& rOrg, const OUString& rTrans ):
405 HashedEntry( rOrg ),
406 maTranslatedName( rTrans )
410 inline NameTranslationEntry::NameTranslationEntry( const ByteString& rOrg, const ByteString& rTrans ):
411 HashedEntry( OUString( rOrg.GetBuffer(), rOrg.Len(), RTL_TEXTENCODING_ASCII_US ) ),
412 maTranslatedName( OUString( rTrans.GetBuffer(), rTrans.Len(), RTL_TEXTENCODING_UTF8 ) )
416 inline const OUString& NameTranslationEntry::GetTranslation() const
418 return maTranslatedName;
421 // class NameTranslationList -----------------------------------------
423 class NameTranslationList : protected HashedEntryList
424 { // contains a list of substitutes of strings for a given folder (as URL)
425 // explanation of the circumstances see in remarks for Init();
426 protected:
427 INetURLObject maTransFile; // URL of file with translation entries
428 HashedEntry maHashedURL; // for future purposes when dealing with a set of cached
429 // NameTranslationLists
430 private:
431 const String maTransFileName;
432 void Init(); // reads the translation file and fills the (internal) list
434 public:
435 NameTranslationList( const INetURLObject& rBaseURL );
436 // rBaseURL: path to folder for which the translation of the entries
437 // should be done
439 using List::operator==;
440 inline sal_Bool operator ==( const HashedEntry& rRef ) const;
441 using List::operator!=;
442 inline sal_Bool operator !=( const HashedEntry& rRef ) const;
444 const OUString* Translate( const OUString& rName ) const;
445 // returns NULL, if rName can't be found
447 inline void Update(); // clears list and init
449 inline const String& GetTransTableFileName() const;
450 // returns the name for the file, which contains the translation strings
453 inline const String& NameTranslationList::GetTransTableFileName() const
455 return maTransFileName;
458 void NameTranslationList::Init()
460 // Tries to read the file ".nametranslation.table" in the base folder. Complete path/name is in maTransFile.
461 // Further on, the found entries in the section "TRANSLATIONNAMES" are used to replace names in the
462 // base folder by translated ones. The translation must be given in UTF8
463 // See examples of such a files in the samples-folder of an Office installation
467 ::ucbhelper::Content aTestContent( maTransFile.GetMainURL( INetURLObject::NO_DECODE ), Reference< XCommandEnvironment >() );
469 if( aTestContent.isDocument() )
470 {// ... also tests the existence of maTransFile by throwing an Exception
471 const sal_Char* pSection = "TRANSLATIONNAMES";
472 String aFsysName( maTransFile.getFSysPath( INetURLObject::FSYS_DETECT ) );
473 Config aConfig( aFsysName );
475 aConfig.SetGroup( ByteString( pSection ) );
477 USHORT nKeyCnt = aConfig.GetKeyCount();
479 for( USHORT nCnt = 0 ; nCnt < nKeyCnt ; ++nCnt )
480 Insert( new NameTranslationEntry( aConfig.GetKeyName( nCnt ), aConfig.ReadKey( nCnt ) ) );
483 catch( Exception& ) {}
486 NameTranslationList::NameTranslationList( const INetURLObject& rBaseURL ):
487 maTransFile( rBaseURL ),
488 maHashedURL( rBaseURL ),
489 maTransFileName( String::CreateFromAscii( ".nametranslation.table" ) )
491 maTransFile.insertName( maTransFileName );
492 Init();
495 inline sal_Bool NameTranslationList::operator ==( const HashedEntry& rRef ) const
497 return maHashedURL == rRef;
500 inline sal_Bool NameTranslationList::operator !=( const HashedEntry& rRef ) const
502 return maHashedURL != rRef;
505 const OUString* NameTranslationList::Translate( const OUString& rName ) const
507 const NameTranslationEntry* pSearch = static_cast< const NameTranslationEntry* >(
508 ( const_cast< NameTranslationList* >( this ) )->Find( rName ) );
510 return pSearch? &pSearch->GetTranslation() : NULL;
513 inline void NameTranslationList::Update()
515 Clear();
516 Init();
519 // class NameTranslator_Impl ------------------------------------------
521 // enables the user to get string substitutions (translations for the content) for a given folder
522 // see more explanations above in the description for NameTranslationList
523 class NameTranslator_Impl : public ::svt::IContentTitleTranslation
525 private:
526 NameTranslationList* mpActFolder;
527 public:
528 NameTranslator_Impl( void );
529 NameTranslator_Impl( const INetURLObject& rActualFolder );
530 virtual ~NameTranslator_Impl();
532 // IContentTitleTranslation
533 virtual sal_Bool GetTranslation( const OUString& rOriginalName, OUString& rTranslatedName ) const;
535 void UpdateTranslationTable(); // reads the translation file again
537 void SetActualFolder( const INetURLObject& rActualFolder );
538 const String* GetTransTableFileName() const;
539 // returns the name for the file, which contains the translation strings
542 //====================================================================
543 //= SvtFileView_Impl
544 //====================================================================
546 class SvtFileView_Impl :public ::svt::IEnumerationResultHandler
547 ,public ITimeoutHandler
549 protected:
550 SvtFileView* mpAntiImpl;
551 Link m_aSelectHandler;
553 ::rtl::Reference< ::svt::FileViewContentEnumerator >
554 m_pContentEnumerator;
555 Link m_aCurrentAsyncActionHandler;
556 ::osl::Condition m_aAsyncActionFinished;
557 ::rtl::Reference< ::vos::OTimer > m_pCancelAsyncTimer;
558 ::svt::EnumerationResult m_eAsyncActionResult;
559 bool m_bRunningAsyncAction;
560 bool m_bAsyncActionCancelled;
563 public:
565 ::std::vector< SortingData_Impl* > maContent;
566 ::osl::Mutex maMutex;
568 ViewTabListBox_Impl* mpView;
569 NameTranslator_Impl* mpNameTrans;
570 const IUrlFilter* mpUrlFilter;
571 sal_uInt16 mnSortColumn;
572 sal_Bool mbAscending : 1;
573 sal_Bool mbOnlyFolder : 1;
574 sal_Bool mbReplaceNames : 1; // translate folder names or display doc-title instead of file name
575 sal_Int16 mnSuspendSelectCallback : 1;
576 sal_Bool mbIsFirstResort : 1;
578 IntlWrapper aIntlWrapper;
580 String maViewURL;
581 String maAllFilter;
582 String maCurrentFilter;
583 Image maFolderImage;
584 Link maOpenDoneLink;
585 Reference< XCommandEnvironment > mxCmdEnv;
587 SvtFileView_Impl( SvtFileView* pAntiImpl, Reference < XCommandEnvironment > xEnv,
588 sal_Int16 nFlags,
589 sal_Bool bOnlyFolder );
590 virtual ~SvtFileView_Impl();
592 void Clear();
594 FileViewResult GetFolderContent_Impl(
595 const String& rFolder,
596 const FileViewAsyncAction* pAsyncDescriptor,
597 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList = ::com::sun::star::uno::Sequence< ::rtl::OUString >() );
599 FileViewResult GetFolderContent_Impl(
600 const FolderDescriptor& _rFolder,
601 const FileViewAsyncAction* pAsyncDescriptor,
602 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList = ::com::sun::star::uno::Sequence< ::rtl::OUString >());
603 void FilterFolderContent_Impl( const OUString &rFilter );
604 void CancelRunningAsyncAction();
606 void OpenFolder_Impl();
607 // #83004# -------
608 void ReplaceTabWithString( OUString& aValue );
609 void CreateDisplayText_Impl();
610 void CreateVector_Impl( const Sequence < OUString > &rList );
611 void SortFolderContent_Impl();
613 void EntryRemoved( const OUString& rURL );
614 void EntryRenamed( OUString& rURL,
615 const OUString& rName );
616 String FolderInserted( const OUString& rURL,
617 const OUString& rTitle );
619 ULONG GetEntryPos( const OUString& rURL );
621 inline void EnableContextMenu( sal_Bool bEnable );
622 inline void EnableDelete( sal_Bool bEnable );
624 void Resort_Impl( sal_Int16 nColumn, sal_Bool bAscending );
625 sal_Bool SearchNextEntry( sal_uInt32 &nIndex,
626 const OUString& rTitle,
627 sal_Bool bWrapAround );
629 inline sal_Bool EnableNameReplacing( sal_Bool bEnable = sal_True ); // returns false, if action wasn't possible
630 void SetActualFolder( const INetURLObject& rActualFolder );
632 sal_Bool GetDocTitle( const OUString& rTargetURL, OUString& rDocTitle ) const;
634 void SetSelectHandler( const Link& _rHdl );
636 void InitSelection();
637 void ResetCursor();
639 inline void EndEditing( bool _bCancel );
641 protected:
642 DECL_LINK( SelectionMultiplexer, void* );
644 protected:
645 // IEnumerationResultHandler overridables
646 virtual void enumerationDone( ::svt::EnumerationResult _eResult );
647 void implEnumerationSuccess();
649 // ITimeoutHandler
650 virtual void onTimeout( CallbackTimer* _pInstigator );
653 inline void SvtFileView_Impl::EnableContextMenu( sal_Bool bEnable )
655 mpView->EnableContextMenuHandling( bEnable );
656 if( bEnable )
657 mbReplaceNames = sal_False;
660 inline void SvtFileView_Impl::EnableDelete( sal_Bool bEnable )
662 mpView->EnableDelete( bEnable );
663 if( bEnable )
664 mbReplaceNames = sal_False;
667 inline sal_Bool SvtFileView_Impl::EnableNameReplacing( sal_Bool bEnable )
669 sal_Bool bRet;
670 if( mpView->IsDeleteOrContextMenuEnabled() )
672 DBG_ASSERT( !mbReplaceNames, "SvtFileView_Impl::EnableNameReplacing(): state should be not possible!" );
673 bRet = !bEnable; // only for enabling this is an unsuccessful result
675 else
677 mbReplaceNames = bEnable;
678 bRet = sal_True;
681 return bRet;
684 inline void SvtFileView_Impl::EndEditing( bool _bCancel )
686 if ( mpView->IsEditingActive() )
687 mpView->EndEditing( _bCancel != false );
690 // functions -------------------------------------------------------------
692 OUString CreateExactSizeText_Impl( sal_Int64 nSize )
694 double fSize( ( double ) nSize );
695 int nDec;
697 long nMega = 1024 * 1024;
698 long nGiga = nMega * 1024;
700 String aUnitStr = ' ';
702 if ( nSize < 10000 )
704 aUnitStr += String( SvtResId( STR_SVT_BYTES ) );
705 nDec = 0;
707 else if ( nSize < nMega )
709 fSize /= 1024;
710 aUnitStr += String( SvtResId( STR_SVT_KB ) );
711 nDec = 1;
713 else if ( nSize < nGiga )
715 fSize /= nMega;
716 aUnitStr += String( SvtResId( STR_SVT_MB ) );
717 nDec = 2;
719 else
721 fSize /= nGiga;
722 aUnitStr += String( SvtResId( STR_SVT_GB ) );
723 nDec = 3;
726 OUString aSizeStr( ::rtl::math::doubleToUString( fSize,
727 rtl_math_StringFormat_F, nDec,
728 SvtSysLocale().GetLocaleData().getNumDecimalSep().GetChar(0)));
729 aSizeStr += aUnitStr;
731 return aSizeStr;
734 // -----------------------------------------------------------------------
735 // class ViewTabListBox_Impl ---------------------------------------------
736 // -----------------------------------------------------------------------
738 ViewTabListBox_Impl::ViewTabListBox_Impl( Window* pParentWin,
739 SvtFileView_Impl* pParent,
740 sal_Int16 nFlags ) :
742 SvHeaderTabListBox( pParentWin, WB_TABSTOP ),
744 mpHeaderBar ( NULL ),
745 mpParent ( pParent ),
746 msAccessibleDescText( SvtResId( STR_SVT_ACC_DESC_FILEVIEW ) ),
747 msFolder ( SvtResId( STR_SVT_ACC_DESC_FOLDER ) ),
748 msFile ( SvtResId( STR_SVT_ACC_DESC_FILE ) ),
749 mnSearchIndex ( 0 ),
750 mbResizeDisabled ( sal_False ),
751 mbAutoResize ( sal_False ),
752 mbEnableDelete ( sal_True )
755 sal_Bool bViewHeader = true;
756 Size aBoxSize = pParentWin->GetSizePixel();
757 mpHeaderBar = new HeaderBar( pParentWin, WB_BUTTONSTYLE | WB_BOTTOMBORDER );
758 mpHeaderBar->SetPosSizePixel( Point( 0, 0 ), mpHeaderBar->CalcWindowSizePixel() );
760 HeaderBarItemBits nBits = ( HIB_LEFT | HIB_VCENTER | HIB_CLICKABLE );
761 if ( ( nFlags & FILEVIEW_SHOW_ALL ) == FILEVIEW_SHOW_ALL )
763 mpHeaderBar->InsertItem( COLUMN_TITLE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_TITLE ) ), 180, nBits | HIB_UPARROW );
764 mpHeaderBar->InsertItem( COLUMN_TYPE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_TYPE ) ), 140, nBits );
765 mpHeaderBar->InsertItem( COLUMN_SIZE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_SIZE ) ), 80, nBits );
766 mpHeaderBar->InsertItem( COLUMN_DATE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_DATE ) ), 500, nBits );
768 if( ( nFlags & FILEVIEW_SHOW_NONE ) == FILEVIEW_SHOW_NONE )
769 bViewHeader = false;
770 else
771 mpHeaderBar->InsertItem( COLUMN_TITLE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_TITLE ) ), 600, nBits );
773 Size aHeadSize = mpHeaderBar->GetSizePixel();
774 SetPosSizePixel( Point( 0, aHeadSize.Height() ),
775 Size( aBoxSize.Width(), aBoxSize.Height() - aHeadSize.Height() ) );
776 InitHeaderBar( mpHeaderBar );
777 SetHighlightRange();
778 SetEntryHeight( ROW_HEIGHT );
780 Show();
781 if( bViewHeader )
782 mpHeaderBar->Show();
784 maResetQuickSearch.SetTimeout( QUICK_SEARCH_TIMEOUT );
785 maResetQuickSearch.SetTimeoutHdl( LINK( this, ViewTabListBox_Impl, ResetQuickSearch_Impl ) );
787 Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
788 Reference< XInteractionHandler > xInteractionHandler = Reference< XInteractionHandler > (
789 xFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), UNO_QUERY );
791 mxCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() );
793 EnableContextMenuHandling();
796 // -----------------------------------------------------------------------
798 ViewTabListBox_Impl::~ViewTabListBox_Impl()
800 maResetQuickSearch.Stop();
802 delete mpHeaderBar;
805 // -----------------------------------------------------------------------
807 IMPL_LINK( ViewTabListBox_Impl, ResetQuickSearch_Impl, Timer*, EMPTYARG )
809 ::osl::MutexGuard aGuard( maMutex );
811 maQuickSearchText = OUString();
812 mnSearchIndex = 0;
814 return 0;
817 // -----------------------------------------------------------------------
819 void ViewTabListBox_Impl::Resize()
821 SvTabListBox::Resize();
822 Size aBoxSize = Control::GetParent()->GetOutputSizePixel();
824 if ( mbResizeDisabled || !aBoxSize.Width() )
825 return;
827 Size aBarSize = mpHeaderBar->GetSizePixel();
828 aBarSize.Width() = mbAutoResize ? aBoxSize.Width() : GetSizePixel().Width();
829 mpHeaderBar->SetSizePixel( aBarSize );
831 if ( mbAutoResize )
833 mbResizeDisabled = sal_True;
834 Point aPos = GetPosPixel();
835 SetPosSizePixel( Point( 0, aBarSize.Height() ),
836 Size( aBoxSize.Width(), aBoxSize.Height() - aBarSize.Height() ) );
837 mbResizeDisabled = sal_False;
841 // -----------------------------------------------------------------------
843 void ViewTabListBox_Impl::KeyInput( const KeyEvent& rKEvt )
845 bool bHandled = false;
847 const KeyCode& rKeyCode = rKEvt.GetKeyCode();
848 if ( 0 == rKeyCode.GetModifier() )
850 if ( rKeyCode.GetCode() == KEY_RETURN )
852 ResetQuickSearch_Impl( NULL );
853 GetDoubleClickHdl().Call( this );
854 bHandled = true;
856 else if ( ( rKeyCode.GetCode() == KEY_DELETE ) &&
857 mbEnableDelete )
859 ResetQuickSearch_Impl( NULL );
860 DeleteEntries();
861 bHandled = true;
863 else if ( ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_NUM ) ||
864 ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_ALPHA ) )
866 DoQuickSearch( rKEvt.GetCharCode() );
867 bHandled = true;
871 if ( !bHandled )
873 ResetQuickSearch_Impl( NULL );
874 SvHeaderTabListBox::KeyInput( rKEvt );
878 // -----------------------------------------------------------------------
880 PopupMenu* ViewTabListBox_Impl::CreateContextMenu( void )
882 PopupMenu* pRet;
883 sal_Int32 nSelectedEntries = GetSelectionCount();
885 if ( nSelectedEntries )
887 pRet = new PopupMenu( SvtResId( RID_FILEVIEW_CONTEXTMENU ) );
888 pRet->EnableItem( MID_FILEVIEW_DELETE, 0 < nSelectedEntries );
889 pRet->EnableItem( MID_FILEVIEW_RENAME, 1 == nSelectedEntries );
890 pRet->RemoveDisabledEntries( sal_True, sal_True );
892 else
893 pRet = NULL;
895 return pRet;
898 // -----------------------------------------------------------------------
900 void ViewTabListBox_Impl::ExcecuteContextMenuAction( USHORT nSelectedPopupEntry )
902 switch ( nSelectedPopupEntry )
904 case MID_FILEVIEW_DELETE :
905 DeleteEntries();
906 break;
908 case MID_FILEVIEW_RENAME :
909 EditEntry( FirstSelected() );
910 break;
914 // -----------------------------------------------------------------------
916 void ViewTabListBox_Impl::ClearAll()
918 for ( USHORT i = 0; i < GetEntryCount(); ++i )
919 delete (SvtContentEntry*)GetEntry(i)->GetUserData();
920 Clear();
923 // -----------------------------------------------------------------------
924 void ViewTabListBox_Impl::DeleteEntries()
926 svtools::QueryDeleteResult_Impl eResult = svtools::QUERYDELETE_YES;
927 SvLBoxEntry* pEntry = FirstSelected();
928 String aURL;
930 ByteString sDialogPosition;
931 while ( pEntry && ( eResult != svtools::QUERYDELETE_CANCEL ) )
933 SvLBoxEntry *pCurEntry = pEntry;
934 pEntry = NextSelected( pEntry );
936 if ( pCurEntry->GetUserData() )
937 aURL = ( (SvtContentEntry*)pCurEntry->GetUserData() )->maURL;
939 if ( !aURL.Len() )
940 return;
942 INetURLObject aObj( aURL );
944 if ( eResult != svtools::QUERYDELETE_ALL )
946 svtools::QueryDeleteDlg_Impl aDlg( NULL, aObj.GetName( INetURLObject::DECODE_WITH_CHARSET ) );
947 if ( sDialogPosition.Len() )
948 aDlg.SetWindowState( sDialogPosition );
950 if ( GetSelectionCount() > 1 )
951 aDlg.EnableAllButton();
953 if ( aDlg.Execute() == RET_OK )
954 eResult = aDlg.GetResult();
955 else
956 eResult = svtools::QUERYDELETE_CANCEL;
958 sDialogPosition = aDlg.GetWindowState( );
961 if ( ( eResult == svtools::QUERYDELETE_ALL ) ||
962 ( eResult == svtools::QUERYDELETE_YES ) )
964 if ( Kill( aURL ) )
966 delete (SvtContentEntry*)pCurEntry->GetUserData();
967 GetModel()->Remove( pCurEntry );
968 mpParent->EntryRemoved( aURL );
974 // -----------------------------------------------------------------------
975 BOOL ViewTabListBox_Impl::EditedEntry( SvLBoxEntry* pEntry,
976 const XubString& rNewText )
978 BOOL bRet = FALSE;
980 OUString aURL;
981 SvtContentEntry* pData = (SvtContentEntry*)pEntry->GetUserData();
983 if ( pData )
984 aURL = OUString( pData->maURL );
986 if ( ! aURL.getLength() )
987 return bRet;
991 ::ucbhelper::Content aContent( aURL, mxCmdEnv );
993 OUString aPropName = OUString::createFromAscii( "Title" );
994 Any aValue;
995 aValue <<= OUString( rNewText );
996 aContent.setPropertyValue( aPropName, aValue );
997 mpParent->EntryRenamed( aURL, rNewText );
999 pData->maURL = aURL;
1000 pEntry->SetUserData( pData );
1002 bRet = TRUE;
1004 catch( ::com::sun::star::ucb::ContentCreationException ) {}
1005 catch( ::com::sun::star::ucb::CommandAbortedException ) {}
1006 catch( ::com::sun::star::uno::Exception ) {}
1008 return bRet;
1011 // -----------------------------------------------------------------------
1012 void ViewTabListBox_Impl::DoQuickSearch( const xub_Unicode& rChar )
1014 ::osl::MutexGuard aGuard( maMutex );
1016 maResetQuickSearch.Stop();
1018 OUString aLastText = maQuickSearchText;
1019 sal_uInt32 aLastPos = mnSearchIndex;
1020 sal_Bool bFound = sal_False;
1022 maQuickSearchText += OUString( String( rChar ) ).toAsciiLowerCase();
1024 bFound = mpParent->SearchNextEntry( mnSearchIndex, maQuickSearchText, sal_False );
1026 if ( !bFound && ( aLastText.getLength() == 1 ) &&
1027 ( aLastText == OUString( String( rChar ) ) ) )
1029 mnSearchIndex = aLastPos + 1;
1030 maQuickSearchText = aLastText;
1031 bFound = mpParent->SearchNextEntry( mnSearchIndex, maQuickSearchText, sal_True );
1034 if ( bFound )
1036 SvLBoxEntry* pEntry = GetEntry( mnSearchIndex );
1037 if ( pEntry )
1039 SelectAll( FALSE );
1040 Select( pEntry );
1041 SetCurEntry( pEntry );
1042 MakeVisible( pEntry );
1044 else
1045 bFound = sal_False;
1048 if ( !bFound )
1049 Sound::Beep();
1051 maResetQuickSearch.Start();
1054 // -----------------------------------------------------------------------
1055 BOOL ViewTabListBox_Impl::DoubleClickHdl()
1057 SvHeaderTabListBox::DoubleClickHdl();
1058 return FALSE;
1059 // this means "do no additional handling". Especially this means that the SvImpLBox does not
1060 // recognize that the entry at the double click position change after the handler call (which is
1061 // the case if in the handler, our content was replaced)
1062 // If it _would_ recognize this change, it would take this as a reason to select the entry, again
1063 // - which is not what in the case of content replace
1064 // (I really doubt that this behaviour of the SvImpLBox does make any sense at all, but
1065 // who knows ...)
1066 // 07.12.2001 - 95727 - fs@openoffice.org
1069 ::rtl::OUString ViewTabListBox_Impl::GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const
1071 ::rtl::OUString sRet = SvHeaderTabListBox::GetAccessibleObjectDescription( _eType, _nPos );
1072 if ( ::svt::BBTYPE_TABLECELL == _eType )
1074 sal_Int32 nRow = -1;
1075 const sal_uInt16 nColumnCount = GetColumnCount();
1076 if (nColumnCount > 0)
1077 nRow = _nPos / nColumnCount;
1078 SvLBoxEntry* pEntry = GetEntry( nRow );
1079 if ( pEntry )
1081 SvtContentEntry* pData = (SvtContentEntry*)pEntry->GetUserData();
1082 if ( pData )
1084 static const String sVar1( RTL_CONSTASCII_USTRINGPARAM( "%1" ) );
1085 static const String sVar2( RTL_CONSTASCII_USTRINGPARAM( "%2" ) );
1086 String aText( msAccessibleDescText );
1087 aText.SearchAndReplace( sVar1, pData->mbIsFolder ? msFolder : msFile );
1088 aText.SearchAndReplace( sVar2, pData->maURL );
1089 sRet += ::rtl::OUString( aText );
1094 return sRet;
1097 // -----------------------------------------------------------------------
1098 sal_Bool ViewTabListBox_Impl::Kill( const OUString& rContent )
1100 sal_Bool bRet = sal_True;
1104 ::ucbhelper::Content aCnt( rContent, mxCmdEnv );
1105 aCnt.executeCommand( OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) );
1107 catch( ::com::sun::star::ucb::CommandAbortedException& )
1109 DBG_WARNING( "CommandAbortedException" );
1110 bRet = sal_False;
1112 catch( ::com::sun::star::uno::Exception& )
1114 DBG_WARNING( "Any other exception" );
1115 bRet = sal_False;
1118 return bRet;
1124 // -----------------------------------------------------------------------
1125 // class SvtFileView -----------------------------------------------------
1126 // -----------------------------------------------------------------------
1128 SvtFileView::SvtFileView( Window* pParent, const ResId& rResId,
1129 sal_Bool bOnlyFolder, sal_Bool bMultiSelection ) :
1131 Control( pParent, rResId )
1133 sal_Int8 nFlags = FILEVIEW_SHOW_ALL;
1134 if ( bOnlyFolder )
1135 nFlags |= FILEVIEW_ONLYFOLDER;
1136 if ( bMultiSelection )
1137 nFlags |= FILEVIEW_MULTISELECTION;
1139 Reference< XInteractionHandler > xInteractionHandler = Reference< XInteractionHandler > (
1140 ::comphelper::getProcessServiceFactory()->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), UNO_QUERY );
1141 Reference < XCommandEnvironment > xCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() );
1143 mpImp = new SvtFileView_Impl( this, xCmdEnv, nFlags, bOnlyFolder );
1144 mpImp->mpView->ForbidEmptyText();
1145 SetSortColumn( true );
1147 long pTabs[] = { 5, 20, 180, 320, 400, 600 };
1148 mpImp->mpView->SetTabs( &pTabs[0], MAP_PIXEL );
1149 mpImp->mpView->SetTabJustify( 2, AdjustRight ); // column "Size"
1151 if ( bMultiSelection )
1152 mpImp->mpView->SetSelectionMode( MULTIPLE_SELECTION );
1154 HeaderBar* pHeaderBar = mpImp->mpView->GetHeaderBar();
1155 pHeaderBar->SetSelectHdl( LINK( this, SvtFileView, HeaderSelect_Impl ) );
1156 pHeaderBar->SetEndDragHdl( LINK( this, SvtFileView, HeaderEndDrag_Impl ) );
1159 SvtFileView::SvtFileView( Window* pParent, const ResId& rResId, sal_Int8 nFlags ) :
1161 Control( pParent, rResId )
1163 Reference< XInteractionHandler > xInteractionHandler = Reference< XInteractionHandler > (
1164 ::comphelper::getProcessServiceFactory()->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), UNO_QUERY );
1165 Reference < XCommandEnvironment > xCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() );
1166 mpImp = new SvtFileView_Impl( this, xCmdEnv, nFlags,
1167 ( nFlags & FILEVIEW_ONLYFOLDER ) == FILEVIEW_ONLYFOLDER );
1168 SetSortColumn( true );
1170 if ( ( nFlags & FILEVIEW_SHOW_ALL ) == FILEVIEW_SHOW_ALL )
1172 long pTabs[] = { 5, 20, 180, 320, 400, 600 };
1173 mpImp->mpView->SetTabs( &pTabs[0], MAP_PIXEL );
1174 mpImp->mpView->SetTabJustify( 2, AdjustRight ); // column "Size"
1176 else
1178 // show only title
1179 long pTabs[] = { 2, 20, 600 };
1180 mpImp->mpView->SetTabs( &pTabs[0], MAP_PIXEL );
1182 if ( ( nFlags & FILEVIEW_SHOW_NONE ) == FILEVIEW_SHOW_NONE )
1183 SetSortColumn( false );
1184 if ( ( nFlags & FILEVIEW_MULTISELECTION ) == FILEVIEW_MULTISELECTION )
1185 mpImp->mpView->SetSelectionMode( MULTIPLE_SELECTION );
1187 HeaderBar *pHeaderBar = mpImp->mpView->GetHeaderBar();
1188 pHeaderBar->SetSelectHdl( LINK( this, SvtFileView, HeaderSelect_Impl ) );
1189 pHeaderBar->SetEndDragHdl( LINK( this, SvtFileView, HeaderEndDrag_Impl ) );
1192 // -----------------------------------------------------------------------
1194 SvtFileView::~SvtFileView()
1196 // use temp pointer to prevent access of deleted member (GetFocus())
1197 SvtFileView_Impl* pTemp = mpImp;
1198 mpImp = NULL;
1199 delete pTemp;
1202 // -----------------------------------------------------------------------
1204 void SvtFileView::OpenFolder( const Sequence< OUString >& aContents )
1206 mpImp->mpView->ClearAll();
1207 const OUString* pFileProperties = aContents.getConstArray();
1208 UINT32 i, nCount = aContents.getLength();
1209 for ( i = 0; i < nCount; ++i )
1211 String aRow( pFileProperties[i] );
1212 // extract columns
1213 // the columns are: title, type, size, date, target url, is folder, image url
1214 String aTitle, aType, aSize, aDate, aURL, aImageURL;
1215 xub_StrLen nIdx = 0;
1216 aTitle = aRow.GetToken( 0, '\t', nIdx );
1217 aType = aRow.GetToken( 0, '\t', nIdx );
1218 aSize = aRow.GetToken( 0, '\t', nIdx );
1219 aDate = aRow.GetToken( 0, '\t', nIdx );
1220 aURL = aRow.GetToken( 0, '\t', nIdx );
1221 sal_Unicode cFolder = aRow.GetToken( 0, '\t', nIdx ).GetChar(0);
1222 sal_Bool bIsFolder = ( '1' == cFolder );
1223 if ( nIdx != STRING_NOTFOUND )
1224 aImageURL = aRow.GetToken( 0, '\t', nIdx );
1226 if ( mpImp->mbOnlyFolder && !bIsFolder )
1227 continue;
1229 // build new row
1230 String aNewRow = aTitle;
1231 aNewRow += '\t';
1232 aNewRow += aType;
1233 aNewRow += '\t';
1234 aNewRow += aSize;
1235 aNewRow += '\t';
1236 aNewRow += aDate;
1237 // detect image
1238 sal_Bool bDoInsert = sal_True;
1239 INetURLObject aObj( aImageURL.Len() > 0 ? aImageURL : aURL );
1240 Image aImage = SvFileInformationManager::GetImage( aObj, FALSE, isHighContrast( this ) );
1242 if ( bDoInsert )
1244 // insert entry and set user data
1245 SvLBoxEntry* pEntry = mpImp->mpView->InsertEntry( aNewRow, aImage, aImage, NULL );
1246 SvtContentEntry* pUserData = new SvtContentEntry( aURL, bIsFolder );
1247 pEntry->SetUserData( pUserData );
1251 mpImp->InitSelection();
1252 mpImp->ResetCursor();
1255 // -----------------------------------------------------------------------
1257 String SvtFileView::GetURL( SvLBoxEntry* pEntry ) const
1259 String aURL;
1260 if ( pEntry && pEntry->GetUserData() )
1261 aURL = ( (SvtContentEntry*)pEntry->GetUserData() )->maURL;
1262 return aURL;
1265 // -----------------------------------------------------------------------
1267 String SvtFileView::GetCurrentURL() const
1269 String aURL;
1270 SvLBoxEntry* pEntry = mpImp->mpView->FirstSelected();
1271 if ( pEntry && pEntry->GetUserData() )
1272 aURL = ( (SvtContentEntry*)pEntry->GetUserData() )->maURL;
1273 return aURL;
1275 // -----------------------------------------------------------------------------
1277 sal_Bool SvtFileView::CreateNewFolder( const String& rNewFolder )
1279 sal_Bool bRet = sal_False;
1280 INetURLObject aObj( mpImp->maViewURL );
1281 aObj.insertName( rNewFolder, false, INetURLObject::LAST_SEGMENT, true, INetURLObject::ENCODE_ALL );
1282 String sURL = aObj.GetMainURL( INetURLObject::NO_DECODE );
1283 if ( ::utl::UCBContentHelper::MakeFolder( sURL, sal_True ) )
1285 String sTitle = aObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
1286 String sEntry = mpImp->FolderInserted( sURL, sTitle );
1287 SvLBoxEntry* pEntry = mpImp->mpView->InsertEntry( sEntry, mpImp->maFolderImage, mpImp->maFolderImage );
1288 SvtContentEntry* pUserData = new SvtContentEntry( sURL, TRUE );
1289 pEntry->SetUserData( pUserData );
1290 mpImp->mpView->MakeVisible( pEntry );
1291 bRet = sal_True;
1293 return bRet;
1296 // -----------------------------------------------------------------------
1298 FileViewResult SvtFileView::PreviousLevel( const FileViewAsyncAction* pAsyncDescriptor )
1300 FileViewResult eResult = eFailure;
1302 String sParentURL;
1303 if ( GetParentURL( sParentURL ) )
1304 eResult = Initialize( sParentURL, mpImp->maCurrentFilter, pAsyncDescriptor, mpBlackList );
1306 return eResult;
1309 // -----------------------------------------------------------------------
1311 sal_Bool SvtFileView::GetParentURL( String& rParentURL ) const
1313 sal_Bool bRet = sal_False;
1316 ::ucbhelper::Content aCnt( mpImp->maViewURL, mpImp->mxCmdEnv );
1317 Reference< XContent > xContent( aCnt.get() );
1318 Reference< com::sun::star::container::XChild > xChild( xContent, UNO_QUERY );
1319 if ( xChild.is() )
1321 Reference< XContent > xParent( xChild->getParent(), UNO_QUERY );
1322 if ( xParent.is() )
1324 rParentURL = String( xParent->getIdentifier()->getContentIdentifier() );
1325 bRet = ( rParentURL.Len() > 0 && rParentURL != mpImp->maViewURL );
1329 catch( ::com::sun::star::uno::Exception )
1331 // perhaps an unkown url protocol (e.g. "private:newdoc")
1334 return bRet;
1337 // -----------------------------------------------------------------------
1339 sal_uInt32 SvtFileView::GetHelpId( ) const
1341 return mpImp->mpView->GetHelpId( );
1344 // -----------------------------------------------------------------------
1346 void SvtFileView::SetHelpId( sal_uInt32 nHelpId )
1348 mpImp->mpView->SetHelpId( nHelpId );
1351 // -----------------------------------------------------------------------
1353 void SvtFileView::SetSizePixel( const Size& rNewSize )
1355 Control::SetSizePixel( rNewSize );
1356 mpImp->mpView->SetSizePixel( rNewSize );
1359 // -----------------------------------------------------------------------
1361 void SvtFileView::SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
1363 SetPosPixel( rNewPos );
1364 SetSizePixel( rNewSize );
1367 // -----------------------------------------------------------------------------
1368 sal_Bool SvtFileView::Initialize( const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent>& _xContent, const String& rFilter )
1370 WaitObject aWaitCursor( this );
1372 mpImp->Clear();
1373 ::ucbhelper::Content aContent(_xContent, mpImp->mxCmdEnv );
1374 FileViewResult eResult = mpImp->GetFolderContent_Impl( FolderDescriptor( aContent ), NULL );
1375 OSL_ENSURE( eResult != eStillRunning, "SvtFileView::Initialize: this was expected to be synchronous!" );
1376 if ( eResult != eSuccess )
1377 return sal_False;
1379 mpImp->FilterFolderContent_Impl( rFilter );
1381 mpImp->SortFolderContent_Impl(); // possibly not necessary!!!!!!!!!!
1382 mpImp->CreateDisplayText_Impl();
1383 mpImp->OpenFolder_Impl();
1385 mpImp->maOpenDoneLink.Call( this );
1386 return sal_True;
1389 // -----------------------------------------------------------------------
1390 FileViewResult SvtFileView::Initialize(
1391 const String& rURL,
1392 const String& rFilter,
1393 const FileViewAsyncAction* pAsyncDescriptor,
1394 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList )
1396 WaitObject aWaitCursor( this );
1397 mpBlackList = rBlackList;
1399 String sPushURL( mpImp->maViewURL );
1401 mpImp->maViewURL = rURL;
1402 FileViewResult eResult = ExecuteFilter( rFilter, pAsyncDescriptor );
1403 switch ( eResult )
1405 case eFailure:
1406 case eTimeout:
1407 mpImp->maViewURL = sPushURL;
1408 return eResult;
1410 case eStillRunning:
1411 OSL_ENSURE( pAsyncDescriptor, "SvtFileView::Initialize: we told it to read synchronously!" );
1412 case eSuccess:
1413 return eResult;
1416 OSL_ENSURE( sal_False, "SvtFileView::Initialize: unreachable!" );
1417 return eFailure;
1420 // -----------------------------------------------------------------------
1421 FileViewResult SvtFileView::Initialize(
1422 const String& rURL,
1423 const String& rFilter,
1424 const FileViewAsyncAction* pAsyncDescriptor )
1426 return Initialize( rURL, rFilter, pAsyncDescriptor, ::com::sun::star::uno::Sequence< ::rtl::OUString >());
1429 // -----------------------------------------------------------------------
1431 // -----------------------------------------------------------------------
1432 sal_Bool SvtFileView::Initialize( const Sequence< OUString >& aContents )
1434 WaitObject aWaitCursor( this );
1436 mpImp->maViewURL = String();
1437 mpImp->maCurrentFilter = mpImp->maAllFilter;
1439 mpImp->Clear();
1440 mpImp->CreateVector_Impl( aContents );
1441 if( GetSortColumn() )
1442 mpImp->SortFolderContent_Impl();
1444 mpImp->OpenFolder_Impl();
1446 mpImp->maOpenDoneLink.Call( this );
1448 return sal_True;
1451 // -----------------------------------------------------------------------
1453 FileViewResult SvtFileView::ExecuteFilter( const String& rFilter, const FileViewAsyncAction* pAsyncDescriptor )
1455 mpImp->maCurrentFilter = rFilter;
1456 mpImp->maCurrentFilter.ToLowerAscii();
1458 mpImp->Clear();
1459 FileViewResult eResult = mpImp->GetFolderContent_Impl( mpImp->maViewURL, pAsyncDescriptor, mpBlackList );
1460 OSL_ENSURE( ( eResult != eStillRunning ) || pAsyncDescriptor, "SvtFileView::ExecuteFilter: we told it to read synchronously!" );
1461 return eResult;
1464 // -----------------------------------------------------------------------
1466 void SvtFileView::CancelRunningAsyncAction()
1468 mpImp->CancelRunningAsyncAction();
1471 // -----------------------------------------------------------------------
1473 void SvtFileView::SetNoSelection()
1475 mpImp->mpView->SelectAll( FALSE );
1478 // -----------------------------------------------------------------------
1480 void SvtFileView::GetFocus()
1482 Control::GetFocus();
1483 if ( mpImp && mpImp->mpView )
1484 mpImp->mpView->GrabFocus();
1487 // -----------------------------------------------------------------------
1489 void SvtFileView::ResetCursor()
1491 mpImp->ResetCursor();
1494 // -----------------------------------------------------------------------
1496 void SvtFileView::SetSelectHdl( const Link& rHdl )
1498 mpImp->SetSelectHandler( rHdl );
1501 // -----------------------------------------------------------------------
1503 void SvtFileView::SetDoubleClickHdl( const Link& rHdl )
1505 mpImp->mpView->SetDoubleClickHdl( rHdl );
1508 // -----------------------------------------------------------------------
1510 ULONG SvtFileView::GetSelectionCount() const
1512 return mpImp->mpView->GetSelectionCount();
1515 // -----------------------------------------------------------------------
1517 SvLBoxEntry* SvtFileView::FirstSelected() const
1519 return mpImp->mpView->FirstSelected();
1522 // -----------------------------------------------------------------------
1524 SvLBoxEntry* SvtFileView::NextSelected( SvLBoxEntry* pEntry ) const
1526 return mpImp->mpView->NextSelected( pEntry );
1529 // -----------------------------------------------------------------------
1531 void SvtFileView::EnableAutoResize()
1533 mpImp->mpView->EnableAutoResize();
1536 // -----------------------------------------------------------------------
1538 void SvtFileView::SetFocus()
1540 mpImp->mpView->GrabFocus();
1543 // -----------------------------------------------------------------------
1544 const String& SvtFileView::GetViewURL() const
1546 return mpImp->maViewURL;
1549 // -----------------------------------------------------------------------
1550 void SvtFileView::SetOpenDoneHdl( const Link& rHdl )
1552 mpImp->maOpenDoneLink = rHdl;
1555 // -----------------------------------------------------------------------
1556 void SvtFileView::EnableContextMenu( sal_Bool bEnable )
1558 mpImp->EnableContextMenu( bEnable );
1561 // -----------------------------------------------------------------------
1562 void SvtFileView::EnableDelete( sal_Bool bEnable )
1564 mpImp->EnableDelete( bEnable );
1567 void SvtFileView::EnableNameReplacing( sal_Bool bEnable )
1569 mpImp->EnableNameReplacing( bEnable );
1572 // -----------------------------------------------------------------------
1573 void SvtFileView::EndInplaceEditing( bool _bCancel )
1575 return mpImp->EndEditing( _bCancel );
1578 // -----------------------------------------------------------------------
1579 IMPL_LINK( SvtFileView, HeaderSelect_Impl, HeaderBar*, pBar )
1581 DBG_ASSERT( pBar, "no headerbar" );
1582 USHORT nItemID = pBar->GetCurItemId();
1584 HeaderBarItemBits nBits;
1586 // clear the arrow of the recently used column
1587 if ( nItemID != mpImp->mnSortColumn )
1589 if ( !nItemID )
1591 // first call -> remove arrow from title column,
1592 // because another column is the sort column
1593 nItemID = mpImp->mnSortColumn;
1594 mpImp->mnSortColumn = COLUMN_TITLE;
1596 nBits = pBar->GetItemBits( mpImp->mnSortColumn );
1597 nBits &= ~( HIB_UPARROW | HIB_DOWNARROW );
1598 pBar->SetItemBits( mpImp->mnSortColumn, nBits );
1601 nBits = pBar->GetItemBits( nItemID );
1603 BOOL bUp = ( ( nBits & HIB_UPARROW ) == HIB_UPARROW );
1605 if ( bUp )
1607 nBits &= ~HIB_UPARROW;
1608 nBits |= HIB_DOWNARROW;
1610 else
1612 nBits &= ~HIB_DOWNARROW;
1613 nBits |= HIB_UPARROW;
1616 pBar->SetItemBits( nItemID, nBits );
1617 mpImp->Resort_Impl( nItemID, !bUp );
1618 return 1;
1621 // -----------------------------------------------------------------------
1622 IMPL_LINK( SvtFileView, HeaderEndDrag_Impl, HeaderBar*, pBar )
1624 if ( !pBar->IsItemMode() )
1626 Size aSize;
1627 USHORT nTabs = pBar->GetItemCount();
1628 long nTmpSize = 0;
1630 for ( USHORT i = 1; i <= nTabs; ++i )
1632 long nWidth = pBar->GetItemSize(i);
1633 aSize.Width() = nWidth + nTmpSize;
1634 nTmpSize += nWidth;
1635 mpImp->mpView->SetTab( i, aSize.Width(), MAP_PIXEL );
1639 return 0;
1642 // -----------------------------------------------------------------------
1643 String SvtFileView::GetConfigString() const
1645 String sRet;
1646 HeaderBar* pBar = mpImp->mpView->GetHeaderBar();
1647 DBG_ASSERT( pBar, "invalid headerbar" );
1649 // sort order
1650 sRet += String::CreateFromInt32( mpImp->mnSortColumn );
1651 sRet += ';';
1652 HeaderBarItemBits nBits = pBar->GetItemBits( mpImp->mnSortColumn );
1653 BOOL bUp = ( ( nBits & HIB_UPARROW ) == HIB_UPARROW );
1654 sRet += bUp ? '1' : '0';
1655 sRet += ';';
1657 USHORT nCount = pBar->GetItemCount();
1658 for ( USHORT i = 0; i < nCount; ++i )
1660 USHORT nId = pBar->GetItemId(i);
1661 sRet += String::CreateFromInt32( nId );
1662 sRet += ';';
1663 sRet += String::CreateFromInt32( pBar->GetItemSize( nId ) );
1664 sRet += ';';
1667 sRet.EraseTrailingChars( ';' );
1668 return sRet;
1671 // -----------------------------------------------------------------------
1672 void SvtFileView::SetConfigString( const String& rCfgStr )
1674 HeaderBar* pBar = mpImp->mpView->GetHeaderBar();
1675 DBG_ASSERT( pBar, "invalid headerbar" );
1677 USHORT nIdx = 0;
1678 mpImp->mnSortColumn = (USHORT)rCfgStr.GetToken( 0, ';', nIdx ).ToInt32();
1679 BOOL bUp = (BOOL)(USHORT)rCfgStr.GetToken( 0, ';', nIdx ).ToInt32();
1680 HeaderBarItemBits nBits = pBar->GetItemBits( mpImp->mnSortColumn );
1682 if ( bUp )
1684 nBits &= ~HIB_UPARROW;
1685 nBits |= HIB_DOWNARROW;
1687 else
1689 nBits &= ~HIB_DOWNARROW;
1690 nBits |= HIB_UPARROW;
1692 pBar->SetItemBits( mpImp->mnSortColumn, nBits );
1694 while ( nIdx != STRING_NOTFOUND )
1696 USHORT nItemId = (USHORT)rCfgStr.GetToken( 0, ';', nIdx ).ToInt32();
1697 pBar->SetItemSize( nItemId, rCfgStr.GetToken( 0, ';', nIdx ).ToInt32() );
1700 HeaderSelect_Impl( pBar );
1701 HeaderEndDrag_Impl( pBar );
1704 // -----------------------------------------------------------------------
1705 void SvtFileView::SetUrlFilter( const IUrlFilter* _pFilter )
1707 mpImp->mpUrlFilter = _pFilter;
1710 // -----------------------------------------------------------------------
1711 const IUrlFilter* SvtFileView::GetUrlFilter( ) const
1713 return mpImp->mpUrlFilter;
1716 // -----------------------------------------------------------------------
1717 void SvtFileView::StateChanged( StateChangedType nStateChange )
1719 if ( nStateChange == STATE_CHANGE_ENABLE )
1720 Invalidate();
1721 Control::StateChanged( nStateChange );
1724 // -----------------------------------------------------------------------
1725 // class NameTranslator_Impl
1726 // -----------------------------------------------------------------------
1728 NameTranslator_Impl::NameTranslator_Impl( void ) :
1729 mpActFolder( NULL )
1733 NameTranslator_Impl::NameTranslator_Impl( const INetURLObject& rActualFolder )
1735 mpActFolder = new NameTranslationList( rActualFolder );
1738 NameTranslator_Impl::~NameTranslator_Impl()
1740 if( mpActFolder )
1741 delete mpActFolder;
1744 void NameTranslator_Impl::UpdateTranslationTable()
1746 if( mpActFolder )
1747 mpActFolder->Update();
1750 void NameTranslator_Impl::SetActualFolder( const INetURLObject& rActualFolder )
1752 HashedEntry aActFolder( rActualFolder );
1754 if( mpActFolder )
1756 if( *mpActFolder != aActFolder )
1758 delete mpActFolder;
1759 mpActFolder = new NameTranslationList( rActualFolder );
1762 else
1763 mpActFolder = new NameTranslationList( rActualFolder );
1766 sal_Bool NameTranslator_Impl::GetTranslation( const OUString& rOrg, OUString& rTrans ) const
1768 sal_Bool bRet = sal_False;
1770 if( mpActFolder )
1772 const OUString* pTrans = mpActFolder->Translate( rOrg );
1773 if( pTrans )
1775 rTrans = *pTrans;
1776 bRet = sal_True;
1780 return bRet;
1783 const String* NameTranslator_Impl::GetTransTableFileName() const
1785 return mpActFolder? &mpActFolder->GetTransTableFileName() : NULL;
1788 // -----------------------------------------------------------------------
1789 // class SvtFileView_Impl
1790 // -----------------------------------------------------------------------
1792 SvtFileView_Impl::SvtFileView_Impl( SvtFileView* pAntiImpl, Reference < XCommandEnvironment > xEnv, sal_Int16 nFlags, sal_Bool bOnlyFolder )
1794 :mpAntiImpl ( pAntiImpl )
1795 ,m_eAsyncActionResult ( ::svt::ERROR )
1796 ,m_bRunningAsyncAction ( false )
1797 ,m_bAsyncActionCancelled ( false )
1798 ,mpNameTrans ( NULL )
1799 ,mpUrlFilter ( NULL )
1800 ,mnSortColumn ( COLUMN_TITLE )
1801 ,mbAscending ( sal_True )
1802 ,mbOnlyFolder ( bOnlyFolder )
1803 ,mbReplaceNames ( sal_False )
1804 ,mnSuspendSelectCallback ( 0 )
1805 ,mbIsFirstResort ( sal_True )
1806 ,aIntlWrapper ( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() )
1807 ,maFolderImage ( SvtResId( IMG_SVT_FOLDER ) )
1808 ,mxCmdEnv ( xEnv )
1811 maAllFilter = String::CreateFromAscii( "*.*" );
1812 mpView = new ViewTabListBox_Impl( mpAntiImpl, this, nFlags );
1813 mpView->EnableCellFocus();
1816 // -----------------------------------------------------------------------
1817 SvtFileView_Impl::~SvtFileView_Impl()
1819 Clear();
1821 // use temp pointer to prevent access of deleted member (GetFocus())
1822 ViewTabListBox_Impl* pTemp = mpView;
1823 mpView = NULL;
1824 delete pTemp;
1827 // -----------------------------------------------------------------------
1828 void SvtFileView_Impl::Clear()
1830 ::osl::MutexGuard aGuard( maMutex );
1832 std::vector< SortingData_Impl* >::iterator aIt;
1834 for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
1835 delete (*aIt);
1837 maContent.clear();
1839 if( mpNameTrans )
1840 DELETEZ( mpNameTrans );
1843 // -----------------------------------------------------------------------
1844 FileViewResult SvtFileView_Impl::GetFolderContent_Impl(
1845 const String& rFolder,
1846 const FileViewAsyncAction* pAsyncDescriptor,
1847 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList )
1849 ::osl::ClearableMutexGuard aGuard( maMutex );
1850 INetURLObject aFolderObj( rFolder );
1851 DBG_ASSERT( aFolderObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
1853 // prepare name translation
1854 SetActualFolder( aFolderObj );
1856 FolderDescriptor aFolder( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ) );
1858 aGuard.clear();
1859 return GetFolderContent_Impl( aFolder, pAsyncDescriptor, rBlackList );
1862 // -----------------------------------------------------------------------
1863 FileViewResult SvtFileView_Impl::GetFolderContent_Impl(
1864 const FolderDescriptor& _rFolder,
1865 const FileViewAsyncAction* pAsyncDescriptor,
1866 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList )
1868 DBG_TESTSOLARMUTEX();
1869 ::osl::ClearableMutexGuard aGuard( maMutex );
1871 OSL_ENSURE( !m_pContentEnumerator.is(), "SvtFileView_Impl::GetFolderContent_Impl: still running another enumeration!" );
1872 m_pContentEnumerator = new ::svt::FileViewContentEnumerator(
1873 mpView->GetCommandEnvironment(), maContent, maMutex, mbReplaceNames ? mpNameTrans : NULL );
1874 // TODO: should we cache and re-use this thread?
1876 if ( !pAsyncDescriptor )
1878 ::svt::EnumerationResult eResult = m_pContentEnumerator->enumerateFolderContentSync( _rFolder, mpUrlFilter, rBlackList );
1879 if ( ::svt::SUCCESS == eResult )
1881 implEnumerationSuccess();
1882 m_pContentEnumerator = NULL;
1883 return eSuccess;
1885 m_pContentEnumerator = NULL;
1886 return eFailure;
1889 m_bRunningAsyncAction = true;
1890 m_bAsyncActionCancelled = false;
1891 m_eAsyncActionResult = ::svt::ERROR;
1892 m_aAsyncActionFinished.reset();
1894 // don't (yet) set m_aCurrentAsyncActionHandler to pTimeout->aFinishHandler.
1895 // By definition, this handler *only* get's called when the result cannot be obtained
1896 // during the minimum wait time, so it is only set below, when needed.
1897 m_aCurrentAsyncActionHandler = Link();
1899 // minimum time to wait
1900 ::std::auto_ptr< TimeValue > pTimeout( new TimeValue );
1901 sal_Int32 nMinTimeout = pAsyncDescriptor->nMinTimeout;
1902 OSL_ENSURE( nMinTimeout > 0, "SvtFileView_Impl::GetFolderContent_Impl: invalid minimum timeout!" );
1903 if ( nMinTimeout <= 0 )
1904 nMinTimeout = sal_Int32( 1000L );
1905 pTimeout->Seconds = nMinTimeout / 1000L;
1906 pTimeout->Nanosec = ( nMinTimeout % 1000L ) * 1000000L;
1908 m_pContentEnumerator->enumerateFolderContent( _rFolder, mpUrlFilter, this );
1910 // wait until the enumeration is finished
1911 // for this, release our own mutex (which is used by the enumerator thread)
1912 aGuard.clear();
1914 ::osl::Condition::Result eResult = ::osl::Condition::result_ok;
1916 // also release the SolarMutex. Not all code which is needed during the enumeration
1917 // is Solar-Thread-Safe, in particular there is some code which needs to access
1918 // string resources (and our resource system relies on the SolarMutex :()
1919 ReleaseSolarMutex aSolarRelease;
1921 // now wait. Note that if we didn't get an pAsyncDescriptor, then this is an infinite wait.
1922 eResult = m_aAsyncActionFinished.wait( pTimeout.get() );
1925 ::osl::MutexGuard aGuard2( maMutex );
1926 if ( ::osl::Condition::result_timeout == eResult )
1928 // maximum time to wait
1929 OSL_ENSURE( !m_pCancelAsyncTimer.get(), "SvtFileView_Impl::GetFolderContent_Impl: there's still a previous timer!" );
1930 m_pCancelAsyncTimer = new CallbackTimer( this );
1931 sal_Int32 nMaxTimeout = pAsyncDescriptor->nMaxTimeout;
1932 OSL_ENSURE( nMaxTimeout > nMinTimeout,
1933 "SvtFileView_Impl::GetFolderContent_Impl: invalid maximum timeout!" );
1934 if ( nMaxTimeout <= nMinTimeout )
1935 nMaxTimeout = nMinTimeout + 5000;
1936 m_pCancelAsyncTimer->setRemainingTime( TTimeValue( nMaxTimeout - nMinTimeout ) );
1937 // we already waited for nMinTimeout milliseconds, so take this into account
1938 m_pCancelAsyncTimer->start();
1940 m_aCurrentAsyncActionHandler = pAsyncDescriptor->aFinishHandler;
1941 DBG_ASSERT( m_aCurrentAsyncActionHandler.IsSet(), "SvtFileView_Impl::GetFolderContent_Impl: nobody interested when it's finished?" );
1942 mpView->ClearAll();
1943 return eStillRunning;
1946 m_bRunningAsyncAction = false;
1947 switch ( m_eAsyncActionResult )
1949 case ::svt::SUCCESS:
1950 return eSuccess;
1952 case ::svt::ERROR:
1953 return eFailure;
1955 case ::svt::RUNNING:
1956 return eStillRunning;
1959 DBG_ERRORFILE( "SvtFileView_Impl::GetFolderContent_Impl: unreachable!" );
1960 return eFailure;
1963 // -----------------------------------------------------------------------
1964 void SvtFileView_Impl::FilterFolderContent_Impl( const OUString &rFilter )
1966 sal_Bool bHideTransFile = mbReplaceNames && mpNameTrans;
1968 String sHideEntry;
1969 if( bHideTransFile )
1971 const String* pTransTableFileName = mpNameTrans->GetTransTableFileName();
1972 if( pTransTableFileName )
1974 sHideEntry = *pTransTableFileName;
1975 sHideEntry.ToUpperAscii();
1977 else
1978 bHideTransFile = sal_False;
1981 if ( !bHideTransFile &&
1982 ( !rFilter.getLength() || ( rFilter.compareToAscii( ALL_FILES_FILTER ) == COMPARE_EQUAL ) ) )
1983 // when replacing names, there is always something to filter (no view of ".nametranslation.table")
1984 return;
1986 ::osl::MutexGuard aGuard( maMutex );
1988 if ( maContent.empty() )
1989 return;
1991 // count (estimate) the number of filter tokens
1992 sal_Int32 nTokens=0;
1993 const sal_Unicode* pStart = rFilter.getStr();
1994 const sal_Unicode* pEnd = pStart + rFilter.getLength();
1995 while ( pStart != pEnd )
1996 if ( *pStart++ == ';' )
1997 ++nTokens;
1999 // collect the filter tokens
2000 ::std::vector< WildCard > aFilters;
2001 FilterMatch::createWildCardFilterList(rFilter,aFilters);
2004 // do the filtering
2005 ::std::vector< SortingData_Impl* >::iterator aContentLoop = maContent.begin();
2006 String sCompareString;
2009 if ( (*aContentLoop)->mbIsFolder )
2010 ++aContentLoop;
2011 else
2013 // normalize the content title (we always match case-insensitive)
2014 // 91872 - 11.09.2001 - frank.schoenheit@sun.com
2015 sCompareString = (*aContentLoop)->GetFileName(); // filter works on file name, not on title!
2016 sal_Bool bDelete;
2018 if( bHideTransFile && sCompareString == sHideEntry )
2019 bDelete = sal_True;
2020 else
2022 // search for the first filter which matches
2023 ::std::vector< WildCard >::const_iterator pMatchingFilter =
2024 ::std::find_if(
2025 aFilters.begin(),
2026 aFilters.end(),
2027 FilterMatch( sCompareString )
2030 bDelete = aFilters.end() == pMatchingFilter;
2033 if( bDelete )
2035 // none of the filters did match
2036 delete (*aContentLoop);
2038 if ( maContent.begin() == aContentLoop )
2040 maContent.erase( aContentLoop );
2041 aContentLoop = maContent.begin();
2043 else
2045 std::vector< SortingData_Impl* >::iterator aDelete = aContentLoop;
2046 --aContentLoop; // move the iterator to a position which is not invalidated by the erase
2047 maContent.erase( aDelete );
2048 ++aContentLoop; // this is now the next one ....
2051 else
2052 ++aContentLoop;
2055 while ( aContentLoop != maContent.end() );
2058 // -----------------------------------------------------------------------
2059 IMPL_LINK( SvtFileView_Impl, SelectionMultiplexer, void*, _pSource )
2061 return mnSuspendSelectCallback ? 0L : m_aSelectHandler.Call( _pSource );
2064 // -----------------------------------------------------------------------
2065 void SvtFileView_Impl::SetSelectHandler( const Link& _rHdl )
2067 m_aSelectHandler = _rHdl;
2069 Link aMasterHandler;
2070 if ( m_aSelectHandler.IsSet() )
2071 aMasterHandler = LINK( this, SvtFileView_Impl, SelectionMultiplexer );
2073 mpView->SetSelectHdl( aMasterHandler );
2076 // -----------------------------------------------------------------------
2077 void SvtFileView_Impl::InitSelection()
2079 mpView->SelectAll( sal_False );
2080 SvLBoxEntry* pFirst = mpView->First();
2081 if ( pFirst )
2082 mpView->SetCursor( pFirst, sal_True );
2085 // -----------------------------------------------------------------------
2086 void SvtFileView_Impl::OpenFolder_Impl()
2088 ::osl::MutexGuard aGuard( maMutex );
2090 mpView->SetUpdateMode( FALSE );
2091 mpView->ClearAll();
2093 std::vector< SortingData_Impl* >::iterator aIt;
2095 for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
2097 if ( mbOnlyFolder && ! (*aIt)->mbIsFolder )
2098 continue;
2100 // insert entry and set user data
2101 SvLBoxEntry* pEntry = mpView->InsertEntry( (*aIt)->maDisplayText,
2102 (*aIt)->maImage,
2103 (*aIt)->maImage );
2105 SvtContentEntry* pUserData = new SvtContentEntry( (*aIt)->maTargetURL,
2106 (*aIt)->mbIsFolder );
2107 pEntry->SetUserData( pUserData );
2110 InitSelection();
2112 ++mnSuspendSelectCallback;
2113 mpView->SetUpdateMode( TRUE );
2114 --mnSuspendSelectCallback;
2116 ResetCursor();
2119 // -----------------------------------------------------------------------
2120 void SvtFileView_Impl::ResetCursor()
2122 // deselect
2123 SvLBoxEntry* pEntry = mpView->FirstSelected();
2124 if ( pEntry )
2125 mpView->Select( pEntry, FALSE );
2126 // set cursor to the first entry
2127 mpView->SetCursor( mpView->First(), TRUE );
2128 mpView->Update();
2131 // -----------------------------------------------------------------------
2132 void SvtFileView_Impl::CancelRunningAsyncAction()
2134 DBG_TESTSOLARMUTEX();
2135 ::osl::MutexGuard aGuard( maMutex );
2136 if ( !m_pContentEnumerator.is() )
2137 return;
2139 m_bAsyncActionCancelled = true;
2140 m_pContentEnumerator->cancel();
2141 m_bRunningAsyncAction = false;
2143 m_pContentEnumerator = NULL;
2144 if ( m_pCancelAsyncTimer.is() && m_pCancelAsyncTimer->isTicking() )
2145 m_pCancelAsyncTimer->stop();
2146 m_pCancelAsyncTimer = NULL;
2149 //-----------------------------------------------------------------------
2150 void SvtFileView_Impl::onTimeout( CallbackTimer* )
2152 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
2153 ::osl::MutexGuard aGuard( maMutex );
2154 if ( !m_bRunningAsyncAction )
2155 // there might have been a race condition while we waited for the mutex
2156 return;
2158 CancelRunningAsyncAction();
2160 if ( m_aCurrentAsyncActionHandler.IsSet() )
2162 Application::PostUserEvent( m_aCurrentAsyncActionHandler, reinterpret_cast< void* >( eTimeout ) );
2163 m_aCurrentAsyncActionHandler = Link();
2167 //-----------------------------------------------------------------------
2168 void SvtFileView_Impl::enumerationDone( ::svt::EnumerationResult _eResult )
2170 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
2171 ::osl::MutexGuard aGuard( maMutex );
2173 m_pContentEnumerator = NULL;
2174 if ( m_pCancelAsyncTimer.is() && m_pCancelAsyncTimer->isTicking() )
2175 m_pCancelAsyncTimer->stop();
2176 m_pCancelAsyncTimer = NULL;
2178 if ( m_bAsyncActionCancelled )
2179 // this is to prevent race conditions
2180 return;
2182 m_eAsyncActionResult = _eResult;
2183 m_bRunningAsyncAction = false;
2185 m_aAsyncActionFinished.set();
2187 if ( svt::SUCCESS == _eResult )
2188 implEnumerationSuccess();
2190 if ( m_aCurrentAsyncActionHandler.IsSet() )
2192 Application::PostUserEvent( m_aCurrentAsyncActionHandler, reinterpret_cast< void* >( m_eAsyncActionResult ) );
2193 m_aCurrentAsyncActionHandler = Link();
2197 //-----------------------------------------------------------------------
2198 void SvtFileView_Impl::implEnumerationSuccess()
2200 FilterFolderContent_Impl( maCurrentFilter );
2201 SortFolderContent_Impl();
2202 CreateDisplayText_Impl();
2203 OpenFolder_Impl();
2204 maOpenDoneLink.Call( mpAntiImpl );
2207 // -----------------------------------------------------------------------
2208 void SvtFileView_Impl::ReplaceTabWithString( OUString& aValue )
2210 OUString aTab = OUString::createFromAscii( "\t" );
2211 OUString aTabString = OUString::createFromAscii( "%09" );
2212 sal_Int32 iPos;
2214 while ( ( iPos = aValue.indexOf( aTab ) ) >= 0 )
2215 aValue = aValue.replaceAt( iPos, 1, aTabString );
2218 // -----------------------------------------------------------------------
2219 void SvtFileView_Impl::CreateDisplayText_Impl()
2221 ::osl::MutexGuard aGuard( maMutex );
2223 OUString aValue;
2224 OUString aTab = OUString::createFromAscii( "\t" );
2225 OUString aDateSep = OUString::createFromAscii( ", " );
2227 std::vector< SortingData_Impl* >::iterator aIt;
2229 for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
2231 // title, type, size, date
2232 aValue = (*aIt)->GetTitle();
2233 // #83004# --------------------
2234 ReplaceTabWithString( aValue );
2235 aValue += aTab;
2236 aValue += (*aIt)->maType;
2237 aValue += aTab;
2238 // folders don't have a size
2239 if ( ! (*aIt)->mbIsFolder )
2240 aValue += CreateExactSizeText_Impl( (*aIt)->maSize );
2241 aValue += aTab;
2242 // set the date, but volumes have no date
2243 if ( ! (*aIt)->mbIsFolder || ! (*aIt)->mbIsVolume )
2245 SvtSysLocale aSysLocale;
2246 const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData();
2247 aValue += rLocaleData.getDate( (*aIt)->maModDate );
2248 aValue += aDateSep;
2249 aValue += rLocaleData.getTime( (*aIt)->maModDate );
2251 (*aIt)->maDisplayText = aValue;
2253 // detect image
2254 if ( (*aIt)->mbIsFolder )
2256 ::svtools::VolumeInfo aVolInfo( (*aIt)->mbIsVolume, (*aIt)->mbIsRemote,
2257 (*aIt)->mbIsRemoveable, (*aIt)->mbIsFloppy,
2258 (*aIt)->mbIsCompactDisc );
2259 (*aIt)->maImage = SvFileInformationManager::GetFolderImage( aVolInfo, FALSE, isHighContrast( mpView ) );
2261 else
2262 (*aIt)->maImage = SvFileInformationManager::GetFileImage( INetURLObject( (*aIt)->maTargetURL ), FALSE, isHighContrast( mpView ));
2266 // -----------------------------------------------------------------------
2267 // this function converts the sequence of strings into a vector of SortingData
2268 // the string should have the form :
2269 // title \t type \t size \t date \t target url \t is folder \t image url
2271 void SvtFileView_Impl::CreateVector_Impl( const Sequence < OUString > &rList )
2273 ::osl::MutexGuard aGuard( maMutex );
2275 OUString aTab = OUString::createFromAscii( "\t" );
2277 sal_uInt32 nCount = (sal_uInt32) rList.getLength();
2279 for( sal_uInt32 i = 0; i < nCount; i++ )
2281 SortingData_Impl* pEntry = new SortingData_Impl;
2282 OUString aValue = rList[i];
2283 OUString aDisplayText;
2284 sal_Int32 nIndex = 0;
2286 // get the title
2287 pEntry->SetNewTitle( aValue.getToken( 0, '\t', nIndex ) );
2288 aDisplayText = pEntry->GetTitle();
2289 // #83004# --------------------
2290 ReplaceTabWithString( aDisplayText );
2291 aDisplayText += aTab;
2293 // get the type
2294 if ( nIndex >= 0 )
2296 pEntry->maType = aValue.getToken( 0, '\t', nIndex );
2297 aDisplayText += pEntry->maType;
2299 aDisplayText += aTab;
2301 // get the size
2302 if ( nIndex >= 0 )
2304 OUString aSize = aValue.getToken( 0, '\t', nIndex );
2305 aDisplayText += aSize;
2307 if ( aSize.getLength() )
2308 pEntry->maSize = aSize.toInt64();
2310 aDisplayText += aTab;
2312 // get the date
2313 if ( nIndex >= 0 )
2315 OUString aDate = aValue.getToken( 0, '\t', nIndex );
2316 aDisplayText += aDate;
2318 if ( aDate.getLength() )
2320 DBG_ERRORFILE( "Don't know, how to convert date" );
2321 ;// convert date string to date
2324 // get the target url
2325 if ( nIndex >= 0 )
2327 pEntry->maTargetURL = aValue.getToken( 0, '\t', nIndex );
2329 // get the size
2330 if ( nIndex >= 0 )
2332 OUString aBool = aValue.getToken( 0, '\t', nIndex );
2333 if ( aBool.getLength() )
2334 pEntry->mbIsFolder = aBool.toBoolean();
2336 // get the image url
2337 if ( nIndex >= 0 )
2339 pEntry->maImageURL = aValue.getToken( 0, '\t', nIndex );
2342 // set the display text
2343 pEntry->maDisplayText = aDisplayText;
2345 // detect the image
2346 if( aValue != rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(aSeparatorStr) ) )
2348 INetURLObject aObj( pEntry->maImageURL.getLength() ? pEntry->maImageURL : pEntry->maTargetURL );
2349 pEntry->maImage = SvFileInformationManager::GetImage( aObj, FALSE, isHighContrast( mpView ) );
2351 maContent.push_back( pEntry );
2355 // -----------------------------------------------------------------------
2356 void SvtFileView_Impl::Resort_Impl( sal_Int16 nColumn, sal_Bool bAscending )
2358 ::osl::MutexGuard aGuard( maMutex );
2360 if ( ( nColumn == mnSortColumn ) &&
2361 ( bAscending == mbAscending ) )
2362 return;
2364 // reset the quick search index
2365 mpView->ResetQuickSearch_Impl( NULL );
2367 String aEntryURL;
2368 SvLBoxEntry* pEntry = mpView->GetCurEntry();
2369 if ( pEntry && pEntry->GetUserData() )
2370 aEntryURL = ( (SvtContentEntry*)pEntry->GetUserData() )->maURL;
2372 mnSortColumn = nColumn;
2373 mbAscending = bAscending;
2375 SortFolderContent_Impl();
2376 OpenFolder_Impl();
2378 if ( !mbIsFirstResort )
2380 ULONG nPos = GetEntryPos( aEntryURL );
2381 if ( nPos < mpView->GetEntryCount() )
2383 pEntry = mpView->GetEntry( nPos );
2385 ++mnSuspendSelectCallback; // #i15668# - 2004-04-25 - fs@openoffice.org
2386 mpView->SetCurEntry( pEntry );
2387 --mnSuspendSelectCallback;
2390 else
2391 mbIsFirstResort = sal_False;
2394 // -----------------------------------------------------------------------
2395 static sal_Bool gbAscending = sal_True;
2396 static sal_Int16 gnColumn = COLUMN_TITLE;
2397 static const CollatorWrapper* pCollatorWrapper = NULL;
2399 /* this functions returns true, if aOne is less then aTwo
2401 sal_Bool CompareSortingData_Impl( SortingData_Impl* const aOne, SortingData_Impl* const aTwo )
2403 DBG_ASSERT( pCollatorWrapper, "*CompareSortingData_Impl(): Can't work this way!" );
2405 sal_Int32 nComp;
2406 sal_Bool bRet = sal_False;
2407 sal_Bool bEqual = sal_False;
2409 if ( aOne->mbIsFolder != aTwo->mbIsFolder )
2411 if ( aOne->mbIsFolder )
2412 bRet = sal_True;
2413 else
2414 bRet = sal_False;
2416 // !!! pb: #100376# folder always on top
2417 if ( !gbAscending )
2418 bRet = !bRet;
2420 else
2422 switch ( gnColumn )
2424 case COLUMN_TITLE:
2425 // compare case insensitiv first
2426 nComp = pCollatorWrapper->compareString( aOne->GetLowerTitle(), aTwo->GetLowerTitle() );
2428 if ( nComp == 0 )
2429 nComp = pCollatorWrapper->compareString( aOne->GetTitle(), aTwo->GetTitle() );
2431 if ( nComp < 0 )
2432 bRet = sal_True;
2433 else if ( nComp > 0 )
2434 bRet = sal_False;
2435 else
2436 bEqual = sal_True;
2437 break;
2438 case COLUMN_TYPE:
2439 nComp = pCollatorWrapper->compareString( aOne->maType, aTwo->maType );
2440 if ( nComp < 0 )
2441 bRet = sal_True;
2442 else if ( nComp > 0 )
2443 bRet = sal_False;
2444 else
2445 bEqual = sal_True;
2446 break;
2447 case COLUMN_SIZE:
2448 if ( aOne->maSize < aTwo->maSize )
2449 bRet = sal_True;
2450 else if ( aOne->maSize > aTwo->maSize )
2451 bRet = sal_False;
2452 else
2453 bEqual = sal_True;
2454 break;
2455 case COLUMN_DATE:
2456 if ( aOne->maModDate < aTwo->maModDate )
2457 bRet = sal_True;
2458 else if ( aOne->maModDate > aTwo->maModDate )
2459 bRet = sal_False;
2460 else
2461 bEqual = sal_True;
2462 break;
2463 default:
2464 DBG_WARNING( "CompareSortingData_Impl: Compare unknown type!" );
2465 bRet = sal_False;
2469 // when the two elements are equal, we must not return TRUE (which would
2470 // happen if we just return ! ( a < b ) when not sorting ascending )
2471 if ( bEqual )
2472 return sal_False;
2474 return gbAscending ? bRet : !bRet;
2477 // -----------------------------------------------------------------------
2478 void SvtFileView_Impl::SortFolderContent_Impl()
2480 ::osl::MutexGuard aGuard( maMutex );
2482 sal_uInt32 nSize = maContent.size();
2484 if ( nSize > 1 )
2486 gbAscending = mbAscending;
2487 gnColumn = mnSortColumn;
2488 pCollatorWrapper = aIntlWrapper.getCaseCollator();
2490 std::stable_sort( maContent.begin(), maContent.end(), CompareSortingData_Impl );
2492 pCollatorWrapper = NULL;
2496 // -----------------------------------------------------------------------
2497 void SvtFileView_Impl::EntryRemoved( const OUString& rURL )
2499 ::osl::MutexGuard aGuard( maMutex );
2501 std::vector< SortingData_Impl* >::iterator aIt;
2503 for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
2505 if ( (*aIt)->maTargetURL == rURL )
2507 maContent.erase( aIt );
2508 break;
2513 // -----------------------------------------------------------------------
2514 void SvtFileView_Impl::EntryRenamed( OUString& rURL,
2515 const OUString& rTitle )
2517 ::osl::MutexGuard aGuard( maMutex );
2519 std::vector< SortingData_Impl* >::iterator aIt;
2521 for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
2523 if ( (*aIt)->maTargetURL == rURL )
2525 (*aIt)->SetNewTitle( rTitle );
2526 OUString aDisplayText = (*aIt)->maDisplayText;
2527 sal_Int32 nIndex = aDisplayText.indexOf( '\t' );
2529 if ( nIndex > 0 )
2530 (*aIt)->maDisplayText = aDisplayText.replaceAt( 0, nIndex, rTitle );
2532 INetURLObject aURLObj( rURL );
2533 aURLObj.SetName( rTitle, INetURLObject::ENCODE_ALL );
2535 rURL = aURLObj.GetMainURL( INetURLObject::NO_DECODE );
2537 (*aIt)->maTargetURL = rURL;
2538 break;
2543 // -----------------------------------------------------------------------
2544 String SvtFileView_Impl::FolderInserted( const OUString& rURL, const OUString& rTitle )
2546 ::osl::MutexGuard aGuard( maMutex );
2548 SortingData_Impl* pData = new SortingData_Impl;
2550 pData->SetNewTitle( rTitle );
2551 pData->maSize = 0;
2552 pData->mbIsFolder = sal_True;
2553 pData->maTargetURL = rURL;
2555 INetURLObject aURLObj( rURL );
2557 ::svtools::VolumeInfo aVolInfo;
2558 pData->maType = SvFileInformationManager::GetFolderDescription( aVolInfo );
2559 pData->maImage = SvFileInformationManager::GetFolderImage( aVolInfo, FALSE, isHighContrast( mpView ) );
2561 OUString aValue;
2562 OUString aTab = OUString::createFromAscii( "\t" );
2563 OUString aDateSep = OUString::createFromAscii( ", " );
2565 // title, type, size, date
2566 aValue = pData->GetTitle();
2567 // #83004# --------------------
2568 ReplaceTabWithString( aValue );
2569 aValue += aTab;
2570 aValue += pData->maType;
2571 aValue += aTab;
2572 // folders don't have a size
2573 aValue += aTab;
2574 // set the date
2575 SvtSysLocale aSysLocale;
2576 const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData();
2577 aValue += rLocaleData.getDate( pData->maModDate );
2578 aValue += aDateSep;
2579 aValue += rLocaleData.getTime( pData->maModDate );
2581 pData->maDisplayText = aValue;
2582 maContent.push_back( pData );
2584 return String( aValue );
2587 // -----------------------------------------------------------------------
2588 ULONG SvtFileView_Impl::GetEntryPos( const OUString& rURL )
2590 ::osl::MutexGuard aGuard( maMutex );
2592 std::vector< SortingData_Impl* >::iterator aIt;
2593 ULONG nPos = 0;
2595 for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
2597 if ( (*aIt)->maTargetURL == rURL )
2598 return nPos;
2599 nPos += 1;
2602 return nPos;
2605 // -----------------------------------------------------------------------
2606 sal_Bool SvtFileView_Impl::SearchNextEntry( sal_uInt32& nIndex, const OUString& rTitle, sal_Bool bWrapAround )
2608 ::osl::MutexGuard aGuard( maMutex );
2610 sal_uInt32 nEnd = maContent.size();
2611 sal_uInt32 nStart = nIndex;
2612 while ( nIndex < nEnd )
2614 SortingData_Impl* pData = maContent[ nIndex ];
2615 if ( rTitle.compareTo( pData->GetLowerTitle(), rTitle.getLength() ) == 0 )
2616 return sal_True;
2617 nIndex += 1;
2620 if ( bWrapAround )
2622 nIndex = 0;
2623 while ( nIndex < nEnd && nIndex <= nStart )
2625 SortingData_Impl* pData = maContent[ nIndex ];
2626 if ( rTitle.compareTo( pData->GetLowerTitle(), rTitle.getLength() ) == 0 )
2627 return sal_True;
2628 nIndex += 1;
2632 return sal_False;
2635 // -----------------------------------------------------------------------
2636 void SvtFileView_Impl::SetActualFolder( const INetURLObject& rActualFolder )
2638 if( mbReplaceNames )
2640 if( mpNameTrans )
2641 mpNameTrans->SetActualFolder( rActualFolder );
2642 else
2643 mpNameTrans = new NameTranslator_Impl( rActualFolder );
2647 namespace svtools {
2649 // -----------------------------------------------------------------------
2650 // QueryDeleteDlg_Impl
2651 // -----------------------------------------------------------------------
2653 QueryDeleteDlg_Impl::QueryDeleteDlg_Impl
2655 Window* pParent,
2656 const String& rName // Eintragsname
2659 ModalDialog( pParent, SvtResId( DLG_SVT_QUERYDELETE ) ),
2661 _aEntryLabel ( this, SvtResId( TXT_ENTRY ) ),
2662 _aEntry ( this, SvtResId( TXT_ENTRYNAME ) ),
2663 _aQueryMsg ( this, SvtResId( TXT_QUERYMSG ) ),
2664 _aYesButton ( this, SvtResId( BTN_YES ) ),
2665 _aAllButton ( this, SvtResId( BTN_ALL ) ),
2666 _aNoButton ( this, SvtResId( BTN_NO ) ),
2667 _aCancelButton( this, SvtResId( BTN_CANCEL ) )
2670 FreeResource();
2672 // Handler
2673 Link aLink( STATIC_LINK( this, QueryDeleteDlg_Impl, ClickLink ) );
2674 _aYesButton.SetClickHdl( aLink );
2675 _aAllButton.SetClickHdl( aLink );
2676 _aNoButton.SetClickHdl( aLink );
2678 // Anzeige der spezifizierten Texte
2680 WinBits nTmpStyle = _aEntry.GetStyle();
2681 nTmpStyle |= WB_PATHELLIPSIS;
2682 _aEntry.SetStyle( nTmpStyle );
2683 _aEntry.SetText( rName );
2686 // -----------------------------------------------------------------------
2688 IMPL_STATIC_LINK( QueryDeleteDlg_Impl, ClickLink, PushButton*, pBtn )
2690 /* [Beschreibung]
2692 Die Methode wertet das Resultat der Abfrage aus.
2696 if ( pBtn == &pThis->_aYesButton )
2697 pThis->_eResult = QUERYDELETE_YES;
2698 else if ( pBtn == &pThis->_aNoButton )
2699 pThis->_eResult = QUERYDELETE_NO;
2700 else if ( pBtn == &pThis->_aAllButton )
2701 pThis->_eResult = QUERYDELETE_ALL;
2702 else if ( pBtn == &pThis->_aCancelButton )
2703 pThis->_eResult = QUERYDELETE_CANCEL;
2705 pThis->EndDialog( RET_OK );
2707 return 0;