1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <TemplateScanner.hxx>
22 #include <comphelper/processfactory.hxx>
23 #include <comphelper/documentconstants.hxx>
24 #include <comphelper/string.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/settings.hxx>
28 #include <sfx2/doctempl.hxx>
29 #include <com/sun/star/frame/DocumentTemplates.hpp>
30 #include <com/sun/star/frame/XDocumentTemplates.hpp>
31 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
33 #include <com/sun/star/ucb/XContentAccess.hpp>
34 #include <com/sun/star/sdbc/XResultSet.hpp>
35 #include <com/sun/star/sdbc/XRow.hpp>
39 using namespace ::com::sun::star
;
40 using namespace ::com::sun::star::uno
;
44 const char TITLE
[] = "Title";
46 class FolderDescriptor
51 const OUString
& rsContentIdentifier
,
52 const Reference
<css::ucb::XCommandEnvironment
>& rxFolderEnvironment
)
53 : mnPriority(nPriority
),
54 msContentIdentifier(rsContentIdentifier
),
55 mxFolderEnvironment(rxFolderEnvironment
)
58 OUString msContentIdentifier
;
59 // Reference<sdbc::XResultSet> mxFolderResultSet;
60 Reference
<css::ucb::XCommandEnvironment
> mxFolderEnvironment
;
65 bool operator() (const FolderDescriptor
& r1
, const FolderDescriptor
& r2
) const
66 { return r1
.mnPriority
< r2
.mnPriority
; }
70 /** Use a heuristic based on the URL of a top-level template folder to
71 assign a priority that is used to sort the folders.
73 int Classify (const OUString
&, const OUString
& rsURL
)
79 else if (rsURL
.indexOf("presnt")>=0)
83 else if (rsURL
.indexOf("layout")>=0)
87 else if (rsURL
.indexOf("educate")>=0)
91 else if (rsURL
.indexOf("finance")>=0)
97 // All other folders are taken for user supplied and have the
105 } // end of anonymous namespace
110 class TemplateScanner::FolderDescriptorList
111 : public ::std::multiset
<FolderDescriptor
,FolderDescriptor::Comparator
>
115 TemplateScanner::TemplateScanner()
116 : meState(INITIALIZE_SCANNING
),
118 mpFolderDescriptors(new FolderDescriptorList
),
120 mxFolderEnvironment(),
121 mxEntryEnvironment(),
128 TemplateScanner::~TemplateScanner()
132 TemplateScanner::State
TemplateScanner::GetTemplateRoot()
134 Reference
< XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
135 Reference
<frame::XDocumentTemplates
> xTemplates
= frame::DocumentTemplates::create(xContext
);
136 mxTemplateRoot
= xTemplates
->getContent();
138 return INITIALIZE_FOLDER_SCANNING
;
141 TemplateScanner::State
TemplateScanner::InitializeEntryScanning()
143 State
eNextState (SCAN_ENTRY
);
145 if (maFolderContent
.isFolder())
147 mxEntryEnvironment
.clear();
149 // We are interested only in three properties: the entry's name,
150 // its URL, and its content type.
151 Sequence
<OUString
> aProps (3);
153 aProps
[1] = "TargetURL";
154 aProps
[2] = "TypeDescription";
156 // Create a cursor to iterate over the templates in this folders.
157 mxEntryResultSet
.set( maFolderContent
.createCursor(aProps
, ::ucbhelper::INCLUDE_DOCUMENTS_ONLY
));
165 TemplateScanner::State
TemplateScanner::ScanEntry()
167 State
eNextState (ERROR
);
169 Reference
<css::ucb::XContentAccess
> xContentAccess (mxEntryResultSet
, UNO_QUERY
);
170 Reference
<css::sdbc::XRow
> xRow (mxEntryResultSet
, UNO_QUERY
);
172 if (xContentAccess
.is() && xRow
.is() && mxEntryResultSet
.is())
174 if (mxEntryResultSet
->next())
176 OUString
sTitle (xRow
->getString (1));
177 OUString
sTargetURL (xRow
->getString (2));
178 OUString
sContentType (xRow
->getString (3));
180 OUString aId
= xContentAccess
->queryContentIdentifierString();
181 ::ucbhelper::Content aContent
= ::ucbhelper::Content (aId
, mxEntryEnvironment
, comphelper::getProcessComponentContext());
182 if (aContent
.isDocument ())
184 // Check whether the entry is an impress template. If so
185 // add a new entry to the resulting list (which is created
186 // first if necessary).
187 // These strings are used to find impress templates in the tree of
188 // template files. Should probably be determined dynamically.
189 if ( (sContentType
== MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII
)
190 || (sContentType
== MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII
)
191 || (sContentType
== "application/vnd.stardivision.impress")
192 || (sContentType
== MIMETYPE_VND_SUN_XML_IMPRESS_ASCII
)
193 // The following id comes from the bugdoc in #i2764#.
194 || (sContentType
== "Impress 2.0"))
196 OUString sLocalisedTitle
= SfxDocumentTemplates::ConvertResourceString(sTitle
);
197 mpTemplateEntries
.push_back(o3tl::make_unique
<TemplateEntry
>(sLocalisedTitle
, sTargetURL
));
201 // Continue scanning entries.
202 eNextState
= SCAN_ENTRY
;
206 // Continue with scanning the next folder.
207 eNextState
= SCAN_FOLDER
;
214 TemplateScanner::State
TemplateScanner::InitializeFolderScanning()
216 State
eNextState (ERROR
);
218 mxFolderResultSet
.clear();
222 // Create content for template folders.
223 mxFolderEnvironment
.clear();
224 ::ucbhelper::Content
aTemplateDir (mxTemplateRoot
, mxFolderEnvironment
, comphelper::getProcessComponentContext());
226 // Define the list of properties we are interested in.
227 Sequence
<OUString
> aProps (2);
229 aProps
[1] = "TargetDirURL";
231 // Create an cursor to iterate over the template folders.
232 mxFolderResultSet
.set( aTemplateDir
.createCursor(aProps
, ::ucbhelper::INCLUDE_FOLDERS_ONLY
));
233 if (mxFolderResultSet
.is())
234 eNextState
= GATHER_FOLDER_LIST
;
236 catch (css::uno::Exception
&)
244 TemplateScanner::State
TemplateScanner::GatherFolderList()
246 State
eNextState (ERROR
);
248 Reference
<css::ucb::XContentAccess
> xContentAccess (mxFolderResultSet
, UNO_QUERY
);
249 if (xContentAccess
.is() && mxFolderResultSet
.is())
251 while (mxFolderResultSet
->next())
253 Reference
<sdbc::XRow
> xRow (mxFolderResultSet
, UNO_QUERY
);
256 OUString
sTitle (xRow
->getString (1));
257 OUString
sTargetDir (xRow
->getString (2));
258 OUString aId
= xContentAccess
->queryContentIdentifierString();
260 mpFolderDescriptors
->insert(
262 Classify(sTitle
,sTargetDir
),
264 mxFolderEnvironment
));
268 eNextState
= SCAN_FOLDER
;
274 TemplateScanner::State
TemplateScanner::ScanFolder()
276 State
eNextState (ERROR
);
278 if (mpFolderDescriptors
->size() > 0)
280 FolderDescriptor
aDescriptor (*mpFolderDescriptors
->begin());
281 mpFolderDescriptors
->erase(mpFolderDescriptors
->begin());
283 OUString
aId (aDescriptor
.msContentIdentifier
);
285 maFolderContent
= ::ucbhelper::Content (aId
, aDescriptor
.mxFolderEnvironment
, comphelper::getProcessComponentContext());
286 if (maFolderContent
.isFolder())
288 // Scan the folder and insert it into the list of template
290 // Continue with scanning all entries in the folder.
291 mpTemplateEntries
.clear();
292 eNextState
= INITIALIZE_ENTRY_SCAN
;
303 void TemplateScanner::RunNextStep()
307 case INITIALIZE_SCANNING
:
308 meState
= GetTemplateRoot();
311 case INITIALIZE_FOLDER_SCANNING
:
312 meState
= InitializeFolderScanning();
316 meState
= ScanFolder();
319 case GATHER_FOLDER_LIST
:
320 meState
= GatherFolderList();
323 case INITIALIZE_ENTRY_SCAN
:
324 meState
= InitializeEntryScanning();
328 meState
= ScanEntry();
338 mxTemplateRoot
.clear();
339 mxFolderEnvironment
.clear();
340 mxEntryEnvironment
.clear();
341 mxFolderResultSet
.clear();
342 mxEntryResultSet
.clear();
349 bool TemplateScanner::HasNextStep()
364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */