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:
ReleaseSolarMutex__anon1d7eeefe0111::ReleaseSolarMutex115 inline ReleaseSolarMutex()
116 {
117 m_nCount = Application::ReleaseSolarMutex();
118 }
~ReleaseSolarMutex__anon1d7eeefe0111::ReleaseSolarMutex119 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:
CallbackTimer(ITimeoutHandler * _pHandler)144 CallbackTimer( ITimeoutHandler* _pHandler ) : m_pTimeoutHandler( _pHandler ) { }
145
146 protected:
147 virtual void SAL_CALL onShot();
148 };
149
150 //--------------------------------------------------------------------
onShot()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
isHighContrast(const Window * _pView)163 static sal_Bool isHighContrast( const Window* _pView )
164 {
165 return _pView->GetSettings().GetStyleSettings().GetHighContrastMode();
166 }
167
168 // -----------------------------------------------------------------------
169
createWildCardFilterList(const String & _rFilterList,::std::vector<WildCard> & _rFilters)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();
GetHeaderBar() const230 HeaderBar* GetHeaderBar() const { return mpHeaderBar; }
231
EnableAutoResize()232 void EnableAutoResize() { mbAutoResize = sal_True; }
EnableDelete(sal_Bool bEnable)233 void EnableDelete( sal_Bool bEnable ) { mbEnableDelete = bEnable; }
EnableRename(sal_Bool bEnable)234 void EnableRename( sal_Bool bEnable ) { mbEnableRename = bEnable; }
IsDeleteOrContextMenuEnabled()235 sal_Bool IsDeleteOrContextMenuEnabled() { return mbEnableDelete || IsContextMenuHandlingEnabled(); }
236
GetCommandEnvironment() const237 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
HashedEntry(const OUString & rName)264 inline HashedEntry::HashedEntry( const OUString& rName ): maName( rName ), mnHashCode( rName.hashCode() )
265 {
266 }
267
HashedEntry(const INetURLObject & rURL)268 inline HashedEntry::HashedEntry( const INetURLObject& rURL ):
269 maName( rURL.GetMainURL( INetURLObject::NO_DECODE ) ),
270 mnHashCode( maName.hashCode() )
271 {
272 }
273
HashedEntry(const HashedEntry & r)274 inline HashedEntry::HashedEntry( const HashedEntry& r ): maName( r.maName ), mnHashCode( r.mnHashCode )
275 {
276 }
277
~HashedEntry()278 HashedEntry::~HashedEntry()
279 {
280 }
281
operator ==(const HashedEntry & rRef) const282 inline sal_Bool HashedEntry::operator ==( const HashedEntry& rRef ) const
283 {
284 return mnHashCode == rRef.mnHashCode && maName.reverseCompareTo( rRef.maName ) == 0;
285 }
286
operator !=(const HashedEntry & rRef) const287 inline sal_Bool HashedEntry::operator !=( const HashedEntry& rRef ) const
288 {
289 return mnHashCode != rRef.mnHashCode || maName.reverseCompareTo( rRef.maName ) != 0;
290 }
291
GetName() const292 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
First()319 inline HashedEntry* HashedEntryList::First()
320 {
321 return ( HashedEntry* ) List::First();
322 }
323
Next()324 inline HashedEntry* HashedEntryList::Next()
325 {
326 return ( HashedEntry* ) List::Next();
327 }
328
Append(HashedEntry * pNew)329 inline void HashedEntryList::Append( HashedEntry* pNew )
330 {
331 List::Insert( pNew, LIST_APPEND );
332 }
333
~HashedEntryList()334 HashedEntryList::~HashedEntryList()
335 {
336 Clear();
337 }
338
Find(const OUString & rRefName)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
Find(const HashedEntry & rRef)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
Insert(HashedEntry * pNew)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
Clear()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
NameTranslationEntry(const OUString & rOrg,const OUString & rTrans)399 inline NameTranslationEntry::NameTranslationEntry( const OUString& rOrg, const OUString& rTrans ):
400 HashedEntry( rOrg ),
401 maTranslatedName( rTrans )
402 {
403 }
404
NameTranslationEntry(const ByteString & rOrg,const ByteString & rTrans)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
GetTranslation() const411 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
GetTransTableFileName() const448 inline const String& NameTranslationList::GetTransTableFileName() const
449 {
450 return maTransFileName;
451 }
452
Init()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
NameTranslationList(const INetURLObject & rBaseURL)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
operator ==(const HashedEntry & rRef) const490 inline sal_Bool NameTranslationList::operator ==( const HashedEntry& rRef ) const
491 {
492 return maHashedURL == rRef;
493 }
494
operator !=(const HashedEntry & rRef) const495 inline sal_Bool NameTranslationList::operator !=( const HashedEntry& rRef ) const
496 {
497 return maHashedURL != rRef;
498 }
499
Translate(const OUString & rName) const500 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
Update()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
EnableContextMenu(sal_Bool bEnable)648 inline void SvtFileView_Impl::EnableContextMenu( sal_Bool bEnable )
649 {
650 mpView->EnableContextMenuHandling( bEnable );
651 if( bEnable )
652 mbReplaceNames = sal_False;
653 }
654
EnableDelete(sal_Bool bEnable)655 inline void SvtFileView_Impl::EnableDelete( sal_Bool bEnable )
656 {
657 mpView->EnableDelete( bEnable );
658 if( bEnable )
659 mbReplaceNames = sal_False;
660 }
661
EnableNameReplacing(sal_Bool bEnable)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
EndEditing(bool _bCancel)681 inline void SvtFileView_Impl::EndEditing( bool _bCancel )
682 {
683 if ( mpView->IsEditingActive() )
684 mpView->EndEditing( _bCancel != false );
685 }
686
687 // functions -------------------------------------------------------------
688
CreateExactSizeText_Impl(sal_Int64 nSize)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
ViewTabListBox_Impl(Window * pParentWin,SvtFileView_Impl * pParent,sal_Int16 nFlags)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
~ViewTabListBox_Impl()792 ViewTabListBox_Impl::~ViewTabListBox_Impl()
793 {
794 maResetQuickSearch.Stop();
795
796 delete mpHeaderBar;
797 }
798
799 // -----------------------------------------------------------------------
800
IMPL_LINK(ViewTabListBox_Impl,ResetQuickSearch_Impl,Timer *,EMPTYARG)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
Resize()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
KeyInput(const KeyEvent & rKEvt)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
CreateContextMenu(void)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
ExcecuteContextMenuAction(sal_uInt16 nSelectedPopupEntry)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
ClearAll()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 // -----------------------------------------------------------------------
DeleteEntries()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 // -----------------------------------------------------------------------
EditedEntry(SvLBoxEntry * pEntry,const XubString & rNewText)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 // -----------------------------------------------------------------------
DoQuickSearch(const xub_Unicode & rChar)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 // -----------------------------------------------------------------------
DoubleClickHdl()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
GetAccessibleObjectDescription(::svt::AccessibleBrowseBoxObjType _eType,sal_Int32 _nPos) const1174 ::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 // -----------------------------------------------------------------------
Kill(const OUString & rContent)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
SvtFileView(Window * pParent,const ResId & rResId,sal_Bool bOnlyFolder,sal_Bool bMultiSelection)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
SvtFileView(Window * pParent,const ResId & rResId,sal_Int8 nFlags)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
~SvtFileView()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
OpenFolder(const Sequence<OUString> & aContents)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
GetURL(SvLBoxEntry * pEntry) const1359 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
GetCurrentURL() const1369 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
CreateNewFolder(const String & rNewFolder)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
PreviousLevel(const FileViewAsyncAction * pAsyncDescriptor)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
GetParentURL(String & rParentURL) const1413 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
GetHelpId() const1441 const rtl::OString& SvtFileView::GetHelpId( ) const
1442 {
1443 return mpImp->mpView->GetHelpId( );
1444 }
1445
1446 // -----------------------------------------------------------------------
1447
SetHelpId(const rtl::OString & rHelpId)1448 void SvtFileView::SetHelpId( const rtl::OString& rHelpId )
1449 {
1450 mpImp->mpView->SetHelpId( rHelpId );
1451 }
1452
1453 // -----------------------------------------------------------------------
1454
SetSizePixel(const Size & rNewSize)1455 void SvtFileView::SetSizePixel( const Size& rNewSize )
1456 {
1457 Control::SetSizePixel( rNewSize );
1458 mpImp->mpView->SetSizePixel( rNewSize );
1459 }
1460
1461 // -----------------------------------------------------------------------
1462
SetPosSizePixel(const Point & rNewPos,const Size & rNewSize)1463 void SvtFileView::SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
1464 {
1465 SetPosPixel( rNewPos );
1466 SetSizePixel( rNewSize );
1467 }
1468
1469 // -----------------------------------------------------------------------------
Initialize(const::com::sun::star::uno::Reference<::com::sun::star::ucb::XContent> & _xContent,const String & rFilter)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 // -----------------------------------------------------------------------
Initialize(const String & rURL,const String & rFilter,const FileViewAsyncAction * pAsyncDescriptor,const::com::sun::star::uno::Sequence<::rtl::OUString> & rBlackList)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 // -----------------------------------------------------------------------
Initialize(const String & rURL,const String & rFilter,const FileViewAsyncAction * pAsyncDescriptor)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 // -----------------------------------------------------------------------
Initialize(const Sequence<OUString> & aContents)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
ExecuteFilter(const String & rFilter,const FileViewAsyncAction * pAsyncDescriptor)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
CancelRunningAsyncAction()1567 void SvtFileView::CancelRunningAsyncAction()
1568 {
1569 mpImp->CancelRunningAsyncAction();
1570 }
1571
1572 // -----------------------------------------------------------------------
1573
SetNoSelection()1574 void SvtFileView::SetNoSelection()
1575 {
1576 mpImp->mpView->SelectAll( sal_False );
1577 }
1578
1579 // -----------------------------------------------------------------------
1580
GetFocus()1581 void SvtFileView::GetFocus()
1582 {
1583 Control::GetFocus();
1584 if ( mpImp && mpImp->mpView )
1585 mpImp->mpView->GrabFocus();
1586 }
1587
1588 // -----------------------------------------------------------------------
1589
ResetCursor()1590 void SvtFileView::ResetCursor()
1591 {
1592 mpImp->ResetCursor();
1593 }
1594
1595 // -----------------------------------------------------------------------
1596
SetSelectHdl(const Link & rHdl)1597 void SvtFileView::SetSelectHdl( const Link& rHdl )
1598 {
1599 mpImp->SetSelectHandler( rHdl );
1600 }
1601
1602 // -----------------------------------------------------------------------
1603
SetDoubleClickHdl(const Link & rHdl)1604 void SvtFileView::SetDoubleClickHdl( const Link& rHdl )
1605 {
1606 mpImp->mpView->SetDoubleClickHdl( rHdl );
1607 }
1608
1609 // -----------------------------------------------------------------------
1610
GetSelectionCount() const1611 sal_uLong SvtFileView::GetSelectionCount() const
1612 {
1613 return mpImp->mpView->GetSelectionCount();
1614 }
1615
1616 // -----------------------------------------------------------------------
1617
FirstSelected() const1618 SvLBoxEntry* SvtFileView::FirstSelected() const
1619 {
1620 return mpImp->mpView->FirstSelected();
1621 }
1622
1623 // -----------------------------------------------------------------------
1624
NextSelected(SvLBoxEntry * pEntry) const1625 SvLBoxEntry* SvtFileView::NextSelected( SvLBoxEntry* pEntry ) const
1626 {
1627 return mpImp->mpView->NextSelected( pEntry );
1628 }
1629
1630 // -----------------------------------------------------------------------
1631
EnableAutoResize()1632 void SvtFileView::EnableAutoResize()
1633 {
1634 mpImp->mpView->EnableAutoResize();
1635 }
1636
1637 // -----------------------------------------------------------------------
1638
SetFocus()1639 void SvtFileView::SetFocus()
1640 {
1641 mpImp->mpView->GrabFocus();
1642 }
1643
1644 // -----------------------------------------------------------------------
GetViewURL() const1645 const String& SvtFileView::GetViewURL() const
1646 {
1647 return mpImp->maViewURL;
1648 }
1649
1650 // -----------------------------------------------------------------------
SetOpenDoneHdl(const Link & rHdl)1651 void SvtFileView::SetOpenDoneHdl( const Link& rHdl )
1652 {
1653 mpImp->maOpenDoneLink = rHdl;
1654 }
1655
1656 // -----------------------------------------------------------------------
EnableContextMenu(sal_Bool bEnable)1657 void SvtFileView::EnableContextMenu( sal_Bool bEnable )
1658 {
1659 mpImp->EnableContextMenu( bEnable );
1660 }
1661
1662 // -----------------------------------------------------------------------
EnableDelete(sal_Bool bEnable)1663 void SvtFileView::EnableDelete( sal_Bool bEnable )
1664 {
1665 mpImp->EnableDelete( bEnable );
1666 }
1667
EnableNameReplacing(sal_Bool bEnable)1668 void SvtFileView::EnableNameReplacing( sal_Bool bEnable )
1669 {
1670 mpImp->EnableNameReplacing( bEnable );
1671 }
1672
1673 // -----------------------------------------------------------------------
EndInplaceEditing(bool _bCancel)1674 void SvtFileView::EndInplaceEditing( bool _bCancel )
1675 {
1676 return mpImp->EndEditing( _bCancel );
1677 }
1678
1679 // -----------------------------------------------------------------------
IMPL_LINK(SvtFileView,HeaderSelect_Impl,HeaderBar *,pBar)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 // -----------------------------------------------------------------------
IMPL_LINK(SvtFileView,HeaderEndDrag_Impl,HeaderBar *,pBar)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 // -----------------------------------------------------------------------
GetConfigString() const1744 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 // -----------------------------------------------------------------------
SetConfigString(const String & rCfgStr)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 // -----------------------------------------------------------------------
SetUrlFilter(const IUrlFilter * _pFilter)1806 void SvtFileView::SetUrlFilter( const IUrlFilter* _pFilter )
1807 {
1808 mpImp->mpUrlFilter = _pFilter;
1809 }
1810
1811 // -----------------------------------------------------------------------
GetUrlFilter() const1812 const IUrlFilter* SvtFileView::GetUrlFilter( ) const
1813 {
1814 return mpImp->mpUrlFilter;
1815 }
1816
1817 // -----------------------------------------------------------------------
StateChanged(StateChangedType nStateChange)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
NameTranslator_Impl(void)1829 NameTranslator_Impl::NameTranslator_Impl( void ) :
1830 mpActFolder( NULL )
1831 {
1832 }
1833
NameTranslator_Impl(const INetURLObject & rActualFolder)1834 NameTranslator_Impl::NameTranslator_Impl( const INetURLObject& rActualFolder )
1835 {
1836 mpActFolder = new NameTranslationList( rActualFolder );
1837 }
1838
~NameTranslator_Impl()1839 NameTranslator_Impl::~NameTranslator_Impl()
1840 {
1841 if( mpActFolder )
1842 delete mpActFolder;
1843 }
1844
UpdateTranslationTable()1845 void NameTranslator_Impl::UpdateTranslationTable()
1846 {
1847 if( mpActFolder )
1848 mpActFolder->Update();
1849 }
1850
SetActualFolder(const INetURLObject & rActualFolder)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
GetTranslation(const OUString & rOrg,OUString & rTrans) const1867 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
GetTransTableFileName() const1884 const String* NameTranslator_Impl::GetTransTableFileName() const
1885 {
1886 return mpActFolder? &mpActFolder->GetTransTableFileName() : NULL;
1887 }
1888
1889 // -----------------------------------------------------------------------
1890 // class SvtFileView_Impl
1891 // -----------------------------------------------------------------------
1892
SvtFileView_Impl(SvtFileView * pAntiImpl,Reference<XCommandEnvironment> xEnv,sal_Int16 nFlags,sal_Bool bOnlyFolder)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 // -----------------------------------------------------------------------
~SvtFileView_Impl()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 // -----------------------------------------------------------------------
Clear()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 // -----------------------------------------------------------------------
GetFolderContent_Impl(const String & rFolder,const FileViewAsyncAction * pAsyncDescriptor,const::com::sun::star::uno::Sequence<::rtl::OUString> & rBlackList)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 // -----------------------------------------------------------------------
GetFolderContent_Impl(const FolderDescriptor & _rFolder,const FileViewAsyncAction * pAsyncDescriptor,const::com::sun::star::uno::Sequence<::rtl::OUString> & rBlackList)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 // -----------------------------------------------------------------------
FilterFolderContent_Impl(const OUString & rFilter)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 // -----------------------------------------------------------------------
IMPL_LINK(SvtFileView_Impl,SelectionMultiplexer,void *,_pSource)2160 IMPL_LINK( SvtFileView_Impl, SelectionMultiplexer, void*, _pSource )
2161 {
2162 return mnSuspendSelectCallback ? 0L : m_aSelectHandler.Call( _pSource );
2163 }
2164
2165 // -----------------------------------------------------------------------
SetSelectHandler(const Link & _rHdl)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 // -----------------------------------------------------------------------
InitSelection()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 // -----------------------------------------------------------------------
OpenFolder_Impl()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 // -----------------------------------------------------------------------
ResetCursor()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 // -----------------------------------------------------------------------
CancelRunningAsyncAction()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 //-----------------------------------------------------------------------
onTimeout(CallbackTimer *)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 //-----------------------------------------------------------------------
enumerationDone(::svt::EnumerationResult _eResult)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 //-----------------------------------------------------------------------
implEnumerationSuccess()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 // -----------------------------------------------------------------------
ReplaceTabWithString(OUString & aValue)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 // -----------------------------------------------------------------------
CreateDisplayText_Impl()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
CreateVector_Impl(const Sequence<OUString> & rList)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 // -----------------------------------------------------------------------
Resort_Impl(sal_Int16 nColumn,sal_Bool bAscending)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 */
CompareSortingData_Impl(SortingData_Impl * const aOne,SortingData_Impl * const aTwo)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 // -----------------------------------------------------------------------
SortFolderContent_Impl()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 // -----------------------------------------------------------------------
EntryRemoved(const OUString & rURL)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 // -----------------------------------------------------------------------
EntryRenamed(OUString & rURL,const OUString & rTitle)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 // -----------------------------------------------------------------------
FolderInserted(const OUString & rURL,const OUString & rTitle)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 // -----------------------------------------------------------------------
GetEntryPos(const OUString & rURL)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 // -----------------------------------------------------------------------
SearchNextEntry(sal_uInt32 & nIndex,const OUString & rTitle,sal_Bool bWrapAround)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 // -----------------------------------------------------------------------
SetActualFolder(const INetURLObject & rActualFolder)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
QueryDeleteDlg_Impl(Window * pParent,const String & rName)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
IMPL_STATIC_LINK(QueryDeleteDlg_Impl,ClickLink,PushButton *,pBtn)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