Line data Source code
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 <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
21 : #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
22 : #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
23 : #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
24 : #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
25 : #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
26 : #include <com/sun/star/view/XSelectionSupplier.hpp>
27 : #include <com/sun/star/beans/XPropertyAccess.hpp>
28 : #include <com/sun/star/beans/XPropertySet.hpp>
29 : #include <com/sun/star/beans/XPropertyContainer.hpp>
30 : #include <com/sun/star/beans/PropertyAttribute.hpp>
31 : #include <com/sun/star/document/XExporter.hpp>
32 : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
33 : #include <com/sun/star/document/XDocumentProperties.hpp>
34 : #include <com/sun/star/task/ErrorCodeIOException.hpp>
35 : #include <com/sun/star/task/InteractionHandler.hpp>
36 : #include <com/sun/star/util/DateTime.hpp>
37 : #include <com/sun/star/util/URLTransformer.hpp>
38 : #include <com/sun/star/util/XURLTransformer.hpp>
39 : #include <com/sun/star/frame/ModuleManager.hpp>
40 : #include <com/sun/star/frame/XStorable.hpp>
41 : #include <com/sun/star/frame/XStorable2.hpp>
42 : #include <com/sun/star/frame/XDispatchProvider.hpp>
43 : #include <com/sun/star/frame/XDispatch.hpp>
44 : #include <com/sun/star/frame/XTitle.hpp>
45 : #include <com/sun/star/util/XModifyListener.hpp>
46 : #include <com/sun/star/util/XModifiable.hpp>
47 : #include <com/sun/star/util/XModifyBroadcaster.hpp>
48 :
49 : #include <com/sun/star/util/XCloneable.hpp>
50 : #include <com/sun/star/io/IOException.hpp>
51 :
52 : #include "guisaveas.hxx"
53 :
54 : #include <unotools/pathoptions.hxx>
55 : #include <svl/itemset.hxx>
56 : #include <svl/eitem.hxx>
57 : #include <svl/stritem.hxx>
58 : #include <svl/intitem.hxx>
59 : #include <unotools/useroptions.hxx>
60 : #include <unotools/saveopt.hxx>
61 : #include <svtools/miscopt.hxx>
62 : #include <tools/debug.hxx>
63 : #include <tools/urlobj.hxx>
64 : #include <comphelper/processfactory.hxx>
65 : #include <comphelper/mimeconfighelper.hxx>
66 : #include <vcl/layout.hxx>
67 : #include <vcl/window.hxx>
68 : #include <toolkit/awt/vclxwindow.hxx>
69 :
70 : #include <sfx2/sfxsids.hrc>
71 : #include <doc.hrc>
72 : #include <sfx2/sfxresid.hxx>
73 : #include <sfx2/docfilt.hxx>
74 : #include <sfx2/filedlghelper.hxx>
75 : #include <sfx2/app.hxx>
76 : #include <sfx2/objsh.hxx>
77 : #include <sfx2/dinfdlg.hxx>
78 : #include <sfx2/request.hxx>
79 : #include <sfxtypes.hxx>
80 : #include "alienwarn.hxx"
81 :
82 : #include <sfx2/docmacromode.hxx>
83 : #include <comphelper/interaction.hxx>
84 : #include <com/sun/star/task/ErrorCodeRequest.hpp>
85 : #include <rtl/ref.hxx>
86 : #include <framework/interaction.hxx>
87 : #include <svtools/sfxecode.hxx>
88 : #include "../appl/app.hrc"
89 :
90 : #include <boost/scoped_ptr.hpp>
91 :
92 : #include <com/sun/star/frame/Desktop.hpp>
93 :
94 : #include <officecfg/Office/Common.hxx>
95 :
96 : #include <vcl/FilterConfigItem.hxx>
97 : #include <com/sun/star/system/SystemShellExecute.hpp>
98 : #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
99 :
100 : // flags that specify requested operation
101 : #define EXPORT_REQUESTED 1
102 : #define PDFEXPORT_REQUESTED 2
103 : #define PDFDIRECTEXPORT_REQUESTED 4
104 : #define WIDEEXPORT_REQUESTED 8
105 : #define SAVE_REQUESTED 16
106 : #define SAVEAS_REQUESTED 32
107 : #define SAVEACOPY_REQUESTED 64
108 :
109 : // possible statuses of save operation
110 : #define STATUS_NO_ACTION 0
111 : #define STATUS_SAVE 1
112 : #define STATUS_SAVEAS 2
113 : #define STATUS_SAVEAS_STANDARDNAME 3
114 :
115 : const char aFilterNameString[] = "FilterName";
116 : const char aFilterOptionsString[] = "FilterOptions";
117 : const char aFilterDataString[] = "FilterData";
118 : const char aFilterFlagsString[] = "FilterFlags";
119 :
120 : using namespace ::com::sun::star;
121 : using namespace css::system;
122 :
123 : namespace {
124 :
125 0 : static sal_uInt16 getSlotIDFromMode( sal_Int8 nStoreMode )
126 : {
127 : // This is a temporary hardcoded solution must be removed when
128 : // dialogs do not need parameters in SidSet representation any more
129 :
130 0 : sal_uInt16 nResult = 0;
131 0 : if ( nStoreMode == EXPORT_REQUESTED || nStoreMode == ( EXPORT_REQUESTED | SAVEACOPY_REQUESTED | WIDEEXPORT_REQUESTED ) )
132 0 : nResult = SID_EXPORTDOC;
133 0 : else if ( nStoreMode == ( EXPORT_REQUESTED | PDFEXPORT_REQUESTED ) )
134 0 : nResult = SID_EXPORTDOCASPDF;
135 0 : else if ( nStoreMode == ( EXPORT_REQUESTED | PDFEXPORT_REQUESTED | PDFDIRECTEXPORT_REQUESTED ) )
136 0 : nResult = SID_DIRECTEXPORTDOCASPDF;
137 0 : else if ( nStoreMode == SAVEAS_REQUESTED || nStoreMode == ( EXPORT_REQUESTED | WIDEEXPORT_REQUESTED ) )
138 0 : nResult = SID_SAVEASDOC;
139 : else {
140 : DBG_ASSERT( false, "Unacceptable slot name is provided!\n" );
141 : }
142 :
143 0 : return nResult;
144 : }
145 :
146 :
147 0 : static sal_uInt8 getStoreModeFromSlotName( const OUString& aSlotName )
148 : {
149 0 : sal_uInt8 nResult = 0;
150 0 : if ( aSlotName == "ExportTo" )
151 0 : nResult = EXPORT_REQUESTED;
152 0 : else if ( aSlotName == "ExportToPDF" )
153 0 : nResult = EXPORT_REQUESTED | PDFEXPORT_REQUESTED;
154 0 : else if ( aSlotName == "ExportDirectToPDF" )
155 0 : nResult = EXPORT_REQUESTED | PDFEXPORT_REQUESTED | PDFDIRECTEXPORT_REQUESTED;
156 0 : else if ( aSlotName == "Save" )
157 0 : nResult = SAVE_REQUESTED;
158 0 : else if ( aSlotName == "SaveAs" )
159 0 : nResult = SAVEAS_REQUESTED;
160 : else
161 : throw task::ErrorCodeIOException(
162 0 : ("getStoreModeFromSlotName(\"" + aSlotName
163 0 : + "): ERRCODE_IO_INVALIDPARAMETER"),
164 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_INVALIDPARAMETER );
165 :
166 0 : return nResult;
167 : }
168 :
169 :
170 0 : static sal_Int32 getMustFlags( sal_Int8 nStoreMode )
171 : {
172 : return ( SFX_FILTER_EXPORT
173 0 : | ( ( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & WIDEEXPORT_REQUESTED ) ) ? 0 : SFX_FILTER_IMPORT ) );
174 : }
175 :
176 :
177 0 : static sal_Int32 getDontFlags( sal_Int8 nStoreMode )
178 : {
179 : return ( SFX_FILTER_INTERNAL
180 : | SFX_FILTER_NOTINFILEDLG
181 0 : | ( ( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & WIDEEXPORT_REQUESTED ) ) ? SFX_FILTER_IMPORT : 0 ) );
182 : }
183 :
184 :
185 : // class DocumentSettingsGuard
186 :
187 :
188 : class DocumentSettingsGuard
189 : {
190 : uno::Reference< beans::XPropertySet > m_xDocumentSettings;
191 : bool m_bPreserveReadOnly;
192 : bool m_bReadOnlySupported;
193 :
194 : bool m_bRestoreSettings;
195 : public:
196 0 : DocumentSettingsGuard( const uno::Reference< frame::XModel >& xModel, bool bReadOnly, bool bRestore )
197 : : m_bPreserveReadOnly( false )
198 : , m_bReadOnlySupported( false )
199 0 : , m_bRestoreSettings( bRestore )
200 : {
201 : try
202 : {
203 0 : uno::Reference< lang::XMultiServiceFactory > xDocSettingsSupplier( xModel, uno::UNO_QUERY_THROW );
204 : m_xDocumentSettings.set(
205 0 : xDocSettingsSupplier->createInstance(
206 0 : OUString( "com.sun.star.document.Settings" ) ),
207 0 : uno::UNO_QUERY_THROW );
208 :
209 0 : OUString aLoadReadonlyString( "LoadReadonly" );
210 :
211 : try
212 : {
213 0 : m_xDocumentSettings->getPropertyValue( aLoadReadonlyString ) >>= m_bPreserveReadOnly;
214 0 : m_xDocumentSettings->setPropertyValue( aLoadReadonlyString, uno::makeAny( bReadOnly ) );
215 0 : m_bReadOnlySupported = true;
216 : }
217 0 : catch( const uno::Exception& )
218 0 : {}
219 : }
220 0 : catch( const uno::Exception& )
221 : {}
222 :
223 0 : if ( ( bReadOnly && !m_bReadOnlySupported ) )
224 0 : throw uno::RuntimeException(); // the user could provide the data, so it must be stored
225 0 : }
226 :
227 0 : ~DocumentSettingsGuard()
228 0 : {
229 0 : if ( m_bRestoreSettings )
230 : {
231 0 : OUString aLoadReadonlyString( "LoadReadonly" );
232 :
233 : try
234 : {
235 0 : if ( m_bReadOnlySupported )
236 0 : m_xDocumentSettings->setPropertyValue( aLoadReadonlyString, uno::makeAny( m_bPreserveReadOnly ) );
237 : }
238 0 : catch( const uno::Exception& )
239 : {
240 : OSL_FAIL( "Unexpected exception!" );
241 0 : }
242 : }
243 0 : }
244 : };
245 : } // anonymous namespace
246 :
247 :
248 : // class ModelData_Impl
249 :
250 : class ModelData_Impl
251 : {
252 : SfxStoringHelper* m_pOwner;
253 : uno::Reference< frame::XModel > m_xModel;
254 : uno::Reference< frame::XStorable > m_xStorable;
255 : uno::Reference< frame::XStorable2 > m_xStorable2;
256 : uno::Reference< util::XModifiable > m_xModifiable;
257 :
258 : OUString m_aModuleName;
259 : ::comphelper::SequenceAsHashMap* m_pDocumentPropsHM;
260 : ::comphelper::SequenceAsHashMap* m_pModulePropsHM;
261 :
262 : ::comphelper::SequenceAsHashMap m_aMediaDescrHM;
263 :
264 : bool m_bRecommendReadOnly;
265 :
266 : public:
267 : ModelData_Impl( SfxStoringHelper& aOwner,
268 : const uno::Reference< frame::XModel >& xModel,
269 : const uno::Sequence< beans::PropertyValue >& aMediaDescr );
270 :
271 : ~ModelData_Impl();
272 :
273 : void FreeDocumentProps();
274 :
275 : uno::Reference< frame::XModel > GetModel();
276 : uno::Reference< frame::XStorable > GetStorable();
277 : uno::Reference< frame::XStorable2 > GetStorable2();
278 : uno::Reference< util::XModifiable > GetModifiable();
279 :
280 0 : ::comphelper::SequenceAsHashMap& GetMediaDescr() { return m_aMediaDescrHM; }
281 :
282 0 : bool IsRecommendReadOnly() const { return m_bRecommendReadOnly; }
283 :
284 : const ::comphelper::SequenceAsHashMap& GetDocProps();
285 :
286 : OUString GetModuleName();
287 : const ::comphelper::SequenceAsHashMap& GetModuleProps();
288 :
289 : void CheckInteractionHandler();
290 :
291 :
292 : OUString GetDocServiceName();
293 : uno::Sequence< beans::PropertyValue > GetDocServiceDefaultFilterCheckFlags( sal_Int32 nMust, sal_Int32 nDont );
294 : uno::Sequence< beans::PropertyValue > GetDocServiceAnyFilter( sal_Int32 nMust, sal_Int32 nDont );
295 : uno::Sequence< beans::PropertyValue > GetPreselectedFilter_Impl( sal_Int8 nStoreMode );
296 : uno::Sequence< beans::PropertyValue > GetDocServiceDefaultFilter();
297 :
298 : bool ExecuteFilterDialog_Impl( const OUString& aFilterName );
299 :
300 : sal_Int8 CheckSaveAcceptable( sal_Int8 nCurStatus );
301 : sal_Int8 CheckStateForSave();
302 :
303 : sal_Int8 CheckFilter( const OUString& );
304 :
305 : bool CheckFilterOptionsDialogExistence();
306 :
307 : bool OutputFileDialog( sal_Int8 nStoreMode,
308 : const ::comphelper::SequenceAsHashMap& aPreselectedFilterPropsHM,
309 : bool bSetStandardName,
310 : OUString& aSuggestedName,
311 : bool bPreselectPassword,
312 : OUString& aSuggestedDir,
313 : sal_Int16 nDialog,
314 : const OUString& rStandardDir,
315 : const ::com::sun::star::uno::Sequence< OUString >& rBlackList
316 : );
317 :
318 : bool ShowDocumentInfoDialog();
319 :
320 : OUString GetRecommendedDir( const OUString& aSuggestedDir );
321 : OUString GetRecommendedName( const OUString& aSuggestedName,
322 : const OUString& aTypeName );
323 :
324 : };
325 :
326 :
327 0 : ModelData_Impl::ModelData_Impl( SfxStoringHelper& aOwner,
328 : const uno::Reference< frame::XModel >& xModel,
329 : const uno::Sequence< beans::PropertyValue >& aMediaDescr )
330 : : m_pOwner( &aOwner )
331 : , m_xModel( xModel )
332 : , m_pDocumentPropsHM( NULL )
333 : , m_pModulePropsHM( NULL )
334 : , m_aMediaDescrHM( aMediaDescr )
335 0 : , m_bRecommendReadOnly( false )
336 : {
337 0 : CheckInteractionHandler();
338 0 : OUString sModuleName;
339 : try
340 : {
341 0 : uno::Reference< lang::XComponent > xCurrentComponent = frame::Desktop::create( comphelper::getProcessComponentContext() )->getCurrentComponent();
342 0 : sModuleName = aOwner.GetModuleManager()->identify(xCurrentComponent);
343 0 : if(sModuleName == "com.sun.star.chart2.ChartDocument")
344 : {
345 : // let us switch the model and set the xStorable and
346 : // XStorable2 to the old model.
347 : // This is an ugly hack because we have no SfxObjectShell for chart2 yet.
348 : // We need SfxObjectShell for the heavy work around ODF document creation
349 : // because chart2 only writes the basic stream out.
350 : // In future in might make sense to implement a full scale object shell in
351 : // chart2 and make chart2 an own program.
352 0 : m_xModel = uno::Reference< frame::XModel >(xCurrentComponent, uno::UNO_QUERY_THROW );
353 0 : m_xStorable = uno::Reference< frame::XStorable >(xModel, uno::UNO_QUERY_THROW );
354 0 : m_xStorable2 = uno::Reference< frame::XStorable2 >(xModel, uno::UNO_QUERY_THROW );
355 0 : }
356 : }
357 0 : catch(...)
358 : {
359 : // we don't want to pass on any errors;
360 0 : }
361 0 : }
362 :
363 :
364 0 : ModelData_Impl::~ModelData_Impl()
365 : {
366 0 : FreeDocumentProps();
367 0 : if ( m_pDocumentPropsHM )
368 0 : delete m_pDocumentPropsHM;
369 :
370 0 : if ( m_pModulePropsHM )
371 0 : delete m_pModulePropsHM;
372 0 : }
373 :
374 :
375 0 : void ModelData_Impl::FreeDocumentProps()
376 : {
377 0 : if ( m_pDocumentPropsHM )
378 : {
379 0 : delete m_pDocumentPropsHM;
380 0 : m_pDocumentPropsHM = NULL;
381 : }
382 0 : }
383 :
384 :
385 0 : uno::Reference< frame::XModel > ModelData_Impl::GetModel()
386 : {
387 0 : if ( !m_xModel.is() )
388 0 : throw uno::RuntimeException();
389 :
390 0 : return m_xModel;
391 : }
392 :
393 :
394 0 : uno::Reference< frame::XStorable > ModelData_Impl::GetStorable()
395 : {
396 0 : if ( !m_xStorable.is() )
397 : {
398 0 : m_xStorable = uno::Reference< frame::XStorable >( m_xModel, uno::UNO_QUERY );
399 0 : if ( !m_xStorable.is() )
400 0 : throw uno::RuntimeException();
401 : }
402 :
403 0 : return m_xStorable;
404 : }
405 :
406 :
407 0 : uno::Reference< frame::XStorable2 > ModelData_Impl::GetStorable2()
408 : {
409 0 : if ( !m_xStorable2.is() )
410 : {
411 0 : m_xStorable2 = uno::Reference< frame::XStorable2 >( m_xModel, uno::UNO_QUERY );
412 0 : if ( !m_xStorable2.is() )
413 0 : throw uno::RuntimeException();
414 : }
415 :
416 0 : return m_xStorable2;
417 : }
418 :
419 :
420 0 : uno::Reference< util::XModifiable > ModelData_Impl::GetModifiable()
421 : {
422 0 : if ( !m_xModifiable.is() )
423 : {
424 0 : m_xModifiable = uno::Reference< util::XModifiable >( m_xModel, uno::UNO_QUERY );
425 0 : if ( !m_xModifiable.is() )
426 0 : throw uno::RuntimeException();
427 : }
428 :
429 0 : return m_xModifiable;
430 : }
431 :
432 :
433 0 : const ::comphelper::SequenceAsHashMap& ModelData_Impl::GetDocProps()
434 : {
435 0 : if ( !m_pDocumentPropsHM )
436 0 : m_pDocumentPropsHM = new ::comphelper::SequenceAsHashMap( GetModel()->getArgs() );
437 :
438 0 : return *m_pDocumentPropsHM;
439 : }
440 :
441 :
442 0 : OUString ModelData_Impl::GetModuleName()
443 : {
444 0 : if ( m_aModuleName.isEmpty() )
445 : {
446 0 : m_aModuleName = m_pOwner->GetModuleManager()->identify(
447 0 : uno::Reference< uno::XInterface >( m_xModel, uno::UNO_QUERY ) );
448 0 : if ( m_aModuleName.isEmpty() )
449 0 : throw uno::RuntimeException(); // TODO:
450 : }
451 0 : return m_aModuleName;
452 : }
453 :
454 :
455 0 : const ::comphelper::SequenceAsHashMap& ModelData_Impl::GetModuleProps()
456 : {
457 0 : if ( !m_pModulePropsHM )
458 : {
459 0 : uno::Sequence< beans::PropertyValue > aModuleProps;
460 0 : m_pOwner->GetModuleManager()->getByName( GetModuleName() ) >>= aModuleProps;
461 0 : if ( !aModuleProps.getLength() )
462 0 : throw uno::RuntimeException(); // TODO;
463 0 : m_pModulePropsHM = new ::comphelper::SequenceAsHashMap( aModuleProps );
464 : }
465 :
466 0 : return *m_pModulePropsHM;
467 : }
468 :
469 :
470 0 : OUString ModelData_Impl::GetDocServiceName()
471 : {
472 0 : return GetModuleProps().getUnpackedValueOrDefault("ooSetupFactoryDocumentService", OUString());
473 : }
474 :
475 :
476 0 : void ModelData_Impl::CheckInteractionHandler()
477 : {
478 : ::comphelper::SequenceAsHashMap::const_iterator aInteractIter =
479 0 : m_aMediaDescrHM.find( OUString("InteractionHandler") );
480 :
481 0 : if ( aInteractIter == m_aMediaDescrHM.end() )
482 : {
483 : try {
484 0 : m_aMediaDescrHM[ OUString("InteractionHandler") ]
485 0 : <<= task::InteractionHandler::createWithParent( comphelper::getProcessComponentContext(), 0);
486 : }
487 0 : catch( const uno::Exception& )
488 : {
489 : }
490 : }
491 : else
492 : {
493 0 : uno::Reference< task::XInteractionHandler > xInteract;
494 0 : DBG_ASSERT( ( aInteractIter->second >>= xInteract ) && xInteract.is(), "Broken interaction handler is provided!\n" );
495 : }
496 0 : }
497 :
498 :
499 0 : uno::Sequence< beans::PropertyValue > ModelData_Impl::GetDocServiceDefaultFilter()
500 : {
501 0 : uno::Sequence< beans::PropertyValue > aProps;
502 :
503 0 : OUString aFilterName = GetModuleProps().getUnpackedValueOrDefault(
504 : OUString("ooSetupFactoryDefaultFilter"),
505 0 : OUString() );
506 :
507 0 : m_pOwner->GetFilterConfiguration()->getByName( aFilterName ) >>= aProps;
508 :
509 0 : return aProps;
510 : }
511 :
512 :
513 0 : uno::Sequence< beans::PropertyValue > ModelData_Impl::GetDocServiceDefaultFilterCheckFlags( sal_Int32 nMust,
514 : sal_Int32 nDont )
515 : {
516 0 : uno::Sequence< beans::PropertyValue > aFilterProps;
517 0 : uno::Sequence< beans::PropertyValue > aProps = GetDocServiceDefaultFilter();
518 0 : if ( aProps.getLength() )
519 : {
520 0 : ::comphelper::SequenceAsHashMap aFiltHM( aProps );
521 : sal_Int32 nFlags = aFiltHM.getUnpackedValueOrDefault("Flags",
522 0 : (sal_Int32)0 );
523 0 : if ( ( ( nFlags & nMust ) == nMust ) && !( nFlags & nDont ) )
524 0 : aFilterProps = aProps;
525 : }
526 :
527 0 : return aFilterProps;
528 : }
529 :
530 :
531 :
532 0 : uno::Sequence< beans::PropertyValue > ModelData_Impl::GetDocServiceAnyFilter( sal_Int32 nMust, sal_Int32 nDont )
533 : {
534 0 : uno::Sequence< beans::NamedValue > aSearchRequest( 1 );
535 0 : aSearchRequest[0].Name = "DocumentService";
536 0 : aSearchRequest[0].Value <<= GetDocServiceName();
537 :
538 0 : return ::comphelper::MimeConfigurationHelper::SearchForFilter( m_pOwner->GetFilterQuery(), aSearchRequest, nMust, nDont );
539 : }
540 :
541 :
542 0 : uno::Sequence< beans::PropertyValue > ModelData_Impl::GetPreselectedFilter_Impl( sal_Int8 nStoreMode )
543 : {
544 0 : uno::Sequence< beans::PropertyValue > aFilterProps;
545 :
546 0 : sal_Int32 nMust = getMustFlags( nStoreMode );
547 0 : sal_Int32 nDont = getDontFlags( nStoreMode );
548 :
549 0 : if ( nStoreMode & PDFEXPORT_REQUESTED )
550 : {
551 : // Preselect PDF-Filter for EXPORT
552 0 : uno::Sequence< beans::NamedValue > aSearchRequest( 2 );
553 0 : aSearchRequest[0].Name = "Type";
554 0 : aSearchRequest[0].Value <<= OUString("pdf_Portable_Document_Format");
555 0 : aSearchRequest[1].Name = "DocumentService";
556 0 : aSearchRequest[1].Value <<= GetDocServiceName();
557 :
558 0 : aFilterProps = ::comphelper::MimeConfigurationHelper::SearchForFilter( m_pOwner->GetFilterQuery(), aSearchRequest, nMust, nDont );
559 : }
560 : else
561 : {
562 0 : aFilterProps = GetDocServiceDefaultFilterCheckFlags( nMust, nDont );
563 :
564 0 : if ( !aFilterProps.getLength() )
565 : {
566 : // the default filter was not faund, use just the first acceptable one
567 0 : aFilterProps = GetDocServiceAnyFilter( nMust, nDont );
568 : }
569 : }
570 :
571 0 : return aFilterProps;
572 : }
573 :
574 :
575 0 : bool ModelData_Impl::ExecuteFilterDialog_Impl( const OUString& aFilterName )
576 : {
577 0 : bool bDialogUsed = false;
578 :
579 : try {
580 0 : uno::Sequence < beans::PropertyValue > aProps;
581 0 : uno::Any aAny = m_pOwner->GetFilterConfiguration()->getByName( aFilterName );
582 0 : if ( aAny >>= aProps )
583 : {
584 0 : sal_Int32 nPropertyCount = aProps.getLength();
585 0 : for( sal_Int32 nProperty=0; nProperty < nPropertyCount; ++nProperty )
586 : {
587 0 : if( aProps[nProperty].Name == "UIComponent" )
588 : {
589 0 : OUString aServiceName;
590 0 : aProps[nProperty].Value >>= aServiceName;
591 0 : if( !aServiceName.isEmpty() )
592 : {
593 : uno::Reference< ui::dialogs::XExecutableDialog > xFilterDialog(
594 0 : comphelper::getProcessServiceFactory()->createInstance( aServiceName ), uno::UNO_QUERY );
595 0 : uno::Reference< beans::XPropertyAccess > xFilterProperties( xFilterDialog, uno::UNO_QUERY );
596 :
597 0 : if( xFilterDialog.is() && xFilterProperties.is() )
598 : {
599 0 : bDialogUsed = true;
600 :
601 0 : uno::Reference< document::XExporter > xExporter( xFilterDialog, uno::UNO_QUERY );
602 0 : if( xExporter.is() )
603 0 : xExporter->setSourceDocument(
604 0 : uno::Reference< lang::XComponent >( GetModel(), uno::UNO_QUERY ) );
605 :
606 0 : uno::Sequence< beans::PropertyValue > aPropsForDialog;
607 0 : GetMediaDescr() >> aPropsForDialog;
608 0 : xFilterProperties->setPropertyValues( aPropsForDialog );
609 :
610 0 : if( xFilterDialog->execute() )
611 : {
612 : uno::Sequence< beans::PropertyValue > aPropsFromDialog =
613 0 : xFilterProperties->getPropertyValues();
614 0 : for ( sal_Int32 nInd = 0; nInd < aPropsFromDialog.getLength(); nInd++ )
615 0 : GetMediaDescr()[aPropsFromDialog[nInd].Name] = aPropsFromDialog[nInd].Value;
616 : }
617 : else
618 : {
619 : throw task::ErrorCodeIOException(
620 : ("ModelData_Impl::ExecuteFilterDialog_Impl:"
621 : " ERRCODE_IO_ABORT"),
622 : uno::Reference< uno::XInterface >(),
623 0 : ERRCODE_IO_ABORT);
624 0 : }
625 0 : }
626 : }
627 :
628 0 : break;
629 : }
630 : }
631 0 : }
632 : }
633 0 : catch( const container::NoSuchElementException& e )
634 : {
635 : // the filter name is unknown
636 : throw task::ErrorCodeIOException(
637 : ("ModelData_Impl::ExecuteFilterDialog_Impl: NoSuchElementException"
638 0 : " \"" + e.Message + "\": ERRCODE_IO_ABORT"),
639 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_INVALIDPARAMETER);
640 : }
641 0 : catch( const task::ErrorCodeIOException& )
642 : {
643 0 : throw;
644 : }
645 0 : catch( const uno::Exception& e )
646 : {
647 : SAL_WARN("sfx.doc", "ignoring UNO exception " << e.Message);
648 : }
649 :
650 0 : return bDialogUsed;
651 : }
652 :
653 :
654 0 : sal_Int8 ModelData_Impl::CheckSaveAcceptable( sal_Int8 nCurStatus )
655 : {
656 0 : sal_Int8 nResult = nCurStatus;
657 :
658 0 : if ( nResult != STATUS_NO_ACTION && GetStorable()->hasLocation() )
659 : {
660 : // the saving is acceptable
661 : // in case the configuration entry is not set or set to false
662 : // or in case of version creation
663 0 : OUString aVersionCommentString = "VersionComment";
664 0 : if ( officecfg::Office::Common::Save::Document::AlwaysSaveAs::get()
665 0 : && GetMediaDescr().find( aVersionCommentString ) == GetMediaDescr().end() )
666 : {
667 : // notify the user that SaveAs is going to be done
668 0 : vcl::Window* pWin = SfxStoringHelper::GetModelWindow( m_xModel );
669 : MessageDialog aMessageBox(pWin, SfxResId(STR_NEW_FILENAME_SAVE),
670 0 : VCL_MESSAGE_QUESTION, VCL_BUTTONS_OK_CANCEL);
671 0 : if ( aMessageBox.Execute() == RET_OK )
672 0 : nResult = STATUS_SAVEAS;
673 : else
674 0 : nResult = STATUS_NO_ACTION;
675 0 : }
676 : }
677 :
678 0 : return nResult;
679 : }
680 :
681 :
682 0 : sal_Int8 ModelData_Impl::CheckStateForSave()
683 : {
684 : // if the document is readonly or a new one a SaveAs operation must be used
685 0 : if ( !GetStorable()->hasLocation() || GetStorable()->isReadonly() )
686 0 : return STATUS_SAVEAS;
687 :
688 : // check acceptable entries for media descriptor
689 0 : bool bVersInfoNeedsStore = false;
690 0 : ::comphelper::SequenceAsHashMap aAcceptedArgs;
691 :
692 0 : OUString aVersionCommentString("VersionComment");
693 0 : OUString aAuthorString("Author");
694 0 : OUString aInteractionHandlerString("InteractionHandler");
695 0 : OUString aStatusIndicatorString("StatusIndicator");
696 0 : OUString aFailOnWarningString("FailOnWarning");
697 :
698 0 : if ( GetMediaDescr().find( aVersionCommentString ) != GetMediaDescr().end() )
699 : {
700 0 : bVersInfoNeedsStore = true;
701 0 : aAcceptedArgs[ aVersionCommentString ] = GetMediaDescr()[ aVersionCommentString ];
702 : }
703 0 : if ( GetMediaDescr().find( aAuthorString ) != GetMediaDescr().end() )
704 0 : aAcceptedArgs[ aAuthorString ] = GetMediaDescr()[ aAuthorString ];
705 0 : if ( GetMediaDescr().find( aInteractionHandlerString ) != GetMediaDescr().end() )
706 0 : aAcceptedArgs[ aInteractionHandlerString ] = GetMediaDescr()[ aInteractionHandlerString ];
707 0 : if ( GetMediaDescr().find( aStatusIndicatorString ) != GetMediaDescr().end() )
708 0 : aAcceptedArgs[ aStatusIndicatorString ] = GetMediaDescr()[ aStatusIndicatorString ];
709 0 : if ( GetMediaDescr().find( aFailOnWarningString ) != GetMediaDescr().end() )
710 0 : aAcceptedArgs[ aFailOnWarningString ] = GetMediaDescr()[ aFailOnWarningString ];
711 :
712 : // remove unacceptable entry if there is any
713 : DBG_ASSERT( GetMediaDescr().size() == aAcceptedArgs.size(),
714 : "Unacceptable parameters are provided in Save request!\n" );
715 0 : if ( GetMediaDescr().size() != aAcceptedArgs.size() )
716 0 : GetMediaDescr() = aAcceptedArgs;
717 :
718 : // the document must be modified unless the always-save flag is set.
719 0 : SvtMiscOptions aMiscOptions;
720 0 : bool bAlwaysAllowSave = aMiscOptions.IsSaveAlwaysAllowed();
721 0 : if (!bAlwaysAllowSave)
722 : {
723 0 : if ( !GetModifiable()->isModified() && !bVersInfoNeedsStore )
724 0 : return STATUS_NO_ACTION;
725 : }
726 :
727 : // check that the old filter is acceptable
728 0 : OUString aOldFilterName = GetDocProps().getUnpackedValueOrDefault(
729 : OUString(aFilterNameString),
730 0 : OUString() );
731 0 : sal_Int8 nResult = CheckFilter( aOldFilterName );
732 :
733 0 : return nResult;
734 : }
735 :
736 0 : bool hasMacros( const uno::Reference< frame::XModel >& xModel )
737 : {
738 0 : bool bHasMacros = false;
739 0 : uno::Reference< script::XLibraryContainer > xContainer;
740 0 : uno::Reference< beans::XPropertySet > xProps( xModel, uno::UNO_QUERY );
741 0 : if ( xProps.is() )
742 : {
743 0 : xProps->getPropertyValue( "BasicLibraries" ) >>= xContainer;
744 0 : bHasMacros = sfx2::DocumentMacroMode::containerHasBasicMacros( xContainer );
745 : }
746 0 : return bHasMacros;
747 : }
748 :
749 0 : sal_Int8 ModelData_Impl::CheckFilter( const OUString& aFilterName )
750 : {
751 0 : ::comphelper::SequenceAsHashMap aFiltPropsHM;
752 0 : sal_Int32 nFiltFlags = 0;
753 0 : if ( !aFilterName.isEmpty() )
754 : {
755 : // get properties of filter
756 0 : uno::Sequence< beans::PropertyValue > aFilterProps;
757 0 : if ( !aFilterName.isEmpty() )
758 0 : m_pOwner->GetFilterConfiguration()->getByName( aFilterName ) >>= aFilterProps;
759 :
760 0 : aFiltPropsHM = ::comphelper::SequenceAsHashMap( aFilterProps );
761 0 : nFiltFlags = aFiltPropsHM.getUnpackedValueOrDefault("Flags", (sal_Int32)0 );
762 : }
763 :
764 : // only a temporary solution until default filter retrieving feature is implemented
765 : // then GetDocServiceDefaultFilter() must be used
766 0 : ::comphelper::SequenceAsHashMap aDefFiltPropsHM = GetDocServiceDefaultFilterCheckFlags( 3, 0 );
767 0 : sal_Int32 nDefFiltFlags = aDefFiltPropsHM.getUnpackedValueOrDefault("Flags", (sal_Int32)0 );
768 :
769 : // if the old filter is not acceptable
770 : // and there is no default filter or it is not acceptable for requested parameters then proceed with saveAs
771 0 : if ( ( !aFiltPropsHM.size() || !( nFiltFlags & SFX_FILTER_EXPORT ) )
772 0 : && ( !aDefFiltPropsHM.size() || !( nDefFiltFlags & SFX_FILTER_EXPORT ) || nDefFiltFlags & SFX_FILTER_INTERNAL ) )
773 0 : return STATUS_SAVEAS;
774 :
775 : // so at this point there is either an acceptable old filter or default one
776 0 : if ( !aFiltPropsHM.size() || !( nFiltFlags & SFX_FILTER_EXPORT ) )
777 : {
778 : // so the default filter must be acceptable
779 0 : return STATUS_SAVEAS_STANDARDNAME;
780 : }
781 0 : else if ( ( !( nFiltFlags & SFX_FILTER_OWN ) || ( nFiltFlags & SFX_FILTER_ALIEN ) )
782 0 : && aDefFiltPropsHM.size()
783 0 : && ( nDefFiltFlags & SFX_FILTER_EXPORT ) && !( nDefFiltFlags & SFX_FILTER_INTERNAL ))
784 : {
785 : // the default filter is acceptable and the old filter is alien one
786 : // so ask to make a saveAs operation
787 : OUString aUIName = aFiltPropsHM.getUnpackedValueOrDefault("UIName",
788 0 : OUString() );
789 : OUString aDefUIName = aDefFiltPropsHM.getUnpackedValueOrDefault("UIName",
790 0 : OUString() );
791 0 : OUString aPreusedFilterName = GetDocProps().getUnpackedValueOrDefault(
792 : OUString("PreusedFilterName"),
793 0 : OUString() );
794 0 : if ( !aPreusedFilterName.equals( aFilterName ) && !aUIName.equals( aDefUIName ) )
795 : {
796 : // is it possible to get these names from somewhere and not just
797 : // hardcode them?
798 0 : OUString sXLSXFilter("Calc MS Excel 2007 XML");
799 0 : OUString sOtherXLSXFilter("Calc Office Open XML");
800 0 : bool bHasMacros = hasMacros( GetModel() );
801 0 : if ( bHasMacros && ( aFilterName == sXLSXFilter || aFilterName == sOtherXLSXFilter ) )
802 : {
803 0 : uno::Reference< task::XInteractionHandler > xHandler;
804 0 : GetMediaDescr()[ OUString( "InteractionHandler" ) ] >>= xHandler;
805 0 : bool bResult = false;
806 0 : if ( xHandler.is() )
807 : {
808 : try
809 : {
810 0 : task::ErrorCodeRequest aErrorCode;
811 0 : aErrorCode.ErrCode = ERRCODE_SFX_VBASIC_CANTSAVE_STORAGE;
812 :
813 0 : uno::Any aRequest = uno::makeAny( aErrorCode );
814 0 : uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 2 );
815 :
816 0 : ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove );
817 0 : aContinuations[ 0 ] = pApprove.get();
818 :
819 0 : ::rtl::Reference< ::comphelper::OInteractionAbort > pAbort( new ::comphelper::OInteractionAbort );
820 0 : aContinuations[ 1 ] = pAbort.get();
821 0 : xHandler->handle(::framework::InteractionRequest::CreateRequest (aRequest,aContinuations));
822 0 : bResult = pApprove->wasSelected();
823 : }
824 0 : catch( const uno::Exception& )
825 : {
826 : }
827 0 : if ( !bResult )
828 0 : return STATUS_SAVEAS;
829 0 : }
830 : }
831 0 : if ( !SfxStoringHelper::WarnUnacceptableFormat( GetModel(), aUIName, aDefUIName, true ) )
832 0 : return STATUS_SAVEAS_STANDARDNAME;
833 0 : }
834 : }
835 :
836 0 : return STATUS_SAVE;
837 : }
838 :
839 :
840 0 : bool ModelData_Impl::CheckFilterOptionsDialogExistence()
841 : {
842 0 : uno::Sequence< beans::NamedValue > aSearchRequest( 1 );
843 0 : aSearchRequest[0].Name = "DocumentService";
844 0 : aSearchRequest[0].Value <<= GetDocServiceName();
845 :
846 : uno::Reference< container::XEnumeration > xFilterEnum =
847 0 : m_pOwner->GetFilterQuery()->createSubSetEnumerationByProperties( aSearchRequest );
848 :
849 0 : while ( xFilterEnum->hasMoreElements() )
850 : {
851 0 : uno::Sequence< beans::PropertyValue > pProps;
852 0 : if ( xFilterEnum->nextElement() >>= pProps )
853 : {
854 0 : ::comphelper::SequenceAsHashMap aPropsHM( pProps );
855 : OUString aUIServName = aPropsHM.getUnpackedValueOrDefault(
856 : OUString("UIComponent"),
857 0 : OUString() );
858 0 : if ( !aUIServName.isEmpty() )
859 0 : return true;
860 : }
861 0 : }
862 :
863 0 : return false;
864 : }
865 :
866 :
867 0 : bool ModelData_Impl::OutputFileDialog( sal_Int8 nStoreMode,
868 : const ::comphelper::SequenceAsHashMap& aPreselectedFilterPropsHM,
869 : bool bSetStandardName,
870 : OUString& aSuggestedName,
871 : bool bPreselectPassword,
872 : OUString& aSuggestedDir,
873 : sal_Int16 nDialog,
874 : const OUString& rStandardDir,
875 : const ::com::sun::star::uno::Sequence< OUString >& rBlackList)
876 : {
877 0 : bool bUseFilterOptions = false;
878 :
879 : ::comphelper::SequenceAsHashMap::const_iterator aOverwriteIter =
880 0 : GetMediaDescr().find( OUString("Overwrite") );
881 :
882 : // the file name must be specified if overwrite option is set
883 0 : if ( aOverwriteIter != GetMediaDescr().end() )
884 : throw task::ErrorCodeIOException(
885 : "ModelData_Impl::OutputFileDialog: ERRCODE_IO_INVALIDPARAMETER",
886 : uno::Reference< uno::XInterface >(),
887 0 : ERRCODE_IO_INVALIDPARAMETER);
888 :
889 : // no target file name is specified
890 : // we need to show the file dialog
891 :
892 : // check if we have a filter which allows for filter options, so we need a corresponding checkbox in the dialog
893 0 : bool bAllowOptions = false;
894 :
895 : // in case of Export, filter options dialog is used if available
896 0 : if( !( nStoreMode & EXPORT_REQUESTED ) || ( nStoreMode & WIDEEXPORT_REQUESTED ) )
897 0 : bAllowOptions = CheckFilterOptionsDialogExistence();
898 :
899 : // get the filename by dialog ...
900 : // create the file dialog
901 : sal_Int16 aDialogMode = bAllowOptions
902 : ? (com::sun::star::ui::dialogs::TemplateDescription::
903 : FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS)
904 : : (com::sun::star::ui::dialogs::TemplateDescription::
905 0 : FILESAVE_AUTOEXTENSION_PASSWORD);
906 0 : sal_Int64 aDialogFlags = 0;
907 :
908 0 : if( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & WIDEEXPORT_REQUESTED ) )
909 : {
910 0 : if ( nStoreMode & PDFEXPORT_REQUESTED )
911 : aDialogMode = com::sun::star::ui::dialogs::TemplateDescription::
912 0 : FILESAVE_AUTOEXTENSION;
913 : else
914 : aDialogMode = com::sun::star::ui::dialogs::TemplateDescription::
915 0 : FILESAVE_AUTOEXTENSION_SELECTION;
916 0 : aDialogFlags = SFXWB_EXPORT;
917 : }
918 :
919 0 : if( ( nStoreMode & EXPORT_REQUESTED ) && ( nStoreMode & SAVEACOPY_REQUESTED ) && ( nStoreMode & WIDEEXPORT_REQUESTED ) )
920 : {
921 0 : aDialogFlags = SFXWB_SAVEACOPY;
922 : }
923 :
924 0 : boost::scoped_ptr<sfx2::FileDialogHelper> pFileDlg;
925 :
926 0 : OUString aDocServiceName = GetDocServiceName();
927 : DBG_ASSERT( !aDocServiceName.isEmpty(), "No document service for this module set!" );
928 :
929 0 : sal_Int32 nMust = getMustFlags( nStoreMode );
930 0 : sal_Int32 nDont = getDontFlags( nStoreMode );
931 0 : sfx2::FileDialogHelper::Context eCtxt = sfx2::FileDialogHelper::UNKNOWN_CONTEXT;
932 :
933 0 : if ( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & WIDEEXPORT_REQUESTED ) )
934 : {
935 0 : if ( ( nStoreMode & PDFEXPORT_REQUESTED ) && aPreselectedFilterPropsHM.size() )
936 : {
937 : // this is a PDF export
938 : // the filter options has been shown already
939 : OUString aFilterUIName = aPreselectedFilterPropsHM.getUnpackedValueOrDefault(
940 : OUString("UIName"),
941 0 : OUString() );
942 :
943 0 : pFileDlg.reset(new sfx2::FileDialogHelper( aDialogMode, aDialogFlags, aFilterUIName, OUString( "pdf" ), rStandardDir, rBlackList ));
944 0 : pFileDlg->SetCurrentFilter( aFilterUIName );
945 : }
946 : else
947 : {
948 : // This is the normal dialog
949 0 : pFileDlg.reset(new sfx2::FileDialogHelper( aDialogMode, aDialogFlags, aDocServiceName, nDialog, nMust, nDont, rStandardDir, rBlackList ));
950 : }
951 :
952 0 : if ( aDocServiceName == "com.sun.star.drawing.DrawingDocument" )
953 0 : eCtxt = sfx2::FileDialogHelper::SD_EXPORT;
954 0 : else if ( aDocServiceName == "com.sun.star.presentation.PresentationDocument" )
955 0 : eCtxt = sfx2::FileDialogHelper::SI_EXPORT;
956 0 : else if ( aDocServiceName == "com.sun.star.text.TextDocument" )
957 0 : eCtxt = sfx2::FileDialogHelper::SW_EXPORT;
958 :
959 0 : if ( eCtxt != sfx2::FileDialogHelper::UNKNOWN_CONTEXT )
960 0 : pFileDlg->SetContext( eCtxt );
961 :
962 0 : pFileDlg->CreateMatcher( aDocServiceName );
963 :
964 0 : uno::Reference< ui::dialogs::XFilePicker > xFilePicker = pFileDlg->GetFilePicker();
965 : uno::Reference< ui::dialogs::XFilePickerControlAccess > xControlAccess =
966 0 : uno::Reference< ui::dialogs::XFilePickerControlAccess >( xFilePicker, uno::UNO_QUERY );
967 :
968 0 : if ( xControlAccess.is() )
969 : {
970 0 : OUString aCtrlText = SfxResId(STR_EXPORTBUTTON).toString();
971 0 : xControlAccess->setLabel( ui::dialogs::CommonFilePickerElementIds::PUSHBUTTON_OK, aCtrlText );
972 :
973 0 : aCtrlText = SfxResId(STR_LABEL_FILEFORMAT).toString();
974 0 : xControlAccess->setLabel( ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER_LABEL, aCtrlText );
975 0 : }
976 : }
977 : else
978 : {
979 : // This is the normal dialog
980 0 : pFileDlg.reset(new sfx2::FileDialogHelper( aDialogMode, aDialogFlags, aDocServiceName, nDialog, nMust, nDont, rStandardDir, rBlackList ));
981 0 : pFileDlg->CreateMatcher( aDocServiceName );
982 : }
983 :
984 0 : OUString aAdjustToType;
985 :
986 0 : const OUString sFilterNameString(aFilterNameString);
987 :
988 0 : if ( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & WIDEEXPORT_REQUESTED ) )
989 : {
990 : // it is export, set the preselected filter
991 : OUString aFilterUIName = aPreselectedFilterPropsHM.getUnpackedValueOrDefault(
992 : OUString("UIName"),
993 0 : OUString() );
994 0 : pFileDlg->SetCurrentFilter( aFilterUIName );
995 0 : aAdjustToType = aPreselectedFilterPropsHM.getUnpackedValueOrDefault(
996 : OUString("Type"),
997 0 : OUString() );
998 : }
999 : // it is no export, bSetStandardName == true means that user agreed to store document in the default (default default ;-)) format
1000 0 : else if ( bSetStandardName || GetStorable()->hasLocation() )
1001 : {
1002 0 : uno::Sequence< beans::PropertyValue > aOldFilterProps;
1003 0 : OUString aOldFilterName = GetDocProps().getUnpackedValueOrDefault(
1004 : sFilterNameString,
1005 0 : OUString() );
1006 :
1007 0 : if ( !aOldFilterName.isEmpty() )
1008 0 : m_pOwner->GetFilterConfiguration()->getByName( aOldFilterName ) >>= aOldFilterProps;
1009 :
1010 0 : ::comphelper::SequenceAsHashMap aOldFiltPropsHM( aOldFilterProps );
1011 0 : sal_Int32 nOldFiltFlags = aOldFiltPropsHM.getUnpackedValueOrDefault("Flags", (sal_Int32)0 );
1012 :
1013 0 : if ( bSetStandardName || ( nOldFiltFlags & nMust ) != nMust || nOldFiltFlags & nDont )
1014 : {
1015 : // the suggested type will be changed, the extension should be adjusted
1016 0 : aAdjustToType = aPreselectedFilterPropsHM.getUnpackedValueOrDefault(
1017 : OUString("Type"),
1018 0 : OUString() );
1019 :
1020 : OUString aFilterUIName = aPreselectedFilterPropsHM.getUnpackedValueOrDefault(
1021 : OUString("UIName"),
1022 0 : OUString() );
1023 0 : pFileDlg->SetCurrentFilter( aFilterUIName );
1024 : }
1025 : else
1026 : {
1027 : pFileDlg->SetCurrentFilter( aOldFiltPropsHM.getUnpackedValueOrDefault(
1028 : OUString("UIName"),
1029 0 : OUString() ) );
1030 0 : }
1031 : }
1032 :
1033 0 : OUString aRecommendedDir = GetRecommendedDir( aSuggestedDir );
1034 0 : if ( !aRecommendedDir.isEmpty() )
1035 0 : pFileDlg->SetDisplayFolder( aRecommendedDir );
1036 0 : OUString aRecommendedName = GetRecommendedName( aSuggestedName, aAdjustToType );
1037 0 : if ( !aRecommendedName.isEmpty() )
1038 0 : pFileDlg->SetFileName( aRecommendedName );
1039 :
1040 0 : uno::Reference < view::XSelectionSupplier > xSel( GetModel()->getCurrentController(), uno::UNO_QUERY );
1041 0 : if ( xSel.is() && xSel->getSelection().hasValue() )
1042 0 : GetMediaDescr()[OUString("SelectionOnly")] <<= sal_True;
1043 :
1044 : // This is a temporary hardcoded solution must be removed when
1045 : // dialogs do not need parameters in SidSet representation any more
1046 0 : sal_uInt16 nSlotID = getSlotIDFromMode( nStoreMode );
1047 0 : if ( !nSlotID )
1048 0 : throw lang::IllegalArgumentException(); // TODO:
1049 :
1050 : // generate SidSet from MediaDescriptor and provide it into FileDialog
1051 : // than merge changed SidSet back
1052 0 : SfxAllItemSet aDialogParams( SfxGetpApp()->GetPool() );
1053 0 : SfxItemSet* pDialogParams = &aDialogParams;
1054 : TransformParameters( nSlotID,
1055 0 : GetMediaDescr().getAsConstPropertyValueList(),
1056 : aDialogParams,
1057 0 : NULL );
1058 :
1059 0 : const SfxPoolItem* pItem = NULL;
1060 0 : if ( bPreselectPassword && aDialogParams.GetItemState( SID_ENCRYPTIONDATA, true, &pItem ) != SfxItemState::SET )
1061 : {
1062 : // the file dialog preselects the password checkbox if the provided mediadescriptor has encryption data entry
1063 : // after dialog execution the password interaction flag will be either removed or not
1064 0 : aDialogParams.Put( SfxBoolItem( SID_PASSWORDINTERACTION, true ) );
1065 : }
1066 :
1067 : // aStringTypeFN is a pure output parameter, pDialogParams is an in/out parameter
1068 0 : OUString aStringTypeFN;
1069 0 : if ( pFileDlg->Execute( pDialogParams, aStringTypeFN ) != ERRCODE_NONE )
1070 : {
1071 : throw task::ErrorCodeIOException(
1072 : "ModelData_Impl::OutputFileDialog: ERRCODE_IO_ABORT",
1073 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_ABORT);
1074 : }
1075 :
1076 0 : OUString aFilterName = aStringTypeFN;
1077 :
1078 : // the following two arguments can not be converted in MediaDescriptor,
1079 : // so they should be removed from the ItemSet after retrieving
1080 0 : SFX_ITEMSET_ARG( pDialogParams, pRecommendReadOnly, SfxBoolItem, SID_RECOMMENDREADONLY, false );
1081 0 : m_bRecommendReadOnly = ( pRecommendReadOnly && pRecommendReadOnly->GetValue() );
1082 0 : pDialogParams->ClearItem( SID_RECOMMENDREADONLY );
1083 :
1084 0 : uno::Sequence< beans::PropertyValue > aPropsFromDialog;
1085 0 : TransformItems( nSlotID, *pDialogParams, aPropsFromDialog, NULL );
1086 0 : GetMediaDescr() << aPropsFromDialog;
1087 :
1088 : // get the path from the dialog
1089 0 : INetURLObject aURL( pFileDlg->GetPath() );
1090 : // the path should be provided outside since it might be used for further calls to the dialog
1091 0 : aSuggestedName = aURL.GetName( INetURLObject::DECODE_WITH_CHARSET );
1092 0 : aSuggestedDir = pFileDlg->GetDisplayDirectory();
1093 :
1094 : // old filter options should be cleared in case different filter is used
1095 :
1096 0 : OUString aFilterFromMediaDescr = GetMediaDescr().getUnpackedValueOrDefault(
1097 : sFilterNameString,
1098 0 : OUString() );
1099 0 : OUString aOldFilterName = GetDocProps().getUnpackedValueOrDefault(
1100 : sFilterNameString,
1101 0 : OUString() );
1102 :
1103 0 : const OUString sFilterOptionsString(aFilterOptionsString);
1104 0 : const OUString sFilterDataString(aFilterDataString);
1105 :
1106 0 : if ( aFilterName.equals( aFilterFromMediaDescr ) )
1107 : {
1108 : // preserv current settings if any
1109 : // if there no current settings and the name is the same
1110 : // as old filter name use old filter settings
1111 :
1112 0 : if ( aFilterFromMediaDescr.equals( aOldFilterName ) )
1113 : {
1114 : ::comphelper::SequenceAsHashMap::const_iterator aIter =
1115 0 : GetDocProps().find( sFilterOptionsString );
1116 0 : if ( aIter != GetDocProps().end()
1117 0 : && GetMediaDescr().find( sFilterOptionsString ) == GetMediaDescr().end() )
1118 0 : GetMediaDescr()[aIter->first] = aIter->second;
1119 :
1120 0 : aIter = GetDocProps().find( sFilterDataString );
1121 0 : if ( aIter != GetDocProps().end()
1122 0 : && GetMediaDescr().find( sFilterDataString ) == GetMediaDescr().end() )
1123 0 : GetMediaDescr()[aIter->first] = aIter->second;
1124 : }
1125 : }
1126 : else
1127 : {
1128 0 : GetMediaDescr().erase( sFilterDataString );
1129 0 : GetMediaDescr().erase( sFilterOptionsString );
1130 :
1131 0 : if ( aFilterName.equals( aOldFilterName ) )
1132 : {
1133 : // merge filter option of the document filter
1134 :
1135 : ::comphelper::SequenceAsHashMap::const_iterator aIter =
1136 0 : GetDocProps().find( sFilterOptionsString );
1137 0 : if ( aIter != GetDocProps().end() )
1138 0 : GetMediaDescr()[aIter->first] = aIter->second;
1139 :
1140 0 : aIter = GetDocProps().find( sFilterDataString );
1141 0 : if ( aIter != GetDocProps().end() )
1142 0 : GetMediaDescr()[aIter->first] = aIter->second;
1143 : }
1144 : }
1145 :
1146 0 : uno::Reference< ui::dialogs::XFilePickerControlAccess > xExtFileDlg( pFileDlg->GetFilePicker(), uno::UNO_QUERY );
1147 0 : if ( xExtFileDlg.is() )
1148 : {
1149 0 : if ( SfxStoringHelper::CheckFilterOptionsAppearence( m_pOwner->GetFilterConfiguration(), aFilterName ) )
1150 0 : bUseFilterOptions = true;
1151 :
1152 0 : if ( ( !( nStoreMode & EXPORT_REQUESTED ) || ( nStoreMode & WIDEEXPORT_REQUESTED ) ) && bUseFilterOptions )
1153 : {
1154 : try
1155 : {
1156 : // for exporters: always show dialog if format uses options
1157 : // for save: show dialog if format uses options and no options given or if forced by user
1158 : uno::Any aVal =
1159 0 : xExtFileDlg->getValue( ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS, 0 );
1160 :
1161 0 : aVal >>= bUseFilterOptions;
1162 0 : if ( !bUseFilterOptions )
1163 : bUseFilterOptions =
1164 0 : ( GetMediaDescr().find( sFilterDataString ) == GetMediaDescr().end()
1165 0 : && GetMediaDescr().find( sFilterOptionsString ) == GetMediaDescr().end() );
1166 : }
1167 0 : catch( const lang::IllegalArgumentException& )
1168 : {}
1169 : }
1170 : }
1171 :
1172 : // merge in results of the dialog execution
1173 0 : GetMediaDescr()[OUString("URL")] <<=
1174 0 : OUString( aURL.GetMainURL( INetURLObject::NO_DECODE ));
1175 0 : GetMediaDescr()[sFilterNameString] <<= aFilterName;
1176 :
1177 0 : return bUseFilterOptions;
1178 : }
1179 :
1180 :
1181 0 : bool ModelData_Impl::ShowDocumentInfoDialog()
1182 : {
1183 0 : bool bDialogUsed = false;
1184 :
1185 : try {
1186 0 : uno::Reference< frame::XController > xController = GetModel()->getCurrentController();
1187 0 : if ( xController.is() )
1188 : {
1189 0 : uno::Reference< frame::XDispatchProvider > xFrameDispatch( xController->getFrame(), uno::UNO_QUERY );
1190 0 : if ( xFrameDispatch.is() )
1191 : {
1192 0 : util::URL aURL;
1193 0 : aURL.Complete = ".uno:SetDocumentProperties";
1194 :
1195 0 : uno::Reference < util::XURLTransformer > xTransformer( util::URLTransformer::create( comphelper::getProcessComponentContext() ) );
1196 0 : if ( xTransformer->parseStrict( aURL ) )
1197 : {
1198 0 : uno::Reference< frame::XDispatch > xDispatch = xFrameDispatch->queryDispatch(
1199 : aURL,
1200 : OUString("_self"),
1201 0 : 0 );
1202 0 : if ( xDispatch.is() )
1203 : {
1204 0 : xDispatch->dispatch( aURL, uno::Sequence< beans::PropertyValue >() );
1205 0 : bDialogUsed = true;
1206 0 : }
1207 0 : }
1208 0 : }
1209 0 : }
1210 : }
1211 0 : catch ( const uno::Exception& )
1212 : {
1213 : }
1214 :
1215 0 : return bDialogUsed;
1216 : }
1217 :
1218 :
1219 0 : OUString ModelData_Impl::GetRecommendedDir( const OUString& aSuggestedDir )
1220 : {
1221 0 : OUString aRecommendedDir;
1222 :
1223 0 : if ( ( !aSuggestedDir.isEmpty() || GetStorable()->hasLocation() )
1224 0 : && !GetMediaDescr().getUnpackedValueOrDefault("RepairPackage",
1225 0 : sal_False ) )
1226 : {
1227 0 : INetURLObject aLocation;
1228 0 : if ( !aSuggestedDir.isEmpty() )
1229 0 : aLocation = INetURLObject( aSuggestedDir );
1230 : else
1231 : {
1232 0 : OUString aOldURL = GetStorable()->getLocation();
1233 0 : if ( !aOldURL.isEmpty() )
1234 : {
1235 0 : INetURLObject aTmp( aOldURL );
1236 0 : if ( aTmp.removeSegment() )
1237 0 : aLocation = aTmp;
1238 : }
1239 :
1240 0 : if ( aLocation.HasError() )
1241 0 : aLocation = INetURLObject( SvtPathOptions().GetWorkPath() );
1242 : }
1243 :
1244 0 : aLocation.setFinalSlash();
1245 0 : if ( !aLocation.HasError() )
1246 0 : aRecommendedDir = aLocation.GetMainURL( INetURLObject::NO_DECODE );
1247 : }
1248 : else
1249 : {
1250 0 : aRecommendedDir = INetURLObject( SvtPathOptions().GetWorkPath() ).GetMainURL( INetURLObject::NO_DECODE );
1251 : }
1252 :
1253 0 : return aRecommendedDir;
1254 : }
1255 :
1256 :
1257 0 : OUString ModelData_Impl::GetRecommendedName( const OUString& aSuggestedName, const OUString& aTypeName )
1258 : {
1259 : // the last used name might be provided by aSuggestedName from the old selection, or from the MediaDescriptor
1260 0 : OUString aRecommendedName;
1261 :
1262 0 : if ( !aSuggestedName.isEmpty() )
1263 0 : aRecommendedName = aSuggestedName;
1264 : else
1265 : {
1266 0 : aRecommendedName = INetURLObject( GetStorable()->getLocation() ).GetName( INetURLObject::DECODE_WITH_CHARSET );
1267 0 : if ( aRecommendedName.isEmpty() )
1268 : {
1269 : try {
1270 0 : uno::Reference< frame::XTitle > xTitle( GetModel(), uno::UNO_QUERY_THROW );
1271 0 : aRecommendedName = xTitle->getTitle();
1272 0 : } catch( const uno::Exception& ) {}
1273 : }
1274 :
1275 0 : if ( !aRecommendedName.isEmpty() && !aTypeName.isEmpty() )
1276 : {
1277 : // adjust the extension to the type
1278 : uno::Reference< container::XNameAccess > xTypeDetection = uno::Reference< container::XNameAccess >(
1279 0 : comphelper::getProcessServiceFactory()->createInstance("com.sun.star.document.TypeDetection"),
1280 0 : uno::UNO_QUERY );
1281 0 : if ( xTypeDetection.is() )
1282 : {
1283 0 : INetURLObject aObj( OUString( "c:/" ) + aRecommendedName, INET_PROT_FILE,
1284 0 : INetURLObject::ENCODE_ALL, RTL_TEXTENCODING_UTF8, INetURLObject::FSYS_DOS );
1285 :
1286 0 : uno::Sequence< beans::PropertyValue > aTypeNameProps;
1287 0 : if ( ( xTypeDetection->getByName( aTypeName ) >>= aTypeNameProps ) && aTypeNameProps.getLength() )
1288 : {
1289 0 : ::comphelper::SequenceAsHashMap aTypeNamePropsHM( aTypeNameProps );
1290 : uno::Sequence< OUString > aExtensions = aTypeNamePropsHM.getUnpackedValueOrDefault(
1291 : OUString("Extensions"),
1292 0 : ::uno::Sequence< OUString >() );
1293 0 : if ( aExtensions.getLength() )
1294 0 : aObj.SetExtension( aExtensions[0] );
1295 : }
1296 :
1297 0 : aRecommendedName = aObj.GetName( INetURLObject::DECODE_WITH_CHARSET, RTL_TEXTENCODING_UTF8 );
1298 0 : }
1299 : }
1300 : }
1301 :
1302 0 : return aRecommendedName;
1303 : }
1304 :
1305 :
1306 :
1307 : // class SfxStoringHelper
1308 :
1309 :
1310 0 : SfxStoringHelper::SfxStoringHelper()
1311 : {
1312 0 : }
1313 :
1314 :
1315 0 : uno::Reference< container::XNameAccess > SfxStoringHelper::GetFilterConfiguration()
1316 : {
1317 0 : if ( !m_xFilterCFG.is() )
1318 : {
1319 0 : m_xFilterCFG = uno::Reference< container::XNameAccess >(
1320 0 : comphelper::getProcessServiceFactory()->createInstance("com.sun.star.document.FilterFactory"),
1321 0 : uno::UNO_QUERY );
1322 :
1323 0 : if ( !m_xFilterCFG.is() )
1324 0 : throw uno::RuntimeException();
1325 : }
1326 :
1327 0 : return m_xFilterCFG;
1328 : }
1329 :
1330 :
1331 0 : uno::Reference< container::XContainerQuery > SfxStoringHelper::GetFilterQuery()
1332 : {
1333 0 : if ( !m_xFilterQuery.is() )
1334 : {
1335 0 : m_xFilterQuery = uno::Reference< container::XContainerQuery >( GetFilterConfiguration(), uno::UNO_QUERY );
1336 0 : if ( !m_xFilterQuery.is() )
1337 0 : throw uno::RuntimeException();
1338 : }
1339 :
1340 0 : return m_xFilterQuery;
1341 : }
1342 :
1343 :
1344 0 : uno::Reference< ::com::sun::star::frame::XModuleManager2 > SfxStoringHelper::GetModuleManager()
1345 : {
1346 0 : if ( !m_xModuleManager.is() )
1347 : {
1348 0 : m_xModuleManager = frame::ModuleManager::create(
1349 0 : comphelper::getProcessComponentContext() );
1350 : }
1351 :
1352 0 : return m_xModuleManager;
1353 : }
1354 :
1355 :
1356 0 : bool SfxStoringHelper::GUIStoreModel( uno::Reference< frame::XModel > xModel,
1357 : const OUString& aSlotName,
1358 : uno::Sequence< beans::PropertyValue >& aArgsSequence,
1359 : bool bPreselectPassword,
1360 : const OUString& _aSuggestedName,
1361 : sal_uInt16 nDocumentSignatureState )
1362 : {
1363 0 : OUString aSuggestedName = _aSuggestedName;
1364 0 : ModelData_Impl aModelData( *this, xModel, aArgsSequence );
1365 :
1366 0 : bool bDialogUsed = false;
1367 :
1368 0 : INetURLObject aURL;
1369 :
1370 0 : bool bSetStandardName = false; // can be set only for SaveAs
1371 :
1372 : // parse the slot name
1373 0 : sal_Int8 nStoreMode = getStoreModeFromSlotName( aSlotName );
1374 0 : sal_Int8 nStatusSave = STATUS_NO_ACTION;
1375 :
1376 : ::comphelper::SequenceAsHashMap::const_iterator aSaveACopyIter =
1377 0 : aModelData.GetMediaDescr().find( ::rtl::OUString("SaveACopy") );
1378 0 : if ( aSaveACopyIter != aModelData.GetMediaDescr().end() )
1379 : {
1380 0 : bool bSaveACopy = false;
1381 0 : aSaveACopyIter->second >>= bSaveACopy;
1382 0 : if ( bSaveACopy )
1383 0 : nStoreMode = EXPORT_REQUESTED | SAVEACOPY_REQUESTED | WIDEEXPORT_REQUESTED;
1384 : }
1385 : // handle the special cases
1386 0 : if ( nStoreMode & SAVEAS_REQUESTED )
1387 : {
1388 : ::comphelper::SequenceAsHashMap::const_iterator aSaveToIter =
1389 0 : aModelData.GetMediaDescr().find( OUString("SaveTo") );
1390 0 : if ( aSaveToIter != aModelData.GetMediaDescr().end() )
1391 : {
1392 0 : bool bWideExport = false;
1393 0 : aSaveToIter->second >>= bWideExport;
1394 0 : if ( bWideExport )
1395 0 : nStoreMode = EXPORT_REQUESTED | WIDEEXPORT_REQUESTED;
1396 : }
1397 :
1398 : // if saving is not acceptable the warning must be shown even in case of SaveAs operation
1399 0 : if ( ( nStoreMode & SAVEAS_REQUESTED ) && aModelData.CheckSaveAcceptable( STATUS_SAVEAS ) == STATUS_NO_ACTION )
1400 : throw task::ErrorCodeIOException(
1401 : "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT",
1402 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_ABORT);
1403 : }
1404 0 : else if ( nStoreMode & SAVE_REQUESTED )
1405 : {
1406 : // if saving is not acceptable by the configuration the warning must be shown
1407 0 : nStatusSave = aModelData.CheckSaveAcceptable( STATUS_SAVE );
1408 :
1409 0 : if ( nStatusSave == STATUS_NO_ACTION )
1410 : throw task::ErrorCodeIOException(
1411 : "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT",
1412 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_ABORT);
1413 0 : else if ( nStatusSave == STATUS_SAVE )
1414 : {
1415 : // check whether it is possible to use save operation
1416 0 : nStatusSave = aModelData.CheckStateForSave();
1417 : }
1418 :
1419 0 : if ( nStatusSave == STATUS_NO_ACTION )
1420 : {
1421 : throw task::ErrorCodeIOException(
1422 : "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT",
1423 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_ABORT);
1424 : }
1425 0 : else if ( nStatusSave != STATUS_SAVE )
1426 : {
1427 : // this should be a usual SaveAs operation
1428 0 : nStoreMode = SAVEAS_REQUESTED;
1429 0 : if ( nStatusSave == STATUS_SAVEAS_STANDARDNAME )
1430 0 : bSetStandardName = true;
1431 : }
1432 : }
1433 :
1434 0 : if ( !( nStoreMode & EXPORT_REQUESTED ) )
1435 : {
1436 : // if it is no export, warn user that the signature will be removed
1437 0 : if ( SIGNATURESTATE_SIGNATURES_OK == nDocumentSignatureState
1438 0 : || SIGNATURESTATE_SIGNATURES_INVALID == nDocumentSignatureState
1439 0 : || SIGNATURESTATE_SIGNATURES_NOTVALIDATED == nDocumentSignatureState
1440 0 : || SIGNATURESTATE_SIGNATURES_PARTIAL_OK == nDocumentSignatureState)
1441 : {
1442 0 : if (MessageDialog(NULL, SfxResId(RID_SVXSTR_XMLSEC_QUERY_LOSINGSIGNATURE),
1443 0 : VCL_MESSAGE_QUESTION, VCL_BUTTONS_YES_NO).Execute() != RET_YES)
1444 : {
1445 : // the user has decided not to store the document
1446 : throw task::ErrorCodeIOException(
1447 : "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT",
1448 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_ABORT);
1449 : }
1450 : }
1451 : }
1452 :
1453 0 : if ( nStoreMode & SAVE_REQUESTED && nStatusSave == STATUS_SAVE )
1454 : {
1455 : // Document properties can contain streams that should be freed before storing
1456 0 : aModelData.FreeDocumentProps();
1457 :
1458 0 : if ( aModelData.GetStorable2().is() )
1459 : {
1460 : try
1461 : {
1462 0 : aModelData.GetStorable2()->storeSelf( aModelData.GetMediaDescr().getAsConstPropertyValueList() );
1463 : }
1464 0 : catch (const lang::IllegalArgumentException& e)
1465 : {
1466 : SAL_WARN("sfx", "Ignoring parameters! "
1467 : "ModelData considers this illegal: " << e.Message);
1468 0 : aModelData.GetStorable()->store();
1469 : }
1470 : }
1471 : else
1472 : {
1473 : OSL_FAIL( "XStorable2 is not supported by the model!\n" );
1474 0 : aModelData.GetStorable()->store();
1475 : }
1476 :
1477 0 : return false;
1478 : }
1479 :
1480 : // preselect a filter for the storing process
1481 0 : uno::Sequence< beans::PropertyValue > aFilterProps = aModelData.GetPreselectedFilter_Impl( nStoreMode );
1482 :
1483 : DBG_ASSERT( aFilterProps.getLength(), "No filter for storing!\n" );
1484 0 : if ( !aFilterProps.getLength() )
1485 : throw task::ErrorCodeIOException(
1486 : "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_INVALIDPARAMETER",
1487 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_INVALIDPARAMETER);
1488 :
1489 0 : ::comphelper::SequenceAsHashMap aFilterPropsHM( aFilterProps );
1490 : OUString aFilterName = aFilterPropsHM.getUnpackedValueOrDefault(
1491 : OUString("Name"),
1492 0 : OUString() );
1493 :
1494 0 : const OUString sFilterNameString(aFilterNameString);
1495 :
1496 0 : OUString aFilterFromMediaDescr = aModelData.GetMediaDescr().getUnpackedValueOrDefault(
1497 : sFilterNameString,
1498 0 : OUString() );
1499 0 : OUString aOldFilterName = aModelData.GetDocProps().getUnpackedValueOrDefault(
1500 : sFilterNameString,
1501 0 : OUString() );
1502 :
1503 0 : bool bUseFilterOptions = false;
1504 0 : ::comphelper::SequenceAsHashMap::const_iterator aFileNameIter = aModelData.GetMediaDescr().find( OUString("URL") );
1505 :
1506 0 : const OUString sFilterOptionsString(aFilterOptionsString);
1507 0 : const OUString sFilterDataString(aFilterDataString);
1508 0 : const OUString sFilterFlagsString(aFilterFlagsString);
1509 :
1510 0 : if ( ( nStoreMode & EXPORT_REQUESTED ) && ( nStoreMode & PDFEXPORT_REQUESTED ) && !( nStoreMode & PDFDIRECTEXPORT_REQUESTED ) )
1511 : {
1512 : // this is PDF export, the filter options dialog should be shown before the export
1513 0 : aModelData.GetMediaDescr()[sFilterNameString] <<= aFilterName;
1514 0 : if ( aModelData.GetMediaDescr().find( sFilterFlagsString ) == aModelData.GetMediaDescr().end()
1515 0 : && aModelData.GetMediaDescr().find( sFilterOptionsString ) == aModelData.GetMediaDescr().end()
1516 0 : && aModelData.GetMediaDescr().find( sFilterDataString ) == aModelData.GetMediaDescr().end() )
1517 : {
1518 : // execute filter options dialog since no options are set in the media descriptor
1519 0 : if ( aModelData.ExecuteFilterDialog_Impl( aFilterName ) )
1520 0 : bDialogUsed = true;
1521 : }
1522 : }
1523 :
1524 0 : if ( aFileNameIter == aModelData.GetMediaDescr().end() )
1525 : {
1526 0 : sal_Int16 nDialog = SFX2_IMPL_DIALOG_CONFIG;
1527 : ::comphelper::SequenceAsHashMap::const_iterator aDlgIter =
1528 0 : aModelData.GetMediaDescr().find( OUString("UseSystemDialog") );
1529 0 : if ( aDlgIter != aModelData.GetMediaDescr().end() )
1530 : {
1531 0 : bool bUseSystemDialog = true;
1532 0 : if ( aDlgIter->second >>= bUseSystemDialog )
1533 : {
1534 0 : if ( bUseSystemDialog )
1535 0 : nDialog = SFX2_IMPL_DIALOG_SYSTEM;
1536 : else
1537 0 : nDialog = SFX2_IMPL_DIALOG_OOO;
1538 : }
1539 : }
1540 :
1541 : // The Dispatch supports parameter FolderName that overwrites SuggestedSaveAsDir
1542 0 : OUString aSuggestedDir = aModelData.GetMediaDescr().getUnpackedValueOrDefault("FolderName", OUString() );
1543 0 : if ( aSuggestedDir.isEmpty() )
1544 : {
1545 0 : aSuggestedDir = aModelData.GetMediaDescr().getUnpackedValueOrDefault("SuggestedSaveAsDir", OUString() );
1546 0 : if ( aSuggestedDir.isEmpty() )
1547 0 : aSuggestedDir = aModelData.GetDocProps().getUnpackedValueOrDefault("SuggestedSaveAsDir", OUString() );
1548 : }
1549 :
1550 0 : aSuggestedName = aModelData.GetMediaDescr().getUnpackedValueOrDefault("SuggestedSaveAsName", OUString() );
1551 0 : if ( aSuggestedName.isEmpty() )
1552 0 : aSuggestedName = aModelData.GetDocProps().getUnpackedValueOrDefault("SuggestedSaveAsName", OUString() );
1553 :
1554 0 : OUString sStandardDir;
1555 : ::comphelper::SequenceAsHashMap::const_iterator aStdDirIter =
1556 0 : aModelData.GetMediaDescr().find( OUString("StandardDir") );
1557 0 : if ( aStdDirIter != aModelData.GetMediaDescr().end() )
1558 0 : aStdDirIter->second >>= sStandardDir;
1559 :
1560 0 : ::com::sun::star::uno::Sequence< OUString > aBlackList;
1561 :
1562 : ::comphelper::SequenceAsHashMap::const_iterator aBlackListIter =
1563 0 : aModelData.GetMediaDescr().find( OUString("BlackList") );
1564 0 : if ( aBlackListIter != aModelData.GetMediaDescr().end() )
1565 0 : aBlackListIter->second >>= aBlackList;
1566 :
1567 0 : bool bExit = false;
1568 0 : while ( !bExit )
1569 : {
1570 : // in case the dialog is opened a second time the folder should be the same as previously navigated to by the user, not what was handed over by initial parameters
1571 0 : bUseFilterOptions = aModelData.OutputFileDialog( nStoreMode, aFilterProps, bSetStandardName, aSuggestedName, bPreselectPassword, aSuggestedDir, nDialog, sStandardDir, aBlackList );
1572 0 : if ( nStoreMode == SAVEAS_REQUESTED )
1573 : {
1574 : // in case of saving check filter for possible alien warning
1575 0 : OUString aSelFilterName = aModelData.GetMediaDescr().getUnpackedValueOrDefault(
1576 : sFilterNameString,
1577 0 : OUString() );
1578 0 : sal_Int8 nStatusFilterSave = aModelData.CheckFilter( aSelFilterName );
1579 0 : if ( nStatusFilterSave == STATUS_SAVEAS_STANDARDNAME )
1580 : {
1581 : // switch to best filter
1582 0 : bSetStandardName = true;
1583 : }
1584 0 : else if ( nStatusFilterSave == STATUS_SAVE )
1585 : {
1586 : // user confirmed alien filter or "good" filter is used
1587 0 : bExit = true;
1588 0 : }
1589 : }
1590 : else
1591 0 : bExit = true;
1592 : }
1593 :
1594 0 : bDialogUsed = true;
1595 0 : aFileNameIter = aModelData.GetMediaDescr().find( OUString("URL") );
1596 : }
1597 : else
1598 : {
1599 : // the target file name is provided so check if new filter options
1600 : // are provided or old options can be used
1601 0 : if ( aFilterFromMediaDescr.equals( aOldFilterName ) )
1602 : {
1603 : ::comphelper::SequenceAsHashMap::const_iterator aIter =
1604 0 : aModelData.GetDocProps().find( sFilterOptionsString );
1605 0 : if ( aIter != aModelData.GetDocProps().end()
1606 0 : && aModelData.GetMediaDescr().find( sFilterOptionsString ) == aModelData.GetMediaDescr().end() )
1607 0 : aModelData.GetMediaDescr()[aIter->first] = aIter->second;
1608 :
1609 0 : aIter = aModelData.GetDocProps().find( sFilterDataString );
1610 0 : if ( aIter != aModelData.GetDocProps().end()
1611 0 : && aModelData.GetMediaDescr().find( sFilterDataString ) == aModelData.GetMediaDescr().end() )
1612 0 : aModelData.GetMediaDescr()[aIter->first] = aIter->second;
1613 : }
1614 : }
1615 :
1616 0 : if ( aFileNameIter != aModelData.GetMediaDescr().end() )
1617 : {
1618 0 : OUString aFileName;
1619 0 : aFileNameIter->second >>= aFileName;
1620 0 : aURL.SetURL( aFileName );
1621 : DBG_ASSERT( aURL.GetProtocol() != INET_PROT_NOT_VALID, "Illegal URL!" );
1622 :
1623 : ::comphelper::SequenceAsHashMap::const_iterator aIter =
1624 0 : aModelData.GetMediaDescr().find( sFilterNameString );
1625 :
1626 0 : if ( aIter != aModelData.GetMediaDescr().end() )
1627 0 : aIter->second >>= aFilterName;
1628 : else
1629 0 : aModelData.GetMediaDescr()[sFilterNameString] <<= aFilterName;
1630 :
1631 0 : DBG_ASSERT( !aFilterName.isEmpty(), "Illegal filter!" );
1632 : }
1633 : else
1634 : {
1635 : DBG_ASSERT( false, "This code must be unreachable!\n" );
1636 : throw task::ErrorCodeIOException(
1637 : "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_INVALIDPARAMETER",
1638 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_INVALIDPARAMETER);
1639 : }
1640 :
1641 : ::comphelper::SequenceAsHashMap::const_iterator aIter =
1642 0 : aModelData.GetMediaDescr().find( OUString("FilterFlags") );
1643 0 : bool bFilterFlagsSet = ( aIter != aModelData.GetMediaDescr().end() );
1644 :
1645 0 : if( !( nStoreMode & PDFEXPORT_REQUESTED ) && !bFilterFlagsSet
1646 0 : && ( ( nStoreMode & EXPORT_REQUESTED ) || bUseFilterOptions ) )
1647 : {
1648 : // execute filter options dialog
1649 0 : if ( aModelData.ExecuteFilterDialog_Impl( aFilterName ) )
1650 0 : bDialogUsed = true;
1651 : }
1652 :
1653 : // so the arguments will not change any more and can be stored to the main location
1654 0 : aArgsSequence = aModelData.GetMediaDescr().getAsConstPropertyValueList();
1655 :
1656 : // store the document and handle it's docinfo
1657 0 : SvtSaveOptions aOptions;
1658 :
1659 0 : DocumentSettingsGuard aSettingsGuard( aModelData.GetModel(), aModelData.IsRecommendReadOnly(), nStoreMode & EXPORT_REQUESTED );
1660 :
1661 : OSL_ENSURE( aModelData.GetMediaDescr().find( OUString( "Password" ) ) == aModelData.GetMediaDescr().end(), "The Password property of MediaDescriptor should not be used here!" );
1662 0 : if ( aOptions.IsDocInfoSave()
1663 0 : && ( !aModelData.GetStorable()->hasLocation()
1664 0 : || INetURLObject( aModelData.GetStorable()->getLocation() ) != aURL ) )
1665 : {
1666 : // this is defenitly not a Save operation
1667 : // so the document info can be updated
1668 :
1669 : // on export document info must be preserved
1670 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1671 0 : aModelData.GetModel(), uno::UNO_QUERY_THROW);
1672 : uno::Reference<util::XCloneable> xCloneable(
1673 0 : xDPS->getDocumentProperties(), uno::UNO_QUERY_THROW);
1674 : uno::Reference<document::XDocumentProperties> xOldDocProps(
1675 0 : xCloneable->createClone(), uno::UNO_QUERY_THROW);
1676 :
1677 : // use dispatch API to show document info dialog
1678 0 : if ( aModelData.ShowDocumentInfoDialog() )
1679 0 : bDialogUsed = true;
1680 : else
1681 : {
1682 : OSL_FAIL( "Can't execute document info dialog!\n" );
1683 : }
1684 :
1685 : try {
1686 : // Document properties can contain streams that should be freed before storing
1687 0 : aModelData.FreeDocumentProps();
1688 0 : if ( nStoreMode & EXPORT_REQUESTED )
1689 0 : aModelData.GetStorable()->storeToURL( aURL.GetMainURL( INetURLObject::NO_DECODE ), aArgsSequence );
1690 : else
1691 0 : aModelData.GetStorable()->storeAsURL( aURL.GetMainURL( INetURLObject::NO_DECODE ), aArgsSequence );
1692 : }
1693 0 : catch( const uno::Exception& )
1694 : {
1695 0 : if ( nStoreMode & EXPORT_REQUESTED )
1696 : {
1697 0 : SetDocInfoState(aModelData.GetModel(), xOldDocProps, true);
1698 : }
1699 0 : throw;
1700 : }
1701 :
1702 0 : if ( nStoreMode & EXPORT_REQUESTED )
1703 : {
1704 0 : SetDocInfoState(aModelData.GetModel(), xOldDocProps, true);
1705 0 : }
1706 : }
1707 : else
1708 : {
1709 : // Document properties can contain streams that should be freed before storing
1710 0 : aModelData.FreeDocumentProps();
1711 :
1712 : // this is actually a save operation with different parameters
1713 : // so storeTo or storeAs without DocInfo operations are used
1714 0 : if ( nStoreMode & EXPORT_REQUESTED )
1715 0 : aModelData.GetStorable()->storeToURL( aURL.GetMainURL( INetURLObject::NO_DECODE ), aArgsSequence );
1716 : else
1717 0 : aModelData.GetStorable()->storeAsURL( aURL.GetMainURL( INetURLObject::NO_DECODE ), aArgsSequence );
1718 : }
1719 :
1720 : // Launch PDF viewer
1721 0 : if ( nStoreMode & PDFEXPORT_REQUESTED )
1722 : {
1723 0 : FilterConfigItem aItem( "Office.Common/Filter/PDF/Export/" );
1724 0 : bool aViewPDF = aItem.ReadBool( "ViewPDFAfterExport", false );
1725 :
1726 0 : if ( aViewPDF )
1727 : {
1728 0 : uno::Reference<XSystemShellExecute> xSystemShellExecute(SystemShellExecute::create( ::comphelper::getProcessComponentContext() ) );
1729 0 : xSystemShellExecute->execute( aURL.GetMainURL( INetURLObject::NO_DECODE ), "", SystemShellExecuteFlags::URIS_ONLY );
1730 0 : }
1731 : }
1732 :
1733 0 : return bDialogUsed;
1734 : }
1735 :
1736 :
1737 : // static
1738 0 : bool SfxStoringHelper::CheckFilterOptionsAppearence(
1739 : const uno::Reference< container::XNameAccess >& xFilterCFG,
1740 : const OUString& aFilterName )
1741 : {
1742 0 : bool bUseFilterOptions = false;
1743 :
1744 : DBG_ASSERT( xFilterCFG.is(), "No filter configuration!\n" );
1745 0 : if( xFilterCFG.is() )
1746 : {
1747 : try {
1748 0 : uno::Sequence < beans::PropertyValue > aProps;
1749 0 : uno::Any aAny = xFilterCFG->getByName( aFilterName );
1750 0 : if ( aAny >>= aProps )
1751 : {
1752 0 : ::comphelper::SequenceAsHashMap aPropsHM( aProps );
1753 : OUString aServiceName = aPropsHM.getUnpackedValueOrDefault(
1754 : OUString("UIComponent"),
1755 0 : OUString() );
1756 0 : if( !aServiceName.isEmpty() )
1757 0 : bUseFilterOptions = true;
1758 0 : }
1759 : }
1760 0 : catch( const uno::Exception& )
1761 : {
1762 : }
1763 : }
1764 :
1765 0 : return bUseFilterOptions;
1766 : }
1767 :
1768 :
1769 : // static
1770 0 : void SfxStoringHelper::SetDocInfoState(
1771 : const uno::Reference< frame::XModel >& xModel,
1772 : const uno::Reference< document::XDocumentProperties>& i_xOldDocProps,
1773 : bool bNoModify )
1774 : {
1775 : uno::Reference<document::XDocumentPropertiesSupplier> const
1776 0 : xModelDocPropsSupplier(xModel, uno::UNO_QUERY_THROW);
1777 : uno::Reference<document::XDocumentProperties> const xDocPropsToFill =
1778 0 : xModelDocPropsSupplier->getDocumentProperties();
1779 : uno::Reference< beans::XPropertySet > const xPropSet(
1780 0 : i_xOldDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
1781 :
1782 0 : uno::Reference< util::XModifiable > xModifiable( xModel, uno::UNO_QUERY );
1783 0 : if ( bNoModify && !xModifiable.is() )
1784 0 : throw uno::RuntimeException();
1785 :
1786 0 : bool bIsModified = bNoModify && xModifiable->isModified();
1787 :
1788 : try
1789 : {
1790 : uno::Reference< beans::XPropertySet > const xSet(
1791 0 : xDocPropsToFill->getUserDefinedProperties(), uno::UNO_QUERY);
1792 0 : uno::Reference< beans::XPropertyContainer > xContainer( xSet, uno::UNO_QUERY );
1793 0 : uno::Reference< beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo();
1794 0 : uno::Sequence< beans::Property > lProps = xSetInfo->getProperties();
1795 0 : const beans::Property* pProps = lProps.getConstArray();
1796 0 : sal_Int32 c = lProps.getLength();
1797 0 : sal_Int32 i = 0;
1798 0 : for (i=0; i<c; ++i)
1799 : {
1800 0 : uno::Any aValue = xPropSet->getPropertyValue( pProps[i].Name );
1801 0 : if ( pProps[i].Attributes & ::com::sun::star::beans::PropertyAttribute::REMOVABLE )
1802 : {
1803 : try
1804 : {
1805 : // QUESTION: DefaultValue?!
1806 0 : xContainer->addProperty( pProps[i].Name, pProps[i].Attributes, aValue );
1807 : }
1808 0 : catch (beans::PropertyExistException const&) {}
1809 : try
1810 : {
1811 : // it is possible that the propertysets from XML and binary files differ; we shouldn't break then
1812 0 : xSet->setPropertyValue( pProps[i].Name, aValue );
1813 : }
1814 0 : catch ( const uno::Exception& ) {}
1815 : }
1816 0 : }
1817 :
1818 : // sigh... have to set these manually i'm afraid... wonder why
1819 : // SfxObjectShell doesn't handle this internally, should be easier
1820 0 : xDocPropsToFill->setAuthor(i_xOldDocProps->getAuthor());
1821 0 : xDocPropsToFill->setGenerator(i_xOldDocProps->getGenerator());
1822 0 : xDocPropsToFill->setCreationDate(i_xOldDocProps->getCreationDate());
1823 0 : xDocPropsToFill->setTitle(i_xOldDocProps->getTitle());
1824 0 : xDocPropsToFill->setSubject(i_xOldDocProps->getSubject());
1825 0 : xDocPropsToFill->setDescription(i_xOldDocProps->getDescription());
1826 0 : xDocPropsToFill->setKeywords(i_xOldDocProps->getKeywords());
1827 0 : xDocPropsToFill->setModifiedBy(i_xOldDocProps->getModifiedBy());
1828 0 : xDocPropsToFill->setModificationDate(i_xOldDocProps->getModificationDate());
1829 0 : xDocPropsToFill->setPrintedBy(i_xOldDocProps->getPrintedBy());
1830 0 : xDocPropsToFill->setPrintDate(i_xOldDocProps->getPrintDate());
1831 0 : xDocPropsToFill->setAutoloadURL(i_xOldDocProps->getAutoloadURL());
1832 0 : xDocPropsToFill->setAutoloadSecs(i_xOldDocProps->getAutoloadSecs());
1833 0 : xDocPropsToFill->setDefaultTarget(i_xOldDocProps->getDefaultTarget());
1834 0 : xDocPropsToFill->setEditingCycles(i_xOldDocProps->getEditingCycles());
1835 0 : xDocPropsToFill->setEditingDuration(i_xOldDocProps->getEditingDuration());
1836 : // other attributes e.g. DocumentStatistics are not editable from dialog
1837 : }
1838 0 : catch (const uno::Exception& e)
1839 : {
1840 : SAL_INFO("sfx.doc", "SetDocInfoState: caught exception: " << e.Message);
1841 : }
1842 :
1843 : // set the modified flag back if required
1844 0 : if ( ((bNoModify && bIsModified) ? 1 : 0) != xModifiable->isModified() )
1845 0 : xModifiable->setModified( bIsModified );
1846 0 : }
1847 :
1848 :
1849 : // static
1850 0 : bool SfxStoringHelper::WarnUnacceptableFormat( const uno::Reference< frame::XModel >& xModel,
1851 : const OUString& aOldUIName,
1852 : const OUString& /*aDefUIName*/,
1853 : bool /*bCanProceedFurther*/ )
1854 : {
1855 0 : if ( !SvtSaveOptions().IsWarnAlienFormat() )
1856 0 : return true;
1857 :
1858 0 : vcl::Window* pWin = SfxStoringHelper::GetModelWindow( xModel );
1859 0 : SfxAlienWarningDialog aDlg( pWin, aOldUIName );
1860 :
1861 0 : return aDlg.Execute() == RET_OK;
1862 : }
1863 :
1864 0 : vcl::Window* SfxStoringHelper::GetModelWindow( const uno::Reference< frame::XModel >& xModel )
1865 : {
1866 0 : vcl::Window* pWin = 0;
1867 : try {
1868 0 : if ( xModel.is() )
1869 : {
1870 0 : uno::Reference< frame::XController > xController = xModel->getCurrentController();
1871 0 : if ( xController.is() )
1872 : {
1873 0 : uno::Reference< frame::XFrame > xFrame = xController->getFrame();
1874 0 : if ( xFrame.is() )
1875 : {
1876 0 : uno::Reference< awt::XWindow > xWindow = xFrame->getContainerWindow();
1877 0 : if ( xWindow.is() )
1878 : {
1879 0 : VCLXWindow* pVCLWindow = VCLXWindow::GetImplementation( xWindow );
1880 0 : if ( pVCLWindow )
1881 0 : pWin = pVCLWindow->GetWindow();
1882 0 : }
1883 0 : }
1884 0 : }
1885 : }
1886 : }
1887 0 : catch ( const uno::Exception& )
1888 : {
1889 : }
1890 :
1891 0 : return pWin;
1892 951 : }
1893 :
1894 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|