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::lang
;
68 using namespace ::com::sun::star::sdbc
;
69 using namespace ::com::sun::star::task
;
70 using namespace ::com::sun::star::ucb
;
71 using namespace ::com::sun::star::uno
;
72 using namespace ::com::sun::star::io
;
73 using namespace ::com::sun::star::beans
;
74 using namespace ::comphelper
;
75 using ::svt::SortingData_Impl
;
76 using ::svt::FolderDescriptor
;
78 constexpr OUStringLiteral ALL_FILES_FILTER
= u
"*.*";
80 #define COLUMN_TITLE 1
85 #define QUICK_SEARCH_TIMEOUT 1500 // time in mSec before the quicksearch string will be reset
89 enum class FileViewFlags
92 MULTISELECTION
= 0x02,
101 template<> struct typed_flags
<FileViewFlags
> : is_typed_flags
<FileViewFlags
, 0x26> {};
109 class CallbackTimer
: public ::salhelper::Timer
112 SvtFileView_Impl
* const m_pTimeoutHandler
;
115 explicit CallbackTimer( SvtFileView_Impl
* _pHandler
) : m_pTimeoutHandler( _pHandler
) { }
118 virtual void SAL_CALL
onShot() override
;
121 class ViewTabListBox_Impl
124 Reference
< XCommandEnvironment
> mxCmdEnv
;
125 std::unique_ptr
<weld::TreeView
> mxTreeView
;
126 std::unique_ptr
<weld::TreeIter
> mxScratchIter
;
128 ::osl::Mutex maMutex
;
129 SvtFileView_Impl
* mpParent
;
130 Timer maResetQuickSearch
{ "fpicker SvtFileView_Impl maResetQuickSearch" };
131 OUString maQuickSearchText
;
132 sal_uInt32 mnSearchIndex
;
135 bool const mbShowType
;
137 void DeleteEntries();
138 void DoQuickSearch( sal_Unicode rChar
);
139 bool Kill( const OUString
& rURL
);
142 ViewTabListBox_Impl(std::unique_ptr
<weld::TreeView
> xTreeView
, weld::Window
* pTopLevel
, SvtFileView_Impl
* pParent
, FileViewFlags nFlags
);
144 std::unique_ptr
<weld::TreeIter
> make_iterator() const { return mxTreeView
->make_iterator(); }
145 void insert(const OUString
&rEntry
, const OUString
& rId
, const OUString
& rImage
, weld::TreeIter
& rIter
)
147 mxTreeView
->insert(nullptr, -1, &rEntry
, &rId
, nullptr, nullptr, false, &rIter
);
148 mxTreeView
->set_image(rIter
, rImage
);
150 void append(const OUString
& rId
, const OUString
& rStr
, const OUString
& rType
, const OUString
& rSize
, const OUString
& rDate
, const OUString
& rImage
)
152 mxTreeView
->insert(nullptr, -1, &rStr
, &rId
, nullptr, nullptr, false, mxScratchIter
.get());
153 mxTreeView
->set_image(*mxScratchIter
, rImage
);
156 mxTreeView
->set_text(*mxScratchIter
, rType
, nCol
++);
157 mxTreeView
->set_text(*mxScratchIter
, rSize
, nCol
++);
158 mxTreeView
->set_text(*mxScratchIter
, rDate
, nCol
++);
161 void scroll_to_row(const weld::TreeIter
& rIter
) { mxTreeView
->scroll_to_row(rIter
); }
162 void set_cursor(int nPos
) { mxTreeView
->set_cursor(nPos
); }
163 void set_cursor(const weld::TreeIter
& rIter
) { mxTreeView
->set_cursor(rIter
); }
164 bool get_cursor(weld::TreeIter
* pIter
) const { return mxTreeView
->get_cursor(pIter
); }
165 bool get_iter_first(weld::TreeIter
& rIter
) const { return mxTreeView
->get_iter_first(rIter
); }
166 bool get_selected(weld::TreeIter
* pIter
) const { return mxTreeView
->get_selected(pIter
); }
168 OUString
get_selected_text() const
170 // tdf#131898 only care about column 0
171 int nIndex
= mxTreeView
->get_selected_index();
172 return nIndex
!= -1 ? mxTreeView
->get_text(nIndex
, 0) : OUString();
175 void unselect_all() { mxTreeView
->unselect_all(); }
177 OUString
get_id(const weld::TreeIter
& rIter
) { return mxTreeView
->get_id(rIter
); }
179 void connect_row_activated(const Link
<weld::TreeView
&, bool>& rLink
) { mxTreeView
->connect_row_activated(rLink
); }
180 void connect_changed(const Link
<weld::TreeView
&, void>& rLink
) { mxTreeView
->connect_changed(rLink
); }
182 int n_children() const { return mxTreeView
->n_children(); }
184 void freeze() { mxTreeView
->freeze(); }
185 void thaw() { mxTreeView
->thaw(); }
187 void show() { mxTreeView
->show(); }
188 void hide() { mxTreeView
->hide(); }
189 bool get_visible() const { return mxTreeView
->get_visible(); }
191 int count_selected_rows() const { return mxTreeView
->count_selected_rows(); }
193 void grab_focus() { mxTreeView
->grab_focus(); }
194 bool has_focus() const { return mxTreeView
->has_focus(); }
196 void set_help_id(const OUString
& rHelpId
) { mxTreeView
->set_help_id(rHelpId
); }
197 OUString
get_help_id() const { return mxTreeView
->get_help_id(); }
199 bool IsEditingActive() const { return mbEditing
; }
203 mxTreeView
->end_editing();
204 mxTreeView
->connect_editing(Link
<const weld::TreeIter
&, bool>(), Link
<const IterString
&, bool>());
208 void selected_foreach(const std::function
<bool(weld::TreeIter
&)>& func
)
210 mxTreeView
->selected_foreach(func
);
213 weld::TreeView
* getWidget() const
215 return mxTreeView
.get();
218 void clear() { mxTreeView
->clear(); }
220 void EnableDelete( bool bEnable
) { mbEnableDelete
= bEnable
; }
221 bool TypeColumnVisible() const { return mbShowType
; }
223 const Reference
< XCommandEnvironment
>& GetCommandEnvironment() const { return mxCmdEnv
; }
225 DECL_LINK(ResetQuickSearch_Impl
, Timer
*, void);
226 DECL_LINK(CommandHdl
, const CommandEvent
&, bool);
227 DECL_LINK(EditingEntryHdl
, const weld::TreeIter
&, bool);
228 typedef std::pair
<const weld::TreeIter
&, OUString
> IterString
;
229 DECL_LINK(EditedEntryHdl
, const IterString
&, bool);
230 DECL_LINK(KeyInputHdl
, const KeyEvent
&, bool);
232 void ExecuteContextMenuAction(std::u16string_view rSelectedPopentry
);
238 class SvtFileView_Impl
:public ::svt::IEnumerationResultHandler
241 SvtFileView
* m_pAntiImpl
;
242 Link
<SvtFileView
*,void> m_aSelectHandler
;
244 ::rtl::Reference
< ::svt::FileViewContentEnumerator
>
245 m_xContentEnumerator
;
246 Link
<void*,void> m_aCurrentAsyncActionHandler
;
247 ::osl::Condition m_aAsyncActionFinished
;
248 ::rtl::Reference
< ::salhelper::Timer
> m_xCancelAsyncTimer
;
249 ::svt::EnumerationResult m_eAsyncActionResult
;
250 bool m_bRunningAsyncAction
;
251 bool m_bAsyncActionCancelled
;
255 ::std::vector
<std::unique_ptr
<SortingData_Impl
>> maContent
;
256 ::std::vector
<std::unique_ptr
<SvtContentEntry
>> maEntries
;
257 ::osl::Mutex maMutex
;
259 weld::Window
* m_pTopLevel
;
260 std::unique_ptr
<ViewTabListBox_Impl
> mxView
;
261 std::unique_ptr
<weld::IconView
> mxIconView
;
262 sal_uInt16 mnSortColumn
;
263 bool mbAscending
: 1;
264 bool const mbOnlyFolder
: 1;
265 sal_Int16 mnSuspendSelectCallback
: 1;
266 bool mbIsFirstResort
: 1;
268 IntlWrapper
const aIntlWrapper
;
271 OUString maCurrentFilter
;
272 OUString maFolderImage
;
273 Link
<SvtFileView
*,void> maOpenDoneLink
;
274 Link
<SvtFileView
*,bool> maDoubleClickHandler
;
276 Reference
< XCommandEnvironment
> mxCmdEnv
;
278 SvtFileView_Impl(SvtFileView
* pAntiImpl
, weld::Window
* pTopLevel
,
279 std::unique_ptr
<weld::TreeView
> xTreeView
,
280 std::unique_ptr
<weld::IconView
> xIconView
,
281 Reference
< XCommandEnvironment
> const & xEnv
,
282 FileViewFlags nFlags
,
285 virtual ~SvtFileView_Impl();
289 FileViewResult
GetFolderContent_Impl(
290 std::u16string_view rFolder
,
291 const FileViewAsyncAction
* pAsyncDescriptor
,
292 const css::uno::Sequence
< OUString
>& rDenyList
);
294 FileViewResult
GetFolderContent_Impl(
295 const FolderDescriptor
& _rFolder
,
296 const FileViewAsyncAction
* pAsyncDescriptor
,
297 const css::uno::Sequence
< OUString
>& rDenyList
);
298 void FilterFolderContent_Impl( std::u16string_view rFilter
);
299 void CancelRunningAsyncAction();
301 void OpenFolder_Impl();
302 static OUString
ReplaceTabWithString(const OUString
& rValue
);
303 void CreateDisplayText_Impl();
304 void SortFolderContent_Impl();
306 void EntryRemoved( std::u16string_view rURL
);
307 void EntryRenamed( OUString
& rURL
,
308 const OUString
& rName
);
309 const SortingData_Impl
& FolderInserted( const OUString
& rURL
,
310 const OUString
& rTitle
);
312 int GetEntryPos( std::u16string_view rURL
);
314 void SetViewMode( FileViewMode eMode
);
316 inline void EnableDelete( bool bEnable
);
318 void Resort_Impl( sal_Int16 nColumn
, bool bAscending
);
319 bool SearchNextEntry( sal_uInt32
&nIndex
,
320 std::u16string_view rTitle
,
323 void SetSelectHandler( const Link
<SvtFileView
*,void>& rHdl
);
324 void SetDoubleClickHandler(const Link
<SvtFileView
*,bool>& rHdl
);
330 if (mxView
->IsEditingActive())
331 mxView
->end_editing();
338 if (mxView
->get_visible())
339 mxView
->grab_focus();
341 mxIconView
->grab_focus();
344 bool has_focus() const
346 return mxView
->has_focus() || mxIconView
->has_focus();
349 int GetSortColumn() const
351 sal_uInt16 nOldSortID
= mnSortColumn
;
353 if (!mxView
->TypeColumnVisible() && nOldSortID
!= COLUMN_TITLE
)
355 return nOldSortID
- 1;
359 DECL_LINK(ChangedHdl
, weld::TreeView
&, void);
360 DECL_LINK(SelectionChangedHdl
, weld::IconView
&, void);
361 DECL_LINK(RowActivatedHdl
, weld::TreeView
&, bool);
362 DECL_LINK(ItemActivatedHdl
, weld::IconView
&, bool);
364 // IEnumerationResultHandler overridables
365 virtual void enumerationDone( ::svt::EnumerationResult eResult
) override
;
366 void implEnumerationSuccess();
369 inline void SvtFileView_Impl::EnableDelete( bool bEnable
)
371 mxView
->EnableDelete( bEnable
);
376 // functions -------------------------------------------------------------
378 OUString
CreateExactSizeText( sal_Int64 nSize
)
380 double fSize( static_cast<double>(nSize
) );
383 tools::Long nMega
= 1024 * 1024;
384 tools::Long nGiga
= nMega
* 1024;
386 OUString
aUnitStr(' ');
390 aUnitStr
+= SvtResId(STR_SVT_BYTES
);
393 else if ( nSize
< nMega
)
396 aUnitStr
+= SvtResId(STR_SVT_KB
);
399 else if ( nSize
< nGiga
)
402 aUnitStr
+= SvtResId(STR_SVT_MB
);
408 aUnitStr
+= SvtResId(STR_SVT_GB
);
413 ::rtl::math::doubleToUString( fSize
,
414 rtl_math_StringFormat_F
, nDec
,
415 SvtSysLocale().GetLocaleData().getNumDecimalSep()[0]) +
422 ViewTabListBox_Impl::ViewTabListBox_Impl(std::unique_ptr
<weld::TreeView
> xTreeView
,
423 weld::Window
* pTopLevel
,
424 SvtFileView_Impl
* pParent
,
425 FileViewFlags nFlags
)
426 : mxTreeView(std::move(xTreeView
))
427 , mxScratchIter(mxTreeView
->make_iterator())
428 , mpParent( pParent
)
430 , mbEnableDelete( false )
432 , mbShowType(nFlags
& FileViewFlags::SHOW_TYPE
)
434 std::vector
<int> aWidths
{ 180 };
435 if (nFlags
& FileViewFlags::SHOW_TYPE
)
436 aWidths
.push_back(140);
437 aWidths
.push_back(80);
438 mxTreeView
->set_column_fixed_widths(aWidths
);
440 if (nFlags
& FileViewFlags::MULTISELECTION
)
441 mxTreeView
->set_selection_mode(SelectionMode::Multiple
);
443 maResetQuickSearch
.SetTimeout( QUICK_SEARCH_TIMEOUT
);
444 maResetQuickSearch
.SetInvokeHandler( LINK( this, ViewTabListBox_Impl
, ResetQuickSearch_Impl
) );
446 Reference
< XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
447 Reference
< XInteractionHandler
> xInteractionHandler(
448 InteractionHandler::createWithParent(xContext
, pTopLevel
->GetXWindow()), UNO_QUERY_THROW
);
450 mxCmdEnv
= new ::ucbhelper::CommandEnvironment( xInteractionHandler
, Reference
< XProgressHandler
>() );
452 mxTreeView
->connect_popup_menu(LINK(this, ViewTabListBox_Impl
, CommandHdl
));
453 mxTreeView
->connect_key_press(LINK(this, ViewTabListBox_Impl
, KeyInputHdl
));
456 IMPL_LINK_NOARG(ViewTabListBox_Impl
, EditingEntryHdl
, const weld::TreeIter
&, bool)
461 IMPL_LINK_NOARG(ViewTabListBox_Impl
, ResetQuickSearch_Impl
, Timer
*, void)
463 ::osl::MutexGuard
aGuard( maMutex
);
465 maQuickSearchText
.clear();
469 IMPL_LINK(ViewTabListBox_Impl
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
474 bool bHandled
= false;
476 const vcl::KeyCode
& rKeyCode
= rKEvt
.GetKeyCode();
477 if ( 0 == rKeyCode
.GetModifier() )
479 if ( ( rKeyCode
.GetCode() == KEY_DELETE
) &&
482 ResetQuickSearch_Impl( nullptr );
486 else if ( ( rKEvt
.GetKeyCode().GetGroup() == KEYGROUP_NUM
) ||
487 ( rKEvt
.GetKeyCode().GetGroup() == KEYGROUP_ALPHA
) )
489 DoQuickSearch( rKEvt
.GetCharCode() );
495 ResetQuickSearch_Impl( nullptr );
499 IMPL_LINK(ViewTabListBox_Impl
, CommandHdl
, const CommandEvent
&, rCEvt
, bool)
501 if (rCEvt
.GetCommand() != CommandEventId::ContextMenu
)
504 bool bEnableDelete
= mbEnableDelete
;
505 bool bEnableRename
= true;
508 mxTreeView
->selected_foreach([this, &nCount
, &bEnableDelete
, &bEnableRename
](weld::TreeIter
& rEntry
){
511 ::ucbhelper::Content aCnt
;
514 OUString
aURL(weld::fromId
<SvtContentEntry
*>(
515 mxTreeView
->get_id(rEntry
))->maURL
);
516 aCnt
= ::ucbhelper::Content( aURL
, mxCmdEnv
, comphelper::getProcessComponentContext() );
518 catch( Exception
const & )
520 bEnableDelete
= bEnableRename
= false;
527 Reference
< XCommandInfo
> aCommands
= aCnt
.getCommands();
528 if ( aCommands
.is() )
529 bEnableDelete
= aCommands
->hasCommandByName( "delete" );
531 bEnableDelete
= false;
533 catch( Exception
const & )
535 bEnableDelete
= false;
543 Reference
< XPropertySetInfo
> aProps
= aCnt
.getProperties();
546 Property aProp
= aProps
->getPropertyByName("Title");
548 = !( aProp
.Attributes
& PropertyAttribute::READONLY
);
551 bEnableRename
= false;
553 catch( Exception
const & )
555 bEnableRename
= false;
559 bool bStop
= !bEnableDelete
&& !bEnableRename
;
564 bEnableDelete
= false;
566 bEnableRename
= false;
568 if (bEnableDelete
|| bEnableRename
)
570 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(mxTreeView
.get(), "svt/ui/fileviewmenu.ui"));
571 auto xContextMenu
= xBuilder
->weld_menu("menu");
572 xContextMenu
->set_visible("delete", bEnableDelete
);
573 xContextMenu
->set_visible("rename", bEnableRename
);
574 OUString
sCommand(xContextMenu
->popup_at_rect(mxTreeView
.get(), tools::Rectangle(rCEvt
.GetMousePosPixel(), Size(1,1))));
575 ExecuteContextMenuAction(sCommand
);
581 void ViewTabListBox_Impl::ExecuteContextMenuAction(std::u16string_view rSelectedPopupEntry
)
583 if (rSelectedPopupEntry
== u
"delete")
585 else if (rSelectedPopupEntry
== u
"rename")
587 std::unique_ptr
<weld::TreeIter
> xEntry
= mxTreeView
->make_iterator();
588 if (mxTreeView
->get_selected(xEntry
.get()))
592 mxTreeView
->connect_editing(LINK(this, ViewTabListBox_Impl
, EditingEntryHdl
),
593 LINK(this, ViewTabListBox_Impl
, EditedEntryHdl
));
595 mxTreeView
->start_editing(*xEntry
);
600 void ViewTabListBox_Impl::DeleteEntries()
602 short eResult
= svtools::QUERYDELETE_YES
;
604 mxTreeView
->selected_foreach([this, &eResult
](weld::TreeIter
& rCurEntry
){
606 if (!mxTreeView
->get_id(rCurEntry
).isEmpty())
607 aURL
= weld::fromId
<SvtContentEntry
*>(mxTreeView
->get_id(rCurEntry
))->maURL
;
610 mxTreeView
->unselect(rCurEntry
);
614 bool canDelete
= true;
617 ::ucbhelper::Content
aCnt( aURL
, mxCmdEnv
, comphelper::getProcessComponentContext() );
618 Reference
< XCommandInfo
> aCommands
= aCnt
.getCommands();
619 if ( aCommands
.is() )
620 canDelete
= aCommands
->hasCommandByName( "delete" );
624 catch( Exception
const & )
631 mxTreeView
->unselect(rCurEntry
);
632 return false; // process next entry
635 if ( eResult
!= svtools::QUERYDELETE_ALL
)
637 INetURLObject
aObj( aURL
);
638 svtools::QueryDeleteDlg_Impl
aDlg(
639 mxTreeView
.get(), aObj
.GetLastName(INetURLObject::DecodeMechanism::WithCharset
));
641 if (mxTreeView
->count_selected_rows() > 1)
642 aDlg
.EnableAllButton();
644 eResult
= aDlg
.run();
647 bool bDeleted
= false;
649 if (eResult
== svtools::QUERYDELETE_ALL
|| eResult
== svtools::QUERYDELETE_YES
)
653 mpParent
->EntryRemoved( aURL
);
659 mxTreeView
->unselect(rCurEntry
);
664 mxTreeView
->remove_selection();
667 IMPL_LINK(ViewTabListBox_Impl
, EditedEntryHdl
, const IterString
&, rIterString
, bool)
671 mxTreeView
->connect_editing(Link
<const weld::TreeIter
&, bool>(), Link
<const IterString
&, bool>());
673 const weld::TreeIter
& rEntry
= rIterString
.first
;
674 OUString sNewText
= rIterString
.second
;
676 if (sNewText
.isEmpty())
682 SvtContentEntry
* pData
= weld::fromId
<SvtContentEntry
*>(mxTreeView
->get_id(rEntry
));
687 if ( aURL
.isEmpty() )
692 OUString
aPropName( "Title" );
693 bool canRename
= true;
694 ::ucbhelper::Content
aContent( aURL
, mxCmdEnv
, comphelper::getProcessComponentContext() );
698 Reference
< XPropertySetInfo
> aProps
= aContent
.getProperties();
701 Property aProp
= aProps
->getPropertyByName( aPropName
);
702 canRename
= !( aProp
.Attributes
& PropertyAttribute::READONLY
);
709 catch ( Exception
const & )
718 aContent
.setPropertyValue( aPropName
, aValue
);
719 mpParent
->EntryRenamed(aURL
, sNewText
);
724 mxTreeView
->set_id(rEntry
, weld::toId(pData
));
729 catch( Exception
const & )
736 void ViewTabListBox_Impl::DoQuickSearch( sal_Unicode rChar
)
738 ::osl::MutexGuard
aGuard( maMutex
);
740 maResetQuickSearch
.Stop();
742 OUString aLastText
= maQuickSearchText
;
743 sal_uInt32 aLastPos
= mnSearchIndex
;
745 maQuickSearchText
+= OUString(rChar
).toAsciiLowerCase();
747 bool bFound
= mpParent
->SearchNextEntry( mnSearchIndex
, maQuickSearchText
, false );
749 if ( !bFound
&& ( aLastText
.getLength() == 1 ) &&
750 ( aLastText
== OUStringChar(rChar
) ) )
752 mnSearchIndex
= aLastPos
+ 1;
753 maQuickSearchText
= aLastText
;
754 bFound
= mpParent
->SearchNextEntry( mnSearchIndex
, maQuickSearchText
, true );
759 mxTreeView
->unselect_all();
760 mxTreeView
->select(mnSearchIndex
);
761 mxTreeView
->set_cursor(mnSearchIndex
);
762 mxTreeView
->scroll_to_row(mnSearchIndex
);
765 maResetQuickSearch
.Start();
768 bool ViewTabListBox_Impl::Kill( const OUString
& rContent
)
774 ::ucbhelper::Content
aCnt( rContent
, mxCmdEnv
, comphelper::getProcessComponentContext() );
775 aCnt
.executeCommand( "delete", Any( true ) );
777 catch( css::ucb::CommandAbortedException
const & )
779 SAL_INFO( "svtools.contnr", "CommandAbortedException" );
782 catch( Exception
const & )
784 SAL_INFO( "svtools.contnr", "Any other exception" );
791 SvtFileView::SvtFileView(weld::Window
* pTopLevel
,
792 std::unique_ptr
<weld::TreeView
> xTreeView
,
793 std::unique_ptr
<weld::IconView
> xIconView
,
794 bool bOnlyFolder
, bool bMultiSelection
, bool bShowType
)
796 FileViewFlags nFlags
= FileViewFlags::NONE
;
797 if ( bMultiSelection
)
798 nFlags
|= FileViewFlags::MULTISELECTION
;
800 nFlags
|= FileViewFlags::SHOW_TYPE
;
802 Reference
< XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
803 Reference
< XInteractionHandler
> xInteractionHandler(
804 InteractionHandler::createWithParent(xContext
, pTopLevel
->GetXWindow()), UNO_QUERY_THROW
);
805 Reference
< XCommandEnvironment
> xCmdEnv
= new ::ucbhelper::CommandEnvironment( xInteractionHandler
, Reference
< XProgressHandler
>() );
807 mpImpl
.reset(new SvtFileView_Impl(this, pTopLevel
, std::move(xTreeView
), std::move(xIconView
), xCmdEnv
, nFlags
, bOnlyFolder
));
809 weld::TreeView
* pView
= mpImpl
->mxView
->getWidget();
810 pView
->connect_column_clicked(LINK(this, SvtFileView
, HeaderSelect_Impl
));
813 void SvtFileView::grab_focus()
815 mpImpl
->grab_focus();
818 bool SvtFileView::has_focus() const
820 return mpImpl
->has_focus();
823 SvtFileView::~SvtFileView()
827 void SvtFileView::SetViewMode( FileViewMode eMode
)
829 mpImpl
->SetViewMode( eMode
);
832 OUString
SvtFileView::GetURL(const weld::TreeIter
& rEntry
) const
834 SvtContentEntry
* pEntry
;
835 if (mpImpl
->mxView
->get_visible())
836 pEntry
= weld::fromId
<SvtContentEntry
*>(mpImpl
->mxView
->get_id(rEntry
));
838 pEntry
= weld::fromId
<SvtContentEntry
*>(mpImpl
->mxIconView
->get_id(rEntry
));
840 return pEntry
->maURL
;
844 OUString
SvtFileView::GetCurrentURL() const
846 SvtContentEntry
* pEntry
= nullptr;
848 if (mpImpl
->mxView
->get_visible())
850 std::unique_ptr
<weld::TreeIter
> xEntry
= mpImpl
->mxView
->make_iterator();
851 if (mpImpl
->mxView
->get_selected(xEntry
.get()))
852 pEntry
= weld::fromId
<SvtContentEntry
*>(mpImpl
->mxView
->get_id(*xEntry
));
856 std::unique_ptr
<weld::TreeIter
> xEntry
= mpImpl
->mxIconView
->make_iterator();
857 if (mpImpl
->mxIconView
->get_selected(xEntry
.get()))
858 pEntry
= weld::fromId
<SvtContentEntry
*>(mpImpl
->mxIconView
->get_id(*xEntry
));
861 aURL
= pEntry
->maURL
;
865 void SvtFileView::CreatedFolder( const OUString
& rUrl
, const OUString
& rNewFolder
)
867 const SortingData_Impl
& rEntry
= mpImpl
->FolderInserted( rUrl
, rNewFolder
);
869 mpImpl
->maEntries
.emplace_back(std::make_unique
<SvtContentEntry
>(rUrl
, true));
870 OUString
sId(weld::toId(mpImpl
->maEntries
.back().get()));
872 std::unique_ptr
<weld::TreeIter
> xEntry
= mpImpl
->mxView
->make_iterator();
873 mpImpl
->mxView
->insert(rEntry
.maDisplayName
, sId
, mpImpl
->maFolderImage
, *xEntry
);
874 mpImpl
->mxView
->scroll_to_row(*xEntry
);
876 std::unique_ptr
<weld::TreeIter
> xIconEntry
= mpImpl
->mxIconView
->make_iterator();
877 mpImpl
->mxIconView
->insert(-1, &rEntry
.maDisplayName
, &sId
, &mpImpl
->maFolderImage
, xIconEntry
.get());
878 mpImpl
->mxIconView
->scroll_to_item(*xIconEntry
);
881 FileViewResult
SvtFileView::PreviousLevel( const FileViewAsyncAction
* pAsyncDescriptor
)
883 FileViewResult eResult
= eFailure
;
886 if ( GetParentURL( sParentURL
) )
887 eResult
= Initialize( sParentURL
, mpImpl
->maCurrentFilter
, pAsyncDescriptor
, maDenyList
);
892 bool SvtFileView::GetParentURL( OUString
& rParentURL
) const
897 ::ucbhelper::Content
aCnt( mpImpl
->maViewURL
, mpImpl
->mxCmdEnv
, comphelper::getProcessComponentContext() );
898 Reference
< XContent
> xContent( aCnt
.get() );
899 Reference
< css::container::XChild
> xChild( xContent
, UNO_QUERY
);
902 Reference
< XContent
> xParent( xChild
->getParent(), UNO_QUERY
);
905 rParentURL
= xParent
->getIdentifier()->getContentIdentifier();
906 bRet
= !rParentURL
.isEmpty() && rParentURL
!= mpImpl
->maViewURL
;
910 catch( Exception
const & )
912 // perhaps an unknown url protocol (e.g. "private:newdoc")
918 OUString
SvtFileView::get_help_id() const
920 return mpImpl
->mxView
->get_help_id();
923 void SvtFileView::set_help_id(const OUString
& rHelpId
)
925 mpImpl
->mxView
->set_help_id(rHelpId
);
928 OUString
SvtFileView::get_selected_text() const
930 if (mpImpl
->mxView
->get_visible())
931 return mpImpl
->mxView
->get_selected_text();
932 return mpImpl
->mxIconView
->get_selected_text();
935 FileViewResult
SvtFileView::Initialize(
936 const OUString
& rURL
,
937 const OUString
& rFilter
,
938 const FileViewAsyncAction
* pAsyncDescriptor
,
939 const css::uno::Sequence
< OUString
>& rDenyList
)
941 weld::WaitObject
aWaitCursor(mpImpl
->m_pTopLevel
);
942 maDenyList
= rDenyList
;
944 OUString
sPushURL( mpImpl
->maViewURL
);
946 mpImpl
->maViewURL
= rURL
;
947 FileViewResult eResult
= ExecuteFilter( rFilter
, pAsyncDescriptor
);
952 mpImpl
->maViewURL
= sPushURL
;
956 OSL_ENSURE( pAsyncDescriptor
, "SvtFileView::Initialize: we told it to read synchronously!" );
962 OSL_FAIL( "SvtFileView::Initialize: unreachable!" );
966 FileViewResult
SvtFileView::ExecuteFilter( const OUString
& rFilter
, const FileViewAsyncAction
* pAsyncDescriptor
)
968 mpImpl
->maCurrentFilter
= rFilter
.toAsciiLowerCase();
971 FileViewResult eResult
= mpImpl
->GetFolderContent_Impl(mpImpl
->maViewURL
, pAsyncDescriptor
, maDenyList
);
972 OSL_ENSURE( ( eResult
!= eStillRunning
) || pAsyncDescriptor
, "SvtFileView::ExecuteFilter: we told it to read synchronously!" );
976 void SvtFileView::CancelRunningAsyncAction()
978 mpImpl
->CancelRunningAsyncAction();
981 void SvtFileView::SetNoSelection()
983 mpImpl
->mxView
->unselect_all();
984 mpImpl
->mxIconView
->unselect_all();
987 void SvtFileView::SetSelectHdl(const Link
<SvtFileView
*,void>& rHdl
)
989 mpImpl
->SetSelectHandler(rHdl
);
992 void SvtFileView::SetDoubleClickHdl(const Link
<SvtFileView
*,bool>& rHdl
)
994 mpImpl
->SetDoubleClickHandler(rHdl
);
997 sal_uInt32
SvtFileView::GetSelectionCount() const
999 if (mpImpl
->mxView
->get_visible())
1000 return mpImpl
->mxView
->count_selected_rows();
1001 return mpImpl
->mxIconView
->count_selected_items();
1004 SvtContentEntry
* SvtFileView::FirstSelected() const
1006 if (mpImpl
->mxView
->get_visible())
1008 SvtContentEntry
* pRet
= nullptr;
1009 std::unique_ptr
<weld::TreeIter
> xEntry
= mpImpl
->mxView
->make_iterator();
1010 if (mpImpl
->mxView
->get_selected(xEntry
.get()))
1011 pRet
= weld::fromId
<SvtContentEntry
*>(mpImpl
->mxView
->get_id(*xEntry
));
1015 SvtContentEntry
* pRet
= nullptr;
1016 std::unique_ptr
<weld::TreeIter
> xEntry
= mpImpl
->mxIconView
->make_iterator();
1017 if (mpImpl
->mxIconView
->get_selected(xEntry
.get()))
1018 pRet
= weld::fromId
<SvtContentEntry
*>(mpImpl
->mxIconView
->get_id(*xEntry
));
1022 const OUString
& SvtFileView::GetViewURL() const
1024 return mpImpl
->maViewURL
;
1027 void SvtFileView::SetOpenDoneHdl( const Link
<SvtFileView
*,void>& rHdl
)
1029 mpImpl
->maOpenDoneLink
= rHdl
;
1032 void SvtFileView::EnableDelete( bool bEnable
)
1034 mpImpl
->EnableDelete( bEnable
);
1037 void SvtFileView::EndInplaceEditing()
1039 return mpImpl
->EndEditing();
1042 IMPL_LINK(SvtFileView
, HeaderSelect_Impl
, int, nColumn
, void)
1044 sal_uInt16 nItemID
= nColumn
+ 1;
1046 if (!mpImpl
->mxView
->TypeColumnVisible() && nItemID
!= COLUMN_TITLE
)
1049 weld::TreeView
* pView
= mpImpl
->mxView
->getWidget();
1050 bool bSortAtoZ
= mpImpl
->mbAscending
;
1052 //set new arrow positions in headerbar
1053 if (nItemID
!= mpImpl
->mnSortColumn
)
1055 // remove old indicator, new will be created in OpenFolder_Impl
1056 pView
->set_sort_indicator(TRISTATE_INDET
, mpImpl
->GetSortColumn());
1059 bSortAtoZ
= !bSortAtoZ
;
1061 mpImpl
->Resort_Impl(nItemID
, bSortAtoZ
);
1064 OUString
SvtFileView::GetConfigString() const
1067 OUString sRet
= OUString::number( mpImpl
->mnSortColumn
) + ";";
1069 bool bUp
= mpImpl
->mbAscending
;
1070 sRet
+= OUString::Concat(bUp
? std::u16string_view(u
"1") : std::u16string_view(u
"0")) + ";";
1072 weld::TreeView
* pView
= mpImpl
->mxView
->getWidget();
1073 sal_uInt16 nCount
= mpImpl
->mxView
->TypeColumnVisible() ? 4 : 3;
1074 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
1076 sal_uInt16 nId
= i
+ 1;
1078 if (!mpImpl
->mxView
->TypeColumnVisible() && nId
!= COLUMN_TITLE
)
1081 sRet
+= OUString::number( nId
)
1083 + OUString::number(pView
->get_column_width(i
))
1087 return comphelper::string::stripEnd(sRet
, ';');
1090 ::std::vector
< SvtContentEntry
> SvtFileView::GetContent()
1092 ::std::vector
< SvtContentEntry
> aContent
;
1094 for(auto const& elem
: mpImpl
->maContent
)
1096 SvtContentEntry
aEntry( elem
->maTargetURL
, elem
->mbIsFolder
);
1097 aContent
.push_back( aEntry
);
1103 void SvtFileView::SetConfigString(std::u16string_view rCfgStr
)
1106 sal_uInt16 nSortColumn
= static_cast<sal_uInt16
>(o3tl::toInt32(o3tl::getToken(rCfgStr
, 0, ';', nIdx
)));
1107 bool bAscending
= static_cast<bool>(static_cast<sal_uInt16
>(o3tl::toInt32(o3tl::getToken(rCfgStr
, 0, ';', nIdx
))));
1109 std::vector
<int> aWidths(mpImpl
->mxView
->TypeColumnVisible() ? 4 : 3, -1);
1111 while ( nIdx
!= -1 )
1113 sal_uInt16 nItemId
= static_cast<sal_uInt16
>(o3tl::toInt32(o3tl::getToken(rCfgStr
, 0, ';', nIdx
)));
1115 int nWidth
= o3tl::toInt32(o3tl::getToken(rCfgStr
, 0, ';', nIdx
));
1118 if (!mpImpl
->mxView
->TypeColumnVisible() && nItemId
!= COLUMN_TITLE
)
1120 int nColumn
= nItemId
- 1;
1122 if (nColumn
>= 0 && o3tl::make_unsigned(nColumn
) < aWidths
.size())
1123 aWidths
[nColumn
] = nWidth
;
1126 weld::TreeView
* pView
= mpImpl
->mxView
->getWidget();
1127 pView
->set_column_fixed_widths(aWidths
);
1128 if (mpImpl
->mnSortColumn
!= nSortColumn
)
1129 pView
->set_sort_indicator(TRISTATE_INDET
, mpImpl
->GetSortColumn());
1130 mpImpl
->Resort_Impl(nSortColumn
, bAscending
);
1133 SvtFileView_Impl::SvtFileView_Impl(SvtFileView
* pAntiImpl
, weld::Window
* pTopLevel
,
1134 std::unique_ptr
<weld::TreeView
> xTreeView
,
1135 std::unique_ptr
<weld::IconView
> xIconView
,
1136 Reference
< XCommandEnvironment
> const & xEnv
,
1137 FileViewFlags nFlags
, bool bOnlyFolder
)
1138 : m_pAntiImpl ( pAntiImpl
)
1139 , m_eAsyncActionResult ( ::svt::EnumerationResult::ERROR
)
1140 , m_bRunningAsyncAction ( false )
1141 , m_bAsyncActionCancelled ( false )
1142 , m_pTopLevel ( pTopLevel
)
1143 , mxView(new ViewTabListBox_Impl(std::move(xTreeView
), pTopLevel
, this, nFlags
))
1144 , mxIconView(std::move(xIconView
))
1145 , mnSortColumn ( COLUMN_TITLE
)
1146 , mbAscending ( true )
1147 , mbOnlyFolder ( bOnlyFolder
)
1148 , mnSuspendSelectCallback ( 0 )
1149 , mbIsFirstResort ( true )
1150 , aIntlWrapper ( Application::GetSettings().GetLanguageTag() )
1151 , maFolderImage (RID_BMP_FOLDER
)
1154 weld::TreeView
* pWidget
= mxView
->getWidget();
1156 // set the width to something small so it's the parent that decides the final
1158 Size
aSize(42, pWidget
->get_height_rows(7));
1159 pWidget
->set_size_request(aSize
.Width(), aSize
.Height());
1160 mxIconView
->set_size_request(aSize
.Width(), aSize
.Height());
1163 SvtFileView_Impl::~SvtFileView_Impl()
1168 void SvtFileView_Impl::Clear()
1170 ::osl::MutexGuard
aGuard( maMutex
);
1175 FileViewResult
SvtFileView_Impl::GetFolderContent_Impl(
1176 std::u16string_view rFolder
,
1177 const FileViewAsyncAction
* pAsyncDescriptor
,
1178 const css::uno::Sequence
< OUString
>& rDenyList
)
1180 ::osl::ClearableMutexGuard
aGuard( maMutex
);
1181 INetURLObject
aFolderObj( rFolder
);
1182 DBG_ASSERT( aFolderObj
.GetProtocol() != INetProtocol::NotValid
, "Invalid URL!" );
1184 FolderDescriptor
aFolder( aFolderObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
1187 return GetFolderContent_Impl( aFolder
, pAsyncDescriptor
, rDenyList
);
1190 FileViewResult
SvtFileView_Impl::GetFolderContent_Impl(
1191 const FolderDescriptor
& _rFolder
,
1192 const FileViewAsyncAction
* pAsyncDescriptor
,
1193 const css::uno::Sequence
< OUString
>& rDenyList
)
1195 DBG_TESTSOLARMUTEX();
1196 ::osl::ClearableMutexGuard
aGuard( maMutex
);
1198 OSL_ENSURE( !m_xContentEnumerator
.is(), "SvtFileView_Impl::GetFolderContent_Impl: still running another enumeration!" );
1199 m_xContentEnumerator
.set(new ::svt::FileViewContentEnumerator(
1200 mxView
->GetCommandEnvironment(), maContent
, maMutex
));
1201 // TODO: should we cache and re-use this thread?
1203 if ( !pAsyncDescriptor
)
1205 ::svt::EnumerationResult eResult
= m_xContentEnumerator
->enumerateFolderContentSync( _rFolder
, rDenyList
);
1206 if ( ::svt::EnumerationResult::SUCCESS
== eResult
)
1208 implEnumerationSuccess();
1209 m_xContentEnumerator
.clear();
1212 m_xContentEnumerator
.clear();
1216 m_bRunningAsyncAction
= true;
1217 m_bAsyncActionCancelled
= false;
1218 m_eAsyncActionResult
= ::svt::EnumerationResult::ERROR
;
1219 m_aAsyncActionFinished
.reset();
1221 // don't (yet) set m_aCurrentAsyncActionHandler to pTimeout->aFinishHandler.
1222 // By definition, this handler *only* gets called when the result cannot be obtained
1223 // during the minimum wait time, so it is only set below, when needed.
1224 m_aCurrentAsyncActionHandler
= Link
<void*,void>();
1226 // minimum time to wait
1228 sal_Int32 nMinTimeout
= pAsyncDescriptor
->nMinTimeout
;
1229 OSL_ENSURE( nMinTimeout
> 0, "SvtFileView_Impl::GetFolderContent_Impl: invalid minimum timeout!" );
1230 if ( nMinTimeout
<= 0 )
1231 nMinTimeout
= sal_Int32( 1000 );
1232 aTimeout
.Seconds
= nMinTimeout
/ 1000;
1233 aTimeout
.Nanosec
= ( nMinTimeout
% 1000 ) * 1000000;
1235 m_xContentEnumerator
->enumerateFolderContent( _rFolder
, this );
1237 // wait until the enumeration is finished
1238 // for this, release our own mutex (which is used by the enumerator thread)
1241 ::osl::Condition::Result eResult
= ::osl::Condition::result_ok
;
1243 // also release the SolarMutex. Not all code which is needed during the enumeration
1244 // is Solar-Thread-Safe, in particular there is some code which needs to access
1245 // string resources (and our resource system relies on the SolarMutex :()
1246 SolarMutexReleaser aSolarRelease
;
1248 // now wait. Note that if we didn't get a pAsyncDescriptor, then this is an infinite wait.
1249 eResult
= m_aAsyncActionFinished
.wait( &aTimeout
);
1252 ::osl::MutexGuard
aGuard2( maMutex
);
1253 if ( ::osl::Condition::result_timeout
== eResult
)
1255 // maximum time to wait
1256 OSL_ENSURE(!m_xCancelAsyncTimer
,
1257 "SvtFileView_Impl::GetFolderContent_Impl: there's still a previous timer!");
1258 m_xCancelAsyncTimer
.set(new CallbackTimer(this));
1259 sal_Int32 nMaxTimeout
= pAsyncDescriptor
->nMaxTimeout
;
1260 OSL_ENSURE( nMaxTimeout
> nMinTimeout
,
1261 "SvtFileView_Impl::GetFolderContent_Impl: invalid maximum timeout!" );
1262 if ( nMaxTimeout
<= nMinTimeout
)
1263 nMaxTimeout
= nMinTimeout
+ 5000;
1264 m_xCancelAsyncTimer
->setRemainingTime( salhelper::TTimeValue( nMaxTimeout
- nMinTimeout
) );
1265 // we already waited for nMinTimeout milliseconds, so take this into account
1266 m_xCancelAsyncTimer
->start();
1268 m_aCurrentAsyncActionHandler
= pAsyncDescriptor
->aFinishHandler
;
1269 DBG_ASSERT( m_aCurrentAsyncActionHandler
.IsSet(), "SvtFileView_Impl::GetFolderContent_Impl: nobody interested when it's finished?" );
1272 mxIconView
->clear();
1273 return eStillRunning
;
1276 m_bRunningAsyncAction
= false;
1277 switch ( m_eAsyncActionResult
)
1279 case ::svt::EnumerationResult::SUCCESS
:
1282 case ::svt::EnumerationResult::ERROR
:
1286 SAL_WARN( "svtools.contnr", "SvtFileView_Impl::GetFolderContent_Impl: unreachable!" );
1290 void SvtFileView_Impl::FilterFolderContent_Impl( std::u16string_view rFilter
)
1292 if ( rFilter
.empty() || ( rFilter
== ALL_FILES_FILTER
) )
1293 // when replacing names, there is always something to filter (no view of ".nametranslation.table")
1296 ::osl::MutexGuard
aGuard( maMutex
);
1298 if ( maContent
.empty() )
1301 // collect the filter tokens
1302 ::std::vector
< WildCard
> aFilters
;
1303 FilterMatch::createWildCardFilterList(rFilter
,aFilters
);
1307 std::erase_if(maContent
,
1308 [&aFilters
](const std::unique_ptr
<SortingData_Impl
>& rxContent
) {
1309 if (rxContent
->mbIsFolder
)
1311 // normalize the content title (we always match case-insensitive)
1312 // 91872 - 11.09.2001 - frank.schoenheit@sun.com
1313 OUString sCompareString
= rxContent
->GetFileName(); // filter works on file name, not on title!
1314 return std::none_of(aFilters
.begin(), aFilters
.end(), FilterMatch(sCompareString
));
1318 IMPL_LINK_NOARG(SvtFileView_Impl
, ChangedHdl
, weld::TreeView
&, void)
1320 if (!mnSuspendSelectCallback
)
1321 m_aSelectHandler
.Call(m_pAntiImpl
);
1324 IMPL_LINK_NOARG(SvtFileView_Impl
, SelectionChangedHdl
, weld::IconView
&, void)
1326 if (!mnSuspendSelectCallback
)
1327 m_aSelectHandler
.Call(m_pAntiImpl
);
1330 void SvtFileView_Impl::SetSelectHandler(const Link
<SvtFileView
*,void>& rHdl
)
1332 m_aSelectHandler
= rHdl
;
1334 mxView
->connect_changed(LINK(this, SvtFileView_Impl
, ChangedHdl
));
1335 mxIconView
->connect_selection_changed(LINK(this, SvtFileView_Impl
, SelectionChangedHdl
));
1338 IMPL_LINK_NOARG(SvtFileView_Impl
, RowActivatedHdl
, weld::TreeView
&, bool)
1340 return maDoubleClickHandler
.Call(m_pAntiImpl
);
1343 IMPL_LINK_NOARG(SvtFileView_Impl
, ItemActivatedHdl
, weld::IconView
&, bool)
1345 return maDoubleClickHandler
.Call(m_pAntiImpl
);
1348 void SvtFileView_Impl::SetDoubleClickHandler(const Link
<SvtFileView
*,bool>& rHdl
)
1350 maDoubleClickHandler
= rHdl
;
1352 mxView
->connect_row_activated(LINK(this, SvtFileView_Impl
, RowActivatedHdl
));
1353 mxIconView
->connect_item_activated(LINK(this, SvtFileView_Impl
, ItemActivatedHdl
));
1356 void SvtFileView_Impl::OpenFolder_Impl()
1358 ::osl::MutexGuard
aGuard( maMutex
);
1361 mxIconView
->freeze();
1364 mxIconView
->clear();
1366 for (auto const& elem
: maContent
)
1368 if (mbOnlyFolder
&& !elem
->mbIsFolder
)
1371 // insert entry and set user data
1372 maEntries
.emplace_back(std::make_unique
<SvtContentEntry
>(elem
->maTargetURL
, elem
->mbIsFolder
));
1373 OUString
sId(weld::toId(maEntries
.back().get()));
1374 mxView
->append(sId
, elem
->maDisplayName
, elem
->maType
, elem
->maDisplaySize
, elem
->maDisplayDate
, elem
->maImage
);
1375 mxIconView
->append(sId
, elem
->maDisplayName
, elem
->maImage
);
1378 ++mnSuspendSelectCallback
;
1381 //set sort indicator
1382 weld::TreeView
* pView
= mxView
->getWidget();
1383 pView
->set_sort_indicator(mbAscending
? TRISTATE_TRUE
: TRISTATE_FALSE
, GetSortColumn());
1386 --mnSuspendSelectCallback
;
1391 void SvtFileView_Impl::ResetCursor()
1393 if (mxView
->get_visible())
1395 std::unique_ptr
<weld::TreeIter
> xFirst
= mxView
->make_iterator();
1396 if (mxView
->get_iter_first(*xFirst
))
1398 // set cursor to the first entry
1399 mxView
->set_cursor(*xFirst
);
1402 mxView
->unselect_all();
1406 std::unique_ptr
<weld::TreeIter
> xFirst
= mxIconView
->make_iterator();
1407 if (mxIconView
->get_iter_first(*xFirst
))
1409 // set cursor to the first entry
1410 mxIconView
->set_cursor(*xFirst
);
1413 mxIconView
->unselect_all();
1417 void SvtFileView_Impl::CancelRunningAsyncAction()
1419 DBG_TESTSOLARMUTEX();
1420 ::osl::MutexGuard
aGuard( maMutex
);
1421 if ( !m_xContentEnumerator
.is() )
1424 m_bAsyncActionCancelled
= true;
1425 m_xContentEnumerator
->cancel();
1426 m_bRunningAsyncAction
= false;
1428 m_xContentEnumerator
.clear();
1429 if ( m_xCancelAsyncTimer
.is() && m_xCancelAsyncTimer
->isTicking() )
1430 m_xCancelAsyncTimer
->stop();
1431 m_xCancelAsyncTimer
.clear();
1435 void SvtFileView_Impl::onTimeout()
1437 SolarMutexGuard aSolarGuard
;
1438 ::osl::MutexGuard
aGuard( maMutex
);
1439 if ( !m_bRunningAsyncAction
)
1440 // there might have been a race condition while we waited for the mutex
1443 CancelRunningAsyncAction();
1445 if ( m_aCurrentAsyncActionHandler
.IsSet() )
1447 Application::PostUserEvent( m_aCurrentAsyncActionHandler
, reinterpret_cast< void* >( eTimeout
) );
1448 m_aCurrentAsyncActionHandler
= Link
<void*,void>();
1453 void SvtFileView_Impl::enumerationDone( ::svt::EnumerationResult eResult
)
1455 SolarMutexGuard aSolarGuard
;
1456 ::osl::MutexGuard
aGuard( maMutex
);
1458 m_xContentEnumerator
.clear();
1459 if ( m_xCancelAsyncTimer
.is() && m_xCancelAsyncTimer
->isTicking() )
1460 m_xCancelAsyncTimer
->stop();
1461 m_xCancelAsyncTimer
.clear();
1463 if ( m_bAsyncActionCancelled
)
1464 // this is to prevent race conditions
1467 m_eAsyncActionResult
= eResult
;
1468 m_bRunningAsyncAction
= false;
1470 m_aAsyncActionFinished
.set();
1472 if ( svt::EnumerationResult::SUCCESS
== eResult
)
1473 implEnumerationSuccess();
1475 if ( m_aCurrentAsyncActionHandler
.IsSet() )
1477 Application::PostUserEvent( m_aCurrentAsyncActionHandler
, reinterpret_cast< void* >( m_eAsyncActionResult
) );
1478 m_aCurrentAsyncActionHandler
= Link
<void*,void>();
1483 void SvtFileView_Impl::implEnumerationSuccess()
1485 FilterFolderContent_Impl( maCurrentFilter
);
1486 SortFolderContent_Impl();
1487 CreateDisplayText_Impl();
1489 maOpenDoneLink
.Call( m_pAntiImpl
);
1492 OUString
SvtFileView_Impl::ReplaceTabWithString(const OUString
& rValue
)
1494 return rValue
.replaceAll(u
"\t", u
"%09");
1497 void SvtFileView_Impl::CreateDisplayText_Impl()
1499 ::osl::MutexGuard
aGuard( maMutex
);
1501 for (auto const& elem
: maContent
)
1503 // title, type, size, date
1504 elem
->maDisplayName
= ReplaceTabWithString(elem
->GetTitle());
1505 // folders don't have a size
1506 if ( ! elem
->mbIsFolder
)
1507 elem
->maDisplaySize
= CreateExactSizeText( elem
->maSize
);
1508 // set the date, but volumes have no date
1509 if ( ! elem
->mbIsFolder
|| ! elem
->mbIsVolume
)
1511 SvtSysLocale aSysLocale
;
1512 const LocaleDataWrapper
& rLocaleData
= aSysLocale
.GetLocaleData();
1513 elem
->maDisplayDate
= rLocaleData
.getDate( elem
->maModDate
)
1515 + rLocaleData
.getTime( elem
->maModDate
, false );
1519 if ( elem
->mbIsFolder
)
1521 ::svtools::VolumeInfo
aVolInfo( elem
->mbIsVolume
, elem
->mbIsRemote
,
1522 elem
->mbIsRemoveable
, elem
->mbIsFloppy
,
1523 elem
->mbIsCompactDisc
);
1524 elem
->maImage
= SvFileInformationManager::GetFolderImageId(aVolInfo
);
1527 elem
->maImage
= SvFileInformationManager::GetFileImageId(INetURLObject(elem
->maTargetURL
));
1531 void SvtFileView_Impl::Resort_Impl( sal_Int16 nColumn
, bool bAscending
)
1533 // TODO: IconView ()
1534 ::osl::MutexGuard
aGuard( maMutex
);
1536 if ( ( nColumn
== mnSortColumn
) &&
1537 ( bAscending
== mbAscending
) )
1540 // reset the quick search index
1541 mxView
->ResetQuickSearch_Impl( nullptr );
1543 std::unique_ptr
<weld::TreeIter
> xEntry(mxView
->make_iterator());
1544 bool bEntry
= mxView
->get_cursor(xEntry
.get());
1547 if (bEntry
&& !mxView
->get_id(*xEntry
).isEmpty())
1548 aEntryURL
= weld::fromId
<SvtContentEntry
*>(mxView
->get_id(*xEntry
))->maURL
;
1550 mnSortColumn
= nColumn
;
1551 mbAscending
= bAscending
;
1553 SortFolderContent_Impl();
1556 if ( !mbIsFirstResort
)
1558 int nPos
= GetEntryPos( aEntryURL
);
1559 if (nPos
!= -1 && nPos
< mxView
->n_children())
1561 ++mnSuspendSelectCallback
; // #i15668#
1562 mxView
->set_cursor(nPos
);
1563 --mnSuspendSelectCallback
;
1567 mbIsFirstResort
= false;
1570 static bool gbAscending
= true;
1571 static sal_Int16 gnColumn
= COLUMN_TITLE
;
1572 static const CollatorWrapper
* pCollatorWrapper
= nullptr;
1574 /* this function returns true, if aOne is less than aTwo
1576 static bool CompareSortingData_Impl( std::unique_ptr
<SortingData_Impl
> const & aOne
, std::unique_ptr
<SortingData_Impl
> const & aTwo
)
1578 DBG_ASSERT( pCollatorWrapper
, "*CompareSortingData_Impl(): Can't work this way!" );
1582 bool bEqual
= false;
1584 if ( aOne
->mbIsFolder
!= aTwo
->mbIsFolder
)
1586 bRet
= aOne
->mbIsFolder
;
1588 // !!! pb: #100376# folder always on top
1597 // compare case insensitive first
1598 nComp
= pCollatorWrapper
->compareString( aOne
->GetLowerTitle(), aTwo
->GetLowerTitle() );
1601 nComp
= pCollatorWrapper
->compareString( aOne
->GetTitle(), aTwo
->GetTitle() );
1605 else if ( nComp
> 0 )
1611 nComp
= pCollatorWrapper
->compareString( aOne
->maType
, aTwo
->maType
);
1614 else if ( nComp
> 0 )
1620 if ( aOne
->maSize
< aTwo
->maSize
)
1622 else if ( aOne
->maSize
> aTwo
->maSize
)
1628 if ( aOne
->maModDate
< aTwo
->maModDate
)
1630 else if ( aOne
->maModDate
> aTwo
->maModDate
)
1636 SAL_INFO( "svtools.contnr", "CompareSortingData_Impl: Compare unknown type!" );
1641 // when the two elements are equal, we must not return sal_True (which would
1642 // happen if we just return ! ( a < b ) when not sorting ascending )
1646 return gbAscending
? bRet
: !bRet
;
1650 void SvtFileView_Impl::SortFolderContent_Impl()
1652 ::osl::MutexGuard
aGuard( maMutex
);
1654 if ( maContent
.size() > 1 )
1656 gbAscending
= mbAscending
;
1657 gnColumn
= mnSortColumn
;
1658 pCollatorWrapper
= aIntlWrapper
.getCaseCollator();
1660 std::stable_sort( maContent
.begin(), maContent
.end(), CompareSortingData_Impl
);
1662 pCollatorWrapper
= nullptr;
1667 void SvtFileView_Impl::EntryRemoved( std::u16string_view rURL
)
1669 ::osl::MutexGuard
aGuard( maMutex
);
1671 maContent
.erase(std::find_if(maContent
.begin(), maContent
.end(),
1672 [&](const std::unique_ptr
<SortingData_Impl
> & data
) { return data
->maTargetURL
== rURL
; }));
1676 void SvtFileView_Impl::EntryRenamed( OUString
& rURL
,
1677 const OUString
& rTitle
)
1679 ::osl::MutexGuard
aGuard( maMutex
);
1681 auto aFoundElem
= std::find_if(maContent
.begin(), maContent
.end(),
1682 [&](const std::unique_ptr
<SortingData_Impl
> & data
) { return data
->maTargetURL
== rURL
; });
1683 if (aFoundElem
!= maContent
.end())
1685 (*aFoundElem
)->SetNewTitle( rTitle
);
1686 (*aFoundElem
)->maDisplayName
= ReplaceTabWithString(rTitle
);
1688 INetURLObject
aURLObj( rURL
);
1689 aURLObj
.setName( rTitle
, INetURLObject::EncodeMechanism::All
);
1691 rURL
= aURLObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1693 (*aFoundElem
)->maTargetURL
= rURL
;
1697 const SortingData_Impl
& SvtFileView_Impl::FolderInserted( const OUString
& rURL
, const OUString
& rTitle
)
1699 ::osl::MutexGuard
aGuard( maMutex
);
1701 std::unique_ptr
<SortingData_Impl
> pData(new SortingData_Impl
);
1703 pData
->SetNewTitle( rTitle
);
1705 pData
->mbIsFolder
= true;
1706 pData
->maTargetURL
= rURL
;
1708 ::svtools::VolumeInfo aVolInfo
;
1709 pData
->maType
= SvFileInformationManager::GetFolderDescription( aVolInfo
);
1710 pData
->maImage
= SvFileInformationManager::GetFolderImageId( aVolInfo
);
1712 // title, type, size, date
1713 pData
->maDisplayName
= ReplaceTabWithString(pData
->GetTitle());
1715 SvtSysLocale aSysLocale
;
1716 const LocaleDataWrapper
& rLocaleData
= aSysLocale
.GetLocaleData();
1717 pData
->maDisplayDate
= rLocaleData
.getDate( pData
->maModDate
)
1719 + rLocaleData
.getTime( pData
->maModDate
);
1721 maContent
.push_back( std::move(pData
) );
1723 return *maContent
.back();
1726 int SvtFileView_Impl::GetEntryPos(std::u16string_view rURL
)
1728 ::osl::MutexGuard
aGuard( maMutex
);
1730 auto aFoundElem
= std::find_if(maContent
.begin(), maContent
.end(),
1731 [&](const std::unique_ptr
<SortingData_Impl
> & data
) { return data
->maTargetURL
== rURL
; });
1732 return aFoundElem
!= maContent
.end() ? std::distance(maContent
.begin(), aFoundElem
) : -1;
1735 void SvtFileView_Impl::SetViewMode( FileViewMode eMode
)
1755 bool SvtFileView_Impl::SearchNextEntry( sal_uInt32
& nIndex
, std::u16string_view rTitle
, bool bWrapAround
)
1757 ::osl::MutexGuard
aGuard( maMutex
);
1759 sal_uInt32 nEnd
= maContent
.size();
1760 sal_uInt32 nStart
= nIndex
;
1761 while ( nIndex
< nEnd
)
1763 SortingData_Impl
* pData
= maContent
[ nIndex
].get();
1764 if ( pData
->GetLowerTitle().startsWith( rTitle
) )
1772 while ( nIndex
< nEnd
&& nIndex
<= nStart
)
1774 SortingData_Impl
* pData
= maContent
[ nIndex
].get();
1775 if ( pData
->GetLowerTitle().startsWith( rTitle
) )
1785 void SAL_CALL
CallbackTimer::onShot()
1787 OSL_ENSURE( m_pTimeoutHandler
, "CallbackTimer::onShot: nobody interested in?" );
1788 SvtFileView_Impl
* pHandler( m_pTimeoutHandler
);
1790 pHandler
->onTimeout();
1794 void SvtFileView::selected_foreach(const std::function
<bool(weld::TreeIter
&)>& func
)
1796 if (mpImpl
->mxView
->get_visible())
1797 mpImpl
->mxView
->selected_foreach(func
);
1799 mpImpl
->mxIconView
->selected_foreach(func
);
1802 weld::Widget
* SvtFileView::identifier() const
1804 return mpImpl
->mxView
->getWidget();
1807 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */