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