1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 #include "vbafiledialog.hxx"
23 #include "helperdecl.hxx"
24 #include "comphelper/processfactory.hxx"
25 #include <com/sun/star/lang/XServiceInfo.hpp>
26 #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
27 #include <com/sun/star/ui/dialogs/XFilePicker2.hpp>
28 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
29 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
30 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
31 #include "tools/urlobj.hxx"
32 #include <sfx2/filedlghelper.hxx>
33
34 using namespace ::com::sun::star;
35 using namespace ::com::sun::star::uno;
36
37
ScVbaFileDialog(const css::uno::Reference<ooo::vba::XHelperInterface> & xParent,const css::uno::Reference<css::uno::XComponentContext> & xContext,const css::uno::Reference<css::frame::XModel> & xModel)38 ScVbaFileDialog::ScVbaFileDialog( const css::uno::Reference< ooo::vba::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext > &xContext, const css::uno::Reference< css::frame::XModel >& xModel )
39 : ScVbaFileDialog_BASE( xParent, xContext ), m_xModel( xModel )
40 {
41 m_nDialogType = 3;
42 m_bAllowMultiSelect = sal_True;
43 m_pSelectedItems = new VbaFileDialogSelectedItems(xParent, xContext,
44 uno::Reference< container::XIndexAccess >(
45 static_cast< container::XIndexAccess* >( &m_FileDialogSelectedObj ),
46 UNO_QUERY ));
47 }
48
ScVbaFileDialog(const css::uno::Sequence<css::uno::Any> &,const css::uno::Reference<css::uno::XComponentContext> & xContext)49 ScVbaFileDialog::ScVbaFileDialog( const css::uno::Sequence< css::uno::Any >& /*args*/,
50 const css::uno::Reference< css::uno::XComponentContext >& xContext )
51 : ScVbaFileDialog_BASE( xContext ), m_xModel(), m_pSelectedItems(NULL)
52 {
53 m_nDialogType = 3;
54 m_bAllowMultiSelect = sal_True;
55 }
56
~ScVbaFileDialog()57 ScVbaFileDialog::~ScVbaFileDialog()
58 {
59 if (m_pSelectedItems != NULL)
60 {
61 delete m_pSelectedItems;
62 }
63 }
64
65 rtl::OUString&
getServiceImplName()66 ScVbaFileDialog::getServiceImplName()
67 {
68 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("ScVbaFileDialog") );
69 return sImplName;
70 }
71
72 css::uno::Sequence<rtl::OUString>
getServiceNames()73 ScVbaFileDialog::getServiceNames()
74 {
75 static Sequence< rtl::OUString > aServiceNames;
76 if ( aServiceNames.getLength() == 0 )
77 {
78 aServiceNames.realloc( 1 );
79 aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.excel.FileDialog" ) );
80 }
81 return aServiceNames;
82 }
83
84 sal_Int32 SAL_CALL
getMsoFileDialogType()85 ScVbaFileDialog::getMsoFileDialogType() throw ( css::uno::RuntimeException )
86 {
87 return m_nDialogType;
88 }
89
90 void SAL_CALL
setMsoFileDialogType(sal_Int32 nType)91 ScVbaFileDialog::setMsoFileDialogType( sal_Int32 nType ) throw ( css::uno::RuntimeException )
92 {
93 m_nDialogType = nType;
94 }
95
96 rtl::OUString SAL_CALL
getTitle()97 ScVbaFileDialog::getTitle() throw ( css::uno::RuntimeException )
98 {
99 return m_sTitle;
100 }
101
102 void SAL_CALL
setTitle(const rtl::OUString & rTitle)103 ScVbaFileDialog::setTitle( const rtl::OUString& rTitle ) throw ( css::uno::RuntimeException )
104 {
105 m_sTitle = rTitle;
106 }
107
108 sal_Bool SAL_CALL
getAllowMultiSelect()109 ScVbaFileDialog::getAllowMultiSelect() throw ( css::uno::RuntimeException )
110 {
111 return m_bAllowMultiSelect;
112 }
113
114 void SAL_CALL
setAllowMultiSelect(sal_Bool bAllow)115 ScVbaFileDialog::setAllowMultiSelect( sal_Bool bAllow ) throw ( css::uno::RuntimeException )
116 {
117 m_bAllowMultiSelect = bAllow;
118 }
119
120 css::uno::Reference< ooo::vba::XFileDialogSelectedItems > SAL_CALL
getSelectedItems()121 ScVbaFileDialog::getSelectedItems() throw ( css::uno::RuntimeException )
122 {
123 return css::uno::Reference< ooo::vba::XFileDialogSelectedItems >( m_pSelectedItems );
124 }
125
126 sal_Int32 SAL_CALL
Show()127 ScVbaFileDialog::Show() throw ( css::uno::RuntimeException )
128 {
129 // Returns an Integer indicating if user pressed "Open" button(-1) or "Cancel" button(0).
130 sal_Int32 nResult = -1;
131 try
132 {
133 m_sSelectedItems.realloc(0);
134
135 const ::rtl::OUString sServiceName = ::rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.FilePicker" );
136
137 Reference< lang::XMultiServiceFactory > xMSF( comphelper::getProcessServiceFactory(), uno::UNO_QUERY );
138 // Map MsoFileDialogType to appropriate AOO picker template.
139 // msoFileDialogOpen = 1, msoFileDialogSaveAs = 2,
140 // msoFileDialogFilePicker = 3 (default), msoFileDialogFolderPicker = 4
141 // Note: AOO's current FilePicker API does not expose a dedicated folder
142 // picker template; we fall back to FILEOPEN_SIMPLE for that case.
143 sal_Int16 nTemplateDesc = ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE;
144 switch ( m_nDialogType )
145 {
146 case 1: // msoFileDialogOpen
147 nTemplateDesc = ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE;
148 break;
149 case 2: // msoFileDialogSaveAs
150 nTemplateDesc = ui::dialogs::TemplateDescription::FILESAVE_SIMPLE;
151 break;
152 case 3: // msoFileDialogFilePicker
153 nTemplateDesc = ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE;
154 break;
155 case 4: // msoFileDialogFolderPicker - fall back to FILEOPEN_SIMPLE
156 default:
157 nTemplateDesc = ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE;
158 break;
159 }
160 Sequence< uno::Any > aDialogType( 1 );
161 aDialogType[0] <<= nTemplateDesc;
162 Reference< ui::dialogs::XFilePicker > xFilePicker( xMSF->createInstanceWithArguments( sServiceName, aDialogType ), UNO_QUERY );
163 Reference< ui::dialogs::XFilePicker2 > xFilePicker2( xFilePicker, UNO_QUERY );
164 Reference< ui::dialogs::XFilterManager > xFilterManager( xFilePicker, UNO_QUERY );
165 if ( xFilePicker.is() )
166 {
167 // Apply the title if one was set (XFilePicker inherits
168 // XExecutableDialog which provides setTitle)
169 if ( m_sTitle.getLength() > 0 )
170 {
171 uno::Reference< ui::dialogs::XExecutableDialog > xExecDialog( xFilePicker, UNO_QUERY );
172 if ( xExecDialog.is() )
173 xExecDialog->setTitle( m_sTitle );
174 }
175 xFilePicker->setMultiSelectionMode( m_bAllowMultiSelect );
176 // Only when there is no any filter in the msoFileDialogFilePicker dialog, then we need to add the All File Filter.
177 if ( xFilterManager.is() && xFilterManager->getCurrentFilter().equalsAscii("") )
178 {
179 xFilterManager->appendFilter( rtl::OUString::createFromAscii( "All Files" ), rtl::OUString::createFromAscii( "*.*" ) );
180 }
181 if ( xFilePicker->execute() )
182 {
183 sal_Bool bUseXFilePicker2 = sal_False;
184 Reference< lang::XServiceInfo > xServiceInfo( xFilePicker, UNO_QUERY );
185 if (xServiceInfo.is())
186 {
187 rtl::OUString sImplName = xServiceInfo->getImplementationName();
188 if (sImplName.equalsAscii("com.sun.star.comp.fpicker.VistaFileDialog") ||
189 sImplName.equalsAscii("com.sun.star.ui.dialogs.SalGtkFilePicker"))
190 {
191 bUseXFilePicker2 = sal_True;
192 }
193 }
194 if ( bUseXFilePicker2 && xFilePicker2.is() )
195 {
196 // On Linux, XFilePicker->getFiles() always return one selected file although we select
197 // more than one file, also on Vista XFilePicker->getFiles() does not work well too,
198 // so we call XFilePicker2->getSelectedFiles() to get selected files.
199 m_sSelectedItems = xFilePicker2->getSelectedFiles();
200 }
201 else
202 {
203 // If only one file is selected, the first entry of the sequence contains the complete path/filename in
204 // URL format. If multiple files are selected, the first entry of the sequence contains the path in URL
205 // format, and the other entries contains the names of the selected files without path information.
206 Sequence< rtl::OUString > aSelectedFiles = xFilePicker->getFiles();
207 sal_Int32 iFileCount = aSelectedFiles.getLength();
208 if ( iFileCount > 1 )
209 {
210 m_sSelectedItems.realloc( iFileCount - 1 );
211 INetURLObject aPath( aSelectedFiles[0] );
212 aPath.setFinalSlash();
213 for ( sal_Int32 i = 1; i < iFileCount; i++ )
214 {
215 if ( aSelectedFiles[i].indexOf ('/') > 0 || aSelectedFiles[i].indexOf ('\\') > 0 )
216 {
217 m_sSelectedItems[i - 1] = aSelectedFiles[i];
218 }
219 else
220 {
221 if ( i == 1 )
222 aPath.Append( aSelectedFiles[i] );
223 else
224 aPath.setName( aSelectedFiles[i] );
225 m_sSelectedItems[i - 1] = aPath.GetMainURL(INetURLObject::NO_DECODE);
226 }
227 }
228 }
229 else if ( iFileCount == 1 )
230 {
231 m_sSelectedItems = aSelectedFiles;
232 }
233 }
234
235 sal_Int32 iFileCount = m_sSelectedItems.getLength();
236 rtl::OUString aTemp;
237 for ( sal_Int32 i = 0; i < iFileCount; i++ )
238 {
239 INetURLObject aObj( m_sSelectedItems[i] );
240 if ( aObj.GetProtocol() == INET_PROT_FILE )
241 {
242 aTemp = aObj.PathToFileName();
243 m_sSelectedItems[i] = aTemp.getLength() > 0 ? aTemp : m_sSelectedItems[i];
244 }
245 }
246 }
247 else
248 {
249 nResult = 0;
250 }
251 }
252
253 m_FileDialogSelectedObj.SetSelectedFile(m_sSelectedItems);
254 }
255 catch( const uno::Exception& )
256 {
257 return 0;
258 }
259
260 return nResult;
261 }
262