LibreOffice Module fpicker (master) 1
VistaFilePickerImpl.cxx
Go to the documentation of this file.
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
22#include <memory>
23
25
26#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
27#include <com/sun/star/ui/dialogs/ControlActions.hpp>
28#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
29#include <com/sun/star/beans/StringPair.hpp>
30#include <com/sun/star/awt/XWindow.hpp>
31#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
32#include <com/sun/star/lang/SystemDependent.hpp>
34#include <fpicker/strings.hrc>
36#include <osl/file.hxx>
37#include <rtl/process.h>
39#include <o3tl/string_view.hxx>
40#include <vcl/svapp.hxx>
41#include "WinImplHelper.hxx"
42
43#include <shlguid.h>
44#include <shlobj.h>
45
46static bool is_current_process_window(HWND hwnd)
47{
48 DWORD pid;
49 GetWindowThreadProcessId(hwnd, &pid);
50 return (pid == GetCurrentProcessId());
51}
52
54{
55 HWND hwnd_parent = GetForegroundWindow();
56 if (!is_current_process_window(hwnd_parent))
57 hwnd_parent = GetDesktopWindow();
58 return hwnd_parent;
59}
60
61namespace {
62
63bool createFolderItem(OUString const& url, sal::systools::COMReference<IShellItem>& folder)
64{
65 OUString path;
66 if (osl::FileBase::getSystemPathFromFileURL(url, path)
67 != osl::FileBase::E_None)
68 {
69 return false;
70 }
71 HRESULT res = SHCreateItemFromParsingName(
72 o3tl::toW(path.getStr()), nullptr,
73 IID_PPV_ARGS(&folder));
74 return SUCCEEDED(res);
75}
76
77}
78
79namespace fpicker{
80namespace win32{
81namespace vista{
82
83
84// types, const etcpp.
85
86
87const ::sal_Int16 INVALID_CONTROL_ID = -1;
88const ::sal_Int16 INVALID_CONTROL_ACTION = -1;
89
90// Guids used for IFileDialog::SetClientGuid
91const GUID CLIENTID_FILEDIALOG_SIMPLE = {0xB8628FD3, 0xA3F5, 0x4845, 0x9B, 0x62, 0xD5, 0x1E, 0xDF, 0x97, 0xC4, 0x83};
92const GUID CLIENTID_FILEDIALOG_OPTIONS = {0x93ED486F, 0x0D04, 0x4807, 0x8C, 0x44, 0xAC, 0x26, 0xCB, 0x6C, 0x5D, 0x36};
93const GUID CLIENTID_FILESAVE_PASSWORD = {0xC12D4F4C, 0x4D41, 0x4D4F, 0x97, 0xEF, 0x87, 0xF9, 0x8D, 0xB6, 0x1E, 0xA6};
94const GUID CLIENTID_FILESAVE_SELECTION = {0x5B2482B3, 0x0358, 0x4E09, 0xAA, 0x64, 0x2B, 0x76, 0xB2, 0xA0, 0xDD, 0xFE};
95const GUID CLIENTID_FILESAVE_TEMPLATE = {0x9996D877, 0x20D5, 0x424B, 0x9C, 0x2E, 0xD3, 0xB6, 0x31, 0xEC, 0xF7, 0xCE};
96const GUID CLIENTID_FILEOPEN_LINK_TEMPLATE = {0x32237796, 0x1509, 0x49D1, 0xBB, 0x7E, 0x63, 0xAD, 0x36, 0xAE, 0x86, 0x8C};
97const GUID CLIENTID_FILEOPEN_LINK_ANCHOR = {0xBE3188CB, 0x399A, 0x45AE, 0x8F, 0x78, 0x75, 0x17, 0xAF, 0x26, 0x81, 0xEA};
98const GUID CLIENTID_FILEOPEN_PLAY = {0x32CFB147, 0xF5AE, 0x4F90, 0xA1, 0xF1, 0x81, 0x20, 0x72, 0xBB, 0x2F, 0xC5};
99const GUID CLIENTID_FILEOPEN_LINK = {0x39AC4BAE, 0x7D2D, 0x46BC, 0xBE, 0x2E, 0xF8, 0x8C, 0xB5, 0x65, 0x5E, 0x6A};
100
101
103{
104public:
105 TDialogImplBase(IFileDialog* iDialog)
106 : m_iDialog(iDialog)
107 {
108 }
109
110 virtual ~TDialogImplBase() = default;
111
113 virtual sal::systools::COMReference<IShellItemArray> getResult(bool bInExecute)
114 {
115 sal::systools::COMReference<IShellItem> iItem;
116 if (m_iDialog.is())
117 {
118 if (bInExecute)
119 m_iDialog->GetCurrentSelection(&iItem);
120 else
121 m_iDialog->GetResult(&iItem);
122 }
123 void* iItems = nullptr;
124 if (iItem.is())
125 SHCreateShellItemArrayFromShellItem(iItem.get(), IID_IShellItemArray, &iItems);
126 return static_cast<IShellItemArray*>(iItems);
127 }
128
129private:
131};
132
133namespace {
134
135template <class ComPtrDialog, REFCLSID CLSID> class TDialogImpl : public TDialogImplBase
136{
137public:
138 TDialogImpl()
139 : TDialogImplBase(ComPtrDialog(CLSID).get())
140 {
141 }
142};
143
144class TOpenDialogImpl : public TDialogImpl<TFileOpenDialog, CLSID_FileOpenDialog>
145{
146public:
147 sal::systools::COMReference<IShellItemArray> getResult(bool bInExecute) override
148 {
149 sal::systools::COMReference<IShellItemArray> iItems;
150 TFileOpenDialog iDialog(getComPtr(), sal::systools::COM_QUERY_THROW);
151 bool bGetResult = false;
152 if (!iDialog.is())
153 bGetResult = true;
154 else if (FAILED(bInExecute ? iDialog->GetSelectedItems(&iItems) : iDialog->GetResults(&iItems)))
155 bGetResult = true;
156
157 if (bGetResult)
158 iItems = TDialogImplBase::getResult(bInExecute);
159
160 return iItems;
161 }
162};
163
164}
165
166using TSaveDialogImpl = TDialogImpl<TFileSaveDialog, CLSID_FileSaveDialog>;
167using TFolderPickerDialogImpl = TDialogImpl<TFileOpenDialog, CLSID_FileOpenDialog>;
168
169
170static OUString lcl_getURLFromShellItem (IShellItem* pItem)
171{
172 sal::systools::CoTaskMemAllocated<wchar_t> pStr;
173 HRESULT hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pStr);
174 if (FAILED(hr))
175 {
176 // tdf#155176: One could think that querying SIGDN_URL would go first. But Windows uses
177 // current 8-bit codepage for the filenames, and URL-encodes those octets. So check it
178 // only after SIGDN_FILESYSPATH query failed (can it ever happen?)
179 if (SUCCEEDED(pItem->GetDisplayName(SIGDN_URL, &pStr)))
180 return OUString(o3tl::toU(pStr));
181
182 hr = pItem->GetDisplayName(SIGDN_PARENTRELATIVEPARSING, &pStr);
183 if (SUCCEEDED(hr))
184 {
185 GUID known_folder_id;
186 wchar_t* pStr2 = pStr;
187 if (pStr2[0] == ':' && pStr2[1] == ':' && pStr2[2] == '{')
188 pStr2 += 2;
189 hr = IIDFromString(pStr2, &known_folder_id);
190 if (SUCCEEDED(hr))
191 hr = SHGetKnownFolderPath(known_folder_id, 0, nullptr, &pStr);
192 }
193 }
194
195 // Default fallback
196 if (FAILED(hr))
197 hr = SHGetKnownFolderPath(FOLDERID_Documents, 0, nullptr, &pStr);
198
199 OUString sURL;
200 if (SUCCEEDED(hr))
201 ::osl::FileBase::getFileURLFromSystemPath(OUString(o3tl::toU(pStr)), sURL);
202 return sURL;
203}
204
205// Vista file picker shows the filter mask next to filter name in the list; so we need to remove the
206// mask from the filter name to avoid duplicating masks
207static OUString lcl_AdjustFilterName(const OUString& sName)
208{
209 const sal_Int32 idx = sName.indexOf("(.");
210 return (idx > 0) ? OUString(o3tl::trim(sName.subView(0, idx))) : sName;
211}
212
213// rvStrings holds the OUStrings, pointers to which data are stored in returned COMDLG_FILTERSPEC
214static ::std::vector<COMDLG_FILTERSPEC> lcl_buildFilterList(CFilterContainer& rContainer,
215 std::vector<OUString>& rvStrings)
216{
217 ::std::vector< COMDLG_FILTERSPEC > lList ;
219
220 rContainer.beginEnumFilter( );
221 while( rContainer.getNextFilter(aFilter) )
222 {
223 COMDLG_FILTERSPEC aSpec;
224
225 rvStrings.push_back(lcl_AdjustFilterName(aFilter.first)); // to avoid dangling pointer
226 aSpec.pszName = o3tl::toW(rvStrings.back().getStr());
227 aSpec.pszSpec = o3tl::toW(aFilter.second.getStr());
228
229 lList.push_back(aSpec);
230 }
231
232 return lList;
233}
234
235
237 : m_lFilters ()
238 , m_iEventHandler(new VistaFilePickerEventHandler(this))
239 , m_bInExecute (false)
240 , m_bWasExecuted (false)
241 , m_hParentWindow(nullptr)
242 , m_sDirectory ()
243 , m_sFilename ()
244{
245}
246
247
249{
250}
251
252
254{
255 try
256 {
257 switch(rRequest.getRequest())
258 {
261 break;
262
265 break;
266
267 case E_APPEND_FILTER :
268 impl_sta_appendFilter(rRequest);
269 break;
270
273 break;
274
277 break;
278
281 break;
282
285 break;
286
289 break;
290
293 break;
294
297 break;
298
299 case E_SET_TITLE :
300 impl_sta_SetTitle(rRequest);
301 break;
302
303 case E_SET_FILENAME:
304 impl_sta_SetFileName(rRequest);
305 break;
306
307 case E_SET_DIRECTORY :
308 impl_sta_SetDirectory(rRequest);
309 break;
310
311 case E_GET_DIRECTORY :
312 impl_sta_GetDirectory(rRequest);
313 break;
314
315 case E_SET_DEFAULT_NAME :
316 impl_sta_SetDefaultName(rRequest);
317 break;
318
321 break;
322
324 impl_sta_ShowDialogModal(rRequest);
325 break;
326
328 impl_sta_SetControlValue(rRequest);
329 break;
330
332 impl_sta_GetControlValue(rRequest);
333 break;
334
336 impl_sta_SetControlLabel(rRequest);
337 break;
338
340 impl_sta_GetControlLabel(rRequest);
341 break;
342
343 case E_ENABLE_CONTROL :
344 impl_sta_EnableControl(rRequest);
345 break;
346
347 // no default: let the compiler detect changes on enum ERequest !
348 }
349 }
350 catch(...)
351 {}
352}
353
354
356{
357 const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest.getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >());
358 if ( ! xListener.is())
359 return;
360
361 if (m_iEventHandler.is())
362 {
363 auto* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(m_iEventHandler.get());
364 pHandlerImpl->addFilePickerListener(xListener);
365 }
366}
367
368
370{
371 const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest.getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >());
372 if ( ! xListener.is())
373 return;
374
375 if (m_iEventHandler.is())
376 {
377 auto* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(m_iEventHandler.get());
378 pHandlerImpl->removeFilePickerListener(xListener);
379 }
380}
381
382
384{
385 const OUString sTitle = rRequest.getArgumentOrDefault(PROP_FILTER_TITLE, OUString());
386 const OUString sFilter = rRequest.getArgumentOrDefault(PROP_FILTER_VALUE, OUString());
387
388 m_lFilters.addFilter(sTitle, sFilter);
389}
390
391
393{
394 const css::uno::Sequence< css::beans::StringPair > aFilterGroup =
395 rRequest.getArgumentOrDefault(PROP_FILTER_GROUP, css::uno::Sequence< css::beans::StringPair >());
396
397 if ( m_lFilters.numFilter() > 0 && aFilterGroup.getLength() > 0 )
399
400 ::sal_Int32 c = aFilterGroup.getLength();
401 ::sal_Int32 i = 0;
402 for (i=0; i<c; ++i)
403 {
404 const css::beans::StringPair& rFilter = aFilterGroup[i];
405 m_lFilters.addFilter(rFilter.First, rFilter.Second);
406 }
407}
408
409
411{
412 const OUString sTitle = rRequest.getArgumentOrDefault(PROP_FILTER_TITLE, OUString());
413
415}
416
417
419{
421 if (!iDialog.is())
422 return;
423
424 UINT nIndex = UINT_MAX;
425 HRESULT hResult = iDialog->GetFileTypeIndex(&nIndex);
426 if (
427 ( FAILED(hResult) ) ||
428 ( nIndex == UINT_MAX ) // COM dialog sometimes return S_OK for empty filter lists .-(
429 )
430 return;
431
432 OUString sTitle;
433 ::sal_Int32 nRealIndex = nIndex-1; // COM dialog base on 1 ... filter container on 0 .-)
434 if (
435 (nRealIndex >= 0 ) &&
436 (m_lFilters.getFilterNameByIndex(nRealIndex, sTitle))
437 )
438 rRequest.setArgument(PROP_FILTER_TITLE, sTitle);
439 else if ( nRealIndex == -1 ) // Dialog not visible yet
440 {
441 sTitle = m_lFilters.getCurrentFilter();
442 rRequest.setArgument(PROP_FILTER_TITLE, sTitle);
443 }
444}
445
446
447template <class TDialogImplClass> void VistaFilePickerImpl::impl_sta_CreateDialog()
448{
449 m_pDialog = std::make_shared<TDialogImplClass>();
450}
451
452
454{
456 if (!iDialog.is())
457 return;
458
459 DWORD nFlags = 0;
460 iDialog->GetOptions ( &nFlags );
461
462 nFlags &= ~FOS_FORCESHOWHIDDEN;
463 nFlags |= FOS_PATHMUSTEXIST;
464 nFlags |= FOS_DONTADDTORECENT;
465 nFlags |= nOrFlags;
466
467 iDialog->SetOptions ( nFlags );
468
469 css::uno::Reference<css::awt::XWindow> xWindow = rRequest.getArgumentOrDefault(PROP_PARENT_WINDOW, css::uno::Reference<css::awt::XWindow>());
470 if(xWindow.is())
471 {
472 css::uno::Reference<css::awt::XSystemDependentWindowPeer> xSysDepWin(xWindow,css::uno::UNO_QUERY);
473 if(xSysDepWin.is()) {
474 css::uno::Sequence<sal_Int8> aProcessIdent(16);
475 rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8*>(aProcessIdent.getArray()));
476 css::uno::Any aAny = xSysDepWin->getWindowHandle(aProcessIdent,css::lang::SystemDependent::SYSTEM_WIN32);
477 sal_Int64 tmp = 0;
478 aAny >>= tmp;
479 if(tmp != 0)
480 {
481 m_hParentWindow = reinterpret_cast<HWND>(tmp);
482 }
483 }
484 }
485
486 ::sal_Int32 nFeatures = rRequest.getArgumentOrDefault(PROP_FEATURES, ::sal_Int32(0));
487 ::sal_Int32 nTemplate = rRequest.getArgumentOrDefault(PROP_TEMPLATE_DESCR, ::sal_Int32(0));
488 impl_sta_enableFeatures(nFeatures, nTemplate);
489
490 if (m_iEventHandler.is())
491 {
492 auto* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(m_iEventHandler.get());
493 pHandlerImpl->startListening(iDialog);
494 }
495}
496
497
499{
500 impl_sta_CreateDialog<TOpenDialogImpl>();
501 impl_sta_InitDialog(rRequest, FOS_FILEMUSTEXIST | FOS_OVERWRITEPROMPT);
502}
503
504
506{
507 impl_sta_CreateDialog<TSaveDialogImpl>();
508 impl_sta_InitDialog(rRequest, FOS_FILEMUSTEXIST | FOS_OVERWRITEPROMPT);
509}
510
511
513{
514 impl_sta_CreateDialog<TFolderPickerDialogImpl>();
515 impl_sta_InitDialog(rRequest, FOS_PICKFOLDERS);
516}
517
518
519const ::sal_Int32 GROUP_VERSION = 1;
520const ::sal_Int32 GROUP_TEMPLATE = 2;
521const ::sal_Int32 GROUP_IMAGETEMPLATE = 3;
522const ::sal_Int32 GROUP_CHECKBOXES = 4;
523const ::sal_Int32 GROUP_IMAGEANCHOR = 5;
524
525
526static void setLabelToControl(TFileDialogCustomize iCustom, sal_uInt16 nControlId)
527{
530 iCustom->SetControlLabel(nControlId, o3tl::toW(aLabel.getStr()) );
531}
532
533
534void VistaFilePickerImpl::impl_sta_enableFeatures(::sal_Int32 nFeatures, ::sal_Int32 nTemplate)
535{
536 GUID aGUID = {};
537 switch (nTemplate)
538 {
539 case css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE :
540 case css::ui::dialogs::TemplateDescription::FILEOPEN_PREVIEW :
541 case css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE :
543 break;
544
545 case css::ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION :
546 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS :
548 break;
549
550 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD :
552 break;
553
554 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION :
555 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION :
557 break;
558
559 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE :
561 break;
562
563 case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE :
565 break;
566
567 case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR :
569 break;
570
571 case css::ui::dialogs::TemplateDescription::FILEOPEN_PLAY :
572 case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PLAY :
574 break;
575
576 case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW :
578 break;
579 }
581 if (iDialog.is())
582 iDialog->SetClientGuid ( aGUID );
583
585 if (!iCustom.is())
586 return;
587
588 if ((nFeatures & FEATURE_VERSION) == FEATURE_VERSION)
589 {
590 iCustom->StartVisualGroup (GROUP_VERSION, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_VERSION).replaceFirst("~","").getStr()));
591 iCustom->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION);
592 iCustom->EndVisualGroup ();
593 iCustom->MakeProminent (GROUP_VERSION);
594 }
595
596 if ((nFeatures & FEATURE_TEMPLATE) == FEATURE_TEMPLATE)
597 {
598 iCustom->StartVisualGroup (GROUP_TEMPLATE, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_TEMPLATES).replaceFirst("~","").getStr()));
599 iCustom->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE);
600 iCustom->EndVisualGroup ();
601 iCustom->MakeProminent (GROUP_TEMPLATE);
602 }
603
604 if ((nFeatures & FEATURE_IMAGETEMPLATE) == FEATURE_IMAGETEMPLATE)
605 {
606 iCustom->StartVisualGroup (GROUP_IMAGETEMPLATE, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_IMAGE_TEMPLATE).replaceFirst("~","").getStr()));
607 iCustom->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE);
608 iCustom->EndVisualGroup ();
609 iCustom->MakeProminent (GROUP_IMAGETEMPLATE);
610 }
611
612 if ((nFeatures & FEATURE_IMAGEANCHOR) == FEATURE_IMAGEANCHOR)
613 {
614 iCustom->StartVisualGroup (GROUP_IMAGEANCHOR, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_IMAGE_ANCHOR).replaceFirst("~","").getStr()));
615 iCustom->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR);
616 iCustom->EndVisualGroup ();
617 iCustom->MakeProminent (GROUP_IMAGEANCHOR);
618 }
619
620 iCustom->StartVisualGroup (GROUP_CHECKBOXES, L"");
621
622 sal_uInt16 nControlId(0);
623 if ((nFeatures & FEATURE_AUTOEXTENSION) == FEATURE_AUTOEXTENSION)
624 {
625 nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION;
626 iCustom->AddCheckButton (nControlId, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_AUTO_EXTENSION).replaceFirst("~","").getStr()), true);
628 }
629
630 if ((nFeatures & FEATURE_PASSWORD) == FEATURE_PASSWORD)
631 {
632 nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD;
633 iCustom->AddCheckButton (nControlId, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_PASSWORD).replaceFirst("~","").getStr()), false);
635 }
636
637 if ((nFeatures & FEATURE_GPGPASSWORD) == FEATURE_GPGPASSWORD)
638 {
639 nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION;
640 iCustom->AddCheckButton (nControlId, L"GpgPassword", false);
642 }
643
644 if ((nFeatures & FEATURE_READONLY) == FEATURE_READONLY)
645 {
646 nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY;
647 iCustom->AddCheckButton (nControlId, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_READONLY).replaceFirst("~","").getStr()), false);
649 }
650
651 if ((nFeatures & FEATURE_FILTEROPTIONS) == FEATURE_FILTEROPTIONS)
652 {
653 nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS;
654 iCustom->AddCheckButton (nControlId, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_FILTER_OPTIONS).replaceFirst("~","").getStr()), false);
656 }
657
658 if ((nFeatures & FEATURE_LINK) == FEATURE_LINK)
659 {
660 nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK;
661 iCustom->AddCheckButton (nControlId, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_INSERT_AS_LINK).replaceFirst("~","").getStr()), false);
663 }
664
665 if ((nFeatures & FEATURE_SELECTION) == FEATURE_SELECTION)
666 {
667 nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION;
668 iCustom->AddCheckButton (nControlId, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_SELECTION).replaceFirst("~","").getStr()), false);
670 }
671
672 /* can be ignored ... new COM dialog supports preview native now !
673 if ((nFeatures & FEATURE_PREVIEW) == FEATURE_PREVIEW)
674 iCustom->AddCheckButton (css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, L"Preview", false);
675 */
676
677 iCustom->EndVisualGroup();
678
679 if ((nFeatures & FEATURE_PLAY) == FEATURE_PLAY)
680 iCustom->AddPushButton (css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_PLAY).replaceFirst("~","").getStr()));
681
682}
683
684
686{
687 const bool bMultiSelection = rRequest.getArgumentOrDefault(PROP_MULTISELECTION_MODE, true);
688
690 if (!iDialog.is())
691 return;
692
693 DWORD nFlags = 0;
694 iDialog->GetOptions(&nFlags);
695
696 if (bMultiSelection)
697 nFlags |= FOS_ALLOWMULTISELECT;
698 else
699 nFlags &= ~FOS_ALLOWMULTISELECT;
700
701 iDialog->SetOptions ( nFlags );
702}
703
704
706{
707 OUString sTitle = rRequest.getArgumentOrDefault(PROP_TITLE, OUString());
708
710 if (!iDialog.is())
711 return;
712
713 iDialog->SetTitle(o3tl::toW(sTitle.getStr()));
714}
715
716
718{
719 OUString sFileName = rRequest.getArgumentOrDefault(PROP_FILENAME, OUString());
720
722 if (!iDialog.is())
723 return;
724
725 iDialog->SetFileName(o3tl::toW(sFileName.getStr()));
726}
727
728
730{
731 OUString sDirectory = rRequest.getArgumentOrDefault(PROP_DIRECTORY, OUString());
732
733 if( !m_bInExecute)
734 {
735 // Vista stores last used folders for file dialogs
736 // so we don't want the application to change the folder
737 // in most cases.
738 // Store the requested folder in the meantime and decide later
739 // what to do
740 m_sDirectory = sDirectory;
741 }
742
744 if (!iDialog.is())
745 return;
746
747 sal::systools::COMReference<IShellItem> pFolder;
748 if ( !createFolderItem(sDirectory, pFolder) )
749 return;
750
751 iDialog->SetFolder(pFolder.get());
752}
753
755{
757 if (!iDialog.is())
758 return OUString();
759 sal::systools::COMReference<IShellItem> pFolder;
760 HRESULT hResult = iDialog->GetFolder( &pFolder );
761 if ( FAILED(hResult) )
762 return OUString();
763 return lcl_getURLFromShellItem(pFolder.get());
764}
765
767{
768 const OUString sFolder = m_sDirectory.isEmpty() ? GetDirectory() : m_sDirectory;
769 if (!sFolder.isEmpty())
770 rRequest.setArgument(PROP_DIRECTORY, sFolder);
771}
772
774{
775 OUString sFilename = rRequest.getArgumentOrDefault(PROP_FILENAME, OUString());
777 if (!iDialog.is())
778 return;
779
781 if ( ! iCustom.is())
782 return;
783
784 // if we have the autoextension check box set, remove (or change ???) the extension of the filename
785 // so that the autoextension mechanism can do its job
786 BOOL bValue = FALSE;
787 HRESULT hResult = iCustom->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue);
788 if ( FAILED(hResult) )
789 return;
790 if ( bValue )
791 {
792 sal_Int32 nSepPos = sFilename.lastIndexOf( '.' );
793 if ( -1 != nSepPos )
794 sFilename = sFilename.copy(0, nSepPos);
795 }
796
797 iDialog->SetFileName (o3tl::toW(sFilename.getStr()));
798 m_sFilename = sFilename;
799}
800
801
803{
804 std::vector<OUString> vStrings; // to hold the adjusted filter names, pointers to which will be
805 // stored in lFilters
806 ::std::vector< COMDLG_FILTERSPEC > lFilters = lcl_buildFilterList(m_lFilters, vStrings);
807 OUString sCurrentFilter = m_lFilters.getCurrentFilter();
808 sal_Int32 nCurrentFilter = m_lFilters.getFilterPos(sCurrentFilter);
810 if (!iDialog.is())
811 return;
813 if (!iCustomize.is())
814 return;
815
816 if (lFilters.empty())
817 return;
818
819 COMDLG_FILTERSPEC *pFilt = lFilters.data();
820 iDialog->SetFileTypes(lFilters.size(), pFilt/*&lFilters[0]*/);
821 iDialog->SetFileTypeIndex(nCurrentFilter + 1);
822
823 BOOL bValue = FALSE;
824 HRESULT hResult = iCustomize->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue);
825 if ( FAILED(hResult) )
826 return;
827
828 if ( bValue )
829 {
830 PCWSTR lpFilterExt = lFilters[0].pszSpec;
831
832 lpFilterExt = wcsrchr( lpFilterExt, '.' );
833 if ( lpFilterExt )
834 lpFilterExt++;
835 iDialog->SetDefaultExtension( lpFilterExt );
836 }
837
838}
839
840
842{
843 if (m_pDialog == nullptr)
844 return;
845
846 // ask dialog for results
847 // we must react different if dialog is in execute or not .-(
848 sal::systools::COMReference<IShellItemArray> iItems = m_pDialog->getResult(m_bInExecute);
849 if (!iItems.is())
850 return;
851
852 // convert and pack results
853 std::vector< OUString > lFiles;
854 if (DWORD nCount; SUCCEEDED(iItems->GetCount(&nCount)))
855 {
856 for (DWORD i = 0; i < nCount; ++i)
857 {
858 if (sal::systools::COMReference<IShellItem> iItem;
859 SUCCEEDED(iItems->GetItemAt(i, &iItem)))
860 {
861 if (const OUString sURL = lcl_getURLFromShellItem(iItem.get()); !sURL.isEmpty())
862 lFiles.push_back(sURL);
863 }
864 }
865 }
866
868}
869
870
872{
874
876 if (!iDialog.is())
877 return;
878
879 // it's important to know if we are showing the dialog.
880 // Some dialog interface methods can't be called then or some
881 // tasks must be done differently .-) (e.g. see impl_sta_getSelectedFiles())
882 m_bInExecute = true;
883
884 m_bWasExecuted = true;
885
886 // we set the directory only if we have a save dialog and a filename
887 // for the other cases, the file dialog remembers its last location
888 // according to its client guid.
889 if( m_sDirectory.getLength())
890 {
891 sal::systools::COMReference<IShellItem> pFolder;
892 if ( createFolderItem(m_sDirectory, pFolder) )
893 {
894 if (m_sFilename.getLength())
895 {
896 OUString aFileURL(m_sDirectory);
897 sal_Int32 nIndex = aFileURL.lastIndexOf('/');
898 if (nIndex != aFileURL.getLength()-1)
899 aFileURL += "/";
900 aFileURL += m_sFilename;
901
903 if (!iCustom.is())
904 return;
905
906 BOOL bValue = FALSE;
907 HRESULT hResult = iCustom->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue);
908 if ( bValue )
909 {
910 UINT nFileType;
911 hResult = iDialog->GetFileTypeIndex(&nFileType);
912 if ( SUCCEEDED(hResult) && nFileType > 0 )
913 {
914 // COM dialog base on 1 ... filter container on 0 .-)
915 ::size_t nRealIndex = nFileType-1;
916 OUString sFilter;
917 if (m_lFilters.getFilterByIndex(nRealIndex, sFilter))
918 {
919 const sal_Int32 idx = sFilter.indexOf('.');
920 if (idx >= 0)
921 aFileURL += sFilter.subView(idx);
922 }
923 }
924 }
925
926 // Check existence of file. Set folder only for this special case
927 OUString aSystemPath;
928 osl_getSystemPathFromFileURL( aFileURL.pData, &aSystemPath.pData );
929
930 WIN32_FIND_DATAW aFindFileData;
931 HANDLE hFind = FindFirstFileW( o3tl::toW(aSystemPath.getStr()), &aFindFileData );
932 if (hFind != INVALID_HANDLE_VALUE)
933 iDialog->SetFolder(pFolder.get());
934 else
935 hResult = iDialog->AddPlace(pFolder.get(), FDAP_TOP);
936
937 FindClose( hFind );
938 }
939 else
940 iDialog->AddPlace(pFolder.get(), FDAP_TOP);
941 }
942 }
943
944 HRESULT hResult = E_FAIL;
945 try
946 {
947 // tdf#146007: Make sure we don't hold solar mutex: COM may need to forward
948 // the execution to the main thread, and holding solar mutex could deadlock
949 SolarMutexGuard g; // First acquire, to avoid releaser failure
951 // show dialog and wait for user decision
952 hResult = iDialog->Show(m_hParentWindow ? m_hParentWindow
953 : choose_parent_window()); // parent window needed
954 }
955 catch(...)
956 {}
957
958 m_bInExecute = false;
959
960 if (m_iEventHandler.is())
961 {
962 auto* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(m_iEventHandler.get());
963 pHandlerImpl->stopListening();
964 }
965
966 if ( FAILED(hResult) )
967 return;
968
970 rRequest.setArgument(PROP_DIALOG_SHOW_RESULT, true);
971}
972
973
975{
976 TFileDialog iDialog;
977
978 if (m_pDialog != nullptr)
979 iDialog = m_pDialog->getComPtr();
980
981 return iDialog;
982}
983
984
986{
987 if (m_pDialog != nullptr)
988 return { m_pDialog->getComPtr(), sal::systools::COM_QUERY_THROW };
989
990 return {};
991}
992
993
995 ::sal_Int16 nControlId)
996{
997 (void)iCustom->SetSelectedControlItem(nControlId, 1000); // Don't care if this fails (useless?)
998 DWORD i = 0;
999 HRESULT hResult = S_OK;
1000 while ( SUCCEEDED(hResult) )
1001 hResult = iCustom->RemoveControlItem(nControlId, i++);
1002}
1003
1004
1006{
1008 ::sal_Int16 nAction = rRequest.getArgumentOrDefault(PROP_CONTROL_ACTION, INVALID_CONTROL_ACTION);
1009 css::uno::Any aValue = rRequest.getValue(PROP_CONTROL_VALUE);
1010
1011 // don't check for right values here ...
1012 // most parameters are optional !
1013
1015 if ( ! iCustom.is())
1016 return;
1017
1018 switch (nId)
1019 {
1020 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION :
1021 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD :
1022 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY :
1023 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS :
1024 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK :
1025 //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
1026 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION :
1027 {
1028 bool bValue = false;
1029 aValue >>= bValue;
1030 iCustom->SetCheckButtonState(nId, bValue);
1031 }
1032 break;
1033
1034 case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION :
1035 case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE :
1036 case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE :
1037 case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR :
1038 {
1039 HRESULT hResult;
1040 switch (nAction)
1041 {
1042 case css::ui::dialogs::ControlActions::DELETE_ITEMS :
1043 {
1044 hResult = iCustom->RemoveAllControlItems(nId);
1045 if ( FAILED(hResult) )
1047 }
1048 break;
1049
1050 case css::ui::dialogs::ControlActions::ADD_ITEMS :
1051 {
1052 aValue >>= m_lItems;
1053 for (::sal_Int32 i=0; i<m_lItems.getLength(); ++i)
1054 {
1055 const OUString& sItem = m_lItems[i];
1056 hResult = iCustom->AddControlItem(nId, i, o3tl::toW(sItem.getStr()));
1057 }
1058 }
1059 break;
1060
1061 case css::ui::dialogs::ControlActions::SET_SELECT_ITEM :
1062 {
1063 ::sal_Int32 nItem = 0;
1064 aValue >>= nItem;
1065 hResult = iCustom->SetSelectedControlItem(nId, nItem);
1066 }
1067 break;
1068 }
1069 }
1070 break;
1071
1072 case css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY :
1073 {
1074 }
1075 break;
1076 }
1077}
1078
1079
1081{
1083
1084 // don't check for right values here ...
1085 // most parameters are optional !
1086
1088 if ( ! iCustom.is())
1089 return;
1090
1091 css::uno::Any aValue;
1092 if( m_bWasExecuted )
1093 switch (nId)
1094 {
1095 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD :
1096 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION :
1097 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY :
1098 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS :
1099 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK :
1100 //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
1101 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION :
1102 {
1103 BOOL bValue = FALSE;
1104 HRESULT hResult = iCustom->GetCheckButtonState(nId, &bValue);
1105 if ( SUCCEEDED(hResult) )
1106 aValue <<= bool(bValue);
1107 }
1108 break;
1109 case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION:
1110 case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE:
1111 case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE:
1112 case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR:
1113 {
1114 DWORD bValue = 0;
1115 HRESULT hResult = iCustom->GetSelectedControlItem(nId, &bValue);
1116 if ( SUCCEEDED(hResult) )
1117 {
1118 const OUString& sItem = m_lItems[bValue];
1119 aValue <<= OUString(sItem.getStr());
1120 }
1121 }
1122 break;
1123 }
1124
1125 if (aValue.hasValue())
1126 rRequest.setArgument(PROP_CONTROL_VALUE, aValue);
1127}
1128
1129
1131{
1133 OUString sLabel = rRequest.getArgumentOrDefault(PROP_CONTROL_LABEL, OUString() );
1134
1135 // don't check for right values here ...
1136 // most parameters are optional !
1137
1139 if ( ! iCustom.is())
1140 return;
1141 iCustom->SetControlLabel (nId, o3tl::toW(sLabel.getStr()));
1142}
1143
1144
1146{
1147}
1148
1149
1151{
1153 bool bEnabled = rRequest.getArgumentOrDefault(PROP_CONTROL_ENABLE, true);
1154
1155 // don't check for right values here ...
1156 // most parameters are optional !
1157
1159 if ( ! iCustom.is())
1160 return;
1161
1162 CDCONTROLSTATEF eState = CDCS_VISIBLE;
1163 if (bEnabled)
1164 eState |= CDCS_ENABLED;
1165 else
1166 eState |= CDCS_INACTIVE;
1167
1168 iCustom->SetControlState(nId, eState);
1169}
1170
1171void VistaFilePickerImpl::impl_SetDefaultExtension( const OUString& currentFilter )
1172{
1174 if (!iDialog.is())
1175 return;
1176
1177 if (currentFilter.getLength())
1178 {
1179 OUString FilterExt;
1180 m_lFilters.getFilterByName(currentFilter, FilterExt);
1181
1182 sal_Int32 posOfPoint = FilterExt.indexOf(L'.');
1183 const sal_Unicode* pFirstExtStart = FilterExt.getStr() + posOfPoint + 1;
1184
1185 sal_Int32 posOfSemiColon = FilterExt.indexOf(L';') - 1;
1186 if (posOfSemiColon < 0)
1187 posOfSemiColon = FilterExt.getLength() - 1;
1188
1189 FilterExt = OUString(pFirstExtStart, posOfSemiColon - posOfPoint);
1190 iDialog->SetDefaultExtension ( o3tl::toW(FilterExt.getStr()) );
1191 }
1192}
1193
1195{
1196 const OUString sFilter = m_lFilters.getCurrentFilter ();
1197 OUString sExt ;
1198 if (!m_lFilters.getFilterByName(sFilter, sExt))
1199 return;
1200
1202 if (!iDialog.is())
1203 return;
1204
1205 PCWSTR pExt = nullptr;
1206 if ( bChecked )
1207 {
1208 pExt = o3tl::toW(sExt.getStr());
1209 pExt = wcsrchr( pExt, '.' );
1210 if ( pExt )
1211 pExt++;
1212 }
1213 iDialog->SetDefaultExtension( pExt );
1214}
1215
1217{
1218 return true;
1219}
1220
1222{
1224}
1225
1226} // namespace vista
1227} // namespace win32
1228} // namespace fpicker
1229
1230/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int16 nControlId
static bool is_current_process_window(HWND hwnd)
static HWND choose_parent_window()
OUString SOfficeToWindowsLabel(const OUString &aSOLabel)
bool getFilterByIndex(sal_Int32 aIndex, OUString &theFilter) const
void setCurrentFilter(const OUString &aName)
std::pair< OUString, OUString > FILTER_ENTRY_T
bool getFilterByName(const OUString &aName, OUString &theFilter) const
sal_Int32 numFilter()
OUString getCurrentFilter() const
sal_Int32 getFilterPos(const OUString &aName) const
bool getFilterNameByIndex(sal_Int32 aIndex, OUString &theName) const
bool getNextFilter(FILTER_ENTRY_T &nextFilterEntry)
bool addFilter(const OUString &aName, const OUString &aFilter, bool bAllowDuplicates=false)
void setArgument(const OUString &sName, const TArgumentType &aValue)
Definition: requests.hxx:52
css::uno::Any getValue(OUString const &key) const
Definition: requests.hxx:63
TArgumentType getArgumentOrDefault(const OUString &sName, const TArgumentType &aDefault)
Definition: requests.hxx:58
virtual sal::systools::COMReference< IShellItemArray > getResult(bool bInExecute)
virtual void addFilePickerListener(const css::uno::Reference< css::ui::dialogs::XFilePickerListener > &xListener)
void stopListening()
stop listening for file picker events on the internally cached dialog COM object.
virtual void removeFilePickerListener(const css::uno::Reference< css::ui::dialogs::XFilePickerListener > &xListener)
void startListening(const TFileDialog &pBroadcaster)
start listening for file picker events on the given file open dialog COM object.
void impl_sta_enableFeatures(::sal_Int32 nFeatures, ::sal_Int32 nTemplate)
create all needed (optional!) UI controls addressed by the field nFeatures.
void impl_sta_SetDefaultName(Request &rRequest)
implementation of request E_SET_DEFAULT_NAME
void impl_sta_CreateOpenDialog(Request &rRequest)
implementation of request E_CREATE_OPEN_DIALOG
void impl_sta_appendFilterGroup(Request &rRequest)
implementation of request E_APPEND_FILTERGROUP
void impl_sta_removeFilePickerListener(Request &rRequest)
implementation of request E_REMOVE_FILEPICKER_LISTENER
void impl_sta_setCurrentFilter(Request &rRequest)
implementation of request E_SET_CURRENT_FILTER
void impl_sta_SetControlLabel(Request &rRequest)
implementation of request E_SET_CONTROL_LABEL
TFileDialogCustomize impl_getCustomizeInterface()
returns an interface, which can be used to customize the internally used COM dialog.
void impl_sta_SetControlValue(Request &rRequest)
implementation of request E_SET_CONTROL_VALUE
static void impl_sta_GetControlLabel(Request &rRequest)
implementation of request E_GET_CONTROL_LABEL
virtual void onAutoExtensionChanged(bool bChecked) override
virtual bool onFileTypeChanged(UINT nTypeIndex) override
void impl_sta_ShowDialogModal(Request &rRequest)
implementation of request E_SHOW_DIALOG_MODAL
void impl_sta_SetTitle(Request &rRequest)
implementation of request E_SET_TITLE
void impl_sta_appendFilter(Request &rRequest)
implementation of request E_APPEND_FILTER
void impl_sta_GetControlValue(Request &rRequest)
implementation of request E_GET_CONTROL_VALUE
void impl_sta_addFilePickerListener(Request &rRequest)
implementation of request E_ADD_FILEPICKER_LISTENER
void impl_sta_InitDialog(Request &rRequest, DWORD nOrFlags)
void impl_sta_getSelectedFiles(Request &rRequest)
implementation of request E_GET_SELECTED_FILES
void impl_sta_CreateSaveDialog(Request &rRequest)
implementation of request E_CREATE_SAVE_DIALOG
void impl_sta_GetDirectory(Request &rRequest)
implementation of request E_GET_DIRECTORY
void impl_sta_EnableControl(Request &rRequest)
implementation of request E_ENABLE_CONTROL
void impl_SetDefaultExtension(const OUString &currentFilter)
void impl_sta_getCurrentFilter(Request &rRequest)
implementation of request E_GET_CURRENT_FILTER
void impl_sta_SetDirectory(Request &rRequest)
implementation of request E_SET_DIRECTORY
void impl_sta_setFiltersOnDialog()
fill filter list of internal used dialog.
std::shared_ptr< TDialogImplBase > m_pDialog
object representing a file dialog
void impl_sta_SetMultiSelectionMode(Request &rRequest)
implementation of request E_SET_MULTISELECTION_MODE
void impl_sta_CreateFolderPicker(Request &rRequest)
implementation of request E_CREATE_FOLDER_PICKER
void impl_sta_SetFileName(Request &rRequest)
implementation of request E_SET_FILENAME
TFileDialogEvents m_iEventHandler
help us to handle dialog events and provide them to interested office listener.
int nCount
OUString sName
OUString FpsResId(TranslateId aId)
#define FALSE
const sal_uInt16 idx[]
sal_Int32 nIndex
NSString * getResString(sal_Int32 aId)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
const OUStringLiteral PROP_PICKER_LISTENER
const ::sal_Int32 FEATURE_READONLY
constexpr OUStringLiteral PROP_FILTER_GROUP(u"filter-group")
constexpr OUStringLiteral PROP_CONTROL_VALUE(u"control_value")
constexpr OUStringLiteral PROP_FILTER_TITLE(u"filter_title")
sal::systools::COMReference< IFileOpenDialog > TFileOpenDialog
Definition: vistatypes.h:34
static void setLabelToControl(TFileDialogCustomize iCustom, sal_uInt16 nControlId)
TDialogImpl< TFileOpenDialog, CLSID_FileOpenDialog > TFolderPickerDialogImpl
const ::sal_Int32 FEATURE_VERSION
constexpr OUStringLiteral PROP_FILTER_VALUE(u"filter_value")
static void lcl_removeControlItemsWorkaround(const TFileDialogCustomize &iCustom, ::sal_Int16 nControlId)
const ::sal_Int32 FEATURE_SELECTION
sal::systools::COMReference< IFileDialogCustomize > TFileDialogCustomize
Definition: vistatypes.h:37
const ::sal_Int32 FEATURE_TEMPLATE
constexpr OUStringLiteral PROP_FEATURES(u"features")
constexpr OUStringLiteral PROP_TITLE(u"title")
const ::sal_Int32 FEATURE_FILTEROPTIONS
const ::sal_Int32 GROUP_VERSION
constexpr OUStringLiteral PROP_CONTROL_LABEL(u"control_label")
const ::sal_Int32 FEATURE_PLAY
constexpr OUStringLiteral PROP_PARENT_WINDOW(u"ParentWindow")
const ::sal_Int32 GROUP_IMAGEANCHOR
TDialogImpl< TFileSaveDialog, CLSID_FileSaveDialog > TSaveDialogImpl
const ::sal_Int32 FEATURE_LINK
constexpr OUStringLiteral PROP_SELECTED_FILES(u"selected_files")
static OUString lcl_AdjustFilterName(const OUString &sName)
sal::systools::COMReference< IFileDialog > TFileDialog
Definition: vistatypes.h:33
static ::std::vector< COMDLG_FILTERSPEC > lcl_buildFilterList(CFilterContainer &rContainer, std::vector< OUString > &rvStrings)
const GUID CLIENTID_FILEOPEN_LINK_TEMPLATE
constexpr OUStringLiteral PROP_FILENAME(u"filename")
const ::sal_Int16 INVALID_CONTROL_ACTION
const ::sal_Int32 FEATURE_IMAGETEMPLATE
constexpr OUStringLiteral STRING_SEPARATOR(u"------------------------------------------")
const ::sal_Int32 GROUP_IMAGETEMPLATE
const ::sal_Int32 GROUP_TEMPLATE
const ::sal_Int32 FEATURE_AUTOEXTENSION
constexpr OUStringLiteral PROP_TEMPLATE_DESCR(u"templatedescription")
constexpr OUStringLiteral PROP_DIALOG_SHOW_RESULT(u"dialog_show_result")
static OUString lcl_getURLFromShellItem(IShellItem *pItem)
const GUID CLIENTID_FILEOPEN_LINK_ANCHOR
const ::sal_Int32 FEATURE_PASSWORD
const ::sal_Int32 FEATURE_IMAGEANCHOR
const ::sal_Int16 INVALID_CONTROL_ID
constexpr OUStringLiteral PROP_CONTROL_ACTION(u"control_action")
const OUStringLiteral PROP_CONTROL_ID
constexpr OUStringLiteral PROP_MULTISELECTION_MODE(u"multiselection_mode")
const ::sal_Int32 FEATURE_GPGPASSWORD
constexpr OUStringLiteral PROP_DIRECTORY(u"directory")
const ::sal_Int32 GROUP_CHECKBOXES
constexpr OUStringLiteral PROP_CONTROL_ENABLE(u"control_enable")
int i
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
sal_Int16 nId
const wchar_t *typedef BOOL
return hr
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
OUString aLabel
const char * pExt