LCOV - code coverage report
Current view: top level - sd/source/ui/dlg - TemplateScanner.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 0 177 0.0 %
Date: 2015-06-13 12:38:46 Functions: 0 24 0.0 %
Legend: Lines: hit not hit

          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 "TemplateScanner.hxx"
      21             : 
      22             : #include <comphelper/processfactory.hxx>
      23             : #include <comphelper/documentconstants.hxx>
      24             : #include <comphelper/string.hxx>
      25             : 
      26             : #include <osl/mutex.hxx>
      27             : #include <vcl/svapp.hxx>
      28             : #include <vcl/settings.hxx>
      29             : #include <sfx2/doctempl.hxx>
      30             : #include <sfx2/templatelocnames.hrc>
      31             : #include <com/sun/star/frame/DocumentTemplates.hpp>
      32             : #include <com/sun/star/frame/XDocumentTemplates.hpp>
      33             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      34             : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
      35             : #include <com/sun/star/ucb/XContentAccess.hpp>
      36             : #include <com/sun/star/sdbc/XResultSet.hpp>
      37             : #include <com/sun/star/sdbc/XRow.hpp>
      38             : 
      39             : #include <set>
      40             : 
      41             : using namespace ::com::sun::star;
      42             : using namespace ::com::sun::star::uno;
      43             : 
      44             : namespace {
      45             : 
      46             : const char TITLE[] = "Title";
      47             : const char TARGET_DIR_URL[] = "TargetDirURL";
      48             : const char DESCRIPTION[] = "TypeDescription";
      49             : const char TARGET_URL[] = "TargetURL";
      50             : 
      51             : //  These strings are used to find impress templates in the tree of
      52             : //  template files.  Should probably be determined dynamically.
      53             : const char IMPRESS_BIN_TEMPLATE[] = "application/vnd.stardivision.impress";
      54             : const char IMPRESS_XML_TEMPLATE[] = MIMETYPE_VND_SUN_XML_IMPRESS_ASCII;
      55             : // The following id comes from the bugdoc in #i2764#.
      56             : const char IMPRESS_XML_TEMPLATE_B[] = "Impress 2.0";
      57             : const char IMPRESS_XML_TEMPLATE_OASIS[] = MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII;
      58             : 
      59           0 : class FolderDescriptor
      60             : {
      61             : public:
      62           0 :     FolderDescriptor (
      63             :         int nPriority,
      64             :         const OUString& rsTitle,
      65             :         const OUString& rsTargetDir,
      66             :         const OUString& rsContentIdentifier,
      67             :         const Reference<com::sun::star::ucb::XCommandEnvironment>& rxFolderEnvironment)
      68             :         : mnPriority(nPriority),
      69             :           msTitle(rsTitle),
      70             :           msTargetDir(rsTargetDir),
      71             :           msContentIdentifier(rsContentIdentifier),
      72           0 :           mxFolderEnvironment(rxFolderEnvironment)
      73           0 :     { }
      74             :     int mnPriority;
      75             :     OUString msTitle;
      76             :     OUString msTargetDir;
      77             :     OUString msContentIdentifier;
      78             :     //    Reference<sdbc::XResultSet> mxFolderResultSet;
      79             :     Reference<com::sun::star::ucb::XCommandEnvironment> mxFolderEnvironment;
      80             : 
      81             :     class Comparator
      82             :     {
      83             :     public:
      84           0 :         bool operator() (const FolderDescriptor& r1, const FolderDescriptor& r2) const
      85           0 :             { return r1.mnPriority < r2.mnPriority; }
      86             :     };
      87             : };
      88             : 
      89             : /** Use a heuristic based on the URL of a top-level template folder to
      90             :     assign a priority that is used to sort the folders.
      91             : */
      92           0 : int Classify (const OUString&, const OUString& rsURL)
      93             : {
      94           0 :     int nPriority (0);
      95             : 
      96           0 :     if (rsURL.isEmpty())
      97           0 :         nPriority = 100;
      98           0 :     else if (rsURL.indexOf("presnt")>=0)
      99             :     {
     100           0 :         nPriority = 30;
     101             :     }
     102           0 :     else if (rsURL.indexOf("layout")>=0)
     103             :     {
     104           0 :         nPriority = 20;
     105             :     }
     106           0 :     else if (rsURL.indexOf("educate")>=0)
     107             :     {
     108           0 :         nPriority = 40;
     109             :     }
     110           0 :     else if (rsURL.indexOf("finance")>=0)
     111             :     {
     112           0 :         nPriority = 40;
     113             :     }
     114             :     else
     115             :     {
     116             :         // All other folders are taken for user supplied and have the
     117             :         // highest priority.
     118           0 :         nPriority = 10;
     119             :     }
     120             : 
     121           0 :     return nPriority;
     122             : }
     123             : 
     124             : } // end of anonymous namespace
     125             : 
     126             : namespace sd
     127             : {
     128             : 
     129           0 : TemplateEntryCompare::TemplateEntryCompare():
     130             :     mpStringSorter(new comphelper::string::NaturalStringSorter(
     131             :                        ::comphelper::getProcessComponentContext(),
     132           0 :                        Application::GetSettings().GetLanguageTag().getLocale())) {}
     133             : 
     134           0 : bool TemplateEntryCompare::operator()(TemplateEntry* pA, TemplateEntry* pB) const
     135             : {
     136           0 :     return 0 > mpStringSorter->compare(pA->msTitle, pB->msTitle);
     137             : }
     138             : 
     139           0 : void TemplateDir::EnableSorting(bool bSortingEnabled)
     140             : {
     141           0 :     mbSortingEnabled = bSortingEnabled;
     142           0 :     if (mbSortingEnabled)
     143             :     {
     144           0 :         if (mpEntryCompare.get() == NULL)
     145           0 :             mpEntryCompare.reset(new TemplateEntryCompare);
     146             : 
     147           0 :         ::std::sort(maEntries.begin(), maEntries.end(), *mpEntryCompare);
     148             :     }
     149           0 : }
     150             : 
     151           0 : void TemplateDir::InsertEntry(TemplateEntry* pNewEntry)
     152             : {
     153           0 :     if (mbSortingEnabled)
     154             :     {
     155             :         ::std::vector<TemplateEntry*>::iterator aPlaceToInsert =
     156           0 :             ::std::upper_bound(maEntries.begin(), maEntries.end(), pNewEntry, *mpEntryCompare);
     157           0 :         maEntries.insert(aPlaceToInsert, pNewEntry);
     158             :     }
     159             :     else
     160           0 :         maEntries.push_back(pNewEntry);
     161           0 : }
     162             : 
     163           0 : class TemplateScanner::FolderDescriptorList
     164             :     : public ::std::multiset<FolderDescriptor,FolderDescriptor::Comparator>
     165             : {
     166             : };
     167             : 
     168           0 : TemplateScanner::TemplateScanner()
     169             :     : meState(INITIALIZE_SCANNING),
     170             :       maFolderContent(),
     171             :       mpTemplateDirectory(NULL),
     172             :       maFolderList(),
     173             :       mbEntrySortingEnabled(false),
     174             :       mpLastAddedEntry(NULL),
     175           0 :       mpFolderDescriptors(new FolderDescriptorList()),
     176             :       mxTemplateRoot(),
     177             :       mxFolderEnvironment(),
     178             :       mxEntryEnvironment(),
     179             :       mxFolderResultSet(),
     180           0 :       mxEntryResultSet()
     181             : {
     182             :     //  empty;
     183           0 : }
     184             : 
     185           0 : TemplateScanner::~TemplateScanner()
     186             : {
     187           0 :     mpFolderDescriptors.reset();
     188             : 
     189             :     // Delete all entries of the template list that have not been
     190             :     // transferred to another object.
     191           0 :     std::vector<TemplateDir*>::iterator I;
     192           0 :     for (I=maFolderList.begin(); I!=maFolderList.end(); ++I)
     193           0 :         if (*I != NULL)
     194           0 :             delete *I;
     195           0 : }
     196             : 
     197           0 : TemplateScanner::State TemplateScanner::GetTemplateRoot()
     198             : {
     199           0 :     State eNextState (INITIALIZE_FOLDER_SCANNING);
     200             : 
     201           0 :     Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
     202           0 :     Reference<frame::XDocumentTemplates> xTemplates = frame::DocumentTemplates::create(xContext);
     203           0 :     mxTemplateRoot = xTemplates->getContent();
     204             : 
     205           0 :     return eNextState;
     206             : }
     207             : 
     208           0 : TemplateScanner::State TemplateScanner::InitializeEntryScanning()
     209             : {
     210           0 :     State eNextState (SCAN_ENTRY);
     211             : 
     212           0 :     if (maFolderContent.isFolder())
     213             :     {
     214           0 :         mxEntryEnvironment = Reference<com::sun::star::ucb::XCommandEnvironment>();
     215             : 
     216             :         //  We are interested only in three properties: the entry's name,
     217             :         //  its URL, and its content type.
     218           0 :         Sequence<OUString> aProps (3);
     219           0 :         aProps[0] = TITLE;
     220           0 :         aProps[1] = TARGET_URL;
     221           0 :         aProps[2] = DESCRIPTION;
     222             : 
     223             :         //  Create a cursor to iterate over the templates in this folders.
     224           0 :         ::ucbhelper::ResultSetInclude eInclude = ::ucbhelper::INCLUDE_DOCUMENTS_ONLY;
     225           0 :         mxEntryResultSet = Reference<com::sun::star::sdbc::XResultSet>(
     226           0 :             maFolderContent.createCursor(aProps, eInclude));
     227             :     }
     228             :     else
     229           0 :         eNextState = ERROR;
     230             : 
     231           0 :     return eNextState;
     232             : }
     233             : 
     234           0 : TemplateScanner::State TemplateScanner::ScanEntry()
     235             : {
     236           0 :     State eNextState (ERROR);
     237             : 
     238           0 :     Reference<com::sun::star::ucb::XContentAccess> xContentAccess (mxEntryResultSet, UNO_QUERY);
     239           0 :     Reference<com::sun::star::sdbc::XRow> xRow (mxEntryResultSet, UNO_QUERY);
     240             : 
     241           0 :     if (xContentAccess.is() && xRow.is() && mxEntryResultSet.is())
     242             :     {
     243           0 :         if (mxEntryResultSet->next())
     244             :         {
     245           0 :             OUString sTitle (xRow->getString (1));
     246           0 :             OUString sTargetURL (xRow->getString (2));
     247           0 :             OUString sContentType (xRow->getString (3));
     248             : 
     249           0 :             OUString aId = xContentAccess->queryContentIdentifierString();
     250           0 :             ::ucbhelper::Content  aContent = ::ucbhelper::Content (aId, mxEntryEnvironment, comphelper::getProcessComponentContext());
     251           0 :             if (aContent.isDocument ())
     252             :             {
     253             :                 //  Check whether the entry is an impress template.  If so
     254             :                 //  add a new entry to the resulting list (which is created
     255             :                 //  first if necessary).
     256           0 :                 if (    (sContentType == MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII)
     257           0 :                     ||  (sContentType == IMPRESS_XML_TEMPLATE_OASIS)
     258           0 :                     ||  (sContentType == IMPRESS_BIN_TEMPLATE)
     259           0 :                     ||  (sContentType == IMPRESS_XML_TEMPLATE)
     260           0 :                     ||  (sContentType == IMPRESS_XML_TEMPLATE_B))
     261             :                 {
     262             :                     OUString sLocalisedTitle = SfxDocumentTemplates::ConvertResourceString(
     263           0 :                         STR_TEMPLATE_NAME1_DEF, STR_TEMPLATE_NAME1, NUM_TEMPLATE_NAMES, sTitle );
     264           0 :                     mpLastAddedEntry = new TemplateEntry(sLocalisedTitle, sTargetURL);
     265           0 :                     mpTemplateDirectory->InsertEntry(mpLastAddedEntry);
     266             :                 }
     267             :             }
     268             : 
     269             :             // Continue scanning entries.
     270           0 :             eNextState = SCAN_ENTRY;
     271             :         }
     272             :         else
     273             :         {
     274           0 :             if (mpTemplateDirectory->maEntries.empty())
     275             :             {
     276           0 :                 delete mpTemplateDirectory;
     277           0 :                 mpTemplateDirectory = NULL;
     278             :             }
     279             :             else
     280             :             {
     281           0 :                 SolarMutexGuard aGuard;
     282           0 :                 maFolderList.push_back(mpTemplateDirectory);
     283             :             }
     284             : 
     285             :             // Continue with scanning the next folder.
     286           0 :             eNextState = SCAN_FOLDER;
     287             :         }
     288             :     }
     289             : 
     290           0 :     return eNextState;
     291             : }
     292             : 
     293           0 : TemplateScanner::State TemplateScanner::InitializeFolderScanning()
     294             : {
     295           0 :     State eNextState (ERROR);
     296             : 
     297           0 :     mxFolderResultSet = Reference<sdbc::XResultSet>();
     298             : 
     299             :     try
     300             :     {
     301             :         //  Create content for template folders.
     302           0 :         mxFolderEnvironment = Reference<com::sun::star::ucb::XCommandEnvironment>();
     303           0 :         ::ucbhelper::Content aTemplateDir (mxTemplateRoot, mxFolderEnvironment, comphelper::getProcessComponentContext());
     304             : 
     305             :         //  Define the list of properties we are interested in.
     306           0 :         Sequence<OUString> aProps (2);
     307           0 :         aProps[0] = TITLE;
     308           0 :         aProps[1] = TARGET_DIR_URL;
     309             : 
     310             :         //  Create an cursor to iterate over the template folders.
     311           0 :         ::ucbhelper::ResultSetInclude eInclude = ::ucbhelper::INCLUDE_FOLDERS_ONLY;
     312           0 :         mxFolderResultSet = Reference<sdbc::XResultSet>(
     313           0 :             aTemplateDir.createCursor(aProps, eInclude));
     314           0 :         if (mxFolderResultSet.is())
     315           0 :             eNextState = GATHER_FOLDER_LIST;
     316             :     }
     317           0 :     catch (::com::sun::star::uno::Exception&)
     318             :     {
     319           0 :        eNextState = ERROR;
     320             :     }
     321             : 
     322           0 :     return eNextState;
     323             : }
     324             : 
     325           0 : TemplateScanner::State TemplateScanner::GatherFolderList()
     326             : {
     327           0 :     State eNextState (ERROR);
     328             : 
     329           0 :     Reference<com::sun::star::ucb::XContentAccess> xContentAccess (mxFolderResultSet, UNO_QUERY);
     330           0 :     if (xContentAccess.is() && mxFolderResultSet.is())
     331             :     {
     332           0 :         while (mxFolderResultSet->next())
     333             :         {
     334           0 :             Reference<sdbc::XRow> xRow (mxFolderResultSet, UNO_QUERY);
     335           0 :             if (xRow.is())
     336             :             {
     337           0 :                 OUString sTitle (xRow->getString (1));
     338           0 :                 OUString sTargetDir (xRow->getString (2));
     339           0 :                 OUString aId = xContentAccess->queryContentIdentifierString();
     340             : 
     341           0 :                 mpFolderDescriptors->insert(
     342             :                     FolderDescriptor(
     343             :                         Classify(sTitle,sTargetDir),
     344             :                         sTitle,
     345             :                         sTargetDir,
     346             :                         aId,
     347           0 :                         mxFolderEnvironment));
     348             :             }
     349           0 :         }
     350             : 
     351           0 :         eNextState = SCAN_FOLDER;
     352             :     }
     353             : 
     354           0 :     return eNextState;
     355             : }
     356             : 
     357           0 : TemplateScanner::State TemplateScanner::ScanFolder()
     358             : {
     359           0 :     State eNextState (ERROR);
     360             : 
     361           0 :     if (mpFolderDescriptors->size() > 0)
     362             :     {
     363           0 :         FolderDescriptor aDescriptor (*mpFolderDescriptors->begin());
     364           0 :         mpFolderDescriptors->erase(mpFolderDescriptors->begin());
     365             : 
     366           0 :         OUString sTitle (aDescriptor.msTitle);
     367           0 :         OUString sTargetDir (aDescriptor.msTargetDir);
     368           0 :         OUString aId (aDescriptor.msContentIdentifier);
     369             : 
     370           0 :         maFolderContent = ::ucbhelper::Content (aId, aDescriptor.mxFolderEnvironment, comphelper::getProcessComponentContext());
     371           0 :         if (maFolderContent.isFolder())
     372             :         {
     373             :             // Scan the folder and insert it into the list of template
     374             :             // folders.
     375           0 :             mpTemplateDirectory = new TemplateDir (sTitle, sTargetDir);
     376           0 :             mpTemplateDirectory->EnableSorting(mbEntrySortingEnabled);
     377             :             // Continue with scanning all entries in the folder.
     378           0 :             eNextState = INITIALIZE_ENTRY_SCAN;
     379           0 :         }
     380             :     }
     381             :     else
     382             :     {
     383           0 :         eNextState = DONE;
     384             :     }
     385             : 
     386           0 :     return eNextState;
     387             : }
     388             : 
     389           0 : void TemplateScanner::Scan()
     390             : {
     391           0 :     while (HasNextStep())
     392           0 :         RunNextStep();
     393           0 : }
     394             : 
     395           0 : void TemplateScanner::RunNextStep()
     396             : {
     397           0 :     switch (meState)
     398             :     {
     399             :         case INITIALIZE_SCANNING:
     400           0 :             meState = GetTemplateRoot();
     401           0 :             break;
     402             : 
     403             :         case INITIALIZE_FOLDER_SCANNING:
     404           0 :             meState = InitializeFolderScanning();
     405           0 :             break;
     406             : 
     407             :         case SCAN_FOLDER:
     408           0 :             meState = ScanFolder();
     409           0 :             break;
     410             : 
     411             :         case GATHER_FOLDER_LIST:
     412           0 :             meState = GatherFolderList();
     413           0 :             break;
     414             : 
     415             :         case INITIALIZE_ENTRY_SCAN:
     416           0 :             meState = InitializeEntryScanning();
     417           0 :             break;
     418             : 
     419             :         case SCAN_ENTRY:
     420           0 :             meState = ScanEntry();
     421           0 :             break;
     422             :         default:
     423           0 :             break;
     424             :     }
     425             : 
     426           0 :     switch (meState)
     427             :     {
     428             :         case DONE:
     429             :         case ERROR:
     430           0 :             mxTemplateRoot.clear();
     431           0 :             mxTemplateRoot.clear();
     432           0 :             mxFolderEnvironment.clear();
     433           0 :             mxEntryEnvironment.clear();
     434           0 :             mxFolderResultSet.clear();
     435           0 :             mxEntryResultSet.clear();
     436           0 :             mpLastAddedEntry = NULL;
     437           0 :             break;
     438             :         default:
     439           0 :             break;
     440             :     }
     441           0 : }
     442             : 
     443           0 : bool TemplateScanner::HasNextStep()
     444             : {
     445           0 :     switch (meState)
     446             :     {
     447             :         case DONE:
     448             :         case ERROR:
     449           0 :             return false;
     450             : 
     451             :         default:
     452           0 :             return true;
     453             :     }
     454             : }
     455             : 
     456             : }
     457             : 
     458             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11