xref: /trunk/main/uui/source/iahndl-filter.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "com/sun/star/beans/XPropertyAccess.hpp"
25 #include "com/sun/star/container/XContainerQuery.hpp"
26 #include "com/sun/star/container/XNameContainer.hpp"
27 #include "com/sun/star/document/AmbigousFilterRequest.hpp"
28 #include "com/sun/star/document/FilterOptionsRequest.hpp"
29 #include "com/sun/star/document/NoSuchFilterRequest.hpp"
30 #include "com/sun/star/document/XImporter.hpp"
31 #include "com/sun/star/document/XInteractionFilterOptions.hpp"
32 #include "com/sun/star/document/XInteractionFilterSelect.hpp"
33 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
34 #include "com/sun/star/task/XInteractionAbort.hpp"
35 #include "com/sun/star/task/XInteractionRequest.hpp"
36 #include "com/sun/star/ui/dialogs/XExecutableDialog.hpp"
37 
38 #include "vos/mutex.hxx"
39 #include "comphelper/sequenceashashmap.hxx"
40 #include "vcl/svapp.hxx"
41 
42 #include "getcontinuations.hxx"
43 #include "fltdlg.hxx"
44 
45 #include "iahndl.hxx"
46 
47 using namespace com::sun::star;
48 
49 namespace {
50 
51 void
executeFilterDialog(Window * pParent,rtl::OUString const & rURL,uui::FilterNameList const & rFilters,rtl::OUString & rFilter)52 executeFilterDialog(
53     Window                    * pParent ,
54     rtl::OUString       const & rURL    ,
55     uui::FilterNameList const & rFilters,
56     rtl::OUString             & rFilter )
57 {
58     try
59     {
60         vos::OGuard aGuard(Application::GetSolarMutex());
61 
62         std::auto_ptr< ResMgr > xManager(
63             ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(uui)));
64 
65         std::auto_ptr< uui::FilterDialog > xDialog(
66             new uui::FilterDialog(pParent, xManager.get()));
67 
68         xDialog->SetURL(rURL);
69         xDialog->ChangeFilters(&rFilters);
70 
71         uui::FilterNameListPtr pSelected = rFilters.end();
72         if( xDialog->AskForFilter( pSelected ) )
73         {
74             rFilter = pSelected->sInternal;
75         }
76     }
77     catch (std::bad_alloc const &)
78     {
79         throw uno::RuntimeException(
80             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("out of memory")),
81             uno::Reference< uno::XInterface >());
82     }
83 }
84 
85 void
handleNoSuchFilterRequest_(Window * pParent,uno::Reference<lang::XMultiServiceFactory> const & xServiceFactory,document::NoSuchFilterRequest const & rRequest,uno::Sequence<uno::Reference<task::XInteractionContinuation>> const & rContinuations)86 handleNoSuchFilterRequest_(
87     Window * pParent,
88     uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory,
89     document::NoSuchFilterRequest const & rRequest,
90     uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
91             rContinuations )
92 {
93     uno::Reference< task::XInteractionAbort > xAbort;
94     uno::Reference< document::XInteractionFilterSelect > xFilterTransport;
95     getContinuations(rContinuations, &xAbort, &xFilterTransport);
96 
97     // check necessary resources - if they don't exist - abort or
98     // break this operation
99     if (!xAbort.is())
100         return;
101 
102     if (!xFilterTransport.is())
103     {
104         xAbort->select();
105         return;
106     }
107 
108     uno::Reference< container::XContainerQuery > xFilterContainer;
109     try
110     {
111         xFilterContainer.set( xServiceFactory->createInstance(
112                                   ::rtl::OUString::createFromAscii(
113                                       "com.sun.star.document.FilterFactory") ),
114                               uno::UNO_QUERY );
115     }
116     catch ( uno::Exception const & )
117     {
118     }
119 
120     if (!xFilterContainer.is())
121     {
122         xAbort->select();
123         return;
124     }
125 
126     uui::FilterNameList lNames;
127 
128     // Note: We look for all filters here which match the following criteria:
129     //          - they are import filters as minimum (of course they can
130     //            support export too)
131     //          - we don't show any filter which are flaged as "don't show it
132     //            at the UI" or "they are not installed"
133     //          - we ignore filters, which have not set any valid
134     //            DocumentService (e.g. our pure graphic filters)
135     //          - we show it sorted by her UIName's
136     //          - We don't use the order flag or prefer default filters.
137     //            (Because this list shows all filters and the user should
138     //            find his filter vry easy by his UIName ...)
139     //          - We use "_query_all" here ... but we filter graphic filters
140     //            out by using DocumentService property later!
141     uno::Reference< container::XEnumeration > xFilters
142         = xFilterContainer->createSubSetEnumerationByQuery(
143             ::rtl::OUString::createFromAscii(
144                 "_query_all:sort_prop=uiname:iflags=1:eflags=143360"));
145     while (xFilters->hasMoreElements())
146     {
147         try
148         {
149             ::comphelper::SequenceAsHashMap lProps(xFilters->nextElement());
150             uui::FilterNamePair             aPair;
151 
152             aPair.sInternal = lProps.getUnpackedValueOrDefault(
153                 rtl::OUString::createFromAscii("Name"), ::rtl::OUString());
154             aPair.sUI       = lProps.getUnpackedValueOrDefault(
155                  rtl::OUString::createFromAscii("UIName"), ::rtl::OUString());
156             if ( (!aPair.sInternal.Len()) || (!aPair.sUI.Len() ) )
157             {
158                continue;
159             }
160             lNames.push_back( aPair );
161         }
162         catch(const uno::RuntimeException&)
163         {
164             throw;
165         }
166         catch(const uno::Exception&)
167         {
168             continue;
169         }
170     }
171 
172     // no list available for showing
173     // -> abort operation
174     if (lNames.size()<1)
175     {
176         xAbort->select();
177         return;
178     }
179 
180     // let the user select the right filter
181     rtl::OUString sSelectedFilter;
182     executeFilterDialog( pParent,
183                          rRequest.URL,
184                          lNames,
185                          sSelectedFilter );
186 
187     // If he doesn't select anyone
188     // -> abort operation
189     if (sSelectedFilter.getLength()<1)
190     {
191         xAbort->select();
192         return;
193     }
194 
195     // otherwise set it for return
196     xFilterTransport->setFilter( sSelectedFilter );
197     xFilterTransport->select();
198 }
199 
200 void
handleAmbigousFilterRequest_(Window * pParent,uno::Reference<lang::XMultiServiceFactory> const & xServiceFactory,document::AmbigousFilterRequest const & rRequest,uno::Sequence<uno::Reference<task::XInteractionContinuation>> const & rContinuations)201 handleAmbigousFilterRequest_(
202     Window * pParent,
203     uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory,
204     document::AmbigousFilterRequest const & rRequest,
205     uno::Sequence<
206         uno::Reference<
207             task::XInteractionContinuation > > const & rContinuations)
208 {
209     uno::Reference< task::XInteractionAbort > xAbort;
210     uno::Reference< document::XInteractionFilterSelect > xFilterTransport;
211     getContinuations(rContinuations, &xAbort, &xFilterTransport);
212 
213     uui::FilterNameList lNames;
214 
215     uno::Reference< container::XNameContainer > xFilterContainer;
216     try
217     {
218         xFilterContainer.set( xServiceFactory->createInstance(
219             ::rtl::OUString::createFromAscii(
220                 "com.sun.star.document.FilterFactory") ),
221             uno::UNO_QUERY );
222     }
223     catch ( uno::Exception & )
224     {
225     }
226 
227     if( xFilterContainer.is() )
228     {
229         uno::Any                              aPackedSet    ;
230         uno::Sequence< beans::PropertyValue > lProps        ;
231         sal_Int32                             nStep         ;
232         uui::FilterNamePair                   aPair         ;
233 
234         try
235         {
236             aPackedSet = xFilterContainer->getByName( rRequest.SelectedFilter );
237         }
238         catch(const container::NoSuchElementException&)
239         {
240             aPackedSet.clear();
241         }
242         aPackedSet >>= lProps;
243         for( nStep=0; nStep<lProps.getLength(); ++nStep )
244         {
245             if( lProps[nStep].Name.compareToAscii("UIName") == 0 )
246             {
247                 ::rtl::OUString sTemp;
248                 lProps[nStep].Value >>= sTemp;
249                 aPair.sUI       = sTemp;
250                 aPair.sInternal = rRequest.SelectedFilter;
251                 lNames.push_back( aPair );
252                 break;
253             }
254         }
255 
256         try
257         {
258             aPackedSet = xFilterContainer->getByName( rRequest.DetectedFilter );
259         }
260         catch(const container::NoSuchElementException&)
261         {
262             aPackedSet.clear();
263         }
264         aPackedSet >>= lProps;
265         for( nStep=0; nStep<lProps.getLength(); ++nStep )
266         {
267             if( lProps[nStep].Name.compareToAscii("UIName") == 0 )
268             {
269                 ::rtl::OUString sTemp;
270                 lProps[nStep].Value >>= sTemp;
271                 aPair.sUI       = sTemp;
272                 aPair.sInternal = rRequest.DetectedFilter;
273                 lNames.push_back( aPair );
274                 break;
275             }
276         }
277     }
278 
279     if( xAbort.is() && xFilterTransport.is() )
280     {
281         if( lNames.size() < 1 )
282         {
283             xAbort->select();
284         }
285         else
286         {
287             rtl::OUString sFilter;
288             executeFilterDialog( pParent,
289                                  rRequest.URL,
290                                  lNames,
291                                  sFilter );
292 
293             if( sFilter.getLength() > 0 )
294             {
295                 xFilterTransport->setFilter( sFilter );
296                 xFilterTransport->select();
297             }
298             else
299                 xAbort->select();
300         }
301     }
302 }
303 
304 void
handleFilterOptionsRequest_(uno::Reference<lang::XMultiServiceFactory> const & xServiceFactory,document::FilterOptionsRequest const & rRequest,uno::Sequence<uno::Reference<task::XInteractionContinuation>> const & rContinuations)305 handleFilterOptionsRequest_(
306     uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory,
307     document::FilterOptionsRequest const & rRequest,
308     uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
309         rContinuations)
310 {
311     uno::Reference< task::XInteractionAbort > xAbort;
312     uno::Reference< document::XInteractionFilterOptions > xFilterOptions;
313     getContinuations(rContinuations, &xAbort, &xFilterOptions);
314 
315     uno::Reference< container::XNameAccess > xFilterCFG;
316     try
317     {
318         xFilterCFG.set( xServiceFactory->createInstance(
319                             ::rtl::OUString::createFromAscii(
320                                 "com.sun.star.document.FilterFactory" ) ),
321                         uno::UNO_QUERY );
322     }
323     catch ( uno::Exception const & )
324     {
325     }
326 
327     if( xFilterCFG.is() && rRequest.rProperties.getLength() )
328     {
329         try
330         {
331             ::rtl::OUString aFilterName;
332             sal_Int32 nPropCount = rRequest.rProperties.getLength();
333             for( sal_Int32 ind = 0; ind < nPropCount; ++ind )
334             {
335                 rtl::OUString tmp = rRequest.rProperties[ind].Name;
336                 if( rRequest.rProperties[ind].Name.equals(
337                         ::rtl::OUString::createFromAscii("FilterName")) )
338                 {
339                     rRequest.rProperties[ind].Value >>= aFilterName;
340                     break;
341                 }
342             }
343 
344             uno::Sequence < beans::PropertyValue > aProps;
345             if ( xFilterCFG->getByName( aFilterName ) >>= aProps )
346             {
347                 sal_Int32 nPropertyCount = aProps.getLength();
348                 for( sal_Int32 nProperty=0;
349                      nProperty < nPropertyCount;
350                      ++nProperty )
351                     if( aProps[nProperty].Name.equals(
352                             ::rtl::OUString::createFromAscii("UIComponent")) )
353                     {
354                         ::rtl::OUString aServiceName;
355                         aProps[nProperty].Value >>= aServiceName;
356                         if( aServiceName.getLength() )
357                         {
358                             uno::Reference<
359                                 ui::dialogs::XExecutableDialog > xFilterDialog(
360                                     xServiceFactory->createInstance(
361                                         aServiceName ),
362                                     uno::UNO_QUERY );
363                             uno::Reference< beans::XPropertyAccess >
364                                 xFilterProperties( xFilterDialog,
365                                                    uno::UNO_QUERY );
366 
367                             if( xFilterDialog.is() && xFilterProperties.is() )
368                             {
369                                 uno::Reference<
370                                     document::XImporter > xImporter(
371                                         xFilterDialog, uno::UNO_QUERY );
372                                 if( xImporter.is() )
373                                     xImporter->setTargetDocument(
374                                         uno::Reference< lang::XComponent >(
375                                             rRequest.rModel, uno::UNO_QUERY ) );
376 
377                                 xFilterProperties->setPropertyValues(
378                                     rRequest.rProperties );
379 
380                                 if( xFilterDialog->execute() )
381                                 {
382                                     xFilterOptions->setFilterOptions(
383                                         xFilterProperties->getPropertyValues() );
384                                     xFilterOptions->select();
385                                     return;
386                                 }
387                             }
388                         }
389                         break;
390                     }
391             }
392         }
393         catch( container::NoSuchElementException& )
394         {
395             // the filter name is unknown
396         }
397         catch( uno::Exception& )
398         {
399         }
400     }
401 
402     xAbort->select();
403 }
404 
405 } // namespace
406 
407 bool
handleNoSuchFilterRequest(uno::Reference<task::XInteractionRequest> const & rRequest)408 UUIInteractionHelper::handleNoSuchFilterRequest(
409     uno::Reference< task::XInteractionRequest > const & rRequest)
410 {
411     uno::Any aAnyRequest(rRequest->getRequest());
412 
413     document::NoSuchFilterRequest aNoSuchFilterRequest;
414     if (aAnyRequest >>= aNoSuchFilterRequest)
415     {
416         handleNoSuchFilterRequest_(getParentProperty(),
417                                    m_xServiceFactory,
418                                    aNoSuchFilterRequest,
419                                    rRequest->getContinuations());
420         return true;
421     }
422     return false;
423 }
424 
425 bool
handleAmbigousFilterRequest(uno::Reference<task::XInteractionRequest> const & rRequest)426 UUIInteractionHelper::handleAmbigousFilterRequest(
427     uno::Reference< task::XInteractionRequest > const & rRequest)
428 {
429     uno::Any aAnyRequest(rRequest->getRequest());
430 
431     document::AmbigousFilterRequest aAmbigousFilterRequest;
432     if (aAnyRequest >>= aAmbigousFilterRequest)
433     {
434         handleAmbigousFilterRequest_(getParentProperty(),
435                                      m_xServiceFactory,
436                                      aAmbigousFilterRequest,
437                                      rRequest->getContinuations());
438         return true;
439     }
440     return false;
441 }
442 
443 bool
handleFilterOptionsRequest(uno::Reference<task::XInteractionRequest> const & rRequest)444 UUIInteractionHelper::handleFilterOptionsRequest(
445     uno::Reference< task::XInteractionRequest > const & rRequest)
446 {
447     uno::Any aAnyRequest(rRequest->getRequest());
448 
449     document::FilterOptionsRequest aFilterOptionsRequest;
450     if (aAnyRequest >>= aFilterOptionsRequest)
451     {
452         handleFilterOptionsRequest_(m_xServiceFactory,
453                                     aFilterOptionsRequest,
454                                     rRequest->getContinuations());
455         return true;
456     }
457     return false;
458 }
459