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/msgbox.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 : Window* pWin = SfxStoringHelper::GetModelWindow( m_xModel );
669 0 : QueryBox aMessageBox( pWin, WB_OK_CANCEL | WB_DEF_OK, SfxResId(STR_NEW_FILENAME_SAVE).toString() );
670 0 : if ( aMessageBox.Execute() == RET_OK )
671 0 : nResult = STATUS_SAVEAS;
672 : else
673 0 : nResult = STATUS_NO_ACTION;
674 0 : }
675 : }
676 :
677 0 : return nResult;
678 : }
679 :
680 :
681 0 : sal_Int8 ModelData_Impl::CheckStateForSave()
682 : {
683 : // if the document is readonly or a new one a SaveAs operation must be used
684 0 : if ( !GetStorable()->hasLocation() || GetStorable()->isReadonly() )
685 0 : return STATUS_SAVEAS;
686 :
687 : // check acceptable entries for media descriptor
688 0 : bool bVersInfoNeedsStore = false;
689 0 : ::comphelper::SequenceAsHashMap aAcceptedArgs;
690 :
691 0 : OUString aVersionCommentString("VersionComment");
692 0 : OUString aAuthorString("Author");
693 0 : OUString aInteractionHandlerString("InteractionHandler");
694 0 : OUString aStatusIndicatorString("StatusIndicator");
695 0 : OUString aFailOnWarningString("FailOnWarning");
696 :
697 0 : if ( GetMediaDescr().find( aVersionCommentString ) != GetMediaDescr().end() )
698 : {
699 0 : bVersInfoNeedsStore = true;
700 0 : aAcceptedArgs[ aVersionCommentString ] = GetMediaDescr()[ aVersionCommentString ];
701 : }
702 0 : if ( GetMediaDescr().find( aAuthorString ) != GetMediaDescr().end() )
703 0 : aAcceptedArgs[ aAuthorString ] = GetMediaDescr()[ aAuthorString ];
704 0 : if ( GetMediaDescr().find( aInteractionHandlerString ) != GetMediaDescr().end() )
705 0 : aAcceptedArgs[ aInteractionHandlerString ] = GetMediaDescr()[ aInteractionHandlerString ];
706 0 : if ( GetMediaDescr().find( aStatusIndicatorString ) != GetMediaDescr().end() )
707 0 : aAcceptedArgs[ aStatusIndicatorString ] = GetMediaDescr()[ aStatusIndicatorString ];
708 0 : if ( GetMediaDescr().find( aFailOnWarningString ) != GetMediaDescr().end() )
709 0 : aAcceptedArgs[ aFailOnWarningString ] = GetMediaDescr()[ aFailOnWarningString ];
710 :
711 : // remove unacceptable entry if there is any
712 : DBG_ASSERT( GetMediaDescr().size() == aAcceptedArgs.size(),
713 : "Unacceptable parameters are provided in Save request!\n" );
714 0 : if ( GetMediaDescr().size() != aAcceptedArgs.size() )
715 0 : GetMediaDescr() = aAcceptedArgs;
716 :
717 : // the document must be modified unless the always-save flag is set.
718 0 : SvtMiscOptions aMiscOptions;
719 0 : bool bAlwaysAllowSave = aMiscOptions.IsSaveAlwaysAllowed();
720 0 : if (!bAlwaysAllowSave)
721 : {
722 0 : if ( !GetModifiable()->isModified() && !bVersInfoNeedsStore )
723 0 : return STATUS_NO_ACTION;
724 : }
725 :
726 : // check that the old filter is acceptable
727 0 : OUString aOldFilterName = GetDocProps().getUnpackedValueOrDefault(
728 : OUString(aFilterNameString),
729 0 : OUString() );
730 0 : sal_Int8 nResult = CheckFilter( aOldFilterName );
731 :
732 0 : return nResult;
733 : }
734 :
735 0 : bool hasMacros( const uno::Reference< frame::XModel >& xModel )
736 : {
737 0 : bool bHasMacros = false;
738 0 : uno::Reference< script::XLibraryContainer > xContainer;
739 0 : uno::Reference< beans::XPropertySet > xProps( xModel, uno::UNO_QUERY );
740 0 : if ( xProps.is() )
741 : {
742 0 : xProps->getPropertyValue( "BasicLibraries" ) >>= xContainer;
743 0 : bHasMacros = sfx2::DocumentMacroMode::containerHasBasicMacros( xContainer );
744 : }
745 0 : return bHasMacros;
746 : }
747 :
748 0 : sal_Int8 ModelData_Impl::CheckFilter( const OUString& aFilterName )
749 : {
750 0 : ::comphelper::SequenceAsHashMap aFiltPropsHM;
751 0 : sal_Int32 nFiltFlags = 0;
752 0 : if ( !aFilterName.isEmpty() )
753 : {
754 : // get properties of filter
755 0 : uno::Sequence< beans::PropertyValue > aFilterProps;
756 0 : if ( !aFilterName.isEmpty() )
757 0 : m_pOwner->GetFilterConfiguration()->getByName( aFilterName ) >>= aFilterProps;
758 :
759 0 : aFiltPropsHM = ::comphelper::SequenceAsHashMap( aFilterProps );
760 0 : nFiltFlags = aFiltPropsHM.getUnpackedValueOrDefault("Flags", (sal_Int32)0 );
761 : }
762 :
763 : // only a temporary solution until default filter retrieving feature is implemented
764 : // then GetDocServiceDefaultFilter() must be used
765 0 : ::comphelper::SequenceAsHashMap aDefFiltPropsHM = GetDocServiceDefaultFilterCheckFlags( 3, 0 );
766 0 : sal_Int32 nDefFiltFlags = aDefFiltPropsHM.getUnpackedValueOrDefault("Flags", (sal_Int32)0 );
767 :
768 : // if the old filter is not acceptable
769 : // and there is no default filter or it is not acceptable for requested parameters then proceed with saveAs
770 0 : if ( ( !aFiltPropsHM.size() || !( nFiltFlags & SFX_FILTER_EXPORT ) )
771 0 : && ( !aDefFiltPropsHM.size() || !( nDefFiltFlags & SFX_FILTER_EXPORT ) || nDefFiltFlags & SFX_FILTER_INTERNAL ) )
772 0 : return STATUS_SAVEAS;
773 :
774 : // so at this point there is either an acceptable old filter or default one
775 0 : if ( !aFiltPropsHM.size() || !( nFiltFlags & SFX_FILTER_EXPORT ) )
776 : {
777 : // so the default filter must be acceptable
778 0 : return STATUS_SAVEAS_STANDARDNAME;
779 : }
780 0 : else if ( ( !( nFiltFlags & SFX_FILTER_OWN ) || ( nFiltFlags & SFX_FILTER_ALIEN ) )
781 0 : && aDefFiltPropsHM.size()
782 0 : && ( nDefFiltFlags & SFX_FILTER_EXPORT ) && !( nDefFiltFlags & SFX_FILTER_INTERNAL ))
783 : {
784 : // the default filter is acceptable and the old filter is alien one
785 : // so ask to make a saveAs operation
786 : OUString aUIName = aFiltPropsHM.getUnpackedValueOrDefault("UIName",
787 0 : OUString() );
788 : OUString aDefUIName = aDefFiltPropsHM.getUnpackedValueOrDefault("UIName",
789 0 : OUString() );
790 0 : OUString aPreusedFilterName = GetDocProps().getUnpackedValueOrDefault(
791 : OUString("PreusedFilterName"),
792 0 : OUString() );
793 0 : if ( !aPreusedFilterName.equals( aFilterName ) && !aUIName.equals( aDefUIName ) )
794 : {
795 : // is it possible to get these names from somewhere and not just
796 : // hardcode them?
797 0 : OUString sXLSXFilter("Calc MS Excel 2007 XML");
798 0 : OUString sOtherXLSXFilter("Calc Office Open XML");
799 0 : bool bHasMacros = hasMacros( GetModel() );
800 0 : if ( bHasMacros && ( aFilterName == sXLSXFilter || aFilterName == sOtherXLSXFilter ) )
801 : {
802 0 : uno::Reference< task::XInteractionHandler > xHandler;
803 0 : GetMediaDescr()[ OUString( "InteractionHandler" ) ] >>= xHandler;
804 0 : bool bResult = false;
805 0 : if ( xHandler.is() )
806 : {
807 : try
808 : {
809 0 : task::ErrorCodeRequest aErrorCode;
810 0 : aErrorCode.ErrCode = ERRCODE_SFX_VBASIC_CANTSAVE_STORAGE;
811 :
812 0 : uno::Any aRequest = uno::makeAny( aErrorCode );
813 0 : uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 2 );
814 :
815 0 : ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove );
816 0 : aContinuations[ 0 ] = pApprove.get();
817 :
818 0 : ::rtl::Reference< ::comphelper::OInteractionAbort > pAbort( new ::comphelper::OInteractionAbort );
819 0 : aContinuations[ 1 ] = pAbort.get();
820 0 : xHandler->handle(::framework::InteractionRequest::CreateRequest (aRequest,aContinuations));
821 0 : bResult = pApprove->wasSelected();
822 : }
823 0 : catch( const uno::Exception& )
824 : {
825 : }
826 0 : if ( !bResult )
827 0 : return STATUS_SAVEAS;
828 0 : }
829 : }
830 0 : if ( !SfxStoringHelper::WarnUnacceptableFormat( GetModel(), aUIName, aDefUIName, true ) )
831 0 : return STATUS_SAVEAS_STANDARDNAME;
832 0 : }
833 : }
834 :
835 0 : return STATUS_SAVE;
836 : }
837 :
838 :
839 0 : bool ModelData_Impl::CheckFilterOptionsDialogExistence()
840 : {
841 0 : uno::Sequence< beans::NamedValue > aSearchRequest( 1 );
842 0 : aSearchRequest[0].Name = "DocumentService";
843 0 : aSearchRequest[0].Value <<= GetDocServiceName();
844 :
845 : uno::Reference< container::XEnumeration > xFilterEnum =
846 0 : m_pOwner->GetFilterQuery()->createSubSetEnumerationByProperties( aSearchRequest );
847 :
848 0 : while ( xFilterEnum->hasMoreElements() )
849 : {
850 0 : uno::Sequence< beans::PropertyValue > pProps;
851 0 : if ( xFilterEnum->nextElement() >>= pProps )
852 : {
853 0 : ::comphelper::SequenceAsHashMap aPropsHM( pProps );
854 : OUString aUIServName = aPropsHM.getUnpackedValueOrDefault(
855 : OUString("UIComponent"),
856 0 : OUString() );
857 0 : if ( !aUIServName.isEmpty() )
858 0 : return true;
859 : }
860 0 : }
861 :
862 0 : return false;
863 : }
864 :
865 :
866 0 : bool ModelData_Impl::OutputFileDialog( sal_Int8 nStoreMode,
867 : const ::comphelper::SequenceAsHashMap& aPreselectedFilterPropsHM,
868 : bool bSetStandardName,
869 : OUString& aSuggestedName,
870 : bool bPreselectPassword,
871 : OUString& aSuggestedDir,
872 : sal_Int16 nDialog,
873 : const OUString& rStandardDir,
874 : const ::com::sun::star::uno::Sequence< OUString >& rBlackList)
875 : {
876 0 : bool bUseFilterOptions = false;
877 :
878 : ::comphelper::SequenceAsHashMap::const_iterator aOverwriteIter =
879 0 : GetMediaDescr().find( OUString("Overwrite") );
880 :
881 : // the file name must be specified if overwrite option is set
882 0 : if ( aOverwriteIter != GetMediaDescr().end() )
883 : throw task::ErrorCodeIOException(
884 : "ModelData_Impl::OutputFileDialog: ERRCODE_IO_INVALIDPARAMETER",
885 : uno::Reference< uno::XInterface >(),
886 0 : ERRCODE_IO_INVALIDPARAMETER);
887 :
888 : // no target file name is specified
889 : // we need to show the file dialog
890 :
891 : // check if we have a filter which allows for filter options, so we need a corresponding checkbox in the dialog
892 0 : bool bAllowOptions = false;
893 :
894 : // in case of Export, filter options dialog is used if available
895 0 : if( !( nStoreMode & EXPORT_REQUESTED ) || ( nStoreMode & WIDEEXPORT_REQUESTED ) )
896 0 : bAllowOptions = CheckFilterOptionsDialogExistence();
897 :
898 : // get the filename by dialog ...
899 : // create the file dialog
900 : sal_Int16 aDialogMode = bAllowOptions
901 : ? (com::sun::star::ui::dialogs::TemplateDescription::
902 : FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS)
903 : : (com::sun::star::ui::dialogs::TemplateDescription::
904 0 : FILESAVE_AUTOEXTENSION_PASSWORD);
905 0 : sal_Int64 aDialogFlags = 0;
906 :
907 0 : if( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & WIDEEXPORT_REQUESTED ) )
908 : {
909 0 : if ( nStoreMode & PDFEXPORT_REQUESTED )
910 : aDialogMode = com::sun::star::ui::dialogs::TemplateDescription::
911 0 : FILESAVE_AUTOEXTENSION;
912 : else
913 : aDialogMode = com::sun::star::ui::dialogs::TemplateDescription::
914 0 : FILESAVE_AUTOEXTENSION_SELECTION;
915 0 : aDialogFlags = SFXWB_EXPORT;
916 : }
917 :
918 0 : if( ( nStoreMode & EXPORT_REQUESTED ) && ( nStoreMode & SAVEACOPY_REQUESTED ) && ( nStoreMode & WIDEEXPORT_REQUESTED ) )
919 : {
920 0 : aDialogFlags = SFXWB_SAVEACOPY;
921 : }
922 :
923 0 : boost::scoped_ptr<sfx2::FileDialogHelper> pFileDlg;
924 :
925 0 : OUString aDocServiceName = GetDocServiceName();
926 : DBG_ASSERT( !aDocServiceName.isEmpty(), "No document service for this module set!" );
927 :
928 0 : sal_Int32 nMust = getMustFlags( nStoreMode );
929 0 : sal_Int32 nDont = getDontFlags( nStoreMode );
930 0 : sfx2::FileDialogHelper::Context eCtxt = sfx2::FileDialogHelper::UNKNOWN_CONTEXT;
931 :
932 0 : if ( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & WIDEEXPORT_REQUESTED ) )
933 : {
934 0 : if ( ( nStoreMode & PDFEXPORT_REQUESTED ) && aPreselectedFilterPropsHM.size() )
935 : {
936 : // this is a PDF export
937 : // the filter options has been shown already
938 : OUString aFilterUIName = aPreselectedFilterPropsHM.getUnpackedValueOrDefault(
939 : OUString("UIName"),
940 0 : OUString() );
941 :
942 0 : pFileDlg.reset(new sfx2::FileDialogHelper( aDialogMode, aDialogFlags, aFilterUIName, OUString( "pdf" ), rStandardDir, rBlackList ));
943 0 : pFileDlg->SetCurrentFilter( aFilterUIName );
944 : }
945 : else
946 : {
947 : // This is the normal dialog
948 0 : pFileDlg.reset(new sfx2::FileDialogHelper( aDialogMode, aDialogFlags, aDocServiceName, nDialog, nMust, nDont, rStandardDir, rBlackList ));
949 : }
950 :
951 0 : if ( aDocServiceName == "com.sun.star.drawing.DrawingDocument" )
952 0 : eCtxt = sfx2::FileDialogHelper::SD_EXPORT;
953 0 : else if ( aDocServiceName == "com.sun.star.presentation.PresentationDocument" )
954 0 : eCtxt = sfx2::FileDialogHelper::SI_EXPORT;
955 0 : else if ( aDocServiceName == "com.sun.star.text.TextDocument" )
956 0 : eCtxt = sfx2::FileDialogHelper::SW_EXPORT;
957 :
958 0 : if ( eCtxt != sfx2::FileDialogHelper::UNKNOWN_CONTEXT )
959 0 : pFileDlg->SetContext( eCtxt );
960 :
961 0 : pFileDlg->CreateMatcher( aDocServiceName );
962 :
963 0 : uno::Reference< ui::dialogs::XFilePicker > xFilePicker = pFileDlg->GetFilePicker();
964 : uno::Reference< ui::dialogs::XFilePickerControlAccess > xControlAccess =
965 0 : uno::Reference< ui::dialogs::XFilePickerControlAccess >( xFilePicker, uno::UNO_QUERY );
966 :
967 0 : if ( xControlAccess.is() )
968 : {
969 0 : OUString aCtrlText = SfxResId(STR_EXPORTBUTTON).toString();
970 0 : xControlAccess->setLabel( ui::dialogs::CommonFilePickerElementIds::PUSHBUTTON_OK, aCtrlText );
971 :
972 0 : aCtrlText = SfxResId(STR_LABEL_FILEFORMAT).toString();
973 0 : xControlAccess->setLabel( ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER_LABEL, aCtrlText );
974 0 : }
975 : }
976 : else
977 : {
978 : // This is the normal dialog
979 0 : pFileDlg.reset(new sfx2::FileDialogHelper( aDialogMode, aDialogFlags, aDocServiceName, nDialog, nMust, nDont, rStandardDir, rBlackList ));
980 0 : pFileDlg->CreateMatcher( aDocServiceName );
981 : }
982 :
983 0 : OUString aAdjustToType;
984 :
985 0 : const OUString sFilterNameString(aFilterNameString);
986 :
987 0 : if ( ( nStoreMode & EXPORT_REQUESTED ) && !( nStoreMode & WIDEEXPORT_REQUESTED ) )
988 : {
989 : // it is export, set the preselected filter
990 : OUString aFilterUIName = aPreselectedFilterPropsHM.getUnpackedValueOrDefault(
991 : OUString("UIName"),
992 0 : OUString() );
993 0 : pFileDlg->SetCurrentFilter( aFilterUIName );
994 : }
995 : // it is no export, bSetStandardName == true means that user agreed to store document in the default (default default ;-)) format
996 0 : else if ( bSetStandardName || GetStorable()->hasLocation() )
997 : {
998 0 : uno::Sequence< beans::PropertyValue > aOldFilterProps;
999 0 : OUString aOldFilterName = GetDocProps().getUnpackedValueOrDefault(
1000 : sFilterNameString,
1001 0 : OUString() );
1002 :
1003 0 : if ( !aOldFilterName.isEmpty() )
1004 0 : m_pOwner->GetFilterConfiguration()->getByName( aOldFilterName ) >>= aOldFilterProps;
1005 :
1006 0 : ::comphelper::SequenceAsHashMap aOldFiltPropsHM( aOldFilterProps );
1007 0 : sal_Int32 nOldFiltFlags = aOldFiltPropsHM.getUnpackedValueOrDefault("Flags", (sal_Int32)0 );
1008 :
1009 0 : if ( bSetStandardName || ( nOldFiltFlags & nMust ) != nMust || nOldFiltFlags & nDont )
1010 : {
1011 : // the suggested type will be changed, the extension should be adjusted
1012 0 : aAdjustToType = aPreselectedFilterPropsHM.getUnpackedValueOrDefault(
1013 : OUString("Type"),
1014 0 : OUString() );
1015 :
1016 : OUString aFilterUIName = aPreselectedFilterPropsHM.getUnpackedValueOrDefault(
1017 : OUString("UIName"),
1018 0 : OUString() );
1019 0 : pFileDlg->SetCurrentFilter( aFilterUIName );
1020 : }
1021 : else
1022 : {
1023 : pFileDlg->SetCurrentFilter( aOldFiltPropsHM.getUnpackedValueOrDefault(
1024 : OUString("UIName"),
1025 0 : OUString() ) );
1026 0 : }
1027 : }
1028 :
1029 0 : OUString aRecommendedDir = GetRecommendedDir( aSuggestedDir );
1030 0 : if ( !aRecommendedDir.isEmpty() )
1031 0 : pFileDlg->SetDisplayFolder( aRecommendedDir );
1032 0 : OUString aRecommendedName = GetRecommendedName( aSuggestedName, aAdjustToType );
1033 0 : if ( !aRecommendedName.isEmpty() )
1034 0 : pFileDlg->SetFileName( aRecommendedName );
1035 :
1036 0 : uno::Reference < view::XSelectionSupplier > xSel( GetModel()->getCurrentController(), uno::UNO_QUERY );
1037 0 : if ( xSel.is() && xSel->getSelection().hasValue() )
1038 0 : GetMediaDescr()[OUString("SelectionOnly")] <<= sal_True;
1039 :
1040 : // This is a temporary hardcoded solution must be removed when
1041 : // dialogs do not need parameters in SidSet representation any more
1042 0 : sal_uInt16 nSlotID = getSlotIDFromMode( nStoreMode );
1043 0 : if ( !nSlotID )
1044 0 : throw lang::IllegalArgumentException(); // TODO:
1045 :
1046 : // generate SidSet from MediaDescriptor and provide it into FileDialog
1047 : // than merge changed SidSet back
1048 0 : SfxAllItemSet aDialogParams( SFX_APP()->GetPool() );
1049 0 : SfxItemSet* pDialogParams = &aDialogParams;
1050 : TransformParameters( nSlotID,
1051 0 : GetMediaDescr().getAsConstPropertyValueList(),
1052 : aDialogParams,
1053 0 : NULL );
1054 :
1055 0 : const SfxPoolItem* pItem = NULL;
1056 0 : if ( bPreselectPassword && aDialogParams.GetItemState( SID_ENCRYPTIONDATA, true, &pItem ) != SFX_ITEM_SET )
1057 : {
1058 : // the file dialog preselects the password checkbox if the provided mediadescriptor has encryption data entry
1059 : // after dialog execution the password interaction flag will be either removed or not
1060 0 : aDialogParams.Put( SfxBoolItem( SID_PASSWORDINTERACTION, true ) );
1061 : }
1062 :
1063 : // aStringTypeFN is a pure output parameter, pDialogParams is an in/out parameter
1064 0 : OUString aStringTypeFN;
1065 0 : if ( pFileDlg->Execute( pDialogParams, aStringTypeFN ) != ERRCODE_NONE )
1066 : {
1067 : throw task::ErrorCodeIOException(
1068 : "ModelData_Impl::OutputFileDialog: ERRCODE_IO_ABORT",
1069 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_ABORT);
1070 : }
1071 :
1072 0 : OUString aFilterName = aStringTypeFN;
1073 :
1074 : // the following two arguments can not be converted in MediaDescriptor,
1075 : // so they should be removed from the ItemSet after retrieving
1076 0 : SFX_ITEMSET_ARG( pDialogParams, pRecommendReadOnly, SfxBoolItem, SID_RECOMMENDREADONLY, false );
1077 0 : m_bRecommendReadOnly = ( pRecommendReadOnly && pRecommendReadOnly->GetValue() );
1078 0 : pDialogParams->ClearItem( SID_RECOMMENDREADONLY );
1079 :
1080 0 : uno::Sequence< beans::PropertyValue > aPropsFromDialog;
1081 0 : TransformItems( nSlotID, *pDialogParams, aPropsFromDialog, NULL );
1082 0 : GetMediaDescr() << aPropsFromDialog;
1083 :
1084 : // get the path from the dialog
1085 0 : INetURLObject aURL( pFileDlg->GetPath() );
1086 : // the path should be provided outside since it might be used for further calls to the dialog
1087 0 : aSuggestedName = aURL.GetName( INetURLObject::DECODE_WITH_CHARSET );
1088 0 : aSuggestedDir = pFileDlg->GetDisplayDirectory();
1089 :
1090 : // old filter options should be cleared in case different filter is used
1091 :
1092 0 : OUString aFilterFromMediaDescr = GetMediaDescr().getUnpackedValueOrDefault(
1093 : sFilterNameString,
1094 0 : OUString() );
1095 0 : OUString aOldFilterName = GetDocProps().getUnpackedValueOrDefault(
1096 : sFilterNameString,
1097 0 : OUString() );
1098 :
1099 0 : const OUString sFilterOptionsString(aFilterOptionsString);
1100 0 : const OUString sFilterDataString(aFilterDataString);
1101 :
1102 0 : if ( aFilterName.equals( aFilterFromMediaDescr ) )
1103 : {
1104 : // preserv current settings if any
1105 : // if there no current settings and the name is the same
1106 : // as old filter name use old filter settings
1107 :
1108 0 : if ( aFilterFromMediaDescr.equals( aOldFilterName ) )
1109 : {
1110 : ::comphelper::SequenceAsHashMap::const_iterator aIter =
1111 0 : GetDocProps().find( sFilterOptionsString );
1112 0 : if ( aIter != GetDocProps().end()
1113 0 : && GetMediaDescr().find( sFilterOptionsString ) == GetMediaDescr().end() )
1114 0 : GetMediaDescr()[aIter->first] = aIter->second;
1115 :
1116 0 : aIter = GetDocProps().find( sFilterDataString );
1117 0 : if ( aIter != GetDocProps().end()
1118 0 : && GetMediaDescr().find( sFilterDataString ) == GetMediaDescr().end() )
1119 0 : GetMediaDescr()[aIter->first] = aIter->second;
1120 : }
1121 : }
1122 : else
1123 : {
1124 0 : GetMediaDescr().erase( sFilterDataString );
1125 0 : GetMediaDescr().erase( sFilterOptionsString );
1126 :
1127 0 : if ( aFilterName.equals( aOldFilterName ) )
1128 : {
1129 : // merge filter option of the document filter
1130 :
1131 : ::comphelper::SequenceAsHashMap::const_iterator aIter =
1132 0 : GetDocProps().find( sFilterOptionsString );
1133 0 : if ( aIter != GetDocProps().end() )
1134 0 : GetMediaDescr()[aIter->first] = aIter->second;
1135 :
1136 0 : aIter = GetDocProps().find( sFilterDataString );
1137 0 : if ( aIter != GetDocProps().end() )
1138 0 : GetMediaDescr()[aIter->first] = aIter->second;
1139 : }
1140 : }
1141 :
1142 0 : uno::Reference< ui::dialogs::XFilePickerControlAccess > xExtFileDlg( pFileDlg->GetFilePicker(), uno::UNO_QUERY );
1143 0 : if ( xExtFileDlg.is() )
1144 : {
1145 0 : if ( SfxStoringHelper::CheckFilterOptionsAppearence( m_pOwner->GetFilterConfiguration(), aFilterName ) )
1146 0 : bUseFilterOptions = true;
1147 :
1148 0 : if ( ( !( nStoreMode & EXPORT_REQUESTED ) || ( nStoreMode & WIDEEXPORT_REQUESTED ) ) && bUseFilterOptions )
1149 : {
1150 : try
1151 : {
1152 : // for exporters: always show dialog if format uses options
1153 : // for save: show dialog if format uses options and no options given or if forced by user
1154 : uno::Any aVal =
1155 0 : xExtFileDlg->getValue( ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS, 0 );
1156 :
1157 0 : aVal >>= bUseFilterOptions;
1158 0 : if ( !bUseFilterOptions )
1159 : bUseFilterOptions =
1160 0 : ( GetMediaDescr().find( sFilterDataString ) == GetMediaDescr().end()
1161 0 : && GetMediaDescr().find( sFilterOptionsString ) == GetMediaDescr().end() );
1162 : }
1163 0 : catch( const lang::IllegalArgumentException& )
1164 : {}
1165 : }
1166 : }
1167 :
1168 : // merge in results of the dialog execution
1169 0 : GetMediaDescr()[OUString("URL")] <<=
1170 0 : OUString( aURL.GetMainURL( INetURLObject::NO_DECODE ));
1171 0 : GetMediaDescr()[sFilterNameString] <<= aFilterName;
1172 :
1173 0 : return bUseFilterOptions;
1174 : }
1175 :
1176 :
1177 0 : bool ModelData_Impl::ShowDocumentInfoDialog()
1178 : {
1179 0 : bool bDialogUsed = false;
1180 :
1181 : try {
1182 0 : uno::Reference< frame::XController > xController = GetModel()->getCurrentController();
1183 0 : if ( xController.is() )
1184 : {
1185 0 : uno::Reference< frame::XDispatchProvider > xFrameDispatch( xController->getFrame(), uno::UNO_QUERY );
1186 0 : if ( xFrameDispatch.is() )
1187 : {
1188 0 : util::URL aURL;
1189 0 : aURL.Complete = ".uno:SetDocumentProperties";
1190 :
1191 0 : uno::Reference < util::XURLTransformer > xTransformer( util::URLTransformer::create( comphelper::getProcessComponentContext() ) );
1192 0 : if ( xTransformer->parseStrict( aURL ) )
1193 : {
1194 0 : uno::Reference< frame::XDispatch > xDispatch = xFrameDispatch->queryDispatch(
1195 : aURL,
1196 : OUString("_self"),
1197 0 : 0 );
1198 0 : if ( xDispatch.is() )
1199 : {
1200 0 : xDispatch->dispatch( aURL, uno::Sequence< beans::PropertyValue >() );
1201 0 : bDialogUsed = true;
1202 0 : }
1203 0 : }
1204 0 : }
1205 0 : }
1206 : }
1207 0 : catch ( const uno::Exception& )
1208 : {
1209 : }
1210 :
1211 0 : return bDialogUsed;
1212 : }
1213 :
1214 :
1215 0 : OUString ModelData_Impl::GetRecommendedDir( const OUString& aSuggestedDir )
1216 : {
1217 0 : OUString aRecommendedDir;
1218 :
1219 0 : if ( ( !aSuggestedDir.isEmpty() || GetStorable()->hasLocation() )
1220 0 : && !GetMediaDescr().getUnpackedValueOrDefault("RepairPackage",
1221 0 : sal_False ) )
1222 : {
1223 0 : INetURLObject aLocation;
1224 0 : if ( !aSuggestedDir.isEmpty() )
1225 0 : aLocation = INetURLObject( aSuggestedDir );
1226 : else
1227 : {
1228 0 : OUString aOldURL = GetStorable()->getLocation();
1229 0 : if ( !aOldURL.isEmpty() )
1230 : {
1231 0 : INetURLObject aTmp( aOldURL );
1232 0 : if ( aTmp.removeSegment() )
1233 0 : aLocation = aTmp;
1234 : }
1235 :
1236 0 : if ( aLocation.HasError() )
1237 0 : aLocation = INetURLObject( SvtPathOptions().GetWorkPath() );
1238 : }
1239 :
1240 0 : aLocation.setFinalSlash();
1241 0 : if ( !aLocation.HasError() )
1242 0 : aRecommendedDir = aLocation.GetMainURL( INetURLObject::NO_DECODE );
1243 : }
1244 : else
1245 : {
1246 0 : aRecommendedDir = INetURLObject( SvtPathOptions().GetWorkPath() ).GetMainURL( INetURLObject::NO_DECODE );
1247 : }
1248 :
1249 0 : return aRecommendedDir;
1250 : }
1251 :
1252 :
1253 0 : OUString ModelData_Impl::GetRecommendedName( const OUString& aSuggestedName, const OUString& aTypeName )
1254 : {
1255 : // the last used name might be provided by aSuggestedName from the old selection, or from the MediaDescriptor
1256 0 : OUString aRecommendedName;
1257 :
1258 0 : if ( !aSuggestedName.isEmpty() )
1259 0 : aRecommendedName = aSuggestedName;
1260 : else
1261 : {
1262 0 : aRecommendedName = INetURLObject( GetStorable()->getLocation() ).GetName( INetURLObject::DECODE_WITH_CHARSET );
1263 0 : if ( aRecommendedName.isEmpty() )
1264 : {
1265 : try {
1266 0 : uno::Reference< frame::XTitle > xTitle( GetModel(), uno::UNO_QUERY_THROW );
1267 0 : aRecommendedName = xTitle->getTitle();
1268 0 : } catch( const uno::Exception& ) {}
1269 : }
1270 :
1271 0 : if ( !aRecommendedName.isEmpty() && !aTypeName.isEmpty() )
1272 : {
1273 : // adjust the extension to the type
1274 : uno::Reference< container::XNameAccess > xTypeDetection = uno::Reference< container::XNameAccess >(
1275 0 : comphelper::getProcessServiceFactory()->createInstance("com.sun.star.document.TypeDetection"),
1276 0 : uno::UNO_QUERY );
1277 0 : if ( xTypeDetection.is() )
1278 : {
1279 0 : INetURLObject aObj( OUString( "file:///c:/" ) + aRecommendedName );
1280 :
1281 0 : uno::Sequence< beans::PropertyValue > aTypeNameProps;
1282 0 : if ( ( xTypeDetection->getByName( aTypeName ) >>= aTypeNameProps ) && aTypeNameProps.getLength() )
1283 : {
1284 0 : ::comphelper::SequenceAsHashMap aTypeNamePropsHM( aTypeNameProps );
1285 : uno::Sequence< OUString > aExtensions = aTypeNamePropsHM.getUnpackedValueOrDefault(
1286 : OUString("Extensions"),
1287 0 : ::uno::Sequence< OUString >() );
1288 0 : if ( aExtensions.getLength() )
1289 0 : aObj.SetExtension( aExtensions[0] );
1290 : }
1291 :
1292 0 : aRecommendedName = aObj.GetName( INetURLObject::DECODE_WITH_CHARSET );
1293 0 : }
1294 : }
1295 : }
1296 :
1297 0 : return aRecommendedName;
1298 : }
1299 :
1300 :
1301 :
1302 : // class SfxStoringHelper
1303 :
1304 :
1305 0 : SfxStoringHelper::SfxStoringHelper()
1306 : {
1307 0 : }
1308 :
1309 :
1310 0 : uno::Reference< container::XNameAccess > SfxStoringHelper::GetFilterConfiguration()
1311 : {
1312 0 : if ( !m_xFilterCFG.is() )
1313 : {
1314 0 : m_xFilterCFG = uno::Reference< container::XNameAccess >(
1315 0 : comphelper::getProcessServiceFactory()->createInstance("com.sun.star.document.FilterFactory"),
1316 0 : uno::UNO_QUERY );
1317 :
1318 0 : if ( !m_xFilterCFG.is() )
1319 0 : throw uno::RuntimeException();
1320 : }
1321 :
1322 0 : return m_xFilterCFG;
1323 : }
1324 :
1325 :
1326 0 : uno::Reference< container::XContainerQuery > SfxStoringHelper::GetFilterQuery()
1327 : {
1328 0 : if ( !m_xFilterQuery.is() )
1329 : {
1330 0 : m_xFilterQuery = uno::Reference< container::XContainerQuery >( GetFilterConfiguration(), uno::UNO_QUERY );
1331 0 : if ( !m_xFilterQuery.is() )
1332 0 : throw uno::RuntimeException();
1333 : }
1334 :
1335 0 : return m_xFilterQuery;
1336 : }
1337 :
1338 :
1339 0 : uno::Reference< ::com::sun::star::frame::XModuleManager2 > SfxStoringHelper::GetModuleManager()
1340 : {
1341 0 : if ( !m_xModuleManager.is() )
1342 : {
1343 0 : m_xModuleManager = frame::ModuleManager::create(
1344 0 : comphelper::getProcessComponentContext() );
1345 : }
1346 :
1347 0 : return m_xModuleManager;
1348 : }
1349 :
1350 :
1351 0 : bool SfxStoringHelper::GUIStoreModel( uno::Reference< frame::XModel > xModel,
1352 : const OUString& aSlotName,
1353 : uno::Sequence< beans::PropertyValue >& aArgsSequence,
1354 : bool bPreselectPassword,
1355 : const OUString& _aSuggestedName,
1356 : sal_uInt16 nDocumentSignatureState )
1357 : {
1358 0 : OUString aSuggestedName = _aSuggestedName;
1359 0 : ModelData_Impl aModelData( *this, xModel, aArgsSequence );
1360 :
1361 0 : bool bDialogUsed = false;
1362 :
1363 0 : INetURLObject aURL;
1364 :
1365 0 : bool bSetStandardName = false; // can be set only for SaveAs
1366 :
1367 : // parse the slot name
1368 0 : sal_Int8 nStoreMode = getStoreModeFromSlotName( aSlotName );
1369 0 : sal_Int8 nStatusSave = STATUS_NO_ACTION;
1370 :
1371 : ::comphelper::SequenceAsHashMap::const_iterator aSaveACopyIter =
1372 0 : aModelData.GetMediaDescr().find( ::rtl::OUString("SaveACopy") );
1373 0 : if ( aSaveACopyIter != aModelData.GetMediaDescr().end() )
1374 : {
1375 0 : bool bSaveACopy = false;
1376 0 : aSaveACopyIter->second >>= bSaveACopy;
1377 0 : if ( bSaveACopy )
1378 0 : nStoreMode = EXPORT_REQUESTED | SAVEACOPY_REQUESTED | WIDEEXPORT_REQUESTED;
1379 : }
1380 : // handle the special cases
1381 0 : if ( nStoreMode & SAVEAS_REQUESTED )
1382 : {
1383 : ::comphelper::SequenceAsHashMap::const_iterator aSaveToIter =
1384 0 : aModelData.GetMediaDescr().find( OUString("SaveTo") );
1385 0 : if ( aSaveToIter != aModelData.GetMediaDescr().end() )
1386 : {
1387 0 : bool bWideExport = false;
1388 0 : aSaveToIter->second >>= bWideExport;
1389 0 : if ( bWideExport )
1390 0 : nStoreMode = EXPORT_REQUESTED | WIDEEXPORT_REQUESTED;
1391 : }
1392 :
1393 : // if saving is not acceptable the warning must be shown even in case of SaveAs operation
1394 0 : if ( ( nStoreMode & SAVEAS_REQUESTED ) && aModelData.CheckSaveAcceptable( STATUS_SAVEAS ) == STATUS_NO_ACTION )
1395 : throw task::ErrorCodeIOException(
1396 : "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT",
1397 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_ABORT);
1398 : }
1399 0 : else if ( nStoreMode & SAVE_REQUESTED )
1400 : {
1401 : // if saving is not acceptable by the configuration the warning must be shown
1402 0 : nStatusSave = aModelData.CheckSaveAcceptable( STATUS_SAVE );
1403 :
1404 0 : if ( nStatusSave == STATUS_NO_ACTION )
1405 : throw task::ErrorCodeIOException(
1406 : "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT",
1407 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_ABORT);
1408 0 : else if ( nStatusSave == STATUS_SAVE )
1409 : {
1410 : // check whether it is possible to use save operation
1411 0 : nStatusSave = aModelData.CheckStateForSave();
1412 : }
1413 :
1414 0 : if ( nStatusSave == STATUS_NO_ACTION )
1415 : {
1416 : throw task::ErrorCodeIOException(
1417 : "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT",
1418 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_ABORT);
1419 : }
1420 0 : else if ( nStatusSave != STATUS_SAVE )
1421 : {
1422 : // this should be a usual SaveAs operation
1423 0 : nStoreMode = SAVEAS_REQUESTED;
1424 0 : if ( nStatusSave == STATUS_SAVEAS_STANDARDNAME )
1425 0 : bSetStandardName = true;
1426 : }
1427 : }
1428 :
1429 0 : if ( !( nStoreMode & EXPORT_REQUESTED ) )
1430 : {
1431 : // if it is no export, warn user that the signature will be removed
1432 0 : if ( SIGNATURESTATE_SIGNATURES_OK == nDocumentSignatureState
1433 0 : || SIGNATURESTATE_SIGNATURES_INVALID == nDocumentSignatureState
1434 0 : || SIGNATURESTATE_SIGNATURES_NOTVALIDATED == nDocumentSignatureState
1435 0 : || SIGNATURESTATE_SIGNATURES_PARTIAL_OK == nDocumentSignatureState)
1436 : {
1437 0 : if ( QueryBox( NULL, SfxResId( RID_XMLSEC_QUERY_LOSINGSIGNATURE ) ).Execute() != RET_YES )
1438 : {
1439 : // the user has decided not to store the document
1440 : throw task::ErrorCodeIOException(
1441 : "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_ABORT",
1442 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_ABORT);
1443 : }
1444 : }
1445 : }
1446 :
1447 0 : if ( nStoreMode & SAVE_REQUESTED && nStatusSave == STATUS_SAVE )
1448 : {
1449 : // Document properties can contain streams that should be freed before storing
1450 0 : aModelData.FreeDocumentProps();
1451 :
1452 0 : if ( aModelData.GetStorable2().is() )
1453 : {
1454 : try
1455 : {
1456 0 : aModelData.GetStorable2()->storeSelf( aModelData.GetMediaDescr().getAsConstPropertyValueList() );
1457 : }
1458 0 : catch (const lang::IllegalArgumentException& e)
1459 : {
1460 : SAL_WARN("sfx", "Ignoring parameters! "
1461 : "ModelData considers this illegal: " << e.Message);
1462 0 : aModelData.GetStorable()->store();
1463 : }
1464 : }
1465 : else
1466 : {
1467 : OSL_FAIL( "XStorable2 is not supported by the model!\n" );
1468 0 : aModelData.GetStorable()->store();
1469 : }
1470 :
1471 0 : return false;
1472 : }
1473 :
1474 : // preselect a filter for the storing process
1475 0 : uno::Sequence< beans::PropertyValue > aFilterProps = aModelData.GetPreselectedFilter_Impl( nStoreMode );
1476 :
1477 : DBG_ASSERT( aFilterProps.getLength(), "No filter for storing!\n" );
1478 0 : if ( !aFilterProps.getLength() )
1479 : throw task::ErrorCodeIOException(
1480 : "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_INVALIDPARAMETER",
1481 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_INVALIDPARAMETER);
1482 :
1483 0 : ::comphelper::SequenceAsHashMap aFilterPropsHM( aFilterProps );
1484 : OUString aFilterName = aFilterPropsHM.getUnpackedValueOrDefault(
1485 : OUString("Name"),
1486 0 : OUString() );
1487 :
1488 0 : const OUString sFilterNameString(aFilterNameString);
1489 :
1490 0 : OUString aFilterFromMediaDescr = aModelData.GetMediaDescr().getUnpackedValueOrDefault(
1491 : sFilterNameString,
1492 0 : OUString() );
1493 0 : OUString aOldFilterName = aModelData.GetDocProps().getUnpackedValueOrDefault(
1494 : sFilterNameString,
1495 0 : OUString() );
1496 :
1497 0 : bool bUseFilterOptions = false;
1498 0 : ::comphelper::SequenceAsHashMap::const_iterator aFileNameIter = aModelData.GetMediaDescr().find( OUString("URL") );
1499 :
1500 0 : const OUString sFilterOptionsString(aFilterOptionsString);
1501 0 : const OUString sFilterDataString(aFilterDataString);
1502 0 : const OUString sFilterFlagsString(aFilterFlagsString);
1503 :
1504 0 : if ( ( nStoreMode & EXPORT_REQUESTED ) && ( nStoreMode & PDFEXPORT_REQUESTED ) && !( nStoreMode & PDFDIRECTEXPORT_REQUESTED ) )
1505 : {
1506 : // this is PDF export, the filter options dialog should be shown before the export
1507 0 : aModelData.GetMediaDescr()[sFilterNameString] <<= aFilterName;
1508 0 : if ( aModelData.GetMediaDescr().find( sFilterFlagsString ) == aModelData.GetMediaDescr().end()
1509 0 : && aModelData.GetMediaDescr().find( sFilterOptionsString ) == aModelData.GetMediaDescr().end()
1510 0 : && aModelData.GetMediaDescr().find( sFilterDataString ) == aModelData.GetMediaDescr().end() )
1511 : {
1512 : // execute filter options dialog since no options are set in the media descriptor
1513 0 : if ( aModelData.ExecuteFilterDialog_Impl( aFilterName ) )
1514 0 : bDialogUsed = true;
1515 : }
1516 : }
1517 :
1518 0 : if ( aFileNameIter == aModelData.GetMediaDescr().end() )
1519 : {
1520 0 : sal_Int16 nDialog = SFX2_IMPL_DIALOG_CONFIG;
1521 : ::comphelper::SequenceAsHashMap::const_iterator aDlgIter =
1522 0 : aModelData.GetMediaDescr().find( OUString("UseSystemDialog") );
1523 0 : if ( aDlgIter != aModelData.GetMediaDescr().end() )
1524 : {
1525 0 : bool bUseSystemDialog = true;
1526 0 : if ( aDlgIter->second >>= bUseSystemDialog )
1527 : {
1528 0 : if ( bUseSystemDialog )
1529 0 : nDialog = SFX2_IMPL_DIALOG_SYSTEM;
1530 : else
1531 0 : nDialog = SFX2_IMPL_DIALOG_OOO;
1532 : }
1533 : }
1534 :
1535 : // The Dispatch supports parameter FolderName that overwrites SuggestedSaveAsDir
1536 0 : OUString aSuggestedDir = aModelData.GetMediaDescr().getUnpackedValueOrDefault("FolderName", OUString() );
1537 0 : if ( aSuggestedDir.isEmpty() )
1538 : {
1539 0 : aSuggestedDir = aModelData.GetMediaDescr().getUnpackedValueOrDefault("SuggestedSaveAsDir", OUString() );
1540 0 : if ( aSuggestedDir.isEmpty() )
1541 0 : aSuggestedDir = aModelData.GetDocProps().getUnpackedValueOrDefault("SuggestedSaveAsDir", OUString() );
1542 : }
1543 :
1544 0 : aSuggestedName = aModelData.GetMediaDescr().getUnpackedValueOrDefault("SuggestedSaveAsName", OUString() );
1545 0 : if ( aSuggestedName.isEmpty() )
1546 0 : aSuggestedName = aModelData.GetDocProps().getUnpackedValueOrDefault("SuggestedSaveAsName", OUString() );
1547 :
1548 0 : OUString sStandardDir;
1549 : ::comphelper::SequenceAsHashMap::const_iterator aStdDirIter =
1550 0 : aModelData.GetMediaDescr().find( OUString("StandardDir") );
1551 0 : if ( aStdDirIter != aModelData.GetMediaDescr().end() )
1552 0 : aStdDirIter->second >>= sStandardDir;
1553 :
1554 0 : ::com::sun::star::uno::Sequence< OUString > aBlackList;
1555 :
1556 : ::comphelper::SequenceAsHashMap::const_iterator aBlackListIter =
1557 0 : aModelData.GetMediaDescr().find( OUString("BlackList") );
1558 0 : if ( aBlackListIter != aModelData.GetMediaDescr().end() )
1559 0 : aBlackListIter->second >>= aBlackList;
1560 :
1561 0 : bool bExit = false;
1562 0 : while ( !bExit )
1563 : {
1564 : // 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
1565 0 : bUseFilterOptions = aModelData.OutputFileDialog( nStoreMode, aFilterProps, bSetStandardName, aSuggestedName, bPreselectPassword, aSuggestedDir, nDialog, sStandardDir, aBlackList );
1566 0 : if ( nStoreMode == SAVEAS_REQUESTED )
1567 : {
1568 : // in case of saving check filter for possible alien warning
1569 0 : OUString aSelFilterName = aModelData.GetMediaDescr().getUnpackedValueOrDefault(
1570 : sFilterNameString,
1571 0 : OUString() );
1572 0 : sal_Int8 nStatusFilterSave = aModelData.CheckFilter( aSelFilterName );
1573 0 : if ( nStatusFilterSave == STATUS_SAVEAS_STANDARDNAME )
1574 : {
1575 : // switch to best filter
1576 0 : bSetStandardName = true;
1577 : }
1578 0 : else if ( nStatusFilterSave == STATUS_SAVE )
1579 : {
1580 : // user confirmed alien filter or "good" filter is used
1581 0 : bExit = true;
1582 0 : }
1583 : }
1584 : else
1585 0 : bExit = true;
1586 : }
1587 :
1588 0 : bDialogUsed = true;
1589 0 : aFileNameIter = aModelData.GetMediaDescr().find( OUString("URL") );
1590 : }
1591 : else
1592 : {
1593 : // the target file name is provided so check if new filter options
1594 : // are provided or old options can be used
1595 0 : if ( aFilterFromMediaDescr.equals( aOldFilterName ) )
1596 : {
1597 : ::comphelper::SequenceAsHashMap::const_iterator aIter =
1598 0 : aModelData.GetDocProps().find( sFilterOptionsString );
1599 0 : if ( aIter != aModelData.GetDocProps().end()
1600 0 : && aModelData.GetMediaDescr().find( sFilterOptionsString ) == aModelData.GetMediaDescr().end() )
1601 0 : aModelData.GetMediaDescr()[aIter->first] = aIter->second;
1602 :
1603 0 : aIter = aModelData.GetDocProps().find( sFilterDataString );
1604 0 : if ( aIter != aModelData.GetDocProps().end()
1605 0 : && aModelData.GetMediaDescr().find( sFilterDataString ) == aModelData.GetMediaDescr().end() )
1606 0 : aModelData.GetMediaDescr()[aIter->first] = aIter->second;
1607 : }
1608 : }
1609 :
1610 0 : if ( aFileNameIter != aModelData.GetMediaDescr().end() )
1611 : {
1612 0 : OUString aFileName;
1613 0 : aFileNameIter->second >>= aFileName;
1614 0 : aURL.SetURL( aFileName );
1615 : DBG_ASSERT( aURL.GetProtocol() != INET_PROT_NOT_VALID, "Illegal URL!" );
1616 :
1617 : ::comphelper::SequenceAsHashMap::const_iterator aIter =
1618 0 : aModelData.GetMediaDescr().find( sFilterNameString );
1619 :
1620 0 : if ( aIter != aModelData.GetMediaDescr().end() )
1621 0 : aIter->second >>= aFilterName;
1622 : else
1623 0 : aModelData.GetMediaDescr()[sFilterNameString] <<= aFilterName;
1624 :
1625 0 : DBG_ASSERT( !aFilterName.isEmpty(), "Illegal filter!" );
1626 : }
1627 : else
1628 : {
1629 : DBG_ASSERT( false, "This code must be unreachable!\n" );
1630 : throw task::ErrorCodeIOException(
1631 : "SfxStoringHelper::GUIStoreModel: ERRCODE_IO_INVALIDPARAMETER",
1632 0 : uno::Reference< uno::XInterface >(), ERRCODE_IO_INVALIDPARAMETER);
1633 : }
1634 :
1635 : ::comphelper::SequenceAsHashMap::const_iterator aIter =
1636 0 : aModelData.GetMediaDescr().find( OUString("FilterFlags") );
1637 0 : bool bFilterFlagsSet = ( aIter != aModelData.GetMediaDescr().end() );
1638 :
1639 0 : if( !( nStoreMode & PDFEXPORT_REQUESTED ) && !bFilterFlagsSet
1640 0 : && ( ( nStoreMode & EXPORT_REQUESTED ) || bUseFilterOptions ) )
1641 : {
1642 : // execute filter options dialog
1643 0 : if ( aModelData.ExecuteFilterDialog_Impl( aFilterName ) )
1644 0 : bDialogUsed = true;
1645 : }
1646 :
1647 : // so the arguments will not change any more and can be stored to the main location
1648 0 : aArgsSequence = aModelData.GetMediaDescr().getAsConstPropertyValueList();
1649 :
1650 : // store the document and handle it's docinfo
1651 0 : SvtSaveOptions aOptions;
1652 :
1653 0 : DocumentSettingsGuard aSettingsGuard( aModelData.GetModel(), aModelData.IsRecommendReadOnly(), nStoreMode & EXPORT_REQUESTED );
1654 :
1655 : OSL_ENSURE( aModelData.GetMediaDescr().find( OUString( "Password" ) ) == aModelData.GetMediaDescr().end(), "The Password property of MediaDescriptor should not be used here!" );
1656 0 : if ( aOptions.IsDocInfoSave()
1657 0 : && ( !aModelData.GetStorable()->hasLocation()
1658 0 : || INetURLObject( aModelData.GetStorable()->getLocation() ) != aURL ) )
1659 : {
1660 : // this is defenitly not a Save operation
1661 : // so the document info can be updated
1662 :
1663 : // on export document info must be preserved
1664 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1665 0 : aModelData.GetModel(), uno::UNO_QUERY_THROW);
1666 : uno::Reference<util::XCloneable> xCloneable(
1667 0 : xDPS->getDocumentProperties(), uno::UNO_QUERY_THROW);
1668 : uno::Reference<document::XDocumentProperties> xOldDocProps(
1669 0 : xCloneable->createClone(), uno::UNO_QUERY_THROW);
1670 :
1671 : // use dispatch API to show document info dialog
1672 0 : if ( aModelData.ShowDocumentInfoDialog() )
1673 0 : bDialogUsed = true;
1674 : else
1675 : {
1676 : OSL_FAIL( "Can't execute document info dialog!\n" );
1677 : }
1678 :
1679 : try {
1680 : // Document properties can contain streams that should be freed before storing
1681 0 : aModelData.FreeDocumentProps();
1682 0 : if ( nStoreMode & EXPORT_REQUESTED )
1683 0 : aModelData.GetStorable()->storeToURL( aURL.GetMainURL( INetURLObject::NO_DECODE ), aArgsSequence );
1684 : else
1685 0 : aModelData.GetStorable()->storeAsURL( aURL.GetMainURL( INetURLObject::NO_DECODE ), aArgsSequence );
1686 : }
1687 0 : catch( const uno::Exception& )
1688 : {
1689 0 : if ( nStoreMode & EXPORT_REQUESTED )
1690 : {
1691 0 : SetDocInfoState(aModelData.GetModel(), xOldDocProps, true);
1692 : }
1693 0 : throw;
1694 : }
1695 :
1696 0 : if ( nStoreMode & EXPORT_REQUESTED )
1697 : {
1698 0 : SetDocInfoState(aModelData.GetModel(), xOldDocProps, true);
1699 0 : }
1700 : }
1701 : else
1702 : {
1703 : // Document properties can contain streams that should be freed before storing
1704 0 : aModelData.FreeDocumentProps();
1705 :
1706 : // this is actually a save operation with different parameters
1707 : // so storeTo or storeAs without DocInfo operations are used
1708 0 : if ( nStoreMode & EXPORT_REQUESTED )
1709 0 : aModelData.GetStorable()->storeToURL( aURL.GetMainURL( INetURLObject::NO_DECODE ), aArgsSequence );
1710 : else
1711 0 : aModelData.GetStorable()->storeAsURL( aURL.GetMainURL( INetURLObject::NO_DECODE ), aArgsSequence );
1712 : }
1713 :
1714 : // Launch PDF viewer
1715 0 : if ( nStoreMode & PDFEXPORT_REQUESTED ) {
1716 0 : FilterConfigItem aItem( "Office.Common/Filter/PDF/Export/" );
1717 0 : bool aViewPDF = aItem.ReadBool( "ViewPDFAfterExport", false );
1718 :
1719 0 : if ( aViewPDF ) {
1720 0 : uno::Reference<XSystemShellExecute> xSystemShellExecute(SystemShellExecute::create( ::comphelper::getProcessComponentContext() ) );
1721 0 : xSystemShellExecute->execute( aURL.GetMainURL( INetURLObject::NO_DECODE ), "", SystemShellExecuteFlags::URIS_ONLY );
1722 0 : }
1723 : }
1724 :
1725 0 : return bDialogUsed;
1726 : }
1727 :
1728 :
1729 : // static
1730 0 : bool SfxStoringHelper::CheckFilterOptionsAppearence(
1731 : const uno::Reference< container::XNameAccess >& xFilterCFG,
1732 : const OUString& aFilterName )
1733 : {
1734 0 : bool bUseFilterOptions = false;
1735 :
1736 : DBG_ASSERT( xFilterCFG.is(), "No filter configuration!\n" );
1737 0 : if( xFilterCFG.is() )
1738 : {
1739 : try {
1740 0 : uno::Sequence < beans::PropertyValue > aProps;
1741 0 : uno::Any aAny = xFilterCFG->getByName( aFilterName );
1742 0 : if ( aAny >>= aProps )
1743 : {
1744 0 : ::comphelper::SequenceAsHashMap aPropsHM( aProps );
1745 : OUString aServiceName = aPropsHM.getUnpackedValueOrDefault(
1746 : OUString("UIComponent"),
1747 0 : OUString() );
1748 0 : if( !aServiceName.isEmpty() )
1749 0 : bUseFilterOptions = true;
1750 0 : }
1751 : }
1752 0 : catch( const uno::Exception& )
1753 : {
1754 : }
1755 : }
1756 :
1757 0 : return bUseFilterOptions;
1758 : }
1759 :
1760 :
1761 : // static
1762 0 : void SfxStoringHelper::SetDocInfoState(
1763 : const uno::Reference< frame::XModel >& xModel,
1764 : const uno::Reference< document::XDocumentProperties>& i_xOldDocProps,
1765 : bool bNoModify )
1766 : {
1767 : uno::Reference<document::XDocumentPropertiesSupplier> const
1768 0 : xModelDocPropsSupplier(xModel, uno::UNO_QUERY_THROW);
1769 : uno::Reference<document::XDocumentProperties> const xDocPropsToFill =
1770 0 : xModelDocPropsSupplier->getDocumentProperties();
1771 : uno::Reference< beans::XPropertySet > const xPropSet(
1772 0 : i_xOldDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
1773 :
1774 0 : uno::Reference< util::XModifiable > xModifiable( xModel, uno::UNO_QUERY );
1775 0 : if ( bNoModify && !xModifiable.is() )
1776 0 : throw uno::RuntimeException();
1777 :
1778 0 : bool bIsModified = bNoModify && xModifiable->isModified();
1779 :
1780 : try
1781 : {
1782 : uno::Reference< beans::XPropertySet > const xSet(
1783 0 : xDocPropsToFill->getUserDefinedProperties(), uno::UNO_QUERY);
1784 0 : uno::Reference< beans::XPropertyContainer > xContainer( xSet, uno::UNO_QUERY );
1785 0 : uno::Reference< beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo();
1786 0 : uno::Sequence< beans::Property > lProps = xSetInfo->getProperties();
1787 0 : const beans::Property* pProps = lProps.getConstArray();
1788 0 : sal_Int32 c = lProps.getLength();
1789 0 : sal_Int32 i = 0;
1790 0 : for (i=0; i<c; ++i)
1791 : {
1792 0 : uno::Any aValue = xPropSet->getPropertyValue( pProps[i].Name );
1793 0 : if ( pProps[i].Attributes & ::com::sun::star::beans::PropertyAttribute::REMOVABLE )
1794 : {
1795 : try
1796 : {
1797 : // QUESTION: DefaultValue?!
1798 0 : xContainer->addProperty( pProps[i].Name, pProps[i].Attributes, aValue );
1799 : }
1800 0 : catch (beans::PropertyExistException const&) {}
1801 : try
1802 : {
1803 : // it is possible that the propertysets from XML and binary files differ; we shouldn't break then
1804 0 : xSet->setPropertyValue( pProps[i].Name, aValue );
1805 : }
1806 0 : catch ( const uno::Exception& ) {}
1807 : }
1808 0 : }
1809 :
1810 : // sigh... have to set these manually i'm afraid... wonder why
1811 : // SfxObjectShell doesn't handle this internally, should be easier
1812 0 : xDocPropsToFill->setAuthor(i_xOldDocProps->getAuthor());
1813 0 : xDocPropsToFill->setGenerator(i_xOldDocProps->getGenerator());
1814 0 : xDocPropsToFill->setCreationDate(i_xOldDocProps->getCreationDate());
1815 0 : xDocPropsToFill->setTitle(i_xOldDocProps->getTitle());
1816 0 : xDocPropsToFill->setSubject(i_xOldDocProps->getSubject());
1817 0 : xDocPropsToFill->setDescription(i_xOldDocProps->getDescription());
1818 0 : xDocPropsToFill->setKeywords(i_xOldDocProps->getKeywords());
1819 0 : xDocPropsToFill->setModifiedBy(i_xOldDocProps->getModifiedBy());
1820 0 : xDocPropsToFill->setModificationDate(i_xOldDocProps->getModificationDate());
1821 0 : xDocPropsToFill->setPrintedBy(i_xOldDocProps->getPrintedBy());
1822 0 : xDocPropsToFill->setPrintDate(i_xOldDocProps->getPrintDate());
1823 0 : xDocPropsToFill->setAutoloadURL(i_xOldDocProps->getAutoloadURL());
1824 0 : xDocPropsToFill->setAutoloadSecs(i_xOldDocProps->getAutoloadSecs());
1825 0 : xDocPropsToFill->setDefaultTarget(i_xOldDocProps->getDefaultTarget());
1826 0 : xDocPropsToFill->setEditingCycles(i_xOldDocProps->getEditingCycles());
1827 0 : xDocPropsToFill->setEditingDuration(i_xOldDocProps->getEditingDuration());
1828 : // other attributes e.g. DocumentStatistics are not editable from dialog
1829 : }
1830 0 : catch (const uno::Exception& e)
1831 : {
1832 : SAL_INFO("sfx.doc", "SetDocInfoState: caught exception: " << e.Message);
1833 : }
1834 :
1835 : // set the modified flag back if required
1836 0 : if ( ((bNoModify && bIsModified) ? 1 : 0) != xModifiable->isModified() )
1837 0 : xModifiable->setModified( bIsModified );
1838 0 : }
1839 :
1840 :
1841 : // static
1842 0 : bool SfxStoringHelper::WarnUnacceptableFormat( const uno::Reference< frame::XModel >& xModel,
1843 : const OUString& aOldUIName,
1844 : const OUString& /*aDefUIName*/,
1845 : bool /*bCanProceedFurther*/ )
1846 : {
1847 0 : if ( !SvtSaveOptions().IsWarnAlienFormat() )
1848 0 : return true;
1849 :
1850 0 : Window* pWin = SfxStoringHelper::GetModelWindow( xModel );
1851 0 : SfxAlienWarningDialog aDlg( pWin, aOldUIName );
1852 :
1853 0 : return aDlg.Execute() == RET_OK;
1854 : }
1855 :
1856 0 : Window* SfxStoringHelper::GetModelWindow( const uno::Reference< frame::XModel >& xModel )
1857 : {
1858 0 : Window* pWin = 0;
1859 : try {
1860 0 : if ( xModel.is() )
1861 : {
1862 0 : uno::Reference< frame::XController > xController = xModel->getCurrentController();
1863 0 : if ( xController.is() )
1864 : {
1865 0 : uno::Reference< frame::XFrame > xFrame = xController->getFrame();
1866 0 : if ( xFrame.is() )
1867 : {
1868 0 : uno::Reference< awt::XWindow > xWindow = xFrame->getContainerWindow();
1869 0 : if ( xWindow.is() )
1870 : {
1871 0 : VCLXWindow* pVCLWindow = VCLXWindow::GetImplementation( xWindow );
1872 0 : if ( pVCLWindow )
1873 0 : pWin = pVCLWindow->GetWindow();
1874 0 : }
1875 0 : }
1876 0 : }
1877 : }
1878 : }
1879 0 : catch ( const uno::Exception& )
1880 : {
1881 : }
1882 :
1883 0 : return pWin;
1884 3 : }
1885 :
1886 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|