LCOV - code coverage report
Current view: top level - sfx2/source/dialog - filtergrouping.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 409 0.0 %
Date: 2012-08-25 Functions: 0 59 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 670 0.0 %

           Branch data     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 "filtergrouping.hxx"
      21                 :            : #include <sfx2/fcontnr.hxx>
      22                 :            : #include <sfx2/filedlghelper.hxx>
      23                 :            : #include <sfx2/sfx.hrc>
      24                 :            : #include <sfx2/docfac.hxx>
      25                 :            : #include "sfx2/sfxresid.hxx"
      26                 :            : #include <osl/thread.h>
      27                 :            : #include <rtl/oustringostreaminserter.hxx>
      28                 :            : #include <rtl/strbuf.hxx>
      29                 :            : #include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp>
      30                 :            : #include <com/sun/star/beans/StringPair.hpp>
      31                 :            : #include <com/sun/star/uno/Sequence.hxx>
      32                 :            : #include <unotools/confignode.hxx>
      33                 :            : #include <comphelper/processfactory.hxx>
      34                 :            : #include <comphelper/sequenceashashmap.hxx>
      35                 :            : #include <comphelper/string.hxx>
      36                 :            : #include <tools/diagnose_ex.h>
      37                 :            : 
      38                 :            : #include <list>
      39                 :            : #include <vector>
      40                 :            : #include <map>
      41                 :            : #include <algorithm>
      42                 :            : 
      43                 :            : //........................................................................
      44                 :            : namespace sfx2
      45                 :            : {
      46                 :            : //........................................................................
      47                 :            : 
      48                 :            :     using namespace ::com::sun::star::uno;
      49                 :            :     using namespace ::com::sun::star::ui::dialogs;
      50                 :            :     using namespace ::com::sun::star::lang;
      51                 :            :     using namespace ::com::sun::star::beans;
      52                 :            :     using namespace ::utl;
      53                 :            : 
      54                 :            :     //====================================================================
      55                 :            :     /**
      56                 :            : 
      57                 :            :     Some general words about what's going on here ....
      58                 :            : 
      59                 :            :     <p>In our file open dialog, usually we display every filter we know. That's how it was before: every filter
      60                 :            :     lead to an own line in the filter list box, e.g. "StarWriter 5.0 Dokument" or "Microsoft Word 97".</p>
      61                 :            : 
      62                 :            :     <p>But then the PM came. And everything changed ....</p>
      63                 :            : 
      64                 :            :     <p>A basic idea are groups: Why simply listing all the single filters? Couldn't we draw nice separators
      65                 :            :     between the filters which logically belong together? I.e. all the filters which open a document in StarWriter:
      66                 :            :     couldn't we separate them from all the filters which open the document in StarCalc?<br/>
      67                 :            :     So spoke the PM, and engineering obeyed.</p>
      68                 :            : 
      69                 :            :     <p>So we have groups. They're just a visual aspect: All the filters of a group are presented together, separated
      70                 :            :     by a line from other groups.</p>
      71                 :            : 
      72                 :            :     <p>Let's be honest: How the concrete implementation of the file picker service separates the different groups
      73                 :            :     is a matter of this implementation. We only do this grouping and suggest it to the FilePicker service ...</p>
      74                 :            : 
      75                 :            :     <p>Now for the second concept:<br/>
      76                 :            :     Thinking about it (and that's what the PM did), both "StarWriter 5.0 Dokument" and "Microsoft Word 97"
      77                 :            :     describe a text document. It's a text. It's of no interest for the user that one of the texts was saved in
      78                 :            :     MS' format, and one in our own format.<br/>
      79                 :            :     So in a first step, we want to have a filter entry "Text documents". This would cover both above-mentioned
      80                 :            :     filters, as well as any other filters for documents which are texts.</p>
      81                 :            : 
      82                 :            :     <p>Such an entry as "Text documents" is - within the scope of this file - called "class" or "filter class".</p>
      83                 :            : 
      84                 :            :     <p>In the file-open-dialog, such a class looks like an ordinary filter: it's simply a name in the filter
      85                 :            :     listbox. Selecting means that all the files matching one of the "sub-filters" are displayed (in the example above,
      86                 :            :     this would be "*.sdw", "*.doc" and so on).</p>
      87                 :            : 
      88                 :            :     <p>Now there are two types of filter classes: global ones and local ones. "Text documents" is a global class. As
      89                 :            :     well as "Spreadsheets". Or "Web pages".<br/>
      90                 :            :     Let's have a look at a local class: The filters "MS Word 95" and "MS WinWord 6.0" together form the class
      91                 :            :     "Microsoft Word 6.0 / 95" (don't ask for the reasons. At least not me. Ask the PM). There are a lot of such
      92                 :            :     local classes ...</p>
      93                 :            : 
      94                 :            :     <p>The difference between global and local classes is as follows: Global classes are presented in an own group.
      95                 :            :     There is one dedicated group at the top of the list, containing all the global groups - no local groups and no
      96                 :            :     single filters.</p>
      97                 :            : 
      98                 :            :     <p>Ehm - it was a lie. Not really at the top. Before this group, there is this single "All files" entry. It forms
      99                 :            :     it's own group. But this is uninteresting here.</p>
     100                 :            : 
     101                 :            :     <p>Local classes must consist of filters which - without the classification - would all belong to the same group.
     102                 :            :     Then, they're combined to one entry (in the example above: "Microsoft Word 6.0 / 95"), and this entry is inserted
     103                 :            :     into the file picker filter list, instead of the single filters which form the class.</p>
     104                 :            : 
     105                 :            :     <p>This is an interesting difference between local and global classes: Filters which are part of a global class
     106                 :            :     are listed in there own group, too. Filters in local classes aren't listed a second time - neither directly (as
     107                 :            :     the filter itself) nor indirectly (as part of another local group).</p>
     108                 :            : 
     109                 :            :     <p>The only exception are filters which are part of a global class <em>and</em> a local class. This is allowed.
     110                 :            :     Beeing cotained in two local classes isn't.</p>
     111                 :            : 
     112                 :            :     <p>So that's all what you need to know: Understand the concept of "filter classes" (a filter class combines
     113                 :            :     different filters and acts as if it's a filter itself) and the concept of groups (a group just describes a
     114                 :            :     logical correlation of filters and usually is represented to the user by drawing group separators in the filter
     115                 :            :     list).</p>
     116                 :            : 
     117                 :            :     <p>If you got it, go try understanding this file :).</p>
     118                 :            : 
     119                 :            :     */
     120                 :            : 
     121                 :            : 
     122                 :            :     //====================================================================
     123                 :            : 
     124                 :            :     typedef StringPair                          FilterDescriptor;   // a single filter or a filter class (display name and filter mask)
     125                 :            :     typedef ::std::list< FilterDescriptor >     FilterGroup;        // a list of single filter entries
     126                 :            :     typedef ::std::list< FilterGroup >          GroupedFilterList;  // a list of all filters, already grouped
     127                 :            : 
     128                 :            :     /// the logical name of a filter
     129                 :            :     typedef ::rtl::OUString                     FilterName;
     130                 :            : 
     131                 :            :     // a struct which holds references from a logical filter name to a filter group entry
     132                 :            :     // used for quick lookup of classes (means class entries - entries representing a class)
     133                 :            :     // which a given filter may belong to
     134                 :            :     typedef ::std::map< ::rtl::OUString, FilterGroup::iterator >    FilterGroupEntryReferrer;
     135                 :            : 
     136                 :            :     /// a descriptor for a filter class (which in the final dialog is represented by one filter entry)
     137 [ #  # ][ #  # ]:          0 :     typedef struct _tagFilterClass
                 [ #  # ]
     138                 :            :     {
     139                 :            :         ::rtl::OUString             sDisplayName;       // the display name
     140                 :            :         Sequence< FilterName >      aSubFilters;        // the (logical) names of the filter which belong to the class
     141                 :            :     } FilterClass;
     142                 :            : 
     143                 :            :     typedef ::std::list< FilterClass >                                  FilterClassList;
     144                 :            :     typedef ::std::map< ::rtl::OUString, FilterClassList::iterator >    FilterClassReferrer;
     145                 :            : 
     146                 :            :     typedef ::std::vector< ::rtl::OUString >                            StringArray;
     147                 :            : 
     148                 :            : // =======================================================================
     149                 :            : // = reading of configuration data
     150                 :            : // =======================================================================
     151                 :            : 
     152                 :            :     //--------------------------------------------------------------------
     153                 :          0 :     void lcl_ReadFilterClass( const OConfigurationNode& _rClassesNode, const ::rtl::OUString& _rLogicalClassName,
     154                 :            :         FilterClass& /* [out] */ _rClass )
     155                 :            :     {
     156 [ #  # ][ #  # ]:          0 :         static const ::rtl::OUString sDisplaNameNodeName( "DisplayName"  );
     157 [ #  # ][ #  # ]:          0 :         static const ::rtl::OUString sSubFiltersNodeName( "Filters"  );
     158                 :            : 
     159                 :            :             // the description node for the current class
     160                 :          0 :         OConfigurationNode aClassDesc = _rClassesNode.openNode( _rLogicalClassName );
     161                 :            : 
     162                 :            :         // the values
     163                 :          0 :         aClassDesc.getNodeValue( sDisplaNameNodeName ) >>= _rClass.sDisplayName;
     164 [ #  # ][ #  # ]:          0 :         aClassDesc.getNodeValue( sSubFiltersNodeName ) >>= _rClass.aSubFilters;
     165                 :          0 :     }
     166                 :            : 
     167                 :            :     //--------------------------------------------------------------------
     168                 :            :     struct CreateEmptyClassRememberPos : public ::std::unary_function< FilterName, void >
     169                 :            :     {
     170                 :            :     protected:
     171                 :            :         FilterClassList&        m_rClassList;
     172                 :            :         FilterClassReferrer&    m_rClassesReferrer;
     173                 :            : 
     174                 :            :     public:
     175                 :          0 :         CreateEmptyClassRememberPos( FilterClassList& _rClassList, FilterClassReferrer& _rClassesReferrer )
     176                 :            :             :m_rClassList       ( _rClassList )
     177                 :          0 :             ,m_rClassesReferrer ( _rClassesReferrer )
     178                 :            :         {
     179                 :          0 :         }
     180                 :            : 
     181                 :            :         // operate on a single class name
     182                 :          0 :         void operator() ( const FilterName& _rLogicalFilterName )
     183                 :            :         {
     184                 :            :             // insert a new (empty) class
     185 [ #  # ][ #  # ]:          0 :             m_rClassList.push_back( FilterClass() );
                 [ #  # ]
     186                 :            :             // get the position of this new entry
     187                 :          0 :             FilterClassList::iterator aInsertPos = m_rClassList.end();
     188                 :          0 :             --aInsertPos;
     189                 :            :             // remember this position
     190         [ #  # ]:          0 :             m_rClassesReferrer.insert( FilterClassReferrer::value_type( _rLogicalFilterName, aInsertPos ) );
     191                 :          0 :         }
     192                 :            :     };
     193                 :            : 
     194                 :            :     //--------------------------------------------------------------------
     195                 :          0 :     struct ReadGlobalFilter : public ::std::unary_function< FilterName, void >
     196                 :            :     {
     197                 :            :     protected:
     198                 :            :         OConfigurationNode      m_aClassesNode;
     199                 :            :         FilterClassReferrer&    m_aClassReferrer;
     200                 :            : 
     201                 :            :     public:
     202                 :          0 :         ReadGlobalFilter( const OConfigurationNode& _rClassesNode, FilterClassReferrer& _rClassesReferrer )
     203                 :            :             :m_aClassesNode     ( _rClassesNode )
     204                 :          0 :             ,m_aClassReferrer   ( _rClassesReferrer )
     205                 :            :         {
     206                 :          0 :         }
     207                 :            : 
     208                 :            :         // operate on a single logical name
     209                 :          0 :         void operator() ( const FilterName& _rName )
     210                 :            :         {
     211         [ #  # ]:          0 :             FilterClassReferrer::iterator aClassRef = m_aClassReferrer.find( _rName );
     212         [ #  # ]:          0 :             if ( m_aClassReferrer.end() == aClassRef )
     213                 :            :             {
     214                 :            :                 // we do not know this global class
     215                 :            :                 OSL_FAIL( "ReadGlobalFilter::operator(): unknown filter name!" );
     216                 :            :                 // TODO: perhaps we should be more tolerant - at the moment, the filter is dropped
     217                 :            :                 // We could silently push_back it to the container ....
     218                 :            :             }
     219                 :            :             else
     220                 :            :             {
     221                 :            :                 // read the data of this class into the node referred to by aClassRef
     222         [ #  # ]:          0 :                 lcl_ReadFilterClass( m_aClassesNode, _rName, *aClassRef->second );
     223                 :            :             }
     224                 :          0 :         }
     225                 :            :     };
     226                 :            : 
     227                 :            :     //--------------------------------------------------------------------
     228                 :          0 :     void lcl_ReadGlobalFilters( const OConfigurationNode& _rFilterClassification, FilterClassList& _rGlobalClasses, StringArray& _rGlobalClassNames )
     229                 :            :     {
     230                 :          0 :         _rGlobalClasses.clear();
     231                 :          0 :         _rGlobalClassNames.clear();
     232                 :            : 
     233                 :            :         //================================================================
     234                 :            :         // get the list describing the order of all global classes
     235         [ #  # ]:          0 :         Sequence< ::rtl::OUString > aGlobalClasses;
     236 [ #  # ][ #  # ]:          0 :         _rFilterClassification.getNodeValue( DEFINE_CONST_OUSTRING( "GlobalFilters/Order" ) ) >>= aGlobalClasses;
     237                 :            : 
     238                 :          0 :         const ::rtl::OUString* pNames = aGlobalClasses.getConstArray();
     239                 :          0 :         const ::rtl::OUString* pNamesEnd = pNames + aGlobalClasses.getLength();
     240                 :            : 
     241                 :            :         // copy the logical names
     242         [ #  # ]:          0 :         _rGlobalClassNames.resize( aGlobalClasses.getLength() );
     243         [ #  # ]:          0 :         ::std::copy( pNames, pNamesEnd, _rGlobalClassNames.begin() );
     244                 :            : 
     245                 :            :         // Global classes are presented in an own group, so their order matters (while the order of the
     246                 :            :         // "local classes" doesn't).
     247                 :            :         // That's why we can't simply add the global classes to _rGlobalClasses using the order in which they
     248                 :            :         // are returned from the configuration - it is completely undefined, and we need a _defined_ order.
     249         [ #  # ]:          0 :         FilterClassReferrer aClassReferrer;
     250                 :            :         ::std::for_each(
     251                 :            :             pNames,
     252                 :            :             pNamesEnd,
     253                 :            :             CreateEmptyClassRememberPos( _rGlobalClasses, aClassReferrer )
     254         [ #  # ]:          0 :         );
     255                 :            :             // now _rGlobalClasses contains a dummy entry for each global class,
     256                 :            :             // while aClassReferrer maps from the logical name of the class to the position within _rGlobalClasses where
     257                 :            :             // it's dummy entry resides
     258                 :            : 
     259                 :            :         //================================================================
     260                 :            :         // go for all the single class entries
     261                 :            :         OConfigurationNode aFilterClassesNode =
     262         [ #  # ]:          0 :             _rFilterClassification.openNode( DEFINE_CONST_OUSTRING( "GlobalFilters/Classes" ) );
     263                 :          0 :         Sequence< ::rtl::OUString > aFilterClasses = aFilterClassesNode.getNodeNames();
     264                 :            :         ::std::for_each(
     265                 :            :             aFilterClasses.getConstArray(),
     266                 :          0 :             aFilterClasses.getConstArray() + aFilterClasses.getLength(),
     267                 :            :             ReadGlobalFilter( aFilterClassesNode, aClassReferrer )
     268 [ #  # ][ #  # ]:          0 :         );
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     269                 :          0 :     }
     270                 :            : 
     271                 :            :     //--------------------------------------------------------------------
     272                 :          0 :     struct ReadLocalFilter : public ::std::unary_function< FilterName, void >
     273                 :            :     {
     274                 :            :     protected:
     275                 :            :         OConfigurationNode      m_aClassesNode;
     276                 :            :         FilterClassList&        m_rClasses;
     277                 :            : 
     278                 :            :     public:
     279                 :          0 :         ReadLocalFilter( const OConfigurationNode& _rClassesNode, FilterClassList& _rClasses )
     280                 :            :             :m_aClassesNode ( _rClassesNode )
     281                 :          0 :             ,m_rClasses     ( _rClasses )
     282                 :            :         {
     283                 :          0 :         }
     284                 :            : 
     285                 :            :         // operate on a single logical name
     286                 :          0 :         void operator() ( const FilterName& _rName )
     287                 :            :         {
     288                 :            :             // read the data for this class
     289         [ #  # ]:          0 :             FilterClass aClass;
     290         [ #  # ]:          0 :             lcl_ReadFilterClass( m_aClassesNode, _rName, aClass );
     291                 :            : 
     292                 :            :             // insert the class descriptor
     293 [ #  # ][ #  # ]:          0 :             m_rClasses.push_back( aClass );
     294                 :          0 :         }
     295                 :            :     };
     296                 :            : 
     297                 :            :     //--------------------------------------------------------------------
     298                 :          0 :     void lcl_ReadLocalFilters( const OConfigurationNode& _rFilterClassification, FilterClassList& _rLocalClasses )
     299                 :            :     {
     300                 :          0 :         _rLocalClasses.clear();
     301                 :            : 
     302                 :            :         // the node for the local classes
     303                 :            :         OConfigurationNode aFilterClassesNode =
     304         [ #  # ]:          0 :             _rFilterClassification.openNode( DEFINE_CONST_OUSTRING( "LocalFilters/Classes" ) );
     305                 :          0 :         Sequence< ::rtl::OUString > aFilterClasses = aFilterClassesNode.getNodeNames();
     306                 :            : 
     307                 :            :         ::std::for_each(
     308                 :            :             aFilterClasses.getConstArray(),
     309                 :          0 :             aFilterClasses.getConstArray() + aFilterClasses.getLength(),
     310                 :            :             ReadLocalFilter( aFilterClassesNode, _rLocalClasses )
     311 [ #  # ][ #  # ]:          0 :         );
         [ #  # ][ #  # ]
           [ #  #  #  # ]
     312                 :          0 :     }
     313                 :            : 
     314                 :            :     //--------------------------------------------------------------------
     315                 :          0 :     void lcl_ReadClassification( FilterClassList& _rGlobalClasses, StringArray& _rGlobalClassNames, FilterClassList& _rLocalClasses )
     316                 :            :     {
     317                 :            :         //================================================================
     318                 :            :         // open our config node
     319                 :            :         OConfigurationTreeRoot aFilterClassification = OConfigurationTreeRoot::createWithServiceFactory(
     320                 :            :             ::comphelper::getProcessServiceFactory(),
     321                 :            :             DEFINE_CONST_OUSTRING( "org.openoffice.Office.UI/FilterClassification" ),
     322                 :            :             -1,
     323                 :            :             OConfigurationTreeRoot::CM_READONLY
     324 [ #  # ][ #  # ]:          0 :         );
                 [ #  # ]
     325                 :            : 
     326                 :            :         //================================================================
     327                 :            :         // go for the global classes
     328         [ #  # ]:          0 :         lcl_ReadGlobalFilters( aFilterClassification, _rGlobalClasses, _rGlobalClassNames );
     329                 :            : 
     330                 :            :         //================================================================
     331                 :            :         // fo for the local classes
     332 [ #  # ][ #  # ]:          0 :         lcl_ReadLocalFilters( aFilterClassification, _rLocalClasses );
     333                 :            : 
     334                 :          0 :     }
     335                 :            : 
     336                 :            : // =======================================================================
     337                 :            : // = grouping and classifying
     338                 :            : // =======================================================================
     339                 :            : 
     340                 :            :     //--------------------------------------------------------------------
     341                 :            :     // a struct which adds helps remembering a reference to a class entry
     342                 :            :     struct ReferToFilterEntry : public ::std::unary_function< FilterName, void >
     343                 :            :     {
     344                 :            :     protected:
     345                 :            :         FilterGroupEntryReferrer&   m_rEntryReferrer;
     346                 :            :         FilterGroup::iterator       m_aClassPos;
     347                 :            : 
     348                 :            :     public:
     349                 :          0 :         ReferToFilterEntry( FilterGroupEntryReferrer& _rEntryReferrer, const FilterGroup::iterator& _rClassPos )
     350                 :            :             :m_rEntryReferrer( _rEntryReferrer )
     351                 :          0 :             ,m_aClassPos( _rClassPos )
     352                 :            :         {
     353                 :          0 :         }
     354                 :            : 
     355                 :            :         // operate on a single filter name
     356                 :          0 :         void operator() ( const FilterName& _rName )
     357                 :            :         {
     358                 :            : #ifdef DBG_UTIL
     359                 :            :             ::std::pair< FilterGroupEntryReferrer::iterator, bool > aInsertRes =
     360                 :            : #endif
     361         [ #  # ]:          0 :             m_rEntryReferrer.insert( FilterGroupEntryReferrer::value_type( _rName, m_aClassPos ) );
     362                 :            :             DBG_ASSERT( aInsertRes.second, "ReferToFilterEntry::operator(): already have an element for this name!" );
     363                 :          0 :         }
     364                 :            :     };
     365                 :            : 
     366                 :            :     //--------------------------------------------------------------------
     367                 :            :     struct FillClassGroup : public ::std::unary_function< FilterClass, void >
     368                 :            :     {
     369                 :            :     protected:
     370                 :            :         FilterGroup&                m_rClassGroup;
     371                 :            :         FilterGroupEntryReferrer&   m_rClassReferrer;
     372                 :            : 
     373                 :            :     public:
     374                 :          0 :         FillClassGroup( FilterGroup& _rClassGroup, FilterGroupEntryReferrer& _rClassReferrer )
     375                 :            :             :m_rClassGroup      ( _rClassGroup )
     376                 :          0 :             ,m_rClassReferrer   ( _rClassReferrer )
     377                 :            :         {
     378                 :          0 :         }
     379                 :            : 
     380                 :            :         // operate on a single class
     381                 :          0 :         void operator() ( const FilterClass& _rClass )
     382                 :            :         {
     383                 :            :             // create an empty filter descriptor for the class
     384                 :          0 :             FilterDescriptor aClassEntry;
     385                 :            :             // set it's name (which is all we know by now)
     386                 :          0 :             aClassEntry.First = _rClass.sDisplayName;
     387                 :            : 
     388                 :            :             // add it to the group
     389         [ #  # ]:          0 :             m_rClassGroup.push_back( aClassEntry );
     390                 :            :             // the position of the newly added class
     391                 :          0 :             FilterGroup::iterator aClassEntryPos = m_rClassGroup.end();
     392                 :          0 :             --aClassEntryPos;
     393                 :            : 
     394                 :            :             // and for all the sub filters of the class, remember the class
     395                 :            :             // (respectively the position of the class it the group)
     396                 :            :             ::std::for_each(
     397                 :            :                 _rClass.aSubFilters.getConstArray(),
     398                 :          0 :                 _rClass.aSubFilters.getConstArray() + _rClass.aSubFilters.getLength(),
     399                 :            :                 ReferToFilterEntry( m_rClassReferrer, aClassEntryPos )
     400         [ #  # ]:          0 :             );
     401                 :          0 :         }
     402                 :            :     };
     403                 :            : 
     404                 :            :     //--------------------------------------------------------------------
     405                 :            :     static const sal_Unicode s_cWildcardSeparator( ';' );
     406                 :            : 
     407                 :            :     //====================================================================
     408                 :          0 :     const ::rtl::OUString& getSeparatorString()
     409                 :            :     {
     410 [ #  # ][ #  # ]:          0 :         static ::rtl::OUString s_sSeparatorString( &s_cWildcardSeparator, 1 );
     411                 :          0 :         return s_sSeparatorString;
     412                 :            :     }
     413                 :            : 
     414                 :            :     //====================================================================
     415                 :            :     struct CheckAppendSingleWildcard : public ::std::unary_function< ::rtl::OUString, void >
     416                 :            :     {
     417                 :            :         ::rtl::OUString& _rToBeExtended;
     418                 :            : 
     419                 :          0 :         CheckAppendSingleWildcard( ::rtl::OUString& _rBase ) : _rToBeExtended( _rBase ) { }
     420                 :            : 
     421                 :          0 :         void operator() ( const ::rtl::OUString& _rWC )
     422                 :            :         {
     423                 :            :             // check for double wildcards
     424                 :          0 :             sal_Int32 nExistentPos = _rToBeExtended.indexOf( _rWC );
     425         [ #  # ]:          0 :             if  ( -1 < nExistentPos )
     426                 :            :             {   // found this wildcard (already part of _rToBeExtended)
     427                 :          0 :                 const sal_Unicode* pBuffer = _rToBeExtended.getStr();
     428 [ #  # ][ #  # ]:          0 :                 if  (   ( 0 == nExistentPos )
     429                 :          0 :                     ||  ( s_cWildcardSeparator == pBuffer[ nExistentPos - 1 ] )
     430                 :            :                     )
     431                 :            :                 {   // the wildcard really starts at this position (it starts at pos 0 or the previous character is a separator
     432                 :          0 :                     sal_Int32 nExistentWCEnd = nExistentPos + _rWC.getLength();
     433 [ #  # ][ #  # ]:          0 :                     if  (   ( _rToBeExtended.getLength() == nExistentWCEnd )
                 [ #  # ]
     434                 :          0 :                         ||  ( s_cWildcardSeparator == pBuffer[ nExistentWCEnd ] )
     435                 :            :                         )
     436                 :            :                     {   // it's really the complete wildcard we found
     437                 :            :                         // (not something like _rWC beeing "*.t" and _rToBeExtended containing "*.txt")
     438                 :            :                         // -> outta here
     439                 :          0 :                         return;
     440                 :            :                     }
     441                 :            :                 }
     442                 :            :             }
     443                 :            : 
     444         [ #  # ]:          0 :             if ( !_rToBeExtended.isEmpty() )
     445                 :          0 :                 _rToBeExtended += getSeparatorString();
     446                 :          0 :             _rToBeExtended += _rWC;
     447                 :            :         }
     448                 :            :     };
     449                 :            : 
     450                 :            :     //====================================================================
     451                 :            :     // a helper struct which adds a fixed (Sfx-)filter to a filter group entry given by iterator
     452                 :          0 :     struct AppendWildcardToDescriptor : public ::std::unary_function< FilterGroupEntryReferrer::value_type, void >
     453                 :            :     {
     454                 :            :     protected:
     455                 :            :         ::std::vector< ::rtl::OUString > aWildCards;
     456                 :            : 
     457                 :            :     public:
     458                 :            :         AppendWildcardToDescriptor( const String& _rWildCard );
     459                 :            : 
     460                 :            :         // operate on a single class entry
     461                 :          0 :         void operator() ( const FilterGroupEntryReferrer::value_type& _rClassReference )
     462                 :            :         {
     463                 :            :             // simply add our wildcards
     464                 :            :             ::std::for_each(
     465                 :            :                 aWildCards.begin(),
     466                 :            :                 aWildCards.end(),
     467                 :          0 :                 CheckAppendSingleWildcard( _rClassReference.second->Second )
     468         [ #  # ]:          0 :             );
     469                 :          0 :         }
     470                 :            :     };
     471                 :            : 
     472                 :            :     //====================================================================
     473                 :          0 :     AppendWildcardToDescriptor::AppendWildcardToDescriptor( const String& _rWildCard )
     474                 :            :     {
     475                 :            :         DBG_ASSERT( _rWildCard.Len(),
     476                 :            :             "AppendWildcardToDescriptor::AppendWildcardToDescriptor: invalid wildcard!" );
     477                 :            :         DBG_ASSERT( _rWildCard.GetBuffer()[0] != s_cWildcardSeparator,
     478                 :            :             "AppendWildcardToDescriptor::AppendWildcardToDescriptor: wildcard already separated!" );
     479                 :            : 
     480 [ #  # ][ #  # ]:          0 :         aWildCards.reserve( comphelper::string::getTokenCount(_rWildCard, s_cWildcardSeparator) );
                 [ #  # ]
     481                 :            : 
     482                 :          0 :         const sal_Unicode* pTokenLoop = _rWildCard.GetBuffer();
     483                 :          0 :         const sal_Unicode* pTokenLoopEnd = pTokenLoop + _rWildCard.Len();
     484                 :          0 :         const sal_Unicode* pTokenStart = pTokenLoop;
     485         [ #  # ]:          0 :         for ( ; pTokenLoop != pTokenLoopEnd; ++pTokenLoop )
     486                 :            :         {
     487 [ #  # ][ #  # ]:          0 :             if ( ( s_cWildcardSeparator == *pTokenLoop ) && ( pTokenLoop > pTokenStart ) )
     488                 :            :             {   // found a new token separator (and a non-empty token)
     489         [ #  # ]:          0 :                 aWildCards.push_back( ::rtl::OUString( pTokenStart, pTokenLoop - pTokenStart ) );
     490                 :            : 
     491                 :            :                 // search the start of the next token
     492 [ #  # ][ #  # ]:          0 :                 while ( ( pTokenStart != pTokenLoopEnd ) && ( *pTokenStart != s_cWildcardSeparator ) )
                 [ #  # ]
     493                 :          0 :                     ++pTokenStart;
     494                 :            : 
     495         [ #  # ]:          0 :                 if ( pTokenStart == pTokenLoopEnd )
     496                 :            :                     // reached the end
     497                 :          0 :                     break;
     498                 :            : 
     499                 :          0 :                 ++pTokenStart;
     500                 :          0 :                 pTokenLoop = pTokenStart;
     501                 :            :             }
     502                 :            :         }
     503         [ #  # ]:          0 :         if ( pTokenLoop > pTokenStart )
     504                 :            :             // the last one ....
     505         [ #  # ]:          0 :             aWildCards.push_back( ::rtl::OUString( pTokenStart, pTokenLoop - pTokenStart ) );
     506                 :          0 :     }
     507                 :            : 
     508                 :            :     //--------------------------------------------------------------------
     509                 :          0 :     void lcl_InitGlobalClasses( GroupedFilterList& _rAllFilters, const FilterClassList& _rGlobalClasses, FilterGroupEntryReferrer& _rGlobalClassesRef )
     510                 :            :     {
     511                 :            :         // we need an extra group in our "all filters" container
     512         [ #  # ]:          0 :         _rAllFilters.push_front( FilterGroup() );
     513                 :          0 :         FilterGroup& rGlobalFilters = _rAllFilters.front();
     514                 :            :             // it's important to work on the reference: we want to access the members of this filter group
     515                 :            :             // by an iterator (FilterGroup::const_iterator)
     516                 :            :         // the referrer for the global classes
     517                 :            : 
     518                 :            :         // initialize the group
     519                 :            :         ::std::for_each(
     520                 :            :             _rGlobalClasses.begin(),
     521                 :            :             _rGlobalClasses.end(),
     522                 :            :             FillClassGroup( rGlobalFilters, _rGlobalClassesRef )
     523         [ #  # ]:          0 :         );
     524                 :            :             // now we have:
     525                 :            :             // in rGlobalFilters: a list of FilterDescriptor's, where each's discriptor's display name is set to the name of a class
     526                 :            :             // in aGlobalClassesRef: a mapping from logical filter names to positions within rGlobalFilters
     527                 :            :             //  this way, if we encounter an arbitrary filter, we can easily (and efficient) check if it belongs to a global class
     528                 :            :             //  and modify the descriptor for this class accordingly
     529                 :          0 :     }
     530                 :            : 
     531                 :            :     //--------------------------------------------------------------------
     532                 :            :     typedef ::std::vector< ::std::pair< FilterGroupEntryReferrer::mapped_type, FilterGroup::iterator > >
     533                 :            :             MapGroupEntry2GroupEntry;
     534                 :            :             // this is not really a map - it's just called this way because it is used as a map
     535                 :            : 
     536                 :            :     struct FindGroupEntry : public ::std::unary_function< MapGroupEntry2GroupEntry::value_type, sal_Bool >
     537                 :            :     {
     538                 :            :         FilterGroupEntryReferrer::mapped_type aLookingFor;
     539                 :          0 :         FindGroupEntry( FilterGroupEntryReferrer::mapped_type _rLookingFor ) : aLookingFor( _rLookingFor ) { }
     540                 :            : 
     541                 :          0 :         sal_Bool operator() ( const MapGroupEntry2GroupEntry::value_type& _rMapEntry )
     542                 :            :         {
     543         [ #  # ]:          0 :             return _rMapEntry.first == aLookingFor ? sal_True : sal_False;
     544                 :            :         }
     545                 :            :     };
     546                 :            : 
     547                 :            :     struct CopyGroupEntryContent : public ::std::unary_function< MapGroupEntry2GroupEntry::value_type, void >
     548                 :            :     {
     549                 :          0 :         void operator() ( const MapGroupEntry2GroupEntry::value_type& _rMapEntry )
     550                 :            :         {
     551                 :            : #ifdef DBG_UTIL
     552                 :            :             FilterDescriptor aHaveALook = *_rMapEntry.first;
     553                 :            : #endif
     554                 :          0 :             *_rMapEntry.second = *_rMapEntry.first;
     555                 :          0 :         }
     556                 :            :     };
     557                 :            : 
     558                 :            :     //--------------------------------------------------------------------
     559                 :            :     struct CopyNonEmptyFilter : public ::std::unary_function< FilterDescriptor, void >
     560                 :            :     {
     561                 :            :         FilterGroup& rTarget;
     562                 :          0 :         CopyNonEmptyFilter( FilterGroup& _rTarget ) :rTarget( _rTarget ) { }
     563                 :            : 
     564                 :          0 :         void operator() ( const FilterDescriptor& _rFilter )
     565                 :            :         {
     566         [ #  # ]:          0 :             if ( !_rFilter.Second.isEmpty() )
     567                 :          0 :                 rTarget.push_back( _rFilter );
     568                 :          0 :         }
     569                 :            :     };
     570                 :            : 
     571                 :            :     //--------------------------------------------------------------------
     572                 :          0 :     void lcl_GroupAndClassify( TSortedFilterList& _rFilterMatcher, GroupedFilterList& _rAllFilters )
     573                 :            :     {
     574                 :          0 :         _rAllFilters.clear();
     575                 :            : 
     576                 :            :         // ===============================================================
     577                 :            :         // read the classification of filters
     578 [ #  # ][ #  # ]:          0 :         FilterClassList aGlobalClasses, aLocalClasses;
     579         [ #  # ]:          0 :         StringArray aGlobalClassNames;
     580         [ #  # ]:          0 :         lcl_ReadClassification( aGlobalClasses, aGlobalClassNames, aLocalClasses );
     581                 :            : 
     582                 :            :         // ===============================================================
     583                 :            :         // for the global filter classes
     584         [ #  # ]:          0 :         FilterGroupEntryReferrer aGlobalClassesRef;
     585         [ #  # ]:          0 :         lcl_InitGlobalClasses( _rAllFilters, aGlobalClasses, aGlobalClassesRef );
     586                 :            : 
     587                 :            :         // insert as much placeholders (FilterGroup's) into _rAllFilter for groups as we have global classes
     588                 :            :         // (this assumes that both numbers are the same, which, speaking strictly, must not hold - but it does, as we know ...)
     589                 :          0 :         sal_Int32 nGlobalClasses = aGlobalClasses.size();
     590         [ #  # ]:          0 :         while ( nGlobalClasses-- )
     591 [ #  # ][ #  # ]:          0 :             _rAllFilters.push_back( FilterGroup() );
     592                 :            : 
     593                 :            :         // ===============================================================
     594                 :            :         // for the local classes:
     595                 :            :         // if n filters belong to a local class, they do not appear in their respective group explicitly, instead
     596                 :            :         // and entry for the class is added to the group and the extensions of the filters are collected under
     597                 :            :         // this entry
     598         [ #  # ]:          0 :         FilterGroupEntryReferrer aLocalClassesRef;
     599         [ #  # ]:          0 :         FilterGroup aCollectedLocals;
     600                 :            :         ::std::for_each(
     601                 :            :             aLocalClasses.begin(),
     602                 :            :             aLocalClasses.end(),
     603                 :            :             FillClassGroup( aCollectedLocals, aLocalClassesRef )
     604         [ #  # ]:          0 :         );
     605                 :            :         // to map from the position within aCollectedLocals to positions within the real groups
     606                 :            :         // (where they finally belong to)
     607         [ #  # ]:          0 :         MapGroupEntry2GroupEntry    aLocalFinalPositions;
     608                 :            : 
     609                 :            :         // ===============================================================
     610                 :            :         // now add the filters
     611                 :            :         // the group which we currently work with
     612                 :          0 :         GroupedFilterList::iterator aCurrentGroup = _rAllFilters.end(); // no current group
     613                 :            :         // the filter container of the current group - if this changes between two filters, a new group is reached
     614         [ #  # ]:          0 :         String aCurrentServiceName;
     615                 :            : 
     616         [ #  # ]:          0 :         String sFilterWildcard;
     617                 :          0 :         ::rtl::OUString sFilterName;
     618                 :            :         // loop through all the filters
     619 [ #  # ][ #  # ]:          0 :         for ( const SfxFilter* pFilter = _rFilterMatcher.First(); pFilter; pFilter = _rFilterMatcher.Next() )
                 [ #  # ]
     620                 :            :         {
     621         [ #  # ]:          0 :             sFilterName = pFilter->GetFilterName();
     622 [ #  # ][ #  # ]:          0 :             sFilterWildcard = pFilter->GetWildcard().getGlob();
     623         [ #  # ]:          0 :             AppendWildcardToDescriptor aExtendWildcard( sFilterWildcard );
     624                 :            : 
     625                 :            :             DBG_ASSERT( sFilterWildcard.Len(), "sfx2::lcl_GroupAndClassify: invalid wildcard of this filter!" );
     626                 :            : 
     627                 :            :             // ===========================================================
     628                 :            :             // check for a change in the group
     629         [ #  # ]:          0 :             String aServiceName = pFilter->GetServiceName();
     630 [ #  # ][ #  # ]:          0 :             if ( aServiceName != aCurrentServiceName )
     631                 :            :             {   // we reached a new group
     632                 :            : 
     633         [ #  # ]:          0 :                 ::rtl::OUString sDocServName = aServiceName;
     634                 :            : 
     635                 :            :                 // look for the place in _rAllFilters where this ne group belongs - this is determined
     636                 :            :                 // by the order of classes in aGlobalClassNames
     637                 :          0 :                 GroupedFilterList::iterator aGroupPos = _rAllFilters.begin();
     638                 :            :                 DBG_ASSERT( aGroupPos != _rAllFilters.end(),
     639                 :            :                     "sfx2::lcl_GroupAndClassify: invalid all-filters array here!" );
     640                 :            :                     // the loop below will work on invalid objects else ...
     641                 :          0 :                 ++aGroupPos;
     642                 :          0 :                 StringArray::iterator aGlobalIter = aGlobalClassNames.begin();
     643         [ #  # ]:          0 :                 while   (   ( aGroupPos != _rAllFilters.end() )
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     644 [ #  # ][ #  # ]:          0 :                         &&  ( aGlobalIter != aGlobalClassNames.end() )
                 [ #  # ]
     645                 :          0 :                         &&  ( *aGlobalIter != sDocServName )
     646                 :            :                         )
     647                 :            :                 {
     648                 :          0 :                     ++aGlobalIter;
     649                 :          0 :                     ++aGroupPos;
     650                 :            :                 }
     651         [ #  # ]:          0 :                 if ( aGroupPos != _rAllFilters.end() )
     652                 :            :                     // we found a global class name which matchies the doc service name -> fill the filters of this
     653                 :            :                     // group in the respective prepared group
     654                 :          0 :                     aCurrentGroup = aGroupPos;
     655                 :            :                 else
     656                 :            :                     // insert a new entry in our overall-list
     657 [ #  # ][ #  # ]:          0 :                     aCurrentGroup = _rAllFilters.insert( _rAllFilters.end(), FilterGroup() );
     658                 :            : 
     659                 :            :                 // remember the container to properly detect the next group
     660         [ #  # ]:          0 :                 aCurrentServiceName = aServiceName;
     661                 :            :             }
     662                 :            : 
     663                 :            :             DBG_ASSERT( aCurrentGroup != _rAllFilters.end(), "sfx2::lcl_GroupAndClassify: invalid current group!" );
     664                 :            : 
     665                 :            :             // ===========================================================
     666                 :            :             // check if the filter is part of a global group
     667                 :            :             ::std::pair< FilterGroupEntryReferrer::iterator, FilterGroupEntryReferrer::iterator >
     668         [ #  # ]:          0 :                 aBelongsTo = aGlobalClassesRef.equal_range( sFilterName );
     669                 :            :             // add the filter to the entries for these classes
     670                 :            :             // (if they exist - if not, the range is empty and the for_each is a no-op)
     671                 :            :             ::std::for_each(
     672                 :            :                 aBelongsTo.first,
     673                 :            :                 aBelongsTo.second,
     674                 :            :                 aExtendWildcard
     675 [ #  # ][ #  # ]:          0 :             );
     676                 :            : 
     677                 :            :             // ===========================================================
     678                 :            :             // add the filter to it's group
     679                 :            : 
     680                 :            :             // for this, check if the filter is part of a local filter
     681         [ #  # ]:          0 :             FilterGroupEntryReferrer::iterator aBelongsToLocal = aLocalClassesRef.find( sFilterName );
     682         [ #  # ]:          0 :             if ( aLocalClassesRef.end() != aBelongsToLocal )
     683                 :            :             {
     684                 :            :                 // okay, there is a local class which the filter belongs to
     685                 :            :                 // -> append the wildcard
     686         [ #  # ]:          0 :                 aExtendWildcard( *aBelongsToLocal );
     687                 :            : 
     688                 :            :                 MapGroupEntry2GroupEntry::iterator aThisGroupFinalPos =
     689         [ #  # ]:          0 :                     ::std::find_if( aLocalFinalPositions.begin(), aLocalFinalPositions.end(), FindGroupEntry( aBelongsToLocal->second ) );
     690                 :            : 
     691 [ #  # ][ #  # ]:          0 :                 if ( aLocalFinalPositions.end() == aThisGroupFinalPos )
     692                 :            :                 {   // the position within aCollectedLocals has not been mapped to a final position
     693                 :            :                     // within the "real" group (aCollectedLocals is only temporary)
     694                 :            :                     // -> do this now (as we just encountered the first filter belonging to this local class
     695                 :            :                     // add a new entry which is the "real" group entry
     696 [ #  # ][ #  # ]:          0 :                     aCurrentGroup->push_back( FilterDescriptor( aBelongsToLocal->second->First, String() ) );
         [ #  # ][ #  # ]
     697                 :            :                     // the position where we inserted the entry
     698                 :          0 :                     FilterGroup::iterator aInsertPos = aCurrentGroup->end();
     699                 :          0 :                     --aInsertPos;
     700                 :            :                     // remember this pos
     701         [ #  # ]:          0 :                     aLocalFinalPositions.push_back( MapGroupEntry2GroupEntry::value_type( aBelongsToLocal->second, aInsertPos ) );
     702                 :            :                 }
     703                 :            :             }
     704                 :            :             else
     705 [ #  # ][ #  # ]:          0 :                 aCurrentGroup->push_back( FilterDescriptor( pFilter->GetUIName(), sFilterWildcard ) );
                 [ #  # ]
     706         [ #  # ]:          0 :         }
     707                 :            : 
     708                 :            :         // now just complete the infos for the local groups:
     709                 :            :         // During the above loop, they have been collected in aCollectedLocals, but this is only temporary
     710                 :            :         // They have to be copied into their final positions (which are stored in aLocalFinalPositions)
     711                 :            :         ::std::for_each(
     712                 :            :             aLocalFinalPositions.begin(),
     713                 :            :             aLocalFinalPositions.end(),
     714                 :            :             CopyGroupEntryContent()
     715         [ #  # ]:          0 :         );
     716                 :            : 
     717                 :            :         // and remove local groups which do not apply - e.g. have no entries due to the limited content of the
     718                 :            :         // current SfxFilterMatcherIter
     719                 :            : 
     720         [ #  # ]:          0 :         FilterGroup& rGlobalFilters = _rAllFilters.front();
     721         [ #  # ]:          0 :         FilterGroup aNonEmptyGlobalFilters;
     722                 :            :         ::std::for_each(
     723                 :            :             rGlobalFilters.begin(),
     724                 :            :             rGlobalFilters.end(),
     725                 :            :             CopyNonEmptyFilter( aNonEmptyGlobalFilters )
     726         [ #  # ]:          0 :         );
     727 [ #  # ][ #  # ]:          0 :         rGlobalFilters.swap( aNonEmptyGlobalFilters );
                 [ #  # ]
     728                 :          0 :     }
     729                 :            : 
     730                 :            :     //--------------------------------------------------------------------
     731                 :          0 :     struct AppendFilter : public ::std::unary_function< FilterDescriptor, void >
     732                 :            :     {
     733                 :            :         protected:
     734                 :            :             Reference< XFilterManager >         m_xFilterManager;
     735                 :            :             FileDialogHelper_Impl*              m_pFileDlgImpl;
     736                 :            :             bool                                m_bAddExtension;
     737                 :            : 
     738                 :            :         public:
     739                 :          0 :             AppendFilter( const Reference< XFilterManager >& _rxFilterManager,
     740                 :            :                           FileDialogHelper_Impl* _pImpl, bool _bAddExtension ) :
     741                 :            : 
     742                 :            :                 m_xFilterManager( _rxFilterManager ),
     743                 :            :                 m_pFileDlgImpl  ( _pImpl ),
     744                 :          0 :                 m_bAddExtension ( _bAddExtension )
     745                 :            : 
     746                 :            :             {
     747                 :            :                 DBG_ASSERT( m_xFilterManager.is(), "AppendFilter::AppendFilter: invalid filter manager!" );
     748                 :            :                 DBG_ASSERT( m_pFileDlgImpl, "AppendFilter::AppendFilter: invalid filedlg impl!" );
     749                 :          0 :             }
     750                 :            : 
     751                 :            :             // operate on a single filter
     752                 :          0 :             void operator() ( const FilterDescriptor& _rFilterEntry )
     753                 :            :             {
     754                 :            :                 String sDisplayText = m_bAddExtension
     755                 :            :                     ? addExtension( _rFilterEntry.First, _rFilterEntry.Second, sal_True, *m_pFileDlgImpl )
     756 [ #  # ][ #  # ]:          0 :                     : _rFilterEntry.First;
                 [ #  # ]
     757 [ #  # ][ #  # ]:          0 :                 m_xFilterManager->appendFilter( sDisplayText, _rFilterEntry.Second );
         [ #  # ][ #  # ]
     758                 :          0 :             }
     759                 :            :     };
     760                 :            : 
     761                 :            : // =======================================================================
     762                 :            : // = handling for the "all files" entry
     763                 :            : // =======================================================================
     764                 :            : 
     765                 :            :     //--------------------------------------------------------------------
     766                 :          0 :     sal_Bool lcl_hasAllFilesFilter( TSortedFilterList& _rFilterMatcher, String& /* [out] */ _rAllFilterName )
     767                 :            :     {
     768                 :          0 :         ::rtl::OUString sUIName;
     769                 :          0 :         sal_Bool        bHasAll = sal_False;
     770 [ #  # ][ #  # ]:          0 :         _rAllFilterName = SfxResId( STR_SFX_FILTERNAME_ALL ).toString();
                 [ #  # ]
     771                 :            : 
     772                 :            :         // ===============================================================
     773                 :            :         // check if there's already a filter <ALL>
     774 [ #  # ][ #  # ]:          0 :         for ( const SfxFilter* pFilter = _rFilterMatcher.First(); pFilter && !bHasAll; pFilter = _rFilterMatcher.Next() )
         [ #  # ][ #  # ]
                 [ #  # ]
     775                 :            :         {
     776 [ #  # ][ #  # ]:          0 :             if ( pFilter->GetUIName() == _rAllFilterName )
     777                 :          0 :                 bHasAll = sal_True;
     778                 :            :         }
     779                 :          0 :         return bHasAll;
     780                 :            :     }
     781                 :            : 
     782                 :            :     //--------------------------------------------------------------------
     783                 :          0 :     void lcl_EnsureAllFilesEntry( TSortedFilterList& _rFilterMatcher, GroupedFilterList& _rFilters )
     784                 :            :     {
     785                 :            :         // ===============================================================
     786         [ #  # ]:          0 :         String sAllFilterName;
     787 [ #  # ][ #  # ]:          0 :         if ( !lcl_hasAllFilesFilter( _rFilterMatcher, sAllFilterName ) )
     788                 :            :         {
     789                 :            :             // get the first group of filters (by definition, this group contains the global classes)
     790                 :            :             DBG_ASSERT( !_rFilters.empty(), "lcl_EnsureAllFilesEntry: invalid filter list!" );
     791         [ #  # ]:          0 :             if ( !_rFilters.empty() )
     792                 :            :             {
     793                 :          0 :                 FilterGroup& rGlobalClasses = *_rFilters.begin();
     794 [ #  # ][ #  # ]:          0 :                 rGlobalClasses.push_front( FilterDescriptor( sAllFilterName, DEFINE_CONST_UNICODE( FILEDIALOG_FILTER_ALL ) ) );
         [ #  # ][ #  # ]
                 [ #  # ]
     795                 :            :             }
     796         [ #  # ]:          0 :         }
     797                 :          0 :     }
     798                 :            : 
     799                 :            : // =======================================================================
     800                 :            : // = filling an XFilterManager
     801                 :            : // =======================================================================
     802                 :            : 
     803                 :            :     //--------------------------------------------------------------------
     804                 :          0 :     struct AppendFilterGroup : public ::std::unary_function< FilterGroup, void >
     805                 :            :     {
     806                 :            :     protected:
     807                 :            :         Reference< XFilterManager >         m_xFilterManager;
     808                 :            :         Reference< XFilterGroupManager >    m_xFilterGroupManager;
     809                 :            :         FileDialogHelper_Impl*              m_pFileDlgImpl;
     810                 :            : 
     811                 :            :     public:
     812                 :          0 :         AppendFilterGroup( const Reference< XFilterManager >& _rxFilterManager, FileDialogHelper_Impl* _pImpl )
     813                 :            :             :m_xFilterManager       ( _rxFilterManager )
     814                 :            :             ,m_xFilterGroupManager  ( _rxFilterManager, UNO_QUERY )
     815         [ #  # ]:          0 :             ,m_pFileDlgImpl         ( _pImpl )
     816                 :            :         {
     817                 :            :             DBG_ASSERT( m_xFilterManager.is(), "AppendFilterGroup::AppendFilterGroup: invalid filter manager!" );
     818                 :            :             DBG_ASSERT( m_pFileDlgImpl, "AppendFilterGroup::AppendFilterGroup: invalid filedlg impl!" );
     819                 :          0 :         }
     820                 :            : 
     821                 :          0 :         void appendGroup( const FilterGroup& _rGroup, bool _bAddExtension )
     822                 :            :         {
     823                 :            :             try
     824                 :            :             {
     825         [ #  # ]:          0 :                 if ( m_xFilterGroupManager.is() )
     826                 :            :                 {   // the file dialog implementation supports visual grouping of filters
     827                 :            :                     // create a representation of the group which is understandable by the XFilterGroupManager
     828         [ #  # ]:          0 :                     if ( _rGroup.size() )
     829                 :            :                     {
     830         [ #  # ]:          0 :                         Sequence< StringPair > aFilters( _rGroup.size() );
     831                 :            :                         ::std::copy(
     832                 :            :                             _rGroup.begin(),
     833                 :            :                             _rGroup.end(),
     834                 :            :                             aFilters.getArray()
     835 [ #  # ][ #  # ]:          0 :                         );
     836         [ #  # ]:          0 :                         if ( _bAddExtension )
     837                 :            :                         {
     838         [ #  # ]:          0 :                             StringPair* pFilters = aFilters.getArray();
     839                 :          0 :                             StringPair* pEnd = pFilters + aFilters.getLength();
     840         [ #  # ]:          0 :                             for ( ; pFilters != pEnd; ++pFilters )
     841         [ #  # ]:          0 :                                 pFilters->First = addExtension( pFilters->First, pFilters->Second, sal_True, *m_pFileDlgImpl );
     842                 :            :                         }
     843 [ #  # ][ #  # ]:          0 :                         m_xFilterGroupManager->appendFilterGroup( ::rtl::OUString(), aFilters );
                 [ #  # ]
     844                 :            :                     }
     845                 :            :                 }
     846                 :            :                 else
     847                 :            :                 {
     848                 :            :                     ::std::for_each(
     849                 :            :                         _rGroup.begin(),
     850                 :            :                         _rGroup.end(),
     851 [ #  # ][ #  # ]:          0 :                         AppendFilter( m_xFilterManager, m_pFileDlgImpl, _bAddExtension ) );
         [ #  # ][ #  # ]
                 [ #  # ]
     852                 :            :                 }
     853                 :            :             }
     854                 :          0 :             catch( const Exception& )
     855                 :            :             {
     856                 :            :                 DBG_UNHANDLED_EXCEPTION();
     857                 :            :             }
     858                 :          0 :         }
     859                 :            : 
     860                 :            :         // operate on a single filter group
     861                 :          0 :         void operator() ( const FilterGroup& _rGroup )
     862                 :            :         {
     863                 :          0 :             appendGroup( _rGroup, true );
     864                 :          0 :         }
     865                 :            :     };
     866                 :            : 
     867                 :            :     //--------------------------------------------------------------------
     868                 :          0 :     TSortedFilterList::TSortedFilterList(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration >& xFilterList)
     869                 :          0 :         : m_nIterator(0)
     870                 :            :     {
     871         [ #  # ]:          0 :         if (!xFilterList.is())
     872                 :          0 :             return;
     873                 :            : 
     874                 :          0 :         m_lFilters.clear();
     875 [ #  # ][ #  # ]:          0 :         while(xFilterList->hasMoreElements())
                 [ #  # ]
     876                 :            :         {
     877 [ #  # ][ #  # ]:          0 :             ::comphelper::SequenceAsHashMap lFilterProps (xFilterList->nextElement());
                 [ #  # ]
     878                 :            :             ::rtl::OUString                 sFilterName  = lFilterProps.getUnpackedValueOrDefault(
     879                 :            :                                                              ::rtl::OUString("Name"),
     880         [ #  # ]:          0 :                                                              ::rtl::OUString());
     881         [ #  # ]:          0 :             if (!sFilterName.isEmpty())
     882         [ #  # ]:          0 :                 m_lFilters.push_back(sFilterName);
     883         [ #  # ]:          0 :         }
     884                 :            :     }
     885                 :            : 
     886                 :            :     //--------------------------------------------------------------------
     887                 :          0 :     const SfxFilter* TSortedFilterList::First()
     888                 :            :     {
     889                 :          0 :         m_nIterator = 0;
     890                 :          0 :         return impl_getFilter(m_nIterator);
     891                 :            :     }
     892                 :            : 
     893                 :            :     //--------------------------------------------------------------------
     894                 :          0 :     const SfxFilter* TSortedFilterList::Next()
     895                 :            :     {
     896                 :          0 :         ++m_nIterator;
     897                 :          0 :         return impl_getFilter(m_nIterator);
     898                 :            :     }
     899                 :            : 
     900                 :            :     //--------------------------------------------------------------------
     901                 :          0 :     const SfxFilter* TSortedFilterList::impl_getFilter(sal_Int32 nIndex)
     902                 :            :     {
     903 [ #  # ][ #  # ]:          0 :         if (nIndex<0 || nIndex>=(sal_Int32)m_lFilters.size())
                 [ #  # ]
     904                 :          0 :             return 0;
     905                 :          0 :         const ::rtl::OUString& sFilterName = m_lFilters[nIndex];
     906         [ #  # ]:          0 :         if (sFilterName.isEmpty())
     907                 :          0 :             return 0;
     908         [ #  # ]:          0 :         return SfxFilter::GetFilterByName(String(sFilterName));
     909                 :            :     }
     910                 :            : 
     911                 :            :     //--------------------------------------------------------------------
     912                 :          0 :     void appendFiltersForSave( TSortedFilterList& _rFilterMatcher,
     913                 :            :                                const Reference< XFilterManager >& _rxFilterManager,
     914                 :            :                                ::rtl::OUString& _rFirstNonEmpty, FileDialogHelper_Impl& _rFileDlgImpl,
     915                 :            :                                const ::rtl::OUString& _rFactory )
     916                 :            :     {
     917                 :            :         DBG_ASSERT( _rxFilterManager.is(), "sfx2::appendFiltersForSave: invalid manager!" );
     918         [ #  # ]:          0 :         if ( !_rxFilterManager.is() )
     919                 :          0 :             return;
     920                 :            : 
     921                 :          0 :         ::rtl::OUString sUIName;
     922                 :          0 :         ::rtl::OUString sExtension;
     923                 :            : 
     924                 :            :         // retrieve the default filter for this application module.
     925                 :            :         // It must be set as first of the generated filter list.
     926 [ #  # ][ #  # ]:          0 :         const SfxFilter* pDefaultFilter = SfxFilterContainer::GetDefaultFilter_Impl(_rFactory);
                 [ #  # ]
     927                 :            :         // Only use one extension (#i32434#)
     928                 :            :         // (and always the first if there are more than one)
     929                 :            :         using comphelper::string::getToken;
     930         [ #  # ]:          0 :         sExtension = getToken(pDefaultFilter->GetWildcard().getGlob(), 0, ';');
     931 [ #  # ][ #  # ]:          0 :         sUIName = addExtension( pDefaultFilter->GetUIName(), sExtension, sal_False, _rFileDlgImpl );
                 [ #  # ]
     932                 :            :         try
     933                 :            :         {
     934 [ #  # ][ #  # ]:          0 :             _rxFilterManager->appendFilter( sUIName, sExtension );
     935         [ #  # ]:          0 :             if ( _rFirstNonEmpty.isEmpty() )
     936                 :          0 :                 _rFirstNonEmpty = sUIName;
     937                 :            :         }
     938         [ #  # ]:          0 :         catch( const IllegalArgumentException& )
     939                 :            :         {
     940                 :            :             SAL_WARN( "sfx2.dialog", "Could not append DefaultFilter" << sUIName );
     941                 :            :         }
     942                 :            : 
     943 [ #  # ][ #  # ]:          0 :         for ( const SfxFilter* pFilter = _rFilterMatcher.First(); pFilter; pFilter = _rFilterMatcher.Next() )
                 [ #  # ]
     944                 :            :         {
     945 [ #  # ][ #  # ]:          0 :             if (pFilter->GetName() == pDefaultFilter->GetName())
     946                 :          0 :                 continue;
     947                 :            : 
     948                 :            :             // Only use one extension (#i32434#)
     949                 :            :             // (and always the first if there are more than one)
     950         [ #  # ]:          0 :             sExtension = getToken(pFilter->GetWildcard().getGlob(), 0, ';');
     951 [ #  # ][ #  # ]:          0 :             sUIName = addExtension( pFilter->GetUIName(), sExtension, sal_False, _rFileDlgImpl );
                 [ #  # ]
     952                 :            :             try
     953                 :            :             {
     954 [ #  # ][ #  # ]:          0 :                 _rxFilterManager->appendFilter( sUIName, sExtension );
     955         [ #  # ]:          0 :                 if ( _rFirstNonEmpty.isEmpty() )
     956                 :          0 :                     _rFirstNonEmpty = sUIName;
     957                 :            :             }
     958         [ #  # ]:          0 :             catch( const IllegalArgumentException& )
     959                 :            :             {
     960                 :            :                 SAL_WARN( "sfx2.dialog", "Could not append Filter" << sUIName );
     961                 :            :             }
     962                 :          0 :         }
     963                 :            :     }
     964                 :            : 
     965                 :          0 :     struct ExportFilter
     966                 :            :     {
     967                 :          0 :         ExportFilter( const rtl::OUString& _aUIName, const rtl::OUString& _aWildcard ) :
     968                 :          0 :             aUIName( _aUIName ), aWildcard( _aWildcard ) {}
     969                 :            : 
     970                 :            :         rtl::OUString aUIName;
     971                 :            :         rtl::OUString aWildcard;
     972                 :            :     };
     973                 :            : 
     974                 :            :     //--------------------------------------------------------------------
     975                 :          0 :     void appendExportFilters( TSortedFilterList& _rFilterMatcher,
     976                 :            :                               const Reference< XFilterManager >& _rxFilterManager,
     977                 :            :                               ::rtl::OUString& _rFirstNonEmpty, FileDialogHelper_Impl& _rFileDlgImpl )
     978                 :            :     {
     979                 :            :         DBG_ASSERT( _rxFilterManager.is(), "sfx2::appendExportFilters: invalid manager!" );
     980         [ #  # ]:          0 :         if ( !_rxFilterManager.is() )
     981                 :          0 :             return;
     982                 :            : 
     983                 :          0 :         sal_Int32                           nHTMLIndex  = -1;
     984                 :          0 :         sal_Int32                           nXHTMLIndex  = -1;
     985                 :          0 :         sal_Int32                           nPDFIndex   = -1;
     986                 :          0 :         sal_Int32                           nFlashIndex = -1;
     987                 :          0 :         ::rtl::OUString                     sUIName;
     988                 :          0 :         ::rtl::OUString                     sExtensions;
     989         [ #  # ]:          0 :         std::vector< ExportFilter >         aImportantFilterGroup;
     990         [ #  # ]:          0 :         std::vector< ExportFilter >         aFilterGroup;
     991         [ #  # ]:          0 :         Reference< XFilterGroupManager >    xFilterGroupManager( _rxFilterManager, UNO_QUERY );
     992                 :          0 :         ::rtl::OUString                     sTypeName;
     993         [ #  # ]:          0 :         const ::rtl::OUString               sWriterHTMLType( DEFINE_CONST_OUSTRING("generic_HTML") );
     994         [ #  # ]:          0 :         const ::rtl::OUString               sGraphicHTMLType( DEFINE_CONST_OUSTRING("graphic_HTML") );
     995         [ #  # ]:          0 :         const ::rtl::OUString               sXHTMLType( DEFINE_CONST_OUSTRING("XHTML_File") );
     996         [ #  # ]:          0 :         const ::rtl::OUString               sPDFType( DEFINE_CONST_OUSTRING("pdf_Portable_Document_Format") );
     997         [ #  # ]:          0 :         const ::rtl::OUString               sFlashType( DEFINE_CONST_OUSTRING("graphic_SWF") );
     998                 :            : 
     999 [ #  # ][ #  # ]:          0 :         for ( const SfxFilter* pFilter = _rFilterMatcher.First(); pFilter; pFilter = _rFilterMatcher.Next() )
                 [ #  # ]
    1000                 :            :         {
    1001         [ #  # ]:          0 :             sTypeName   = pFilter->GetTypeName();
    1002         [ #  # ]:          0 :             sUIName     = pFilter->GetUIName();
    1003         [ #  # ]:          0 :             sExtensions = pFilter->GetWildcard().getGlob();
    1004                 :          0 :             ExportFilter aExportFilter( sUIName, sExtensions );
    1005         [ #  # ]:          0 :             String aExt = sExtensions;
    1006                 :            : 
    1007   [ #  #  #  #  :          0 :             if ( nHTMLIndex == -1 &&
           #  # ][ #  # ]
    1008                 :          0 :                 ( sTypeName.equals( sWriterHTMLType ) || sTypeName.equals( sGraphicHTMLType ) ) )
    1009                 :            :             {
    1010         [ #  # ]:          0 :                 aImportantFilterGroup.insert( aImportantFilterGroup.begin(), aExportFilter );
    1011                 :          0 :                 nHTMLIndex = 0;
    1012                 :            :             }
    1013 [ #  # ][ #  # ]:          0 :             else if ( nXHTMLIndex == -1 && sTypeName.equals( sXHTMLType ) )
                 [ #  # ]
    1014                 :            :             {
    1015                 :          0 :                 std::vector< ExportFilter >::iterator aIter = aImportantFilterGroup.begin();
    1016         [ #  # ]:          0 :                 if ( nHTMLIndex == -1 )
    1017         [ #  # ]:          0 :                     aImportantFilterGroup.insert( aIter, aExportFilter );
    1018                 :            :                 else
    1019         [ #  # ]:          0 :                     aImportantFilterGroup.insert( ++aIter, aExportFilter );
    1020                 :          0 :                 nXHTMLIndex = 0;
    1021                 :            :             }
    1022 [ #  # ][ #  # ]:          0 :             else if ( nPDFIndex == -1 && sTypeName.equals( sPDFType ) )
                 [ #  # ]
    1023                 :            :             {
    1024                 :          0 :                 std::vector< ExportFilter >::iterator aIter = aImportantFilterGroup.begin();
    1025         [ #  # ]:          0 :                 if ( nHTMLIndex != -1 )
    1026                 :          0 :                     ++aIter;
    1027         [ #  # ]:          0 :                 if ( nXHTMLIndex != -1 )
    1028                 :          0 :                     ++aIter;
    1029         [ #  # ]:          0 :                 aImportantFilterGroup.insert( aIter, aExportFilter );
    1030                 :          0 :                 nPDFIndex = 0;
    1031                 :            :             }
    1032 [ #  # ][ #  # ]:          0 :             else if ( nFlashIndex == -1 && sTypeName.equals( sFlashType ) )
                 [ #  # ]
    1033                 :            :             {
    1034                 :          0 :                 std::vector< ExportFilter >::iterator aIter = aImportantFilterGroup.begin();
    1035         [ #  # ]:          0 :                 if ( nHTMLIndex != -1 )
    1036                 :          0 :                     ++aIter;
    1037         [ #  # ]:          0 :                 if ( nXHTMLIndex != -1 )
    1038                 :          0 :                     ++aIter;
    1039         [ #  # ]:          0 :                 if ( nPDFIndex != -1 )
    1040                 :          0 :                     ++aIter;
    1041         [ #  # ]:          0 :                 aImportantFilterGroup.insert( aIter, aExportFilter );
    1042                 :          0 :                 nFlashIndex = 0;
    1043                 :            :             }
    1044                 :            :             else
    1045         [ #  # ]:          0 :                 aFilterGroup.push_back( aExportFilter );
    1046         [ #  # ]:          0 :         }
    1047                 :            : 
    1048         [ #  # ]:          0 :         if ( xFilterGroupManager.is() )
    1049                 :            :         {
    1050                 :            :             // Add both html/pdf filter as a filter group to get a separator between both groups
    1051         [ #  # ]:          0 :             if ( !aImportantFilterGroup.empty() )
    1052                 :            :             {
    1053         [ #  # ]:          0 :                 Sequence< StringPair > aFilters( aImportantFilterGroup.size() );
    1054         [ #  # ]:          0 :                 for ( sal_Int32 i = 0; i < (sal_Int32)aImportantFilterGroup.size(); i++ )
    1055                 :            :                 {
    1056         [ #  # ]:          0 :                     aFilters[i].First   = addExtension( aImportantFilterGroup[i].aUIName,
    1057                 :          0 :                                                         aImportantFilterGroup[i].aWildcard,
    1058         [ #  # ]:          0 :                                                         sal_False, _rFileDlgImpl );
    1059         [ #  # ]:          0 :                     aFilters[i].Second  = aImportantFilterGroup[i].aWildcard;
    1060                 :            :                 }
    1061                 :            : 
    1062                 :            :                 try
    1063                 :            :                 {
    1064 [ #  # ][ #  # ]:          0 :                     xFilterGroupManager->appendFilterGroup( ::rtl::OUString(), aFilters );
                 [ #  # ]
    1065                 :            :                 }
    1066         [ #  # ]:          0 :                 catch( const IllegalArgumentException& )
    1067                 :            :                 {
    1068         [ #  # ]:          0 :                 }
    1069                 :            :             }
    1070                 :            : 
    1071         [ #  # ]:          0 :             if ( !aFilterGroup.empty() )
    1072                 :            :             {
    1073         [ #  # ]:          0 :                 Sequence< StringPair > aFilters( aFilterGroup.size() );
    1074         [ #  # ]:          0 :                 for ( sal_Int32 i = 0; i < (sal_Int32)aFilterGroup.size(); i++ )
    1075                 :            :                 {
    1076         [ #  # ]:          0 :                     aFilters[i].First   = addExtension( aFilterGroup[i].aUIName,
    1077                 :          0 :                                                         aFilterGroup[i].aWildcard,
    1078         [ #  # ]:          0 :                                                         sal_False, _rFileDlgImpl );
    1079         [ #  # ]:          0 :                     aFilters[i].Second  = aFilterGroup[i].aWildcard;
    1080                 :            :                 }
    1081                 :            : 
    1082                 :            :                 try
    1083                 :            :                 {
    1084 [ #  # ][ #  # ]:          0 :                     xFilterGroupManager->appendFilterGroup( ::rtl::OUString(), aFilters );
                 [ #  # ]
    1085                 :            :                 }
    1086         [ #  # ]:          0 :                 catch( const IllegalArgumentException& )
    1087                 :            :                 {
    1088         [ #  # ]:          0 :                 }
    1089                 :            :             }
    1090                 :            :         }
    1091                 :            :         else
    1092                 :            :         {
    1093                 :            :             // Fallback solution just add both filter groups as single filters
    1094                 :            :             sal_Int32 n;
    1095                 :            : 
    1096         [ #  # ]:          0 :             for ( n = 0; n < (sal_Int32)aImportantFilterGroup.size(); n++ )
    1097                 :            :             {
    1098                 :            :                 try
    1099                 :            :                 {
    1100                 :          0 :                     rtl::OUString aUIName = addExtension( aImportantFilterGroup[n].aUIName,
    1101                 :          0 :                                                           aImportantFilterGroup[n].aWildcard,
    1102         [ #  # ]:          0 :                                                           sal_False, _rFileDlgImpl );
    1103 [ #  # ][ #  # ]:          0 :                     _rxFilterManager->appendFilter( aUIName, aImportantFilterGroup[n].aWildcard  );
    1104         [ #  # ]:          0 :                     if ( _rFirstNonEmpty.isEmpty() )
    1105         [ #  # ]:          0 :                         _rFirstNonEmpty = sUIName;
    1106                 :            : 
    1107                 :            :                 }
    1108         [ #  # ]:          0 :                 catch( const IllegalArgumentException& )
    1109                 :            :                 {
    1110                 :            :                     SAL_WARN( "sfx2.dialog", "Could not append Filter" << sUIName );
    1111                 :            :                 }
    1112                 :            :             }
    1113                 :            : 
    1114         [ #  # ]:          0 :             for ( n = 0; n < (sal_Int32)aFilterGroup.size(); n++ )
    1115                 :            :             {
    1116                 :            :                 try
    1117                 :            :                 {
    1118                 :          0 :                     rtl::OUString aUIName = addExtension( aFilterGroup[n].aUIName,
    1119                 :          0 :                                                           aFilterGroup[n].aWildcard,
    1120         [ #  # ]:          0 :                                                           sal_False, _rFileDlgImpl );
    1121 [ #  # ][ #  # ]:          0 :                     _rxFilterManager->appendFilter( aUIName, aFilterGroup[n].aWildcard );
    1122         [ #  # ]:          0 :                     if ( _rFirstNonEmpty.isEmpty() )
    1123         [ #  # ]:          0 :                         _rFirstNonEmpty = sUIName;
    1124                 :            : 
    1125                 :            :                 }
    1126         [ #  # ]:          0 :                 catch( const IllegalArgumentException& )
    1127                 :            :                 {
    1128                 :            :                     SAL_WARN( "sfx2.dialog", "Could not append Filter" << sUIName );
    1129                 :            :                 }
    1130                 :            :             }
    1131                 :          0 :         }
    1132                 :            :     }
    1133                 :            : 
    1134                 :            :     //--------------------------------------------------------------------
    1135                 :          0 :     void appendFiltersForOpen( TSortedFilterList& _rFilterMatcher,
    1136                 :            :                                const Reference< XFilterManager >& _rxFilterManager,
    1137                 :            :                                ::rtl::OUString& _rFirstNonEmpty, FileDialogHelper_Impl& _rFileDlgImpl )
    1138                 :            :     {
    1139                 :            :         DBG_ASSERT( _rxFilterManager.is(), "sfx2::appendFiltersForOpen: invalid manager!" );
    1140         [ #  # ]:          0 :         if ( !_rxFilterManager.is() )
    1141                 :          0 :             return;
    1142                 :            : 
    1143                 :            :         // ===============================================================
    1144                 :            :         // group and classify the filters
    1145         [ #  # ]:          0 :         GroupedFilterList aAllFilters;
    1146         [ #  # ]:          0 :         lcl_GroupAndClassify( _rFilterMatcher, aAllFilters );
    1147                 :            : 
    1148                 :            :         // ===============================================================
    1149                 :            :         // ensure that we have the one "all files" entry
    1150         [ #  # ]:          0 :         lcl_EnsureAllFilesEntry( _rFilterMatcher, aAllFilters );
    1151                 :            : 
    1152                 :            :         // ===============================================================
    1153                 :            :         // the first non-empty string - which we assume is the first overall entry
    1154         [ #  # ]:          0 :         if ( !aAllFilters.empty() )
    1155                 :            :         {
    1156                 :          0 :             const FilterGroup& rFirstGroup = *aAllFilters.begin();  // should be the global classes
    1157         [ #  # ]:          0 :             if ( !rFirstGroup.empty() )
    1158                 :          0 :                 _rFirstNonEmpty = rFirstGroup.begin()->First;
    1159                 :            :             // append first group, without extension
    1160         [ #  # ]:          0 :             AppendFilterGroup aGroup( _rxFilterManager, &_rFileDlgImpl );
    1161 [ #  # ][ #  # ]:          0 :             aGroup.appendGroup( rFirstGroup, false );
    1162                 :            :         }
    1163                 :            : 
    1164                 :            :         // ===============================================================
    1165                 :            :         // append the filters to the manager
    1166         [ #  # ]:          0 :         if ( !aAllFilters.empty() )
    1167                 :            :         {
    1168                 :          0 :             ::std::list< FilterGroup >::iterator pIter = aAllFilters.begin();
    1169                 :          0 :             ++pIter;
    1170                 :            :             ::std::for_each(
    1171                 :            :                 pIter, // first filter group was handled seperately, see above
    1172                 :            :                 aAllFilters.end(),
    1173 [ #  # ][ #  # ]:          0 :                 AppendFilterGroup( _rxFilterManager, &_rFileDlgImpl ) );
         [ #  # ][ #  # ]
    1174                 :          0 :         }
    1175                 :            :     }
    1176                 :            : 
    1177                 :          0 :     ::rtl::OUString addExtension( const ::rtl::OUString& _rDisplayText,
    1178                 :            :                                   const ::rtl::OUString& _rExtension,
    1179                 :            :                                   sal_Bool _bForOpen, FileDialogHelper_Impl& _rFileDlgImpl )
    1180                 :            :     {
    1181 [ #  # ][ #  # ]:          0 :         static ::rtl::OUString sAllFilter( "(*.*)" );
    1182 [ #  # ][ #  # ]:          0 :         static ::rtl::OUString sOpenBracket( " ("  );
    1183 [ #  # ][ #  # ]:          0 :         static ::rtl::OUString sCloseBracket( ")" );
    1184                 :          0 :         ::rtl::OUString sRet = _rDisplayText;
    1185                 :            : 
    1186         [ #  # ]:          0 :         if ( sRet.indexOf( sAllFilter ) == -1 )
    1187                 :            :         {
    1188         [ #  # ]:          0 :             String sExt = _rExtension;
    1189         [ #  # ]:          0 :             if ( !_bForOpen )
    1190                 :            :             {
    1191                 :            :                 // show '*' in extensions only when opening a document
    1192 [ #  # ][ #  # ]:          0 :                 sExt = comphelper::string::remove(sExt, '*');
    1193                 :            :             }
    1194                 :          0 :             sRet += sOpenBracket;
    1195         [ #  # ]:          0 :             sRet += sExt;
    1196         [ #  # ]:          0 :             sRet += sCloseBracket;
    1197                 :            :         }
    1198         [ #  # ]:          0 :         _rFileDlgImpl.addFilterPair( _rDisplayText, sRet );
    1199                 :          0 :         return sRet;
    1200                 :            :     }
    1201                 :            : 
    1202                 :            : //........................................................................
    1203                 :            : }   // namespace sfx2
    1204                 :            : //........................................................................
    1205                 :            : 
    1206                 :            : 
    1207                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10