1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
22 #include <osl/diagnose.h>
23 #include <svtools/svtresid.hxx>
24 #include <svtools/imagemgr.hxx>
25 #include <svtools/querydelete.hxx>
26 #include <svtools/strings.hrc>
27 #include <bitmaps.hlst>
28 #include "contentenumeration.hxx"
29 #include <com/sun/star/task/InteractionHandler.hpp>
30 #include <com/sun/star/ucb/XProgressHandler.hpp>
31 #include <com/sun/star/ucb/XContent.hpp>
32 #include <com/sun/star/container/XChild.hpp>
33 #include <com/sun/star/ucb/CommandAbortedException.hpp>
34 #include <com/sun/star/ucb/XCommandInfo.hpp>
35 #include <com/sun/star/beans/XPropertySetInfo.hpp>
36 #include <com/sun/star/beans/PropertyAttribute.hpp>
39 #include <string_view>
41 #include <tools/debug.hxx>
42 #include <tools/urlobj.hxx>
43 #include <comphelper/processfactory.hxx>
44 #include <comphelper/string.hxx>
45 #include <ucbhelper/content.hxx>
46 #include <ucbhelper/commandenvironment.hxx>
47 #include <rtl/math.hxx>
48 #include <o3tl/safeint.hxx>
49 #include <o3tl/typed_flags_set.hxx>
50 #include <o3tl/string_view.hxx>
51 #include <osl/mutex.hxx>
52 #include <osl/conditn.hxx>
53 #include <salhelper/timer.hxx>
54 #include <svtools/urlfilter.hxx>
55 #include <unotools/collatorwrapper.hxx>
56 #include <unotools/localedatawrapper.hxx>
57 #include <unotools/intlwrapper.hxx>
58 #include <unotools/syslocale.hxx>
59 #include <vcl/svapp.hxx>
60 #include <vcl/commandevent.hxx>
61 #include <vcl/event.hxx>
62 #include <vcl/settings.hxx>
63 #include <vcl/timer.hxx>
65 #include "fileview.hxx"
67 using namespace ::com::sun::star::sdbc
;
68 using namespace ::com::sun::star::task
;
69 using namespace ::com::sun::star::ucb
;
70 using namespace ::com::sun::star::uno
;
71 using namespace ::com::sun::star::io
;
72 using namespace ::com::sun::star::beans
;
73 using namespace ::comphelper
;
74 using ::svt::SortingData_Impl
;
75 using ::svt::FolderDescriptor
;
77 constexpr OUStringLiteral ALL_FILES_FILTER
= u
"*.*";
79 #define COLUMN_TITLE 1
84 #define QUICK_SEARCH_TIMEOUT 1500 // time in mSec before the quicksearch string will be reset
88 enum class FileViewFlags
91 MULTISELECTION
= 0x02,
100 template<> struct typed_flags
<FileViewFlags
> : is_typed_flags
<FileViewFlags
, 0x26> {};
108 class CallbackTimer
: public ::salhelper::Timer
111 SvtFileView_Impl
* const m_pTimeoutHandler
;
114 explicit CallbackTimer( SvtFileView_Impl
* _pHandler
) : m_pTimeoutHandler( _pHandler
) { }
117 virtual void SAL_CALL
onShot() override
;
120 class ViewTabListBox_Impl
123 rtl::Reference
< ::ucbhelper::CommandEnvironment
> mxCmdEnv
;
124 std::unique_ptr
<weld::TreeView
> mxTreeView
;
125 std::unique_ptr
<weld::TreeIter
> mxScratchIter
;
127 ::osl::Mutex maMutex
;
128 SvtFileView_Impl
* mpParent
;
129 Timer maResetQuickSearch
{ "fpicker SvtFileView_Impl maResetQuickSearch" };
130 OUString maQuickSearchText
;
131 sal_uInt32 mnSearchIndex
;
134 bool const mbShowType
;
136 void DeleteEntries();
137 void DoQuickSearch( sal_Unicode rChar
);
138 bool Kill( const OUString
& rURL
);
141 ViewTabListBox_Impl(std::unique_ptr
<weld::TreeView
> xTreeView
, weld::Window
* pTopLevel
, SvtFileView_Impl
* pParent
, FileViewFlags nFlags
);
143 std::unique_ptr
<weld::TreeIter
> make_iterator() const { return mxTreeView
->make_iterator(); }
144 void insert(const OUString
&rEntry
, const OUString
& rId
, const OUString
& rImage
, weld::TreeIter
& rIter
)
146 mxTreeView
->insert(nullptr, -1, &rEntry
, &rId
, nullptr, nullptr, false, &rIter
);
147 mxTreeView
->set_image(rIter
, rImage
);
149 void append(const OUString
& rId
, const OUString
& rStr
, const OUString
& rType
, const OUString
& rSize
, const OUString
& rDate
, const OUString
& rImage
)
151 mxTreeView
->insert(nullptr, -1, &rStr
, &rId
, nullptr, nullptr, false, mxScratchIter
.get());
152 mxTreeView
->set_image(*mxScratchIter
, rImage
);
155 mxTreeView
->set_text(*mxScratchIter
, rType
, nCol
++);
156 mxTreeView
->set_text(*mxScratchIter
, rSize
, nCol
++);
157 mxTreeView
->set_text(*mxScratchIter
, rDate
, nCol
++);
160 void scroll_to_row(const weld::TreeIter
& rIter
) { mxTreeView
->scroll_to_row(rIter
); }
161 void set_cursor(int nPos
) { mxTreeView
->set_cursor(nPos
); }
162 void set_cursor(const weld::TreeIter
& rIter
) { mxTreeView
->set_cursor(rIter
); }
163 bool get_cursor(weld::TreeIter
* pIter
) const { return mxTreeView
->get_cursor(pIter
); }
164 bool get_iter_first(weld::TreeIter
& rIter
) const { return mxTreeView
->get_iter_first(rIter
); }
165 bool get_selected(weld::TreeIter
* pIter
) const { return mxTreeView
->get_selected(pIter
); }
167 OUString
get_selected_text() const
169 // tdf#131898 only care about column 0
170 int nIndex
= mxTreeView
->get_selected_index();
171 return nIndex
!= -1 ? mxTreeView
->get_text(nIndex
, 0) : OUString();
174 void unselect_all() { mxTreeView
->unselect_all(); }
176 OUString
get_id(const weld::TreeIter
& rIter
) { return mxTreeView
->get_id(rIter
); }
178 void connect_row_activated(const Link
<weld::TreeView
&, bool>& rLink
) { mxTreeView
->connect_row_activated(rLink
); }
179 void connect_changed(const Link
<weld::TreeView
&, void>& rLink
)
181 mxTreeView
->connect_selection_changed(rLink
);
184 int n_children() const { return mxTreeView
->n_children(); }
186 void freeze() { mxTreeView
->freeze(); }
187 void thaw() { mxTreeView
->thaw(); }
189 void show() { mxTreeView
->show(); }
190 void hide() { mxTreeView
->hide(); }
191 bool get_visible() const { return mxTreeView
->get_visible(); }
193 int count_selected_rows() const { return mxTreeView
->count_selected_rows(); }
195 void grab_focus() { mxTreeView
->grab_focus(); }
196 bool has_focus() const { return mxTreeView
->has_focus(); }
198 void set_help_id(const OUString
& rHelpId
) { mxTreeView
->set_help_id(rHelpId
); }
199 OUString
get_help_id() const { return mxTreeView
->get_help_id(); }
201 bool IsEditingActive() const { return mbEditing
; }
205 mxTreeView
->end_editing();
206 mxTreeView
->connect_editing(Link
<const weld::TreeIter
&, bool>(), Link
<const IterString
&, bool>());
210 void selected_foreach(const std::function
<bool(weld::TreeIter
&)>& func
)
212 mxTreeView
->selected_foreach(func
);
215 weld::TreeView
* getWidget() const
217 return mxTreeView
.get();
220 void clear() { mxTreeView
->clear(); }
222 void EnableDelete( bool bEnable
) { mbEnableDelete
= bEnable
; }
223 bool TypeColumnVisible() const { return mbShowType
; }
225 const rtl::Reference
< ::ucbhelper::CommandEnvironment
>& GetCommandEnvironment() const { return mxCmdEnv
; }
227 DECL_LINK(ResetQuickSearch_Impl
, Timer
*, void);
228 DECL_LINK(CommandHdl
, const CommandEvent
&, bool);
229 DECL_LINK(EditingEntryHdl
, const weld::TreeIter
&, bool);
230 typedef std::pair
<const weld::TreeIter
&, OUString
> IterString
;
231 DECL_LINK(EditedEntryHdl
, const IterString
&, bool);
232 DECL_LINK(KeyInputHdl
, const KeyEvent
&, bool);
234 void ExecuteContextMenuAction(std::u16string_view rSelectedPopentry
);
240 class SvtFileView_Impl
:public ::svt::IEnumerationResultHandler
243 SvtFileView
* m_pAntiImpl
;
244 Link
<SvtFileView
*,void> m_aSelectHandler
;
246 ::rtl::Reference
< ::svt::FileViewContentEnumerator
>
247 m_xContentEnumerator
;
248 Link
<void*,void> m_aCurrentAsyncActionHandler
;
249 ::osl::Condition m_aAsyncActionFinished
;
250 ::rtl::Reference
< ::salhelper::Timer
> m_xCancelAsyncTimer
;
251 ::svt::EnumerationResult m_eAsyncActionResult
;
252 bool m_bRunningAsyncAction
;
253 bool m_bAsyncActionCancelled
;
257 ::std::vector
<std::unique_ptr
<SortingData_Impl
>> maContent
;
258 ::std::vector
<std::unique_ptr
<SvtContentEntry
>> maEntries
;
259 ::osl::Mutex maMutex
;
261 weld::Window
* m_pTopLevel
;
262 std::unique_ptr
<ViewTabListBox_Impl
> mxView
;
263 std::unique_ptr
<weld::IconView
> mxIconView
;
264 sal_uInt16 mnSortColumn
;
265 bool mbAscending
: 1;
266 bool const mbOnlyFolder
: 1;
267 sal_Int16 mnSuspendSelectCallback
: 1;
268 bool mbIsFirstResort
: 1;
270 IntlWrapper
const aIntlWrapper
;
273 OUString maCurrentFilter
;
274 OUString maFolderImage
;
275 Link
<SvtFileView
*,void> maOpenDoneLink
;
276 Link
<SvtFileView
*,bool> maDoubleClickHandler
;
278 Reference
< XCommandEnvironment
> mxCmdEnv
;
280 SvtFileView_Impl(SvtFileView
* pAntiImpl
, weld::Window
* pTopLevel
,
281 std::unique_ptr
<weld::TreeView
> xTreeView
,
282 std::unique_ptr
<weld::IconView
> xIconView
,
283 Reference
< XCommandEnvironment
> const & xEnv
,
284 FileViewFlags nFlags
,
287 virtual ~SvtFileView_Impl();
291 FileViewResult
GetFolderContent_Impl(
292 std::u16string_view rFolder
,
293 const FileViewAsyncAction
* pAsyncDescriptor
,
294 const css::uno::Sequence
< OUString
>& rDenyList
);
296 FileViewResult
GetFolderContent_Impl(
297 const FolderDescriptor
& _rFolder
,
298 const FileViewAsyncAction
* pAsyncDescriptor
,
299 const css::uno::Sequence
< OUString
>& rDenyList
);
300 void FilterFolderContent_Impl( std::u16string_view rFilter
);
301 void CancelRunningAsyncAction();
303 void OpenFolder_Impl();
304 static OUString
ReplaceTabWithString(const OUString
& rValue
);
305 void CreateDisplayText_Impl();
306 void SortFolderContent_Impl();
308 void EntryRemoved( std::u16string_view rURL
);
309 void EntryRenamed( OUString
& rURL
,
310 const OUString
& rName
);
311 const SortingData_Impl
& FolderInserted( const OUString
& rURL
,
312 const OUString
& rTitle
);
314 int GetEntryPos( std::u16string_view rURL
);
316 void SetViewMode( FileViewMode eMode
);
318 inline void EnableDelete( bool bEnable
);
320 void Resort_Impl( sal_Int16 nColumn
, bool bAscending
);
321 bool SearchNextEntry( sal_uInt32
&nIndex
,
322 std::u16string_view rTitle
,
325 void SetSelectHandler( const Link
<SvtFileView
*,void>& rHdl
);
326 void SetDoubleClickHandler(const Link
<SvtFileView
*,bool>& rHdl
);
332 if (mxView
->IsEditingActive())
333 mxView
->end_editing();
340 if (mxView
->get_visible())
341 mxView
->grab_focus();
343 mxIconView
->grab_focus();
346 bool has_focus() const
348 return mxView
->has_focus() || mxIconView
->has_focus();
351 int GetSortColumn() const
353 sal_uInt16 nOldSortID
= mnSortColumn
;
355 if (!mxView
->TypeColumnVisible() && nOldSortID
!= COLUMN_TITLE
)
357 return nOldSortID
- 1;
361 DECL_LINK(ChangedHdl
, weld::TreeView
&, void);
362 DECL_LINK(SelectionChangedHdl
, weld::IconView
&, void);
363 DECL_LINK(RowActivatedHdl
, weld::TreeView
&, bool);
364 DECL_LINK(ItemActivatedHdl
, weld::IconView
&, bool);
366 // IEnumerationResultHandler overridables
367 virtual void enumerationDone( ::svt::EnumerationResult eResult
) override
;
368 void implEnumerationSuccess();
371 inline void SvtFileView_Impl::EnableDelete( bool bEnable
)
373 mxView
->EnableDelete( bEnable
);
378 // functions -------------------------------------------------------------
380 OUString
CreateExactSizeText( sal_Int64 nSize
)
382 double fSize( static_cast<double>(nSize
) );
385 tools::Long nMega
= 1024 * 1024;
386 tools::Long nGiga
= nMega
* 1024;
388 OUString
aUnitStr(' ');
392 aUnitStr
+= SvtResId(STR_SVT_BYTES
);
395 else if ( nSize
< nMega
)
398 aUnitStr
+= SvtResId(STR_SVT_KB
);
401 else if ( nSize
< nGiga
)
404 aUnitStr
+= SvtResId(STR_SVT_MB
);
410 aUnitStr
+= SvtResId(STR_SVT_GB
);
415 ::rtl::math::doubleToUString( fSize
,
416 rtl_math_StringFormat_F
, nDec
,
417 SvtSysLocale().GetLocaleData().getNumDecimalSep()[0]) +
424 ViewTabListBox_Impl::ViewTabListBox_Impl(std::unique_ptr
<weld::TreeView
> xTreeView
,
425 weld::Window
* pTopLevel
,
426 SvtFileView_Impl
* pParent
,
427 FileViewFlags nFlags
)
428 : mxTreeView(std::move(xTreeView
))
429 , mxScratchIter(mxTreeView
->make_iterator())
430 , mpParent( pParent
)
432 , mbEnableDelete( false )
434 , mbShowType(nFlags
& FileViewFlags::SHOW_TYPE
)
436 std::vector
<int> aWidths
{ 180 };
437 if (nFlags
& FileViewFlags::SHOW_TYPE
)
438 aWidths
.push_back(140);
439 aWidths
.push_back(80);
440 mxTreeView
->set_column_fixed_widths(aWidths
);
442 if (nFlags
& FileViewFlags::MULTISELECTION
)
443 mxTreeView
->set_selection_mode(SelectionMode::Multiple
);
445 maResetQuickSearch
.SetTimeout( QUICK_SEARCH_TIMEOUT
);
446 maResetQuickSearch
.SetInvokeHandler( LINK( this, ViewTabListBox_Impl
, ResetQuickSearch_Impl
) );
448 const Reference
< XComponentContext
>& xContext
= ::comphelper::getProcessComponentContext();
449 Reference
< XInteractionHandler
> xInteractionHandler(
450 InteractionHandler::createWithParent(xContext
, pTopLevel
->GetXWindow()), UNO_QUERY_THROW
);
452 mxCmdEnv
= new ::ucbhelper::CommandEnvironment( xInteractionHandler
, Reference
< XProgressHandler
>() );
454 mxTreeView
->connect_popup_menu(LINK(this, ViewTabListBox_Impl
, CommandHdl
));
455 mxTreeView
->connect_key_press(LINK(this, ViewTabListBox_Impl
, KeyInputHdl
));
458 IMPL_LINK_NOARG(ViewTabListBox_Impl
, EditingEntryHdl
, const weld::TreeIter
&, bool)
463 IMPL_LINK_NOARG(ViewTabListBox_Impl
, ResetQuickSearch_Impl
, Timer
*, void)
465 ::osl::MutexGuard
aGuard( maMutex
);
467 maQuickSearchText
.clear();
471 IMPL_LINK(ViewTabListBox_Impl
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
476 bool bHandled
= false;
478 const vcl::KeyCode
& rKeyCode
= rKEvt
.GetKeyCode();
479 if ( 0 == rKeyCode
.GetModifier() )
481 if ( ( rKeyCode
.GetCode() == KEY_DELETE
) &&
484 ResetQuickSearch_Impl( nullptr );
488 else if ( ( rKEvt
.GetKeyCode().GetGroup() == KEYGROUP_NUM
) ||
489 ( rKEvt
.GetKeyCode().GetGroup() == KEYGROUP_ALPHA
) )
491 DoQuickSearch( rKEvt
.GetCharCode() );
497 ResetQuickSearch_Impl( nullptr );
501 IMPL_LINK(ViewTabListBox_Impl
, CommandHdl
, const CommandEvent
&, rCEvt
, bool)
503 if (rCEvt
.GetCommand() != CommandEventId::ContextMenu
)
506 bool bEnableDelete
= mbEnableDelete
;
507 bool bEnableRename
= true;
510 mxTreeView
->selected_foreach([this, &nCount
, &bEnableDelete
, &bEnableRename
](weld::TreeIter
& rEntry
){
513 ::ucbhelper::Content aCnt
;
516 OUString
aURL(weld::fromId
<SvtContentEntry
*>(
517 mxTreeView
->get_id(rEntry
))->maURL
);
518 aCnt
= ::ucbhelper::Content( aURL
, mxCmdEnv
, comphelper::getProcessComponentContext() );
520 catch( Exception
const & )
522 bEnableDelete
= bEnableRename
= false;
529 Reference
< XCommandInfo
> aCommands
= aCnt
.getCommands();
530 if ( aCommands
.is() )
531 bEnableDelete
= aCommands
->hasCommandByName( u
"delete"_ustr
);
533 bEnableDelete
= false;
535 catch( Exception
const & )
537 bEnableDelete
= false;
545 Reference
< XPropertySetInfo
> aProps
= aCnt
.getProperties();
548 Property aProp
= aProps
->getPropertyByName(u
"Title"_ustr
);
550 = !( aProp
.Attributes
& PropertyAttribute::READONLY
);
553 bEnableRename
= false;
555 catch( Exception
const & )
557 bEnableRename
= false;
561 bool bStop
= !bEnableDelete
&& !bEnableRename
;
566 bEnableDelete
= false;
568 bEnableRename
= false;
570 if (bEnableDelete
|| bEnableRename
)
572 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(mxTreeView
.get(), u
"svt/ui/fileviewmenu.ui"_ustr
));
573 auto xContextMenu
= xBuilder
->weld_menu(u
"menu"_ustr
);
574 xContextMenu
->set_visible(u
"delete"_ustr
, bEnableDelete
);
575 xContextMenu
->set_visible(u
"rename"_ustr
, bEnableRename
);
576 OUString
sCommand(xContextMenu
->popup_at_rect(mxTreeView
.get(), tools::Rectangle(rCEvt
.GetMousePosPixel(), Size(1,1))));
577 ExecuteContextMenuAction(sCommand
);
583 void ViewTabListBox_Impl::ExecuteContextMenuAction(std::u16string_view rSelectedPopupEntry
)
585 if (rSelectedPopupEntry
== u
"delete")
587 else if (rSelectedPopupEntry
== u
"rename")
589 std::unique_ptr
<weld::TreeIter
> xEntry
= mxTreeView
->make_iterator();
590 if (mxTreeView
->get_selected(xEntry
.get()))
594 mxTreeView
->connect_editing(LINK(this, ViewTabListBox_Impl
, EditingEntryHdl
),
595 LINK(this, ViewTabListBox_Impl
, EditedEntryHdl
));
597 mxTreeView
->start_editing(*xEntry
);
602 void ViewTabListBox_Impl::DeleteEntries()
604 short eResult
= svtools::QUERYDELETE_YES
;
606 mxTreeView
->selected_foreach([this, &eResult
](weld::TreeIter
& rCurEntry
){
608 if (!mxTreeView
->get_id(rCurEntry
).isEmpty())
609 aURL
= weld::fromId
<SvtContentEntry
*>(mxTreeView
->get_id(rCurEntry
))->maURL
;
612 mxTreeView
->unselect(rCurEntry
);
616 bool canDelete
= true;
619 ::ucbhelper::Content
aCnt( aURL
, mxCmdEnv
, comphelper::getProcessComponentContext() );
620 Reference
< XCommandInfo
> aCommands
= aCnt
.getCommands();
621 if ( aCommands
.is() )
622 canDelete
= aCommands
->hasCommandByName( u
"delete"_ustr
);
626 catch( Exception
const & )
633 mxTreeView
->unselect(rCurEntry
);
634 return false; // process next entry
637 if ( eResult
!= svtools::QUERYDELETE_ALL
)
639 INetURLObject
aObj( aURL
);
640 svtools::QueryDeleteDlg_Impl
aDlg(
641 mxTreeView
.get(), aObj
.GetLastName(INetURLObject::DecodeMechanism::WithCharset
));
643 if (mxTreeView
->count_selected_rows() > 1)
644 aDlg
.EnableAllButton();
646 eResult
= aDlg
.run();
649 bool bDeleted
= false;
651 if (eResult
== svtools::QUERYDELETE_ALL
|| eResult
== svtools::QUERYDELETE_YES
)
655 mpParent
->EntryRemoved( aURL
);
661 mxTreeView
->unselect(rCurEntry
);
666 mxTreeView
->remove_selection();
669 IMPL_LINK(ViewTabListBox_Impl
, EditedEntryHdl
, const IterString
&, rIterString
, bool)
673 mxTreeView
->connect_editing(Link
<const weld::TreeIter
&, bool>(), Link
<const IterString
&, bool>());
675 const weld::TreeIter
& rEntry
= rIterString
.first
;
676 OUString sNewText
= rIterString
.second
;
678 if (sNewText
.isEmpty())
684 SvtContentEntry
* pData
= weld::fromId
<SvtContentEntry
*>(mxTreeView
->get_id(rEntry
));
689 if ( aURL
.isEmpty() )
694 OUString
aPropName( u
"Title"_ustr
);
695 bool canRename
= true;
696 ::ucbhelper::Content
aContent( aURL
, mxCmdEnv
, comphelper::getProcessComponentContext() );
700 Reference
< XPropertySetInfo
> aProps
= aContent
.getProperties();
703 Property aProp
= aProps
->getPropertyByName( aPropName
);
704 canRename
= !( aProp
.Attributes
& PropertyAttribute::READONLY
);
711 catch ( Exception
const & )
720 aContent
.setPropertyValue( aPropName
, aValue
);
721 mpParent
->EntryRenamed(aURL
, sNewText
);
726 mxTreeView
->set_id(rEntry
, weld::toId(pData
));
731 catch( Exception
const & )
738 void ViewTabListBox_Impl::DoQuickSearch( sal_Unicode rChar
)
740 ::osl::MutexGuard
aGuard( maMutex
);
742 maResetQuickSearch
.Stop();
744 OUString aLastText
= maQuickSearchText
;
745 sal_uInt32 aLastPos
= mnSearchIndex
;
747 maQuickSearchText
+= OUString(rChar
).toAsciiLowerCase();
749 bool bFound
= mpParent
->SearchNextEntry( mnSearchIndex
, maQuickSearchText
, false );
751 if ( !bFound
&& ( aLastText
.getLength() == 1 ) &&
752 ( aLastText
== OUStringChar(rChar
) ) )
754 mnSearchIndex
= aLastPos
+ 1;
755 maQuickSearchText
= aLastText
;
756 bFound
= mpParent
->SearchNextEntry( mnSearchIndex
, maQuickSearchText
, true );
761 mxTreeView
->unselect_all();
762 mxTreeView
->select(mnSearchIndex
);
763 mxTreeView
->set_cursor(mnSearchIndex
);
764 mxTreeView
->scroll_to_row(mnSearchIndex
);
767 maResetQuickSearch
.Start();
770 bool ViewTabListBox_Impl::Kill( const OUString
& rContent
)
776 ::ucbhelper::Content
aCnt( rContent
, mxCmdEnv
, comphelper::getProcessComponentContext() );
777 aCnt
.executeCommand( u
"delete"_ustr
, Any( true ) );
779 catch( css::ucb::CommandAbortedException
const & )
781 SAL_INFO( "svtools.contnr", "CommandAbortedException" );
784 catch( Exception
const & )
786 SAL_INFO( "svtools.contnr", "Any other exception" );
793 SvtFileView::SvtFileView(weld::Window
* pTopLevel
,
794 std::unique_ptr
<weld::TreeView
> xTreeView
,
795 std::unique_ptr
<weld::IconView
> xIconView
,
796 bool bOnlyFolder
, bool bMultiSelection
, bool bShowType
)
798 FileViewFlags nFlags
= FileViewFlags::NONE
;
799 if ( bMultiSelection
)
800 nFlags
|= FileViewFlags::MULTISELECTION
;
802 nFlags
|= FileViewFlags::SHOW_TYPE
;
804 const Reference
< XComponentContext
>& xContext
= ::comphelper::getProcessComponentContext();
805 Reference
< XInteractionHandler
> xInteractionHandler(
806 InteractionHandler::createWithParent(xContext
, pTopLevel
->GetXWindow()), UNO_QUERY_THROW
);
807 Reference
< XCommandEnvironment
> xCmdEnv
= new ::ucbhelper::CommandEnvironment( xInteractionHandler
, Reference
< XProgressHandler
>() );
809 mpImpl
.reset(new SvtFileView_Impl(this, pTopLevel
, std::move(xTreeView
), std::move(xIconView
), xCmdEnv
, nFlags
, bOnlyFolder
));
811 weld::TreeView
* pView
= mpImpl
->mxView
->getWidget();
812 pView
->connect_column_clicked(LINK(this, SvtFileView
, HeaderSelect_Impl
));
815 void SvtFileView::grab_focus()
817 mpImpl
->grab_focus();
820 bool SvtFileView::has_focus() const
822 return mpImpl
->has_focus();
825 SvtFileView::~SvtFileView()
829 void SvtFileView::SetViewMode( FileViewMode eMode
)
831 mpImpl
->SetViewMode( eMode
);
834 OUString
SvtFileView::GetURL(const weld::TreeIter
& rEntry
) const
836 SvtContentEntry
* pEntry
;
837 if (mpImpl
->mxView
->get_visible())
838 pEntry
= weld::fromId
<SvtContentEntry
*>(mpImpl
->mxView
->get_id(rEntry
));
840 pEntry
= weld::fromId
<SvtContentEntry
*>(mpImpl
->mxIconView
->get_id(rEntry
));
842 return pEntry
->maURL
;
846 OUString
SvtFileView::GetCurrentURL() const
848 SvtContentEntry
* pEntry
= nullptr;
850 if (mpImpl
->mxView
->get_visible())
852 std::unique_ptr
<weld::TreeIter
> xEntry
= mpImpl
->mxView
->make_iterator();
853 if (mpImpl
->mxView
->get_selected(xEntry
.get()))
854 pEntry
= weld::fromId
<SvtContentEntry
*>(mpImpl
->mxView
->get_id(*xEntry
));
858 std::unique_ptr
<weld::TreeIter
> xEntry
= mpImpl
->mxIconView
->make_iterator();
859 if (mpImpl
->mxIconView
->get_selected(xEntry
.get()))
860 pEntry
= weld::fromId
<SvtContentEntry
*>(mpImpl
->mxIconView
->get_id(*xEntry
));
863 aURL
= pEntry
->maURL
;
867 void SvtFileView::CreatedFolder( const OUString
& rUrl
, const OUString
& rNewFolder
)
869 const SortingData_Impl
& rEntry
= mpImpl
->FolderInserted( rUrl
, rNewFolder
);
871 mpImpl
->maEntries
.emplace_back(std::make_unique
<SvtContentEntry
>(rUrl
, true));
872 OUString
sId(weld::toId(mpImpl
->maEntries
.back().get()));
874 std::unique_ptr
<weld::TreeIter
> xEntry
= mpImpl
->mxView
->make_iterator();
875 mpImpl
->mxView
->insert(rEntry
.maDisplayName
, sId
, mpImpl
->maFolderImage
, *xEntry
);
876 mpImpl
->mxView
->scroll_to_row(*xEntry
);
878 std::unique_ptr
<weld::TreeIter
> xIconEntry
= mpImpl
->mxIconView
->make_iterator();
879 mpImpl
->mxIconView
->insert(-1, &rEntry
.maDisplayName
, &sId
, &mpImpl
->maFolderImage
, xIconEntry
.get());
880 mpImpl
->mxIconView
->scroll_to_item(*xIconEntry
);
883 FileViewResult
SvtFileView::PreviousLevel( const FileViewAsyncAction
* pAsyncDescriptor
)
885 FileViewResult eResult
= eFailure
;
888 if ( GetParentURL( sParentURL
) )
889 eResult
= Initialize( sParentURL
, mpImpl
->maCurrentFilter
, pAsyncDescriptor
, maDenyList
);
894 bool SvtFileView::GetParentURL( OUString
& rParentURL
) const
899 ::ucbhelper::Content
aCnt( mpImpl
->maViewURL
, mpImpl
->mxCmdEnv
, comphelper::getProcessComponentContext() );
900 Reference
< XContent
> xContent( aCnt
.get() );
901 Reference
< css::container::XChild
> xChild( xContent
, UNO_QUERY
);
904 Reference
< XContent
> xParent( xChild
->getParent(), UNO_QUERY
);
907 rParentURL
= xParent
->getIdentifier()->getContentIdentifier();
908 bRet
= !rParentURL
.isEmpty() && rParentURL
!= mpImpl
->maViewURL
;
912 catch( Exception
const & )
914 // perhaps an unknown url protocol (e.g. "private:newdoc")
920 OUString
SvtFileView::get_help_id() const
922 return mpImpl
->mxView
->get_help_id();
925 void SvtFileView::set_help_id(const OUString
& rHelpId
)
927 mpImpl
->mxView
->set_help_id(rHelpId
);
930 OUString
SvtFileView::get_selected_text() const
932 if (mpImpl
->mxView
->get_visible())
933 return mpImpl
->mxView
->get_selected_text();
934 return mpImpl
->mxIconView
->get_selected_text();
937 FileViewResult
SvtFileView::Initialize(
938 const OUString
& rURL
,
939 const OUString
& rFilter
,
940 const FileViewAsyncAction
* pAsyncDescriptor
,
941 const css::uno::Sequence
< OUString
>& rDenyList
)
943 weld::WaitObject
aWaitCursor(mpImpl
->m_pTopLevel
);
944 maDenyList
= rDenyList
;
946 OUString
sPushURL( mpImpl
->maViewURL
);
948 mpImpl
->maViewURL
= rURL
;
949 FileViewResult eResult
= ExecuteFilter( rFilter
, pAsyncDescriptor
);
954 mpImpl
->maViewURL
= sPushURL
;
958 OSL_ENSURE( pAsyncDescriptor
, "SvtFileView::Initialize: we told it to read synchronously!" );
964 OSL_FAIL( "SvtFileView::Initialize: unreachable!" );
968 FileViewResult
SvtFileView::ExecuteFilter( const OUString
& rFilter
, const FileViewAsyncAction
* pAsyncDescriptor
)
970 mpImpl
->maCurrentFilter
= rFilter
.toAsciiLowerCase();
973 FileViewResult eResult
= mpImpl
->GetFolderContent_Impl(mpImpl
->maViewURL
, pAsyncDescriptor
, maDenyList
);
974 OSL_ENSURE( ( eResult
!= eStillRunning
) || pAsyncDescriptor
, "SvtFileView::ExecuteFilter: we told it to read synchronously!" );
978 void SvtFileView::CancelRunningAsyncAction()
980 mpImpl
->CancelRunningAsyncAction();
983 void SvtFileView::SetNoSelection()
985 mpImpl
->mxView
->unselect_all();
986 mpImpl
->mxIconView
->unselect_all();
989 void SvtFileView::SetSelectHdl(const Link
<SvtFileView
*,void>& rHdl
)
991 mpImpl
->SetSelectHandler(rHdl
);
994 void SvtFileView::SetDoubleClickHdl(const Link
<SvtFileView
*,bool>& rHdl
)
996 mpImpl
->SetDoubleClickHandler(rHdl
);
999 sal_uInt32
SvtFileView::GetSelectionCount() const
1001 if (mpImpl
->mxView
->get_visible())
1002 return mpImpl
->mxView
->count_selected_rows();
1003 return mpImpl
->mxIconView
->count_selected_items();
1006 SvtContentEntry
* SvtFileView::FirstSelected() const
1008 if (mpImpl
->mxView
->get_visible())
1010 SvtContentEntry
* pRet
= nullptr;
1011 std::unique_ptr
<weld::TreeIter
> xEntry
= mpImpl
->mxView
->make_iterator();
1012 if (mpImpl
->mxView
->get_selected(xEntry
.get()))
1013 pRet
= weld::fromId
<SvtContentEntry
*>(mpImpl
->mxView
->get_id(*xEntry
));
1017 SvtContentEntry
* pRet
= nullptr;
1018 std::unique_ptr
<weld::TreeIter
> xEntry
= mpImpl
->mxIconView
->make_iterator();
1019 if (mpImpl
->mxIconView
->get_selected(xEntry
.get()))
1020 pRet
= weld::fromId
<SvtContentEntry
*>(mpImpl
->mxIconView
->get_id(*xEntry
));
1024 const OUString
& SvtFileView::GetViewURL() const
1026 return mpImpl
->maViewURL
;
1029 void SvtFileView::SetOpenDoneHdl( const Link
<SvtFileView
*,void>& rHdl
)
1031 mpImpl
->maOpenDoneLink
= rHdl
;
1034 void SvtFileView::EnableDelete( bool bEnable
)
1036 mpImpl
->EnableDelete( bEnable
);
1039 void SvtFileView::EndInplaceEditing()
1041 return mpImpl
->EndEditing();
1044 IMPL_LINK(SvtFileView
, HeaderSelect_Impl
, int, nColumn
, void)
1046 sal_uInt16 nItemID
= nColumn
+ 1;
1048 if (!mpImpl
->mxView
->TypeColumnVisible() && nItemID
!= COLUMN_TITLE
)
1051 weld::TreeView
* pView
= mpImpl
->mxView
->getWidget();
1052 bool bSortAtoZ
= mpImpl
->mbAscending
;
1054 //set new arrow positions in headerbar
1055 if (nItemID
!= mpImpl
->mnSortColumn
)
1057 // remove old indicator, new will be created in OpenFolder_Impl
1058 pView
->set_sort_indicator(TRISTATE_INDET
, mpImpl
->GetSortColumn());
1061 bSortAtoZ
= !bSortAtoZ
;
1063 mpImpl
->Resort_Impl(nItemID
, bSortAtoZ
);
1066 OUString
SvtFileView::GetConfigString() const
1069 OUString sRet
= OUString::number( mpImpl
->mnSortColumn
) + ";";
1071 bool bUp
= mpImpl
->mbAscending
;
1072 sRet
+= OUString::Concat(bUp
? std::u16string_view(u
"1") : std::u16string_view(u
"0")) + ";";
1074 weld::TreeView
* pView
= mpImpl
->mxView
->getWidget();
1075 sal_uInt16 nCount
= mpImpl
->mxView
->TypeColumnVisible() ? 4 : 3;
1076 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
1078 sal_uInt16 nId
= i
+ 1;
1080 if (!mpImpl
->mxView
->TypeColumnVisible() && nId
!= COLUMN_TITLE
)
1083 sRet
+= OUString::number( nId
)
1085 + OUString::number(pView
->get_column_width(i
))
1089 return comphelper::string::stripEnd(sRet
, ';');
1092 ::std::vector
< SvtContentEntry
> SvtFileView::GetContent()
1094 ::std::vector
< SvtContentEntry
> aContent
;
1096 for(auto const& elem
: mpImpl
->maContent
)
1098 SvtContentEntry
aEntry( elem
->maTargetURL
, elem
->mbIsFolder
);
1099 aContent
.push_back( aEntry
);
1105 void SvtFileView::SetConfigString(std::u16string_view rCfgStr
)
1108 sal_uInt16 nSortColumn
= static_cast<sal_uInt16
>(o3tl::toInt32(o3tl::getToken(rCfgStr
, 0, ';', nIdx
)));
1109 bool bAscending
= static_cast<bool>(static_cast<sal_uInt16
>(o3tl::toInt32(o3tl::getToken(rCfgStr
, 0, ';', nIdx
))));
1111 std::vector
<int> aWidths(mpImpl
->mxView
->TypeColumnVisible() ? 4 : 3, -1);
1113 while ( nIdx
!= -1 )
1115 int nItemId
= o3tl::toInt32(o3tl::getToken(rCfgStr
, 0, ';', nIdx
));
1117 int nWidth
= o3tl::toInt32(o3tl::getToken(rCfgStr
, 0, ';', nIdx
));
1120 if (!mpImpl
->mxView
->TypeColumnVisible() && nItemId
!= COLUMN_TITLE
)
1122 int nColumn
= nItemId
- 1;
1124 if (nColumn
>= 0 && o3tl::make_unsigned(nColumn
) < aWidths
.size())
1125 aWidths
[nColumn
] = nWidth
;
1128 weld::TreeView
* pView
= mpImpl
->mxView
->getWidget();
1129 pView
->set_column_fixed_widths(aWidths
);
1130 if (mpImpl
->mnSortColumn
!= nSortColumn
)
1131 pView
->set_sort_indicator(TRISTATE_INDET
, mpImpl
->GetSortColumn());
1132 mpImpl
->Resort_Impl(nSortColumn
, bAscending
);
1135 SvtFileView_Impl::SvtFileView_Impl(SvtFileView
* pAntiImpl
, weld::Window
* pTopLevel
,
1136 std::unique_ptr
<weld::TreeView
> xTreeView
,
1137 std::unique_ptr
<weld::IconView
> xIconView
,
1138 Reference
< XCommandEnvironment
> const & xEnv
,
1139 FileViewFlags nFlags
, bool bOnlyFolder
)
1140 : m_pAntiImpl ( pAntiImpl
)
1141 , m_eAsyncActionResult ( ::svt::EnumerationResult::ERROR
)
1142 , m_bRunningAsyncAction ( false )
1143 , m_bAsyncActionCancelled ( false )
1144 , m_pTopLevel ( pTopLevel
)
1145 , mxView(new ViewTabListBox_Impl(std::move(xTreeView
), pTopLevel
, this, nFlags
))
1146 , mxIconView(std::move(xIconView
))
1147 , mnSortColumn ( COLUMN_TITLE
)
1148 , mbAscending ( true )
1149 , mbOnlyFolder ( bOnlyFolder
)
1150 , mnSuspendSelectCallback ( 0 )
1151 , mbIsFirstResort ( true )
1152 , aIntlWrapper ( Application::GetSettings().GetLanguageTag() )
1153 , maFolderImage (RID_BMP_FOLDER
)
1156 weld::TreeView
* pWidget
= mxView
->getWidget();
1158 // set the width to something small so it's the parent that decides the final
1160 Size
aSize(42, pWidget
->get_height_rows(7));
1161 pWidget
->set_size_request(aSize
.Width(), aSize
.Height());
1162 mxIconView
->set_size_request(aSize
.Width(), aSize
.Height());
1165 SvtFileView_Impl::~SvtFileView_Impl()
1170 void SvtFileView_Impl::Clear()
1172 ::osl::MutexGuard
aGuard( maMutex
);
1177 FileViewResult
SvtFileView_Impl::GetFolderContent_Impl(
1178 std::u16string_view rFolder
,
1179 const FileViewAsyncAction
* pAsyncDescriptor
,
1180 const css::uno::Sequence
< OUString
>& rDenyList
)
1182 ::osl::ClearableMutexGuard
aGuard( maMutex
);
1183 INetURLObject
aFolderObj( rFolder
);
1184 DBG_ASSERT( aFolderObj
.GetProtocol() != INetProtocol::NotValid
, "Invalid URL!" );
1186 FolderDescriptor
aFolder( aFolderObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
1189 return GetFolderContent_Impl( aFolder
, pAsyncDescriptor
, rDenyList
);
1192 FileViewResult
SvtFileView_Impl::GetFolderContent_Impl(
1193 const FolderDescriptor
& _rFolder
,
1194 const FileViewAsyncAction
* pAsyncDescriptor
,
1195 const css::uno::Sequence
< OUString
>& rDenyList
)
1197 DBG_TESTSOLARMUTEX();
1198 ::osl::ClearableMutexGuard
aGuard( maMutex
);
1200 OSL_ENSURE( !m_xContentEnumerator
.is(), "SvtFileView_Impl::GetFolderContent_Impl: still running another enumeration!" );
1201 m_xContentEnumerator
.set(new ::svt::FileViewContentEnumerator(
1202 mxView
->GetCommandEnvironment(), maContent
, maMutex
));
1203 // TODO: should we cache and re-use this thread?
1205 if ( !pAsyncDescriptor
)
1207 ::svt::EnumerationResult eResult
= m_xContentEnumerator
->enumerateFolderContentSync( _rFolder
, rDenyList
);
1208 if ( ::svt::EnumerationResult::SUCCESS
== eResult
)
1210 implEnumerationSuccess();
1211 m_xContentEnumerator
.clear();
1214 m_xContentEnumerator
.clear();
1218 m_bRunningAsyncAction
= true;
1219 m_bAsyncActionCancelled
= false;
1220 m_eAsyncActionResult
= ::svt::EnumerationResult::ERROR
;
1221 m_aAsyncActionFinished
.reset();
1223 // don't (yet) set m_aCurrentAsyncActionHandler to pTimeout->aFinishHandler.
1224 // By definition, this handler *only* gets called when the result cannot be obtained
1225 // during the minimum wait time, so it is only set below, when needed.
1226 m_aCurrentAsyncActionHandler
= Link
<void*,void>();
1228 // minimum time to wait
1230 sal_Int32 nMinTimeout
= pAsyncDescriptor
->nMinTimeout
;
1231 OSL_ENSURE( nMinTimeout
> 0, "SvtFileView_Impl::GetFolderContent_Impl: invalid minimum timeout!" );
1232 if ( nMinTimeout
<= 0 )
1233 nMinTimeout
= sal_Int32( 1000 );
1234 aTimeout
.Seconds
= nMinTimeout
/ 1000;
1235 aTimeout
.Nanosec
= ( nMinTimeout
% 1000 ) * 1000000;
1237 m_xContentEnumerator
->enumerateFolderContent( _rFolder
, this );
1239 // wait until the enumeration is finished
1240 // for this, release our own mutex (which is used by the enumerator thread)
1243 ::osl::Condition::Result eResult
= ::osl::Condition::result_ok
;
1245 // also release the SolarMutex. Not all code which is needed during the enumeration
1246 // is Solar-Thread-Safe, in particular there is some code which needs to access
1247 // string resources (and our resource system relies on the SolarMutex :()
1248 SolarMutexReleaser aSolarRelease
;
1250 // now wait. Note that if we didn't get a pAsyncDescriptor, then this is an infinite wait.
1251 eResult
= m_aAsyncActionFinished
.wait( &aTimeout
);
1254 ::osl::MutexGuard
aGuard2( maMutex
);
1255 if ( ::osl::Condition::result_timeout
== eResult
)
1257 // maximum time to wait
1258 OSL_ENSURE(!m_xCancelAsyncTimer
,
1259 "SvtFileView_Impl::GetFolderContent_Impl: there's still a previous timer!");
1260 m_xCancelAsyncTimer
.set(new CallbackTimer(this));
1261 sal_Int32 nMaxTimeout
= pAsyncDescriptor
->nMaxTimeout
;
1262 OSL_ENSURE( nMaxTimeout
> nMinTimeout
,
1263 "SvtFileView_Impl::GetFolderContent_Impl: invalid maximum timeout!" );
1264 if ( nMaxTimeout
<= nMinTimeout
)
1265 nMaxTimeout
= nMinTimeout
+ 5000;
1266 m_xCancelAsyncTimer
->setRemainingTime( salhelper::TTimeValue( nMaxTimeout
- nMinTimeout
) );
1267 // we already waited for nMinTimeout milliseconds, so take this into account
1268 m_xCancelAsyncTimer
->start();
1270 m_aCurrentAsyncActionHandler
= pAsyncDescriptor
->aFinishHandler
;
1271 DBG_ASSERT( m_aCurrentAsyncActionHandler
.IsSet(), "SvtFileView_Impl::GetFolderContent_Impl: nobody interested when it's finished?" );
1274 mxIconView
->clear();
1275 return eStillRunning
;
1278 m_bRunningAsyncAction
= false;
1279 switch ( m_eAsyncActionResult
)
1281 case ::svt::EnumerationResult::SUCCESS
:
1284 case ::svt::EnumerationResult::ERROR
:
1288 SAL_WARN( "svtools.contnr", "SvtFileView_Impl::GetFolderContent_Impl: unreachable!" );
1292 void SvtFileView_Impl::FilterFolderContent_Impl( std::u16string_view rFilter
)
1294 if ( rFilter
.empty() || ( rFilter
== ALL_FILES_FILTER
) )
1295 // when replacing names, there is always something to filter (no view of ".nametranslation.table")
1298 ::osl::MutexGuard
aGuard( maMutex
);
1300 if ( maContent
.empty() )
1303 // collect the filter tokens
1304 ::std::vector
< WildCard
> aFilters
;
1305 FilterMatch::createWildCardFilterList(rFilter
,aFilters
);
1309 std::erase_if(maContent
,
1310 [&aFilters
](const std::unique_ptr
<SortingData_Impl
>& rxContent
) {
1311 if (rxContent
->mbIsFolder
)
1313 // normalize the content title (we always match case-insensitive)
1314 // 91872 - 11.09.2001 - frank.schoenheit@sun.com
1315 OUString sCompareString
= rxContent
->GetFileName(); // filter works on file name, not on title!
1316 return std::none_of(aFilters
.begin(), aFilters
.end(), FilterMatch(sCompareString
));
1320 IMPL_LINK_NOARG(SvtFileView_Impl
, ChangedHdl
, weld::TreeView
&, void)
1322 if (!mnSuspendSelectCallback
)
1323 m_aSelectHandler
.Call(m_pAntiImpl
);
1326 IMPL_LINK_NOARG(SvtFileView_Impl
, SelectionChangedHdl
, weld::IconView
&, void)
1328 if (!mnSuspendSelectCallback
)
1329 m_aSelectHandler
.Call(m_pAntiImpl
);
1332 void SvtFileView_Impl::SetSelectHandler(const Link
<SvtFileView
*,void>& rHdl
)
1334 m_aSelectHandler
= rHdl
;
1336 mxView
->connect_changed(LINK(this, SvtFileView_Impl
, ChangedHdl
));
1337 mxIconView
->connect_selection_changed(LINK(this, SvtFileView_Impl
, SelectionChangedHdl
));
1340 IMPL_LINK_NOARG(SvtFileView_Impl
, RowActivatedHdl
, weld::TreeView
&, bool)
1342 return maDoubleClickHandler
.Call(m_pAntiImpl
);
1345 IMPL_LINK_NOARG(SvtFileView_Impl
, ItemActivatedHdl
, weld::IconView
&, bool)
1347 return maDoubleClickHandler
.Call(m_pAntiImpl
);
1350 void SvtFileView_Impl::SetDoubleClickHandler(const Link
<SvtFileView
*,bool>& rHdl
)
1352 maDoubleClickHandler
= rHdl
;
1354 mxView
->connect_row_activated(LINK(this, SvtFileView_Impl
, RowActivatedHdl
));
1355 mxIconView
->connect_item_activated(LINK(this, SvtFileView_Impl
, ItemActivatedHdl
));
1358 void SvtFileView_Impl::OpenFolder_Impl()
1360 ::osl::MutexGuard
aGuard( maMutex
);
1363 mxIconView
->freeze();
1366 mxIconView
->clear();
1368 for (auto const& elem
: maContent
)
1370 if (mbOnlyFolder
&& !elem
->mbIsFolder
)
1373 // insert entry and set user data
1374 maEntries
.emplace_back(std::make_unique
<SvtContentEntry
>(elem
->maTargetURL
, elem
->mbIsFolder
));
1375 OUString
sId(weld::toId(maEntries
.back().get()));
1376 mxView
->append(sId
, elem
->maDisplayName
, elem
->maType
, elem
->maDisplaySize
, elem
->maDisplayDate
, elem
->maImage
);
1377 mxIconView
->append(sId
, elem
->maDisplayName
, elem
->maImage
);
1380 ++mnSuspendSelectCallback
;
1383 //set sort indicator
1384 weld::TreeView
* pView
= mxView
->getWidget();
1385 pView
->set_sort_indicator(mbAscending
? TRISTATE_TRUE
: TRISTATE_FALSE
, GetSortColumn());
1388 --mnSuspendSelectCallback
;
1393 void SvtFileView_Impl::ResetCursor()
1395 if (mxView
->get_visible())
1397 std::unique_ptr
<weld::TreeIter
> xFirst
= mxView
->make_iterator();
1398 if (mxView
->get_iter_first(*xFirst
))
1400 // set cursor to the first entry
1401 mxView
->set_cursor(*xFirst
);
1404 mxView
->unselect_all();
1408 std::unique_ptr
<weld::TreeIter
> xFirst
= mxIconView
->make_iterator();
1409 if (mxIconView
->get_iter_first(*xFirst
))
1411 // set cursor to the first entry
1412 mxIconView
->set_cursor(*xFirst
);
1415 mxIconView
->unselect_all();
1419 void SvtFileView_Impl::CancelRunningAsyncAction()
1421 DBG_TESTSOLARMUTEX();
1422 ::osl::MutexGuard
aGuard( maMutex
);
1423 if ( !m_xContentEnumerator
.is() )
1426 m_bAsyncActionCancelled
= true;
1427 m_xContentEnumerator
->cancel();
1428 m_bRunningAsyncAction
= false;
1430 m_xContentEnumerator
.clear();
1431 if ( m_xCancelAsyncTimer
.is() && m_xCancelAsyncTimer
->isTicking() )
1432 m_xCancelAsyncTimer
->stop();
1433 m_xCancelAsyncTimer
.clear();
1437 void SvtFileView_Impl::onTimeout()
1439 SolarMutexGuard aSolarGuard
;
1440 ::osl::MutexGuard
aGuard( maMutex
);
1441 if ( !m_bRunningAsyncAction
)
1442 // there might have been a race condition while we waited for the mutex
1445 CancelRunningAsyncAction();
1447 if ( m_aCurrentAsyncActionHandler
.IsSet() )
1449 Application::PostUserEvent( m_aCurrentAsyncActionHandler
, reinterpret_cast< void* >( eTimeout
) );
1450 m_aCurrentAsyncActionHandler
= Link
<void*,void>();
1455 void SvtFileView_Impl::enumerationDone( ::svt::EnumerationResult eResult
)
1457 SolarMutexGuard aSolarGuard
;
1458 ::osl::MutexGuard
aGuard( maMutex
);
1460 m_xContentEnumerator
.clear();
1461 if ( m_xCancelAsyncTimer
.is() && m_xCancelAsyncTimer
->isTicking() )
1462 m_xCancelAsyncTimer
->stop();
1463 m_xCancelAsyncTimer
.clear();
1465 if ( m_bAsyncActionCancelled
)
1466 // this is to prevent race conditions
1469 m_eAsyncActionResult
= eResult
;
1470 m_bRunningAsyncAction
= false;
1472 m_aAsyncActionFinished
.set();
1474 if ( svt::EnumerationResult::SUCCESS
== eResult
)
1475 implEnumerationSuccess();
1477 if ( m_aCurrentAsyncActionHandler
.IsSet() )
1479 Application::PostUserEvent( m_aCurrentAsyncActionHandler
, reinterpret_cast< void* >( m_eAsyncActionResult
) );
1480 m_aCurrentAsyncActionHandler
= Link
<void*,void>();
1485 void SvtFileView_Impl::implEnumerationSuccess()
1487 FilterFolderContent_Impl( maCurrentFilter
);
1488 SortFolderContent_Impl();
1489 CreateDisplayText_Impl();
1491 maOpenDoneLink
.Call( m_pAntiImpl
);
1494 OUString
SvtFileView_Impl::ReplaceTabWithString(const OUString
& rValue
)
1496 return rValue
.replaceAll(u
"\t", u
"%09");
1499 void SvtFileView_Impl::CreateDisplayText_Impl()
1501 ::osl::MutexGuard
aGuard( maMutex
);
1503 for (auto const& elem
: maContent
)
1505 // title, type, size, date
1506 elem
->maDisplayName
= ReplaceTabWithString(elem
->GetTitle());
1507 // folders don't have a size
1508 if ( ! elem
->mbIsFolder
)
1509 elem
->maDisplaySize
= CreateExactSizeText( elem
->maSize
);
1510 // set the date, but volumes have no date
1511 if ( ! elem
->mbIsFolder
|| ! elem
->mbIsVolume
)
1513 SvtSysLocale aSysLocale
;
1514 const LocaleDataWrapper
& rLocaleData
= aSysLocale
.GetLocaleData();
1515 elem
->maDisplayDate
= rLocaleData
.getDate( elem
->maModDate
)
1517 + rLocaleData
.getTime( elem
->maModDate
, false );
1521 if ( elem
->mbIsFolder
)
1523 ::svtools::VolumeInfo
aVolInfo( elem
->mbIsVolume
, elem
->mbIsRemote
,
1524 elem
->mbIsRemoveable
, elem
->mbIsFloppy
,
1525 elem
->mbIsCompactDisc
);
1526 elem
->maImage
= SvFileInformationManager::GetFolderImageId(aVolInfo
);
1529 elem
->maImage
= SvFileInformationManager::GetFileImageId(INetURLObject(elem
->maTargetURL
));
1533 void SvtFileView_Impl::Resort_Impl( sal_Int16 nColumn
, bool bAscending
)
1535 // TODO: IconView ()
1536 ::osl::MutexGuard
aGuard( maMutex
);
1538 if ( ( nColumn
== mnSortColumn
) &&
1539 ( bAscending
== mbAscending
) )
1542 // reset the quick search index
1543 mxView
->ResetQuickSearch_Impl( nullptr );
1545 std::unique_ptr
<weld::TreeIter
> xEntry(mxView
->make_iterator());
1546 bool bEntry
= mxView
->get_cursor(xEntry
.get());
1549 if (bEntry
&& !mxView
->get_id(*xEntry
).isEmpty())
1550 aEntryURL
= weld::fromId
<SvtContentEntry
*>(mxView
->get_id(*xEntry
))->maURL
;
1552 mnSortColumn
= nColumn
;
1553 mbAscending
= bAscending
;
1555 SortFolderContent_Impl();
1558 if ( !mbIsFirstResort
)
1560 int nPos
= GetEntryPos( aEntryURL
);
1561 if (nPos
!= -1 && nPos
< mxView
->n_children())
1563 ++mnSuspendSelectCallback
; // #i15668#
1564 mxView
->set_cursor(nPos
);
1565 --mnSuspendSelectCallback
;
1569 mbIsFirstResort
= false;
1572 static bool gbAscending
= true;
1573 static sal_Int16 gnColumn
= COLUMN_TITLE
;
1574 static const CollatorWrapper
* pCollatorWrapper
= nullptr;
1576 /* this function returns true, if aOne is less than aTwo
1578 static bool CompareSortingData_Impl( std::unique_ptr
<SortingData_Impl
> const & aOne
, std::unique_ptr
<SortingData_Impl
> const & aTwo
)
1580 assert(pCollatorWrapper
&& "*CompareSortingData_Impl(): Can't work this way!");
1584 bool bEqual
= false;
1586 if ( aOne
->mbIsFolder
!= aTwo
->mbIsFolder
)
1588 bRet
= aOne
->mbIsFolder
;
1590 // !!! pb: #100376# folder always on top
1599 // compare case insensitive first
1600 nComp
= pCollatorWrapper
->compareString( aOne
->GetLowerTitle(), aTwo
->GetLowerTitle() );
1603 nComp
= pCollatorWrapper
->compareString( aOne
->GetTitle(), aTwo
->GetTitle() );
1607 else if ( nComp
> 0 )
1613 nComp
= pCollatorWrapper
->compareString( aOne
->maType
, aTwo
->maType
);
1616 else if ( nComp
> 0 )
1622 if ( aOne
->maSize
< aTwo
->maSize
)
1624 else if ( aOne
->maSize
> aTwo
->maSize
)
1630 if ( aOne
->maModDate
< aTwo
->maModDate
)
1632 else if ( aOne
->maModDate
> aTwo
->maModDate
)
1638 SAL_INFO( "svtools.contnr", "CompareSortingData_Impl: Compare unknown type!" );
1643 // when the two elements are equal, we must not return sal_True (which would
1644 // happen if we just return ! ( a < b ) when not sorting ascending )
1648 return gbAscending
? bRet
: !bRet
;
1652 void SvtFileView_Impl::SortFolderContent_Impl()
1654 ::osl::MutexGuard
aGuard( maMutex
);
1656 if ( maContent
.size() > 1 )
1658 gbAscending
= mbAscending
;
1659 gnColumn
= mnSortColumn
;
1660 pCollatorWrapper
= aIntlWrapper
.getCaseCollator();
1662 std::stable_sort( maContent
.begin(), maContent
.end(), CompareSortingData_Impl
);
1664 pCollatorWrapper
= nullptr;
1669 void SvtFileView_Impl::EntryRemoved( std::u16string_view rURL
)
1671 ::osl::MutexGuard
aGuard( maMutex
);
1673 maContent
.erase(std::find_if(maContent
.begin(), maContent
.end(),
1674 [&](const std::unique_ptr
<SortingData_Impl
> & data
) { return data
->maTargetURL
== rURL
; }));
1678 void SvtFileView_Impl::EntryRenamed( OUString
& rURL
,
1679 const OUString
& rTitle
)
1681 ::osl::MutexGuard
aGuard( maMutex
);
1683 auto aFoundElem
= std::find_if(maContent
.begin(), maContent
.end(),
1684 [&](const std::unique_ptr
<SortingData_Impl
> & data
) { return data
->maTargetURL
== rURL
; });
1685 if (aFoundElem
!= maContent
.end())
1687 (*aFoundElem
)->SetNewTitle( rTitle
);
1688 (*aFoundElem
)->maDisplayName
= ReplaceTabWithString(rTitle
);
1690 INetURLObject
aURLObj( rURL
);
1691 aURLObj
.setName( rTitle
, INetURLObject::EncodeMechanism::All
);
1693 rURL
= aURLObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1695 (*aFoundElem
)->maTargetURL
= rURL
;
1699 const SortingData_Impl
& SvtFileView_Impl::FolderInserted( const OUString
& rURL
, const OUString
& rTitle
)
1701 ::osl::MutexGuard
aGuard( maMutex
);
1703 std::unique_ptr
<SortingData_Impl
> pData(new SortingData_Impl
);
1705 pData
->SetNewTitle( rTitle
);
1707 pData
->mbIsFolder
= true;
1708 pData
->maTargetURL
= rURL
;
1710 ::svtools::VolumeInfo aVolInfo
;
1711 pData
->maType
= SvFileInformationManager::GetFolderDescription( aVolInfo
);
1712 pData
->maImage
= SvFileInformationManager::GetFolderImageId( aVolInfo
);
1714 // title, type, size, date
1715 pData
->maDisplayName
= ReplaceTabWithString(pData
->GetTitle());
1717 SvtSysLocale aSysLocale
;
1718 const LocaleDataWrapper
& rLocaleData
= aSysLocale
.GetLocaleData();
1719 pData
->maDisplayDate
= rLocaleData
.getDate( pData
->maModDate
)
1721 + rLocaleData
.getTime( pData
->maModDate
);
1723 maContent
.push_back( std::move(pData
) );
1725 return *maContent
.back();
1728 int SvtFileView_Impl::GetEntryPos(std::u16string_view rURL
)
1730 ::osl::MutexGuard
aGuard( maMutex
);
1732 auto aFoundElem
= std::find_if(maContent
.begin(), maContent
.end(),
1733 [&](const std::unique_ptr
<SortingData_Impl
> & data
) { return data
->maTargetURL
== rURL
; });
1734 return aFoundElem
!= maContent
.end() ? std::distance(maContent
.begin(), aFoundElem
) : -1;
1737 void SvtFileView_Impl::SetViewMode( FileViewMode eMode
)
1757 bool SvtFileView_Impl::SearchNextEntry( sal_uInt32
& nIndex
, std::u16string_view rTitle
, bool bWrapAround
)
1759 ::osl::MutexGuard
aGuard( maMutex
);
1761 sal_uInt32 nEnd
= maContent
.size();
1762 sal_uInt32 nStart
= nIndex
;
1763 while ( nIndex
< nEnd
)
1765 SortingData_Impl
* pData
= maContent
[ nIndex
].get();
1766 if ( pData
->GetLowerTitle().startsWith( rTitle
) )
1774 while ( nIndex
< nEnd
&& nIndex
<= nStart
)
1776 SortingData_Impl
* pData
= maContent
[ nIndex
].get();
1777 if ( pData
->GetLowerTitle().startsWith( rTitle
) )
1787 void SAL_CALL
CallbackTimer::onShot()
1789 OSL_ENSURE( m_pTimeoutHandler
, "CallbackTimer::onShot: nobody interested in?" );
1790 SvtFileView_Impl
* pHandler( m_pTimeoutHandler
);
1792 pHandler
->onTimeout();
1796 void SvtFileView::selected_foreach(const std::function
<bool(weld::TreeIter
&)>& func
)
1798 if (mpImpl
->mxView
->get_visible())
1799 mpImpl
->mxView
->selected_foreach(func
);
1801 mpImpl
->mxIconView
->selected_foreach(func
);
1804 weld::Widget
* SvtFileView::identifier() const
1806 return mpImpl
->mxView
->getWidget();
1809 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */