1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
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 <toolkit/helper/vclunohelper.hxx>
29 #include "contentenumeration.hxx"
30 #include <com/sun/star/task/InteractionHandler.hpp>
31 #include <com/sun/star/ucb/XProgressHandler.hpp>
32 #include <com/sun/star/ucb/XContent.hpp>
33 #include <com/sun/star/container/XChild.hpp>
34 #include <com/sun/star/ucb/CommandAbortedException.hpp>
35 #include <com/sun/star/ucb/XCommandInfo.hpp>
36 #include <com/sun/star/beans/XPropertySetInfo.hpp>
37 #include <com/sun/star/beans/PropertyAttribute.hpp>
38
39 #include <algorithm>
40 #include <vector>
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/typed_flags_set.hxx>
49 #include <osl/mutex.hxx>
50 #include <osl/conditn.hxx>
51 #include <salhelper/timer.hxx>
52 #include <svtools/urlfilter.hxx>
53 #include <unotools/collatorwrapper.hxx>
54 #include <unotools/localedatawrapper.hxx>
55 #include <unotools/intlwrapper.hxx>
56 #include <unotools/syslocale.hxx>
57 #include <vcl/svapp.hxx>
58 #include <vcl/commandevent.hxx>
59 #include <vcl/event.hxx>
60 #include <vcl/settings.hxx>
61 #include <vcl/timer.hxx>
62 #include <memory>
63 #include "fileview.hxx"
64
65 using namespace ::com::sun::star::lang;
66 using namespace ::com::sun::star::sdbc;
67 using namespace ::com::sun::star::task;
68 using namespace ::com::sun::star::ucb;
69 using namespace ::com::sun::star::uno;
70 using namespace ::com::sun::star::io;
71 using namespace ::com::sun::star::beans;
72 using namespace ::comphelper;
73 using ::svt::SortingData_Impl;
74 using ::svt::FolderDescriptor;
75
76 #define ALL_FILES_FILTER "*.*"
77
78 #define COLUMN_TITLE 1
79 #define COLUMN_TYPE 2
80 #define COLUMN_SIZE 3
81 #define COLUMN_DATE 4
82
83 #define QUICK_SEARCH_TIMEOUT 1500 // time in mSec before the quicksearch string will be reset
84
85 enum class FileViewFlags
86 {
87 NONE = 0x00,
88 MULTISELECTION = 0x02,
89 SHOW_TYPE = 0x04,
90 SHOW_NONE = 0x20,
91 };
92 namespace o3tl
93 {
94 template<> struct typed_flags<FileViewFlags> : is_typed_flags<FileViewFlags, 0x26> {};
95 }
96
97 namespace
98 {
99
100 //= CallbackTimer
101
102 class CallbackTimer : public ::salhelper::Timer
103 {
104 protected:
105 SvtFileView_Impl* const m_pTimeoutHandler;
106
107 public:
CallbackTimer(SvtFileView_Impl * _pHandler)108 explicit CallbackTimer( SvtFileView_Impl* _pHandler ) : m_pTimeoutHandler( _pHandler ) { }
109
110 protected:
111 virtual void SAL_CALL onShot() override;
112 };
113
114
115 }
116
117 class ViewTabListBox_Impl
118 {
119 private:
120 Reference< XCommandEnvironment > mxCmdEnv;
121 std::unique_ptr<weld::TreeView> mxTreeView;
122 std::unique_ptr<weld::TreeIter> mxScratchIter;
123
124 ::osl::Mutex maMutex;
125 SvtFileView_Impl* mpParent;
126 Timer maResetQuickSearch;
127 OUString maQuickSearchText;
128 sal_uInt32 mnSearchIndex;
129 bool mbEnableDelete;
130 bool mbEditing;
131 bool const mbShowType;
132
133 void DeleteEntries();
134 void DoQuickSearch( sal_Unicode rChar );
135 bool Kill( const OUString& rURL );
136
137 public:
138 ViewTabListBox_Impl(std::unique_ptr<weld::TreeView> xTreeView, weld::Window* pTopLevel, SvtFileView_Impl* pParent, FileViewFlags nFlags);
139
make_iterator() const140 std::unique_ptr<weld::TreeIter> make_iterator() const { return mxTreeView->make_iterator(); }
insert(const OUString & rEntry,const OUString & rId,const OUString & rImage,weld::TreeIter & rIter)141 void insert(const OUString &rEntry, const OUString& rId, const OUString& rImage, weld::TreeIter& rIter)
142 {
143 mxTreeView->insert(nullptr, -1, &rEntry, &rId, nullptr, nullptr, &rImage, false, &rIter);
144 }
append(const OUString & rId,const OUString & rStr,const OUString & rType,const OUString & rSize,const OUString & rDate,const OUString & rImage)145 void append(const OUString& rId, const OUString& rStr, const OUString& rType, const OUString& rSize, const OUString& rDate, const OUString& rImage)
146 {
147 mxTreeView->insert(nullptr, -1, &rStr, &rId, nullptr, nullptr, &rImage, false, mxScratchIter.get());
148 int nCol = 1;
149 if (mbShowType)
150 mxTreeView->set_text(*mxScratchIter, rType, nCol++);
151 mxTreeView->set_text(*mxScratchIter, rSize, nCol++);
152 mxTreeView->set_text(*mxScratchIter, rDate, nCol++);
153 }
154
scroll_to_row(const weld::TreeIter & rIter)155 void scroll_to_row(const weld::TreeIter& rIter) { mxTreeView->scroll_to_row(rIter); }
set_cursor(int nPos)156 void set_cursor(int nPos) { mxTreeView->set_cursor(nPos); }
set_cursor(const weld::TreeIter & rIter)157 void set_cursor(const weld::TreeIter& rIter) { mxTreeView->set_cursor(rIter); }
get_cursor(weld::TreeIter * pIter) const158 bool get_cursor(weld::TreeIter* pIter) const { return mxTreeView->get_cursor(pIter); }
get_iter_first(weld::TreeIter & rIter) const159 bool get_iter_first(weld::TreeIter& rIter) const { return mxTreeView->get_iter_first(rIter); }
get_selected(weld::TreeIter * pIter) const160 bool get_selected(weld::TreeIter* pIter) const { return mxTreeView->get_selected(pIter); }
161
get_selected_text() const162 OUString get_selected_text() const
163 {
164 // tdf#131898 only care about column 0
165 int nIndex = mxTreeView->get_selected_index();
166 return nIndex != -1 ? mxTreeView->get_text(nIndex, 0) : OUString();
167 }
168
unselect_all()169 void unselect_all() { mxTreeView->unselect_all(); }
170
get_id(const weld::TreeIter & rIter)171 OUString get_id(const weld::TreeIter& rIter) { return mxTreeView->get_id(rIter); }
172
connect_row_activated(const Link<weld::TreeView &,bool> & rLink)173 void connect_row_activated(const Link<weld::TreeView&, bool>& rLink) { mxTreeView->connect_row_activated(rLink); }
connect_changed(const Link<weld::TreeView &,void> & rLink)174 void connect_changed(const Link<weld::TreeView&, void>& rLink) { mxTreeView->connect_changed(rLink); }
175
n_children() const176 int n_children() const { return mxTreeView->n_children(); }
177
freeze()178 void freeze() { mxTreeView->freeze(); }
thaw()179 void thaw() { mxTreeView->thaw(); }
180
show()181 void show() { mxTreeView->show(); }
hide()182 void hide() { mxTreeView->hide(); }
get_visible() const183 bool get_visible() const { return mxTreeView->get_visible(); }
184
count_selected_rows() const185 int count_selected_rows() const { return mxTreeView->count_selected_rows(); }
186
grab_focus()187 void grab_focus() { mxTreeView->grab_focus(); }
has_focus() const188 bool has_focus() const { return mxTreeView->has_focus(); }
189
set_help_id(const OString & rHelpId)190 void set_help_id(const OString& rHelpId) { mxTreeView->set_help_id(rHelpId); }
get_help_id() const191 OString get_help_id() const { return mxTreeView->get_help_id(); }
192
IsEditingActive() const193 bool IsEditingActive() const { return mbEditing; }
194
end_editing()195 void end_editing()
196 {
197 mxTreeView->end_editing();
198 mxTreeView->connect_editing(Link<const weld::TreeIter&, bool>(), Link<const IterString&, bool>());
199 mbEditing = false;
200 }
201
selected_foreach(const std::function<bool (weld::TreeIter &)> & func)202 void selected_foreach(const std::function<bool(weld::TreeIter&)>& func)
203 {
204 mxTreeView->selected_foreach(func);
205 }
206
getWidget() const207 weld::TreeView* getWidget() const
208 {
209 return mxTreeView.get();
210 }
211
clear()212 void clear() { mxTreeView->clear(); }
213
EnableDelete(bool bEnable)214 void EnableDelete( bool bEnable ) { mbEnableDelete = bEnable; }
TypeColumnVisible() const215 bool TypeColumnVisible() const { return mbShowType; }
216
GetCommandEnvironment() const217 const Reference< XCommandEnvironment >& GetCommandEnvironment() const { return mxCmdEnv; }
218
219 DECL_LINK(ResetQuickSearch_Impl, Timer *, void);
220 DECL_LINK(CommandHdl, const CommandEvent&, bool);
221 DECL_LINK(EditingEntryHdl, const weld::TreeIter&, bool);
222 typedef std::pair<const weld::TreeIter&, OUString> IterString;
223 DECL_LINK(EditedEntryHdl, const IterString&, bool);
224 DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
225
226 void ExecuteContextMenuAction(const OString& rSelectedPopentry);
227 };
228
229 //= SvtFileView_Impl
230 class SvtFileView_Impl :public ::svt::IEnumerationResultHandler
231 {
232 protected:
233 SvtFileView* m_pAntiImpl;
234 Link<SvtFileView*,void> m_aSelectHandler;
235
236 ::rtl::Reference< ::svt::FileViewContentEnumerator >
237 m_xContentEnumerator;
238 Link<void*,void> m_aCurrentAsyncActionHandler;
239 ::osl::Condition m_aAsyncActionFinished;
240 ::rtl::Reference< ::salhelper::Timer > m_xCancelAsyncTimer;
241 ::svt::EnumerationResult m_eAsyncActionResult;
242 bool m_bRunningAsyncAction;
243 bool m_bAsyncActionCancelled;
244
245 public:
246
247 ::std::vector<std::unique_ptr<SortingData_Impl>> maContent;
248 ::std::vector<std::unique_ptr<SvtContentEntry>> maEntries;
249 ::osl::Mutex maMutex;
250
251 weld::Window* m_pTopLevel;
252 std::unique_ptr<ViewTabListBox_Impl> mxView;
253 std::unique_ptr<weld::IconView> mxIconView;
254 sal_uInt16 mnSortColumn;
255 bool mbAscending : 1;
256 bool const mbOnlyFolder : 1;
257 sal_Int16 mnSuspendSelectCallback : 1;
258 bool mbIsFirstResort : 1;
259
260 IntlWrapper const aIntlWrapper;
261
262 OUString maViewURL;
263 OUString maCurrentFilter;
264 OUString maFolderImage;
265 Link<SvtFileView*,void> maOpenDoneLink;
266 Link<SvtFileView*,bool> maDoubleClickHandler;
267
268 Reference< XCommandEnvironment > mxCmdEnv;
269
270 SvtFileView_Impl(SvtFileView* pAntiImpl, weld::Window* pTopLevel,
271 std::unique_ptr<weld::TreeView> xTreeView,
272 std::unique_ptr<weld::IconView> xIconView,
273 Reference < XCommandEnvironment > const & xEnv,
274 FileViewFlags nFlags,
275 bool bOnlyFolder);
276
277 virtual ~SvtFileView_Impl();
278
279 void Clear();
280
281 FileViewResult GetFolderContent_Impl(
282 const OUString& rFolder,
283 const FileViewAsyncAction* pAsyncDescriptor,
284 const css::uno::Sequence< OUString >& rBlackList );
285
286 FileViewResult GetFolderContent_Impl(
287 const FolderDescriptor& _rFolder,
288 const FileViewAsyncAction* pAsyncDescriptor,
289 const css::uno::Sequence< OUString >& rBlackList );
290 void FilterFolderContent_Impl( const OUString &rFilter );
291 void CancelRunningAsyncAction();
292
293 void OpenFolder_Impl();
294 static OUString ReplaceTabWithString(const OUString& rValue);
295 void CreateDisplayText_Impl();
296 void SortFolderContent_Impl();
297
298 void EntryRemoved( const OUString& rURL );
299 void EntryRenamed( OUString& rURL,
300 const OUString& rName );
301 const SortingData_Impl& FolderInserted( const OUString& rURL,
302 const OUString& rTitle );
303
304 int GetEntryPos( const OUString& rURL );
305
306 void SetViewMode( FileViewMode eMode );
307
308 inline void EnableDelete( bool bEnable );
309
310 void Resort_Impl( sal_Int16 nColumn, bool bAscending );
311 bool SearchNextEntry( sal_uInt32 &nIndex,
312 const OUString& rTitle,
313 bool bWrapAround );
314
315 void SetSelectHandler( const Link<SvtFileView*,void>& rHdl );
316 void SetDoubleClickHandler(const Link<SvtFileView*,bool>& rHdl);
317
318 void ResetCursor();
319
EndEditing()320 void EndEditing()
321 {
322 if (mxView->IsEditingActive())
323 mxView->end_editing();
324 }
325
326 void onTimeout();
327
grab_focus()328 void grab_focus()
329 {
330 if (mxView->get_visible())
331 mxView->grab_focus();
332 else
333 mxIconView->grab_focus();
334 }
335
has_focus() const336 bool has_focus() const
337 {
338 return mxView->has_focus() || mxIconView->has_focus();
339 }
340
GetSortColumn() const341 int GetSortColumn() const
342 {
343 sal_uInt16 nOldSortID = mnSortColumn;
344 // skip "TYPE"
345 if (!mxView->TypeColumnVisible() && nOldSortID != COLUMN_TITLE)
346 --nOldSortID;
347 return nOldSortID - 1;
348 }
349
350 protected:
351 DECL_LINK(ChangedHdl, weld::TreeView&, void);
352 DECL_LINK(SelectionChangedHdl, weld::IconView&, void);
353 DECL_LINK(RowActivatedHdl, weld::TreeView&, bool);
354 DECL_LINK(ItemActivatedHdl, weld::IconView&, bool);
355
356 // IEnumerationResultHandler overridables
357 virtual void enumerationDone( ::svt::EnumerationResult eResult ) override;
358 void implEnumerationSuccess();
359 };
360
EnableDelete(bool bEnable)361 inline void SvtFileView_Impl::EnableDelete( bool bEnable )
362 {
363 mxView->EnableDelete( bEnable );
364 }
365
366 namespace
367 {
368 // functions -------------------------------------------------------------
369
CreateExactSizeText(sal_Int64 nSize)370 OUString CreateExactSizeText( sal_Int64 nSize )
371 {
372 double fSize( static_cast<double>(nSize) );
373 int nDec;
374
375 long nMega = 1024 * 1024;
376 long nGiga = nMega * 1024;
377
378 OUString aUnitStr(' ');
379
380 if ( nSize < 10000 )
381 {
382 aUnitStr += SvtResId(STR_SVT_BYTES );
383 nDec = 0;
384 }
385 else if ( nSize < nMega )
386 {
387 fSize /= 1024;
388 aUnitStr += SvtResId(STR_SVT_KB);
389 nDec = 1;
390 }
391 else if ( nSize < nGiga )
392 {
393 fSize /= nMega;
394 aUnitStr += SvtResId(STR_SVT_MB);
395 nDec = 2;
396 }
397 else
398 {
399 fSize /= nGiga;
400 aUnitStr += SvtResId(STR_SVT_GB);
401 nDec = 3;
402 }
403
404 OUString aSizeStr( ::rtl::math::doubleToUString( fSize,
405 rtl_math_StringFormat_F, nDec,
406 SvtSysLocale().GetLocaleData().getNumDecimalSep()[0]) );
407 aSizeStr += aUnitStr;
408
409 return aSizeStr;
410 }
411 }
412
ViewTabListBox_Impl(std::unique_ptr<weld::TreeView> xTreeView,weld::Window * pTopLevel,SvtFileView_Impl * pParent,FileViewFlags nFlags)413 ViewTabListBox_Impl::ViewTabListBox_Impl(std::unique_ptr<weld::TreeView> xTreeView,
414 weld::Window* pTopLevel,
415 SvtFileView_Impl* pParent,
416 FileViewFlags nFlags)
417 : mxTreeView(std::move(xTreeView))
418 , mxScratchIter(mxTreeView->make_iterator())
419 , mpParent( pParent )
420 , mnSearchIndex( 0 )
421 , mbEnableDelete( false )
422 , mbEditing( false )
423 , mbShowType(nFlags & FileViewFlags::SHOW_TYPE)
424 {
425 std::vector<int> aWidths;
426 aWidths.push_back(180);
427 if (nFlags & FileViewFlags::SHOW_TYPE)
428 aWidths.push_back(140);
429 aWidths.push_back(80);
430 mxTreeView->set_column_fixed_widths(aWidths);
431
432 if (nFlags & FileViewFlags::MULTISELECTION)
433 mxTreeView->set_selection_mode(SelectionMode::Multiple);
434
435 maResetQuickSearch.SetTimeout( QUICK_SEARCH_TIMEOUT );
436 maResetQuickSearch.SetInvokeHandler( LINK( this, ViewTabListBox_Impl, ResetQuickSearch_Impl ) );
437
438 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
439 Reference< XInteractionHandler > xInteractionHandler(
440 InteractionHandler::createWithParent(xContext, pTopLevel->GetXWindow()), UNO_QUERY_THROW);
441
442 mxCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() );
443
444 mxTreeView->connect_popup_menu(LINK(this, ViewTabListBox_Impl, CommandHdl));
445 mxTreeView->connect_key_press(LINK(this, ViewTabListBox_Impl, KeyInputHdl));
446 }
447
IMPL_LINK_NOARG(ViewTabListBox_Impl,EditingEntryHdl,const weld::TreeIter &,bool)448 IMPL_LINK_NOARG(ViewTabListBox_Impl, EditingEntryHdl, const weld::TreeIter&, bool)
449 {
450 return mbEditing;
451 }
452
IMPL_LINK_NOARG(ViewTabListBox_Impl,ResetQuickSearch_Impl,Timer *,void)453 IMPL_LINK_NOARG(ViewTabListBox_Impl, ResetQuickSearch_Impl, Timer *, void)
454 {
455 ::osl::MutexGuard aGuard( maMutex );
456
457 maQuickSearchText.clear();
458 mnSearchIndex = 0;
459 }
460
IMPL_LINK(ViewTabListBox_Impl,KeyInputHdl,const KeyEvent &,rKEvt,bool)461 IMPL_LINK(ViewTabListBox_Impl, KeyInputHdl, const KeyEvent&, rKEvt, bool)
462 {
463 if (mbEditing)
464 return false;
465
466 bool bHandled = false;
467
468 const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
469 if ( 0 == rKeyCode.GetModifier() )
470 {
471 if ( ( rKeyCode.GetCode() == KEY_DELETE ) &&
472 mbEnableDelete )
473 {
474 ResetQuickSearch_Impl( nullptr );
475 DeleteEntries();
476 bHandled = true;
477 }
478 else if ( ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_NUM ) ||
479 ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_ALPHA ) )
480 {
481 DoQuickSearch( rKEvt.GetCharCode() );
482 bHandled = true;
483 }
484 }
485
486 if (!bHandled)
487 ResetQuickSearch_Impl( nullptr );
488 return bHandled;
489 }
490
IMPL_LINK(ViewTabListBox_Impl,CommandHdl,const CommandEvent &,rCEvt,bool)491 IMPL_LINK(ViewTabListBox_Impl, CommandHdl, const CommandEvent&, rCEvt, bool)
492 {
493 if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
494 return false;
495
496 bool bEnableDelete = mbEnableDelete;
497 bool bEnableRename = true;
498
499 int nCount = 0;
500 mxTreeView->selected_foreach([this, &nCount, &bEnableDelete, &bEnableRename](weld::TreeIter& rEntry){
501 ++nCount;
502
503 ::ucbhelper::Content aCnt;
504 try
505 {
506 OUString aURL(reinterpret_cast<SvtContentEntry*>(
507 mxTreeView->get_id(rEntry).toInt64())->maURL);
508 aCnt = ::ucbhelper::Content( aURL, mxCmdEnv, comphelper::getProcessComponentContext() );
509 }
510 catch( Exception const & )
511 {
512 bEnableDelete = bEnableRename = false;
513 }
514
515 if ( bEnableDelete )
516 {
517 try
518 {
519 Reference< XCommandInfo > aCommands = aCnt.getCommands();
520 if ( aCommands.is() )
521 bEnableDelete = aCommands->hasCommandByName( "delete" );
522 else
523 bEnableDelete = false;
524 }
525 catch( Exception const & )
526 {
527 bEnableDelete = false;
528 }
529 }
530
531 if ( bEnableRename )
532 {
533 try
534 {
535 Reference< XPropertySetInfo > aProps = aCnt.getProperties();
536 if ( aProps.is() )
537 {
538 Property aProp = aProps->getPropertyByName("Title");
539 bEnableRename
540 = !( aProp.Attributes & PropertyAttribute::READONLY );
541 }
542 else
543 bEnableRename = false;
544 }
545 catch( Exception const & )
546 {
547 bEnableRename = false;
548 }
549 }
550
551 bool bStop = !bEnableDelete && !bEnableRename;
552 return bStop;
553 });
554
555 if (nCount == 0)
556 bEnableDelete = false;
557 if (nCount != 1)
558 bEnableRename = false;
559
560 if (bEnableDelete || bEnableRename)
561 {
562 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(mxTreeView.get(), "svt/ui/fileviewmenu.ui"));
563 auto xContextMenu = xBuilder->weld_menu("menu");
564 xContextMenu->set_visible("delete", bEnableDelete);
565 xContextMenu->set_visible("rename", bEnableRename);
566 OString sCommand(xContextMenu->popup_at_rect(mxTreeView.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1))));
567 ExecuteContextMenuAction(sCommand);
568 }
569
570 return true;
571 }
572
ExecuteContextMenuAction(const OString & rSelectedPopupEntry)573 void ViewTabListBox_Impl::ExecuteContextMenuAction(const OString& rSelectedPopupEntry)
574 {
575 if (rSelectedPopupEntry == "delete")
576 DeleteEntries();
577 else if (rSelectedPopupEntry == "rename")
578 {
579 std::unique_ptr<weld::TreeIter> xEntry = mxTreeView->make_iterator();
580 if (mxTreeView->get_selected(xEntry.get()))
581 {
582 mbEditing = true;
583
584 mxTreeView->connect_editing(LINK(this, ViewTabListBox_Impl, EditingEntryHdl),
585 LINK(this, ViewTabListBox_Impl, EditedEntryHdl));
586
587 mxTreeView->start_editing(*xEntry);
588 }
589 }
590 }
591
DeleteEntries()592 void ViewTabListBox_Impl::DeleteEntries()
593 {
594 short eResult = svtools::QUERYDELETE_YES;
595
596 mxTreeView->selected_foreach([this, &eResult](weld::TreeIter& rCurEntry){
597 OUString aURL;
598 if (!mxTreeView->get_id(rCurEntry).isEmpty())
599 aURL = reinterpret_cast<SvtContentEntry*>(mxTreeView->get_id(rCurEntry).toInt64())->maURL;
600 if (aURL.isEmpty())
601 {
602 mxTreeView->unselect(rCurEntry);
603 return false;
604 }
605
606 bool canDelete = true;
607 try
608 {
609 ::ucbhelper::Content aCnt( aURL, mxCmdEnv, comphelper::getProcessComponentContext() );
610 Reference< XCommandInfo > aCommands = aCnt.getCommands();
611 if ( aCommands.is() )
612 canDelete = aCommands->hasCommandByName( "delete" );
613 else
614 canDelete = false;
615 }
616 catch( Exception const & )
617 {
618 canDelete = false;
619 }
620
621 if (!canDelete)
622 {
623 mxTreeView->unselect(rCurEntry);
624 return false; // process next entry
625 }
626
627 if ( eResult != svtools::QUERYDELETE_ALL )
628 {
629 INetURLObject aObj( aURL );
630 svtools::QueryDeleteDlg_Impl aDlg(
631 mxTreeView.get(), aObj.GetLastName(INetURLObject::DecodeMechanism::WithCharset));
632
633 if (mxTreeView->count_selected_rows() > 1)
634 aDlg.EnableAllButton();
635
636 eResult = aDlg.run();
637 }
638
639 if ( ( eResult == svtools::QUERYDELETE_ALL ) ||
640 ( eResult == svtools::QUERYDELETE_YES ) )
641 {
642 if ( Kill( aURL ) )
643 {
644 delete reinterpret_cast<SvtContentEntry*>(mxTreeView->get_id(rCurEntry).toInt64());
645 mpParent->EntryRemoved( aURL );
646 }
647 }
648
649 return false;
650 });
651
652 mxTreeView->remove_selection();
653 }
654
IMPL_LINK(ViewTabListBox_Impl,EditedEntryHdl,const IterString &,rIterString,bool)655 IMPL_LINK(ViewTabListBox_Impl, EditedEntryHdl, const IterString&, rIterString, bool)
656 {
657 mbEditing = false;
658
659 mxTreeView->connect_editing(Link<const weld::TreeIter&, bool>(), Link<const IterString&, bool>());
660
661 const weld::TreeIter& rEntry = rIterString.first;
662 OUString sNewText = rIterString.second;
663
664 if (sNewText.isEmpty())
665 return false;
666
667 bool bRet = false;
668
669 OUString aURL;
670 SvtContentEntry* pData = reinterpret_cast<SvtContentEntry*>(mxTreeView->get_id(rEntry).toInt64());
671
672 if ( pData )
673 aURL = pData->maURL;
674
675 if ( aURL.isEmpty() )
676 return bRet;
677
678 try
679 {
680 OUString aPropName( "Title" );
681 bool canRename = true;
682 ::ucbhelper::Content aContent( aURL, mxCmdEnv, comphelper::getProcessComponentContext() );
683
684 try
685 {
686 Reference< XPropertySetInfo > aProps = aContent.getProperties();
687 if ( aProps.is() )
688 {
689 Property aProp = aProps->getPropertyByName( aPropName );
690 canRename = !( aProp.Attributes & PropertyAttribute::READONLY );
691 }
692 else
693 {
694 canRename = false;
695 }
696 }
697 catch ( Exception const & )
698 {
699 canRename = false;
700 }
701
702 if ( canRename )
703 {
704 Any aValue;
705 aValue <<= sNewText;
706 aContent.setPropertyValue( aPropName, aValue );
707 mpParent->EntryRenamed(aURL, sNewText);
708
709 if (pData)
710 pData->maURL = aURL;
711
712 mxTreeView->set_id(rEntry, OUString::number(reinterpret_cast<sal_Int64>(pData)));
713
714 bRet = true;
715 }
716 }
717 catch( Exception const & )
718 {
719 }
720
721 return bRet;
722 }
723
DoQuickSearch(sal_Unicode rChar)724 void ViewTabListBox_Impl::DoQuickSearch( sal_Unicode rChar )
725 {
726 ::osl::MutexGuard aGuard( maMutex );
727
728 maResetQuickSearch.Stop();
729
730 OUString aLastText = maQuickSearchText;
731 sal_uInt32 aLastPos = mnSearchIndex;
732
733 maQuickSearchText += OUString(rChar).toAsciiLowerCase();
734
735 bool bFound = mpParent->SearchNextEntry( mnSearchIndex, maQuickSearchText, false );
736
737 if ( !bFound && ( aLastText.getLength() == 1 ) &&
738 ( aLastText == OUStringChar(rChar) ) )
739 {
740 mnSearchIndex = aLastPos + 1;
741 maQuickSearchText = aLastText;
742 bFound = mpParent->SearchNextEntry( mnSearchIndex, maQuickSearchText, true );
743 }
744
745 if (bFound)
746 {
747 mxTreeView->unselect_all();
748 mxTreeView->select(mnSearchIndex);
749 mxTreeView->set_cursor(mnSearchIndex);
750 mxTreeView->scroll_to_row(mnSearchIndex);
751 }
752
753 maResetQuickSearch.Start();
754 }
755
Kill(const OUString & rContent)756 bool ViewTabListBox_Impl::Kill( const OUString& rContent )
757 {
758 bool bRet = true;
759
760 try
761 {
762 ::ucbhelper::Content aCnt( rContent, mxCmdEnv, comphelper::getProcessComponentContext() );
763 aCnt.executeCommand( "delete", makeAny( true ) );
764 }
765 catch( css::ucb::CommandAbortedException const & )
766 {
767 SAL_INFO( "svtools.contnr", "CommandAbortedException" );
768 bRet = false;
769 }
770 catch( Exception const & )
771 {
772 SAL_INFO( "svtools.contnr", "Any other exception" );
773 bRet = false;
774 }
775
776 return bRet;
777 }
778
SvtFileView(weld::Window * pTopLevel,std::unique_ptr<weld::TreeView> xTreeView,std::unique_ptr<weld::IconView> xIconView,bool bOnlyFolder,bool bMultiSelection,bool bShowType)779 SvtFileView::SvtFileView(weld::Window* pTopLevel,
780 std::unique_ptr<weld::TreeView> xTreeView,
781 std::unique_ptr<weld::IconView> xIconView,
782 bool bOnlyFolder, bool bMultiSelection, bool bShowType )
783 {
784 FileViewFlags nFlags = FileViewFlags::NONE;
785 if ( bMultiSelection )
786 nFlags |= FileViewFlags::MULTISELECTION;
787 if ( bShowType )
788 nFlags |= FileViewFlags::SHOW_TYPE;
789
790 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
791 Reference< XInteractionHandler > xInteractionHandler(
792 InteractionHandler::createWithParent(xContext, pTopLevel->GetXWindow()), UNO_QUERY_THROW);
793 Reference < XCommandEnvironment > xCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() );
794
795 mpImpl.reset(new SvtFileView_Impl(this, pTopLevel, std::move(xTreeView), std::move(xIconView), xCmdEnv, nFlags, bOnlyFolder));
796
797 weld::TreeView* pView = mpImpl->mxView->getWidget();
798 pView->connect_column_clicked(LINK(this, SvtFileView, HeaderSelect_Impl));
799 }
800
grab_focus()801 void SvtFileView::grab_focus()
802 {
803 mpImpl->grab_focus();
804 }
805
has_focus() const806 bool SvtFileView::has_focus() const
807 {
808 return mpImpl->has_focus();
809 }
810
~SvtFileView()811 SvtFileView::~SvtFileView()
812 {
813 }
814
SetViewMode(FileViewMode eMode)815 void SvtFileView::SetViewMode( FileViewMode eMode )
816 {
817 mpImpl->SetViewMode( eMode );
818 }
819
GetURL(const weld::TreeIter & rEntry) const820 OUString SvtFileView::GetURL(const weld::TreeIter& rEntry) const
821 {
822 SvtContentEntry* pEntry;
823 if (mpImpl->mxView->get_visible())
824 pEntry = reinterpret_cast<SvtContentEntry*>(mpImpl->mxView->get_id(rEntry).toInt64());
825 else
826 pEntry = reinterpret_cast<SvtContentEntry*>(mpImpl->mxIconView->get_id(rEntry).toInt64());
827 if (pEntry)
828 return pEntry->maURL;
829 return OUString();
830 }
831
GetCurrentURL() const832 OUString SvtFileView::GetCurrentURL() const
833 {
834 SvtContentEntry* pEntry = nullptr;
835 OUString aURL;
836 if (mpImpl->mxView->get_visible())
837 {
838 std::unique_ptr<weld::TreeIter> xEntry = mpImpl->mxView->make_iterator();
839 if (mpImpl->mxView->get_selected(xEntry.get()))
840 pEntry = reinterpret_cast<SvtContentEntry*>(mpImpl->mxView->get_id(*xEntry).toInt64());
841 }
842 else
843 {
844 std::unique_ptr<weld::TreeIter> xEntry = mpImpl->mxIconView->make_iterator();
845 if (mpImpl->mxIconView->get_selected(xEntry.get()))
846 pEntry = reinterpret_cast<SvtContentEntry*>(mpImpl->mxIconView->get_id(*xEntry).toInt64());
847 }
848 if (pEntry)
849 aURL = pEntry->maURL;
850 return aURL;
851 }
852
CreatedFolder(const OUString & rUrl,const OUString & rNewFolder)853 void SvtFileView::CreatedFolder( const OUString& rUrl, const OUString& rNewFolder )
854 {
855 const SortingData_Impl& rEntry = mpImpl->FolderInserted( rUrl, rNewFolder );
856
857 mpImpl->maEntries.emplace_back(std::make_unique<SvtContentEntry>(rUrl, true));
858 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(mpImpl->maEntries.back().get())));
859
860 std::unique_ptr<weld::TreeIter> xEntry = mpImpl->mxView->make_iterator();
861 mpImpl->mxView->insert(rEntry.maDisplayName, sId, mpImpl->maFolderImage, *xEntry);
862 mpImpl->mxView->scroll_to_row(*xEntry);
863
864 std::unique_ptr<weld::TreeIter> xIconEntry = mpImpl->mxIconView->make_iterator();
865 mpImpl->mxIconView->insert(-1, &rEntry.maDisplayName, &sId, &mpImpl->maFolderImage, xIconEntry.get());
866 mpImpl->mxIconView->scroll_to_item(*xIconEntry);
867 }
868
PreviousLevel(const FileViewAsyncAction * pAsyncDescriptor)869 FileViewResult SvtFileView::PreviousLevel( const FileViewAsyncAction* pAsyncDescriptor )
870 {
871 FileViewResult eResult = eFailure;
872
873 OUString sParentURL;
874 if ( GetParentURL( sParentURL ) )
875 eResult = Initialize( sParentURL, mpImpl->maCurrentFilter, pAsyncDescriptor, maBlackList );
876
877 return eResult;
878 }
879
GetParentURL(OUString & rParentURL) const880 bool SvtFileView::GetParentURL( OUString& rParentURL ) const
881 {
882 bool bRet = false;
883 try
884 {
885 ::ucbhelper::Content aCnt( mpImpl->maViewURL, mpImpl->mxCmdEnv, comphelper::getProcessComponentContext() );
886 Reference< XContent > xContent( aCnt.get() );
887 Reference< css::container::XChild > xChild( xContent, UNO_QUERY );
888 if ( xChild.is() )
889 {
890 Reference< XContent > xParent( xChild->getParent(), UNO_QUERY );
891 if ( xParent.is() )
892 {
893 rParentURL = xParent->getIdentifier()->getContentIdentifier();
894 bRet = !rParentURL.isEmpty() && rParentURL != mpImpl->maViewURL;
895 }
896 }
897 }
898 catch( Exception const & )
899 {
900 // perhaps an unknown url protocol (e.g. "private:newdoc")
901 }
902
903 return bRet;
904 }
905
get_help_id() const906 OString SvtFileView::get_help_id() const
907 {
908 return mpImpl->mxView->get_help_id();
909 }
910
set_help_id(const OString & rHelpId)911 void SvtFileView::set_help_id(const OString& rHelpId)
912 {
913 mpImpl->mxView->set_help_id(rHelpId);
914 }
915
get_selected_text() const916 OUString SvtFileView::get_selected_text() const
917 {
918 if (mpImpl->mxView->get_visible())
919 return mpImpl->mxView->get_selected_text();
920 return mpImpl->mxIconView->get_selected_text();
921 }
922
Initialize(const OUString & rURL,const OUString & rFilter,const FileViewAsyncAction * pAsyncDescriptor,const css::uno::Sequence<OUString> & rBlackList)923 FileViewResult SvtFileView::Initialize(
924 const OUString& rURL,
925 const OUString& rFilter,
926 const FileViewAsyncAction* pAsyncDescriptor,
927 const css::uno::Sequence< OUString >& rBlackList )
928 {
929 weld::WaitObject aWaitCursor(mpImpl->m_pTopLevel);
930 maBlackList = rBlackList;
931
932 OUString sPushURL( mpImpl->maViewURL );
933
934 mpImpl->maViewURL = rURL;
935 FileViewResult eResult = ExecuteFilter( rFilter, pAsyncDescriptor );
936 switch ( eResult )
937 {
938 case eFailure:
939 case eTimeout:
940 mpImpl->maViewURL = sPushURL;
941 return eResult;
942
943 case eStillRunning:
944 OSL_ENSURE( pAsyncDescriptor, "SvtFileView::Initialize: we told it to read synchronously!" );
945 [[fallthrough]];
946 case eSuccess:
947 return eResult;
948 }
949
950 OSL_FAIL( "SvtFileView::Initialize: unreachable!" );
951 return eFailure;
952 }
953
ExecuteFilter(const OUString & rFilter,const FileViewAsyncAction * pAsyncDescriptor)954 FileViewResult SvtFileView::ExecuteFilter( const OUString& rFilter, const FileViewAsyncAction* pAsyncDescriptor )
955 {
956 mpImpl->maCurrentFilter = rFilter.toAsciiLowerCase();
957
958 mpImpl->Clear();
959 FileViewResult eResult = mpImpl->GetFolderContent_Impl(mpImpl->maViewURL, pAsyncDescriptor, maBlackList);
960 OSL_ENSURE( ( eResult != eStillRunning ) || pAsyncDescriptor, "SvtFileView::ExecuteFilter: we told it to read synchronously!" );
961 return eResult;
962 }
963
CancelRunningAsyncAction()964 void SvtFileView::CancelRunningAsyncAction()
965 {
966 mpImpl->CancelRunningAsyncAction();
967 }
968
SetNoSelection()969 void SvtFileView::SetNoSelection()
970 {
971 mpImpl->mxView->unselect_all();
972 mpImpl->mxIconView->unselect_all();
973 }
974
SetSelectHdl(const Link<SvtFileView *,void> & rHdl)975 void SvtFileView::SetSelectHdl(const Link<SvtFileView*,void>& rHdl)
976 {
977 mpImpl->SetSelectHandler(rHdl);
978 }
979
SetDoubleClickHdl(const Link<SvtFileView *,bool> & rHdl)980 void SvtFileView::SetDoubleClickHdl(const Link<SvtFileView*,bool>& rHdl)
981 {
982 mpImpl->SetDoubleClickHandler(rHdl);
983 }
984
GetSelectionCount() const985 sal_uInt32 SvtFileView::GetSelectionCount() const
986 {
987 if (mpImpl->mxView->get_visible())
988 return mpImpl->mxView->count_selected_rows();
989 return mpImpl->mxIconView->count_selected_items();
990 }
991
FirstSelected() const992 SvtContentEntry* SvtFileView::FirstSelected() const
993 {
994 if (mpImpl->mxView->get_visible())
995 {
996 SvtContentEntry* pRet = nullptr;
997 std::unique_ptr<weld::TreeIter> xEntry = mpImpl->mxView->make_iterator();
998 if (mpImpl->mxView->get_selected(xEntry.get()))
999 pRet = reinterpret_cast<SvtContentEntry*>(mpImpl->mxView->get_id(*xEntry).toInt64());
1000 return pRet;
1001 }
1002
1003 SvtContentEntry* pRet = nullptr;
1004 std::unique_ptr<weld::TreeIter> xEntry = mpImpl->mxIconView->make_iterator();
1005 if (mpImpl->mxIconView->get_selected(xEntry.get()))
1006 pRet = reinterpret_cast<SvtContentEntry*>(mpImpl->mxIconView->get_id(*xEntry).toInt64());
1007 return pRet;
1008 }
1009
GetViewURL() const1010 const OUString& SvtFileView::GetViewURL() const
1011 {
1012 return mpImpl->maViewURL;
1013 }
1014
SetOpenDoneHdl(const Link<SvtFileView *,void> & rHdl)1015 void SvtFileView::SetOpenDoneHdl( const Link<SvtFileView*,void>& rHdl )
1016 {
1017 mpImpl->maOpenDoneLink = rHdl;
1018 }
1019
EnableDelete(bool bEnable)1020 void SvtFileView::EnableDelete( bool bEnable )
1021 {
1022 mpImpl->EnableDelete( bEnable );
1023 }
1024
EndInplaceEditing()1025 void SvtFileView::EndInplaceEditing()
1026 {
1027 return mpImpl->EndEditing();
1028 }
1029
IMPL_LINK(SvtFileView,HeaderSelect_Impl,int,nColumn,void)1030 IMPL_LINK(SvtFileView, HeaderSelect_Impl, int, nColumn, void)
1031 {
1032 sal_uInt16 nItemID = nColumn + 1;
1033 // skip "TYPE"
1034 if (!mpImpl->mxView->TypeColumnVisible() && nItemID != COLUMN_TITLE)
1035 ++nItemID;
1036
1037 weld::TreeView* pView = mpImpl->mxView->getWidget();
1038 bool bSortAtoZ = mpImpl->mbAscending;
1039
1040 //set new arrow positions in headerbar
1041 if (nItemID != mpImpl->mnSortColumn)
1042 {
1043 // remove old indicator, new will be created in OpenFolder_Impl
1044 pView->set_sort_indicator(TRISTATE_INDET, mpImpl->GetSortColumn());
1045 }
1046 else
1047 bSortAtoZ = !bSortAtoZ;
1048
1049 mpImpl->Resort_Impl(nItemID, bSortAtoZ);
1050 }
1051
GetConfigString() const1052 OUString SvtFileView::GetConfigString() const
1053 {
1054 // sort order
1055 OUString sRet = OUString::number( mpImpl->mnSortColumn ) + ";";
1056
1057 bool bUp = mpImpl->mbAscending;
1058 sRet += (bUp ? OUStringLiteral("1") : OUStringLiteral("0")) + ";";
1059
1060 weld::TreeView* pView = mpImpl->mxView->getWidget();
1061 sal_uInt16 nCount = mpImpl->mxView->TypeColumnVisible() ? 4 : 3;
1062 for (sal_uInt16 i = 0; i < nCount; ++i)
1063 {
1064 sal_uInt16 nId = i + 1;
1065 // skip "TYPE"
1066 if (!mpImpl->mxView->TypeColumnVisible() && nId != COLUMN_TITLE)
1067 ++nId;
1068
1069 sRet += OUString::number( nId )
1070 + ";"
1071 + OUString::number(pView->get_column_width(i))
1072 + ";";
1073 }
1074
1075 return comphelper::string::stripEnd(sRet, ';');
1076 }
1077
GetContent()1078 ::std::vector< SvtContentEntry > SvtFileView::GetContent()
1079 {
1080 ::std::vector< SvtContentEntry > aContent;
1081
1082 for(auto const& elem : mpImpl->maContent)
1083 {
1084 SvtContentEntry aEntry( elem->maTargetURL, elem->mbIsFolder );
1085 aContent.push_back( aEntry );
1086 }
1087
1088 return aContent;
1089 }
1090
SetConfigString(const OUString & rCfgStr)1091 void SvtFileView::SetConfigString(const OUString& rCfgStr)
1092 {
1093 sal_Int32 nIdx = 0;
1094 mpImpl->mnSortColumn = static_cast<sal_uInt16>(rCfgStr.getToken( 0, ';', nIdx ).toInt32());
1095 mpImpl->mbAscending = static_cast<bool>(static_cast<sal_uInt16>(rCfgStr.getToken( 0, ';', nIdx ).toInt32()));
1096
1097 std::vector<int> aWidths(mpImpl->mxView->TypeColumnVisible() ? 4 : 3, -1);
1098
1099 while ( nIdx != -1 )
1100 {
1101 sal_uInt16 nItemId = static_cast<sal_uInt16>(rCfgStr.getToken( 0, ';', nIdx ).toInt32());
1102
1103 int nWidth = rCfgStr.getToken( 0, ';', nIdx ).toInt32();
1104
1105 // skip "TYPE"
1106 if (!mpImpl->mxView->TypeColumnVisible() && nItemId != COLUMN_TITLE)
1107 --nItemId;
1108 int nColumn = nItemId - 1;
1109
1110 if (nColumn >= 0 && static_cast<unsigned int>(nColumn) < aWidths.size())
1111 aWidths[nColumn] = nWidth;
1112 }
1113
1114 weld::TreeView* pView = mpImpl->mxView->getWidget();
1115 pView->set_column_fixed_widths(aWidths);
1116 }
1117
1118 // class SvtFileView_Impl
SvtFileView_Impl(SvtFileView * pAntiImpl,weld::Window * pTopLevel,std::unique_ptr<weld::TreeView> xTreeView,std::unique_ptr<weld::IconView> xIconView,Reference<XCommandEnvironment> const & xEnv,FileViewFlags nFlags,bool bOnlyFolder)1119 SvtFileView_Impl::SvtFileView_Impl(SvtFileView* pAntiImpl, weld::Window* pTopLevel,
1120 std::unique_ptr<weld::TreeView> xTreeView,
1121 std::unique_ptr<weld::IconView> xIconView,
1122 Reference < XCommandEnvironment > const & xEnv,
1123 FileViewFlags nFlags, bool bOnlyFolder)
1124 : m_pAntiImpl ( pAntiImpl )
1125 , m_eAsyncActionResult ( ::svt::EnumerationResult::ERROR )
1126 , m_bRunningAsyncAction ( false )
1127 , m_bAsyncActionCancelled ( false )
1128 , m_pTopLevel ( pTopLevel )
1129 , mxView(new ViewTabListBox_Impl(std::move(xTreeView), pTopLevel, this, nFlags))
1130 , mxIconView(std::move(xIconView))
1131 , mnSortColumn ( COLUMN_TITLE )
1132 , mbAscending ( true )
1133 , mbOnlyFolder ( bOnlyFolder )
1134 , mnSuspendSelectCallback ( 0 )
1135 , mbIsFirstResort ( true )
1136 , aIntlWrapper ( Application::GetSettings().GetLanguageTag() )
1137 , maFolderImage (RID_BMP_FOLDER)
1138 , mxCmdEnv ( xEnv )
1139 {
1140 weld::TreeView* pWidget = mxView->getWidget();
1141
1142 // set the width to something small so its the parent that decides the final
1143 // width
1144 Size aSize(42, pWidget->get_height_rows(7));
1145 pWidget->set_size_request(aSize.Width(), aSize.Height());
1146 mxIconView->set_size_request(aSize.Width(), aSize.Height());
1147 }
1148
~SvtFileView_Impl()1149 SvtFileView_Impl::~SvtFileView_Impl()
1150 {
1151 Clear();
1152 }
1153
Clear()1154 void SvtFileView_Impl::Clear()
1155 {
1156 ::osl::MutexGuard aGuard( maMutex );
1157
1158 maContent.clear();
1159 }
1160
GetFolderContent_Impl(const OUString & rFolder,const FileViewAsyncAction * pAsyncDescriptor,const css::uno::Sequence<OUString> & rBlackList)1161 FileViewResult SvtFileView_Impl::GetFolderContent_Impl(
1162 const OUString& rFolder,
1163 const FileViewAsyncAction* pAsyncDescriptor,
1164 const css::uno::Sequence< OUString >& rBlackList )
1165 {
1166 ::osl::ClearableMutexGuard aGuard( maMutex );
1167 INetURLObject aFolderObj( rFolder );
1168 DBG_ASSERT( aFolderObj.GetProtocol() != INetProtocol::NotValid, "Invalid URL!" );
1169
1170 FolderDescriptor aFolder( aFolderObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1171
1172 aGuard.clear();
1173 return GetFolderContent_Impl( aFolder, pAsyncDescriptor, rBlackList );
1174 }
1175
GetFolderContent_Impl(const FolderDescriptor & _rFolder,const FileViewAsyncAction * pAsyncDescriptor,const css::uno::Sequence<OUString> & rBlackList)1176 FileViewResult SvtFileView_Impl::GetFolderContent_Impl(
1177 const FolderDescriptor& _rFolder,
1178 const FileViewAsyncAction* pAsyncDescriptor,
1179 const css::uno::Sequence< OUString >& rBlackList )
1180 {
1181 DBG_TESTSOLARMUTEX();
1182 ::osl::ClearableMutexGuard aGuard( maMutex );
1183
1184 OSL_ENSURE( !m_xContentEnumerator.is(), "SvtFileView_Impl::GetFolderContent_Impl: still running another enumeration!" );
1185 m_xContentEnumerator.set(new ::svt::FileViewContentEnumerator(
1186 mxView->GetCommandEnvironment(), maContent, maMutex));
1187 // TODO: should we cache and re-use this thread?
1188
1189 if ( !pAsyncDescriptor )
1190 {
1191 ::svt::EnumerationResult eResult = m_xContentEnumerator->enumerateFolderContentSync( _rFolder, rBlackList );
1192 if ( ::svt::EnumerationResult::SUCCESS == eResult )
1193 {
1194 implEnumerationSuccess();
1195 m_xContentEnumerator.clear();
1196 return eSuccess;
1197 }
1198 m_xContentEnumerator.clear();
1199 return eFailure;
1200 }
1201
1202 m_bRunningAsyncAction = true;
1203 m_bAsyncActionCancelled = false;
1204 m_eAsyncActionResult = ::svt::EnumerationResult::ERROR;
1205 m_aAsyncActionFinished.reset();
1206
1207 // don't (yet) set m_aCurrentAsyncActionHandler to pTimeout->aFinishHandler.
1208 // By definition, this handler *only* gets called when the result cannot be obtained
1209 // during the minimum wait time, so it is only set below, when needed.
1210 m_aCurrentAsyncActionHandler = Link<void*,void>();
1211
1212 // minimum time to wait
1213 std::unique_ptr< TimeValue > pTimeout( new TimeValue );
1214 sal_Int32 nMinTimeout = pAsyncDescriptor->nMinTimeout;
1215 OSL_ENSURE( nMinTimeout > 0, "SvtFileView_Impl::GetFolderContent_Impl: invalid minimum timeout!" );
1216 if ( nMinTimeout <= 0 )
1217 nMinTimeout = sal_Int32( 1000 );
1218 pTimeout->Seconds = nMinTimeout / 1000L;
1219 pTimeout->Nanosec = ( nMinTimeout % 1000L ) * 1000000L;
1220
1221 m_xContentEnumerator->enumerateFolderContent( _rFolder, this );
1222
1223 // wait until the enumeration is finished
1224 // for this, release our own mutex (which is used by the enumerator thread)
1225 aGuard.clear();
1226
1227 ::osl::Condition::Result eResult = ::osl::Condition::result_ok;
1228 {
1229 // also release the SolarMutex. Not all code which is needed during the enumeration
1230 // is Solar-Thread-Safe, in particular there is some code which needs to access
1231 // string resources (and our resource system relies on the SolarMutex :()
1232 SolarMutexReleaser aSolarRelease;
1233
1234 // now wait. Note that if we didn't get a pAsyncDescriptor, then this is an infinite wait.
1235 eResult = m_aAsyncActionFinished.wait( pTimeout.get() );
1236 }
1237
1238 ::osl::MutexGuard aGuard2( maMutex );
1239 if ( ::osl::Condition::result_timeout == eResult )
1240 {
1241 // maximum time to wait
1242 OSL_ENSURE(!m_xCancelAsyncTimer,
1243 "SvtFileView_Impl::GetFolderContent_Impl: there's still a previous timer!");
1244 m_xCancelAsyncTimer.set(new CallbackTimer(this));
1245 sal_Int32 nMaxTimeout = pAsyncDescriptor->nMaxTimeout;
1246 OSL_ENSURE( nMaxTimeout > nMinTimeout,
1247 "SvtFileView_Impl::GetFolderContent_Impl: invalid maximum timeout!" );
1248 if ( nMaxTimeout <= nMinTimeout )
1249 nMaxTimeout = nMinTimeout + 5000;
1250 m_xCancelAsyncTimer->setRemainingTime( salhelper::TTimeValue( nMaxTimeout - nMinTimeout ) );
1251 // we already waited for nMinTimeout milliseconds, so take this into account
1252 m_xCancelAsyncTimer->start();
1253
1254 m_aCurrentAsyncActionHandler = pAsyncDescriptor->aFinishHandler;
1255 DBG_ASSERT( m_aCurrentAsyncActionHandler.IsSet(), "SvtFileView_Impl::GetFolderContent_Impl: nobody interested when it's finished?" );
1256 maEntries.clear();
1257 mxView->clear();
1258 mxIconView->clear();
1259 return eStillRunning;
1260 }
1261
1262 m_bRunningAsyncAction = false;
1263 switch ( m_eAsyncActionResult )
1264 {
1265 case ::svt::EnumerationResult::SUCCESS:
1266 return eSuccess;
1267
1268 case ::svt::EnumerationResult::ERROR:
1269 return eFailure;
1270 }
1271
1272 SAL_WARN( "svtools.contnr", "SvtFileView_Impl::GetFolderContent_Impl: unreachable!" );
1273 return eFailure;
1274 }
1275
FilterFolderContent_Impl(const OUString & rFilter)1276 void SvtFileView_Impl::FilterFolderContent_Impl( const OUString &rFilter )
1277 {
1278 if ( rFilter.isEmpty() || ( rFilter == ALL_FILES_FILTER ) )
1279 // when replacing names, there is always something to filter (no view of ".nametranslation.table")
1280 return;
1281
1282 ::osl::MutexGuard aGuard( maMutex );
1283
1284 if ( maContent.empty() )
1285 return;
1286
1287 // collect the filter tokens
1288 ::std::vector< WildCard > aFilters;
1289 FilterMatch::createWildCardFilterList(rFilter,aFilters);
1290
1291
1292 // do the filtering
1293 maContent.erase(std::remove_if(maContent.begin(), maContent.end(),
1294 [&aFilters](const std::unique_ptr<SortingData_Impl>& rxContent) {
1295 if (rxContent->mbIsFolder)
1296 return false;
1297 // normalize the content title (we always match case-insensitive)
1298 // 91872 - 11.09.2001 - frank.schoenheit@sun.com
1299 OUString sCompareString = rxContent->GetFileName(); // filter works on file name, not on title!
1300 return std::none_of(aFilters.begin(), aFilters.end(), FilterMatch(sCompareString));
1301 }),
1302 maContent.end());
1303 }
1304
IMPL_LINK_NOARG(SvtFileView_Impl,ChangedHdl,weld::TreeView &,void)1305 IMPL_LINK_NOARG(SvtFileView_Impl, ChangedHdl, weld::TreeView&, void)
1306 {
1307 if (!mnSuspendSelectCallback)
1308 m_aSelectHandler.Call(m_pAntiImpl);
1309 }
1310
IMPL_LINK_NOARG(SvtFileView_Impl,SelectionChangedHdl,weld::IconView &,void)1311 IMPL_LINK_NOARG(SvtFileView_Impl, SelectionChangedHdl, weld::IconView&, void)
1312 {
1313 if (!mnSuspendSelectCallback)
1314 m_aSelectHandler.Call(m_pAntiImpl);
1315 }
1316
SetSelectHandler(const Link<SvtFileView *,void> & rHdl)1317 void SvtFileView_Impl::SetSelectHandler(const Link<SvtFileView*,void>& rHdl)
1318 {
1319 m_aSelectHandler = rHdl;
1320
1321 mxView->connect_changed(LINK(this, SvtFileView_Impl, ChangedHdl));
1322 mxIconView->connect_selection_changed(LINK(this, SvtFileView_Impl, SelectionChangedHdl));
1323 }
1324
IMPL_LINK_NOARG(SvtFileView_Impl,RowActivatedHdl,weld::TreeView &,bool)1325 IMPL_LINK_NOARG(SvtFileView_Impl, RowActivatedHdl, weld::TreeView&, bool)
1326 {
1327 return maDoubleClickHandler.Call(m_pAntiImpl);
1328 }
1329
IMPL_LINK_NOARG(SvtFileView_Impl,ItemActivatedHdl,weld::IconView &,bool)1330 IMPL_LINK_NOARG(SvtFileView_Impl, ItemActivatedHdl, weld::IconView&, bool)
1331 {
1332 return maDoubleClickHandler.Call(m_pAntiImpl);
1333 }
1334
SetDoubleClickHandler(const Link<SvtFileView *,bool> & rHdl)1335 void SvtFileView_Impl::SetDoubleClickHandler(const Link<SvtFileView*,bool>& rHdl)
1336 {
1337 maDoubleClickHandler = rHdl;
1338
1339 mxView->connect_row_activated(LINK(this, SvtFileView_Impl, RowActivatedHdl));
1340 mxIconView->connect_item_activated(LINK(this, SvtFileView_Impl, ItemActivatedHdl));
1341 }
1342
OpenFolder_Impl()1343 void SvtFileView_Impl::OpenFolder_Impl()
1344 {
1345 ::osl::MutexGuard aGuard( maMutex );
1346
1347 mxView->freeze();
1348 mxIconView->freeze();
1349 maEntries.clear();
1350 mxView->clear();
1351 mxIconView->clear();
1352
1353 for (auto const& elem : maContent)
1354 {
1355 if (mbOnlyFolder && !elem->mbIsFolder)
1356 continue;
1357
1358 // insert entry and set user data
1359 maEntries.emplace_back(std::make_unique<SvtContentEntry>(elem->maTargetURL, elem->mbIsFolder));
1360 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(maEntries.back().get())));
1361 mxView->append(sId, elem->maDisplayName, elem->maType, elem->maDisplaySize, elem->maDisplayDate, elem->maImage);
1362 mxIconView->append(sId, elem->maDisplayName, elem->maImage);
1363 }
1364
1365 ++mnSuspendSelectCallback;
1366 mxView->thaw();
1367
1368 //set sort indicator
1369 weld::TreeView* pView = mxView->getWidget();
1370 pView->set_sort_indicator(mbAscending ? TRISTATE_TRUE : TRISTATE_FALSE, GetSortColumn());
1371
1372 mxIconView->thaw();
1373 --mnSuspendSelectCallback;
1374
1375 ResetCursor();
1376 }
1377
ResetCursor()1378 void SvtFileView_Impl::ResetCursor()
1379 {
1380 if (mxView->get_visible())
1381 {
1382 // deselect
1383 mxView->unselect_all();
1384 std::unique_ptr<weld::TreeIter> xFirst = mxView->make_iterator();
1385 if (mxView->get_iter_first(*xFirst))
1386 {
1387 // set cursor to the first entry
1388 mxView->set_cursor(*xFirst);
1389 }
1390 }
1391 else
1392 {
1393 // deselect
1394 mxIconView->unselect_all();
1395 std::unique_ptr<weld::TreeIter> xFirst = mxIconView->make_iterator();
1396 if (mxIconView->get_iter_first(*xFirst))
1397 {
1398 // set cursor to the first entry
1399 mxIconView->set_cursor(*xFirst);
1400 }
1401 }
1402 }
1403
CancelRunningAsyncAction()1404 void SvtFileView_Impl::CancelRunningAsyncAction()
1405 {
1406 DBG_TESTSOLARMUTEX();
1407 ::osl::MutexGuard aGuard( maMutex );
1408 if ( !m_xContentEnumerator.is() )
1409 return;
1410
1411 m_bAsyncActionCancelled = true;
1412 m_xContentEnumerator->cancel();
1413 m_bRunningAsyncAction = false;
1414
1415 m_xContentEnumerator.clear();
1416 if ( m_xCancelAsyncTimer.is() && m_xCancelAsyncTimer->isTicking() )
1417 m_xCancelAsyncTimer->stop();
1418 m_xCancelAsyncTimer.clear();
1419 }
1420
1421
onTimeout()1422 void SvtFileView_Impl::onTimeout()
1423 {
1424 SolarMutexGuard aSolarGuard;
1425 ::osl::MutexGuard aGuard( maMutex );
1426 if ( !m_bRunningAsyncAction )
1427 // there might have been a race condition while we waited for the mutex
1428 return;
1429
1430 CancelRunningAsyncAction();
1431
1432 if ( m_aCurrentAsyncActionHandler.IsSet() )
1433 {
1434 Application::PostUserEvent( m_aCurrentAsyncActionHandler, reinterpret_cast< void* >( eTimeout ) );
1435 m_aCurrentAsyncActionHandler = Link<void*,void>();
1436 }
1437 }
1438
1439
enumerationDone(::svt::EnumerationResult eResult)1440 void SvtFileView_Impl::enumerationDone( ::svt::EnumerationResult eResult )
1441 {
1442 SolarMutexGuard aSolarGuard;
1443 ::osl::MutexGuard aGuard( maMutex );
1444
1445 m_xContentEnumerator.clear();
1446 if ( m_xCancelAsyncTimer.is() && m_xCancelAsyncTimer->isTicking() )
1447 m_xCancelAsyncTimer->stop();
1448 m_xCancelAsyncTimer.clear();
1449
1450 if ( m_bAsyncActionCancelled )
1451 // this is to prevent race conditions
1452 return;
1453
1454 m_eAsyncActionResult = eResult;
1455 m_bRunningAsyncAction = false;
1456
1457 m_aAsyncActionFinished.set();
1458
1459 if ( svt::EnumerationResult::SUCCESS == eResult )
1460 implEnumerationSuccess();
1461
1462 if ( m_aCurrentAsyncActionHandler.IsSet() )
1463 {
1464 Application::PostUserEvent( m_aCurrentAsyncActionHandler, reinterpret_cast< void* >( m_eAsyncActionResult ) );
1465 m_aCurrentAsyncActionHandler = Link<void*,void>();
1466 }
1467 }
1468
1469
implEnumerationSuccess()1470 void SvtFileView_Impl::implEnumerationSuccess()
1471 {
1472 FilterFolderContent_Impl( maCurrentFilter );
1473 SortFolderContent_Impl();
1474 CreateDisplayText_Impl();
1475 OpenFolder_Impl();
1476 maOpenDoneLink.Call( m_pAntiImpl );
1477 }
1478
ReplaceTabWithString(const OUString & rValue)1479 OUString SvtFileView_Impl::ReplaceTabWithString(const OUString& rValue)
1480 {
1481 OUString const aTab( "\t" );
1482 OUString const aTabString( "%09" );
1483
1484 sal_Int32 iPos;
1485 OUString aValue(rValue);
1486 while ( ( iPos = aValue.indexOf( aTab ) ) >= 0 )
1487 aValue = aValue.replaceAt( iPos, 1, aTabString );
1488 return aValue;
1489 }
1490
CreateDisplayText_Impl()1491 void SvtFileView_Impl::CreateDisplayText_Impl()
1492 {
1493 ::osl::MutexGuard aGuard( maMutex );
1494
1495 OUString const aDateSep( ", " );
1496
1497 for (auto const& elem : maContent)
1498 {
1499 // title, type, size, date
1500 elem->maDisplayName = ReplaceTabWithString(elem->GetTitle());
1501 // folders don't have a size
1502 if ( ! elem->mbIsFolder )
1503 elem->maDisplaySize = CreateExactSizeText( elem->maSize );
1504 // set the date, but volumes have no date
1505 if ( ! elem->mbIsFolder || ! elem->mbIsVolume )
1506 {
1507 SvtSysLocale aSysLocale;
1508 const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData();
1509 elem->maDisplayDate = rLocaleData.getDate( elem->maModDate )
1510 + aDateSep
1511 + rLocaleData.getTime( elem->maModDate, false );
1512 }
1513
1514 // detect image
1515 if ( elem->mbIsFolder )
1516 {
1517 ::svtools::VolumeInfo aVolInfo( elem->mbIsVolume, elem->mbIsRemote,
1518 elem->mbIsRemoveable, elem->mbIsFloppy,
1519 elem->mbIsCompactDisc );
1520 elem->maImage = SvFileInformationManager::GetFolderImageId(aVolInfo);
1521 }
1522 else
1523 elem->maImage = SvFileInformationManager::GetFileImageId(INetURLObject(elem->maTargetURL));
1524 }
1525 }
1526
Resort_Impl(sal_Int16 nColumn,bool bAscending)1527 void SvtFileView_Impl::Resort_Impl( sal_Int16 nColumn, bool bAscending )
1528 {
1529 // TODO: IconView ()
1530 ::osl::MutexGuard aGuard( maMutex );
1531
1532 if ( ( nColumn == mnSortColumn ) &&
1533 ( bAscending == mbAscending ) )
1534 return;
1535
1536 // reset the quick search index
1537 mxView->ResetQuickSearch_Impl( nullptr );
1538
1539 std::unique_ptr<weld::TreeIter> xEntry(mxView->make_iterator());
1540 bool bEntry = mxView->get_cursor(xEntry.get());
1541
1542 OUString aEntryURL;
1543 if (bEntry && !mxView->get_id(*xEntry).isEmpty())
1544 aEntryURL = reinterpret_cast<SvtContentEntry*>(mxView->get_id(*xEntry).toInt64())->maURL;
1545
1546 mnSortColumn = nColumn;
1547 mbAscending = bAscending;
1548
1549 SortFolderContent_Impl();
1550 OpenFolder_Impl();
1551
1552 if ( !mbIsFirstResort )
1553 {
1554 int nPos = GetEntryPos( aEntryURL );
1555 if (nPos != -1 && nPos < mxView->n_children())
1556 {
1557 ++mnSuspendSelectCallback; // #i15668#
1558 mxView->set_cursor(nPos);
1559 --mnSuspendSelectCallback;
1560 }
1561 }
1562 else
1563 mbIsFirstResort = false;
1564 }
1565
1566 static bool gbAscending = true;
1567 static sal_Int16 gnColumn = COLUMN_TITLE;
1568 static const CollatorWrapper* pCollatorWrapper = nullptr;
1569
1570 /* this function returns true, if aOne is less than aTwo
1571 */
CompareSortingData_Impl(std::unique_ptr<SortingData_Impl> const & aOne,std::unique_ptr<SortingData_Impl> const & aTwo)1572 static bool CompareSortingData_Impl( std::unique_ptr<SortingData_Impl> const & aOne, std::unique_ptr<SortingData_Impl> const & aTwo )
1573 {
1574 DBG_ASSERT( pCollatorWrapper, "*CompareSortingData_Impl(): Can't work this way!" );
1575
1576 sal_Int32 nComp;
1577 bool bRet = false;
1578 bool bEqual = false;
1579
1580 if ( aOne->mbIsFolder != aTwo->mbIsFolder )
1581 {
1582 bRet = aOne->mbIsFolder;
1583
1584 // !!! pb: #100376# folder always on top
1585 if ( !gbAscending )
1586 bRet = !bRet;
1587 }
1588 else
1589 {
1590 switch ( gnColumn )
1591 {
1592 case COLUMN_TITLE:
1593 // compare case insensitive first
1594 nComp = pCollatorWrapper->compareString( aOne->GetLowerTitle(), aTwo->GetLowerTitle() );
1595
1596 if ( nComp == 0 )
1597 nComp = pCollatorWrapper->compareString( aOne->GetTitle(), aTwo->GetTitle() );
1598
1599 if ( nComp < 0 )
1600 bRet = true;
1601 else if ( nComp > 0 )
1602 bRet = false;
1603 else
1604 bEqual = true;
1605 break;
1606 case COLUMN_TYPE:
1607 nComp = pCollatorWrapper->compareString( aOne->maType, aTwo->maType );
1608 if ( nComp < 0 )
1609 bRet = true;
1610 else if ( nComp > 0 )
1611 bRet = false;
1612 else
1613 bEqual = true;
1614 break;
1615 case COLUMN_SIZE:
1616 if ( aOne->maSize < aTwo->maSize )
1617 bRet = true;
1618 else if ( aOne->maSize > aTwo->maSize )
1619 bRet = false;
1620 else
1621 bEqual = true;
1622 break;
1623 case COLUMN_DATE:
1624 if ( aOne->maModDate < aTwo->maModDate )
1625 bRet = true;
1626 else if ( aOne->maModDate > aTwo->maModDate )
1627 bRet = false;
1628 else
1629 bEqual = true;
1630 break;
1631 default:
1632 SAL_INFO( "svtools.contnr", "CompareSortingData_Impl: Compare unknown type!" );
1633 bRet = false;
1634 }
1635 }
1636
1637 // when the two elements are equal, we must not return sal_True (which would
1638 // happen if we just return ! ( a < b ) when not sorting ascending )
1639 if ( bEqual )
1640 return false;
1641
1642 return gbAscending ? bRet : !bRet;
1643 }
1644
1645
SortFolderContent_Impl()1646 void SvtFileView_Impl::SortFolderContent_Impl()
1647 {
1648 ::osl::MutexGuard aGuard( maMutex );
1649
1650 if ( maContent.size() > 1 )
1651 {
1652 gbAscending = mbAscending;
1653 gnColumn = mnSortColumn;
1654 pCollatorWrapper = aIntlWrapper.getCaseCollator();
1655
1656 std::stable_sort( maContent.begin(), maContent.end(), CompareSortingData_Impl );
1657
1658 pCollatorWrapper = nullptr;
1659 }
1660 }
1661
1662
EntryRemoved(const OUString & rURL)1663 void SvtFileView_Impl::EntryRemoved( const OUString& rURL )
1664 {
1665 ::osl::MutexGuard aGuard( maMutex );
1666
1667 maContent.erase(std::find_if(maContent.begin(), maContent.end(),
1668 [&](const std::unique_ptr<SortingData_Impl> & data) { return data->maTargetURL == rURL; }));
1669 }
1670
1671
EntryRenamed(OUString & rURL,const OUString & rTitle)1672 void SvtFileView_Impl::EntryRenamed( OUString& rURL,
1673 const OUString& rTitle )
1674 {
1675 ::osl::MutexGuard aGuard( maMutex );
1676
1677 auto aFoundElem = std::find_if(maContent.begin(), maContent.end(),
1678 [&](const std::unique_ptr<SortingData_Impl> & data) { return data->maTargetURL == rURL; });
1679 if (aFoundElem != maContent.end())
1680 {
1681 (*aFoundElem)->SetNewTitle( rTitle );
1682 (*aFoundElem)->maDisplayName = ReplaceTabWithString(rTitle);
1683
1684 INetURLObject aURLObj( rURL );
1685 aURLObj.setName( rTitle, INetURLObject::EncodeMechanism::All );
1686
1687 rURL = aURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1688
1689 (*aFoundElem)->maTargetURL = rURL;
1690 }
1691 }
1692
FolderInserted(const OUString & rURL,const OUString & rTitle)1693 const SortingData_Impl& SvtFileView_Impl::FolderInserted( const OUString& rURL, const OUString& rTitle )
1694 {
1695 ::osl::MutexGuard aGuard( maMutex );
1696
1697 std::unique_ptr<SortingData_Impl> pData(new SortingData_Impl);
1698
1699 pData->SetNewTitle( rTitle );
1700 pData->maSize = 0;
1701 pData->mbIsFolder = true;
1702 pData->maTargetURL = rURL;
1703
1704 ::svtools::VolumeInfo aVolInfo;
1705 pData->maType = SvFileInformationManager::GetFolderDescription( aVolInfo );
1706 pData->maImage = SvFileInformationManager::GetFolderImageId( aVolInfo );
1707
1708 OUString const aDateSep( ", " );
1709
1710 // title, type, size, date
1711 pData->maDisplayName = ReplaceTabWithString(pData->GetTitle());
1712 // set the date
1713 SvtSysLocale aSysLocale;
1714 const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData();
1715 pData->maDisplayDate = rLocaleData.getDate( pData->maModDate )
1716 + aDateSep
1717 + rLocaleData.getTime( pData->maModDate );
1718
1719 maContent.push_back( std::move(pData) );
1720
1721 return *maContent.back();
1722 }
1723
GetEntryPos(const OUString & rURL)1724 int SvtFileView_Impl::GetEntryPos(const OUString& rURL)
1725 {
1726 ::osl::MutexGuard aGuard( maMutex );
1727
1728 auto aFoundElem = std::find_if(maContent.begin(), maContent.end(),
1729 [&](const std::unique_ptr<SortingData_Impl> & data) { return data->maTargetURL == rURL; });
1730 return aFoundElem != maContent.end() ? std::distance(maContent.begin(), aFoundElem) : -1;
1731 }
1732
SetViewMode(FileViewMode eMode)1733 void SvtFileView_Impl::SetViewMode( FileViewMode eMode )
1734 {
1735 switch ( eMode )
1736 {
1737 case eDetailedList:
1738 mxView->show();
1739 mxIconView->hide();
1740 break;
1741
1742 case eIcon:
1743 mxView->hide();
1744 mxIconView->show();
1745 break;
1746
1747 default:
1748 mxView->show();
1749 mxIconView->hide();
1750 };
1751 }
1752
SearchNextEntry(sal_uInt32 & nIndex,const OUString & rTitle,bool bWrapAround)1753 bool SvtFileView_Impl::SearchNextEntry( sal_uInt32& nIndex, const OUString& rTitle, bool bWrapAround )
1754 {
1755 ::osl::MutexGuard aGuard( maMutex );
1756
1757 sal_uInt32 nEnd = maContent.size();
1758 sal_uInt32 nStart = nIndex;
1759 while ( nIndex < nEnd )
1760 {
1761 SortingData_Impl* pData = maContent[ nIndex ].get();
1762 if ( pData->GetLowerTitle().startsWith( rTitle ) )
1763 return true;
1764 ++nIndex;
1765 }
1766
1767 if ( bWrapAround )
1768 {
1769 nIndex = 0;
1770 while ( nIndex < nEnd && nIndex <= nStart )
1771 {
1772 SortingData_Impl* pData = maContent[ nIndex ].get();
1773 if ( pData->GetLowerTitle().startsWith( rTitle ) )
1774 return true;
1775 ++nIndex;
1776 }
1777 }
1778
1779 return false;
1780 }
1781
1782 namespace {
onShot()1783 void SAL_CALL CallbackTimer::onShot()
1784 {
1785 OSL_ENSURE( m_pTimeoutHandler, "CallbackTimer::onShot: nobody interested in?" );
1786 SvtFileView_Impl* pHandler( m_pTimeoutHandler );
1787 if ( pHandler )
1788 pHandler->onTimeout();
1789 }
1790 }
1791
selected_foreach(const std::function<bool (weld::TreeIter &)> & func)1792 void SvtFileView::selected_foreach(const std::function<bool(weld::TreeIter&)>& func)
1793 {
1794 if (mpImpl->mxView->get_visible())
1795 mpImpl->mxView->selected_foreach(func);
1796 else
1797 mpImpl->mxIconView->selected_foreach(func);
1798 }
1799
identifier() const1800 weld::Widget* SvtFileView::identifier() const
1801 {
1802 return mpImpl->mxView->getWidget();
1803 }
1804
1805 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1806