LibreOffice Module sd (master) 1
TemplateScanner.cxx
Go to the documentation of this file.
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
24
25#include <sfx2/doctempl.hxx>
26#include <com/sun/star/frame/DocumentTemplates.hpp>
27#include <com/sun/star/frame/XDocumentTemplates.hpp>
28#include <com/sun/star/ucb/XContentAccess.hpp>
29#include <com/sun/star/sdbc/XResultSet.hpp>
30#include <com/sun/star/sdbc/XRow.hpp>
31
32#include <set>
33#include <utility>
34
35using namespace ::com::sun::star;
36using namespace ::com::sun::star::uno;
37
38namespace {
39
40constexpr OUStringLiteral TITLE = u"Title";
41
42class FolderDescriptor
43{
44public:
45 FolderDescriptor (
46 int nPriority,
47 OUString sContentIdentifier,
48 const Reference<css::ucb::XCommandEnvironment>& rxFolderEnvironment)
49 : mnPriority(nPriority),
50 msContentIdentifier(std::move(sContentIdentifier)),
51 mxFolderEnvironment(rxFolderEnvironment)
52 { }
53 int mnPriority;
54 OUString msContentIdentifier;
55 // Reference<sdbc::XResultSet> mxFolderResultSet;
56 Reference<css::ucb::XCommandEnvironment> mxFolderEnvironment;
57
58 class Comparator
59 {
60 public:
61 bool operator() (const FolderDescriptor& r1, const FolderDescriptor& r2) const
62 { return r1.mnPriority < r2.mnPriority; }
63 };
64};
65
69int Classify (std::u16string_view rsURL)
70{
71 int nPriority (0);
72
73 if (rsURL.empty())
74 nPriority = 100;
75 else if (rsURL.find(u"presnt") != std::u16string_view::npos)
76 {
77 nPriority = 30;
78 }
79 else if (rsURL.find(u"layout") != std::u16string_view::npos)
80 {
81 nPriority = 20;
82 }
83 else if (rsURL.find(u"educate") != std::u16string_view::npos)
84 {
85 nPriority = 40;
86 }
87 else if (rsURL.find(u"finance") != std::u16string_view::npos)
88 {
89 nPriority = 40;
90 }
91 else
92 {
93 // All other folders are taken for user supplied and have the
94 // highest priority.
95 nPriority = 10;
96 }
97
98 return nPriority;
99}
100
101} // end of anonymous namespace
102
103namespace sd
104{
105
107 : public ::std::multiset<FolderDescriptor,FolderDescriptor::Comparator>
108{
109};
110
112 : meState(INITIALIZE_SCANNING),
113 mpFolderDescriptors(new FolderDescriptorList)
114{
115 // empty;
116}
117
119{
120}
121
123{
124 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
125 Reference<frame::XDocumentTemplates> xTemplates = frame::DocumentTemplates::create(xContext);
126 mxTemplateRoot = xTemplates->getContent();
127
129}
130
132{
133 State eNextState (SCAN_ENTRY);
134
136 {
137 mxEntryEnvironment.clear();
138
139 // Create a cursor to iterate over the templates in this folders.
140 // We are interested only in three properties: the entry's name,
141 // its URL, and its content type.
142 mxEntryResultSet.set( maFolderContent.createCursor({ TITLE, "TargetURL", "TypeDescription" }, ::ucbhelper::INCLUDE_DOCUMENTS_ONLY));
143 }
144 else
145 eNextState = ERROR;
146
147 return eNextState;
148}
149
151{
152 State eNextState (ERROR);
153
154 Reference<css::ucb::XContentAccess> xContentAccess (mxEntryResultSet, UNO_QUERY);
155 Reference<css::sdbc::XRow> xRow (mxEntryResultSet, UNO_QUERY);
156
157 if (xContentAccess.is() && xRow.is() && mxEntryResultSet.is())
158 {
159 if (mxEntryResultSet->next())
160 {
161 OUString sTitle (xRow->getString (1));
162 OUString sTargetURL (xRow->getString (2));
163 OUString sContentType (xRow->getString (3));
164
165 OUString aId = xContentAccess->queryContentIdentifierString();
167 if (aContent.isDocument ())
168 {
169 // Check whether the entry is an impress template. If so
170 // add a new entry to the resulting list (which is created
171 // first if necessary).
172 // These strings are used to find impress templates in the tree of
173 // template files. Should probably be determined dynamically.
176 || (sContentType == "application/vnd.stardivision.impress")
177 || (sContentType == MIMETYPE_VND_SUN_XML_IMPRESS_ASCII)
178 // The following id comes from the bugdoc in #i2764#.
179 || (sContentType == "Impress 2.0"))
180 {
181 OUString sLocalisedTitle = SfxDocumentTemplates::ConvertResourceString(sTitle);
182 mpTemplateEntries.push_back(std::make_unique<TemplateEntry>(sLocalisedTitle, sTargetURL));
183 }
184 }
185
186 // Continue scanning entries.
187 eNextState = SCAN_ENTRY;
188 }
189 else
190 {
191 // Continue with scanning the next folder.
192 eNextState = SCAN_FOLDER;
193 }
194 }
195
196 return eNextState;
197}
198
200{
201 State eNextState (ERROR);
202
203 mxFolderResultSet.clear();
204
205 try
206 {
207 // Create content for template folders.
208 mxFolderEnvironment.clear();
210
211 // Create a cursor to iterate over the template folders.
212 mxFolderResultSet.set( aTemplateDir.createCursor({ TITLE, "TargetDirURL" }, ::ucbhelper::INCLUDE_FOLDERS_ONLY));
213 if (mxFolderResultSet.is())
214 eNextState = GATHER_FOLDER_LIST;
215 }
216 catch (css::uno::Exception&)
217 {
218 eNextState = ERROR;
219 }
220
221 return eNextState;
222}
223
225{
226 State eNextState (ERROR);
227
228 Reference<css::ucb::XContentAccess> xContentAccess (mxFolderResultSet, UNO_QUERY);
229 if (xContentAccess.is() && mxFolderResultSet.is())
230 {
231 while (mxFolderResultSet->next())
232 {
233 Reference<sdbc::XRow> xRow (mxFolderResultSet, UNO_QUERY);
234 if (xRow.is())
235 {
236 OUString sTargetDir (xRow->getString (2));
237 OUString aId = xContentAccess->queryContentIdentifierString();
238
239 mpFolderDescriptors->insert(
240 FolderDescriptor(
241 Classify(sTargetDir),
242 aId,
244 }
245 }
246
247 eNextState = SCAN_FOLDER;
248 }
249
250 return eNextState;
251}
252
254{
255 State eNextState (ERROR);
256
257 if (!mpFolderDescriptors->empty())
258 {
259 FolderDescriptor aDescriptor (*mpFolderDescriptors->begin());
261
262 OUString aId (aDescriptor.msContentIdentifier);
263
264 maFolderContent = ::ucbhelper::Content (aId, aDescriptor.mxFolderEnvironment, comphelper::getProcessComponentContext());
266 {
267 // Scan the folder and insert it into the list of template
268 // folders.
269 // Continue with scanning all entries in the folder.
270 mpTemplateEntries.clear();
271 eNextState = INITIALIZE_ENTRY_SCAN;
272 }
273 }
274 else
275 {
276 eNextState = DONE;
277 }
278
279 return eNextState;
280}
281
283{
284 switch (meState)
285 {
288 break;
289
292 break;
293
294 case SCAN_FOLDER:
296 break;
297
300 break;
301
304 break;
305
306 case SCAN_ENTRY:
307 meState = ScanEntry();
308 break;
309 default:
310 break;
311 }
312
313 switch (meState)
314 {
315 case DONE:
316 case ERROR:
317 mxTemplateRoot.clear();
318 mxFolderEnvironment.clear();
319 mxEntryEnvironment.clear();
320 mxFolderResultSet.clear();
321 mxEntryResultSet.clear();
322 break;
323 default:
324 break;
325 }
326}
327
329{
330 switch (meState)
331 {
332 case DONE:
333 case ERROR:
334 return false;
335
336 default:
337 return true;
338 }
339}
340
341}
342
343/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static OUString ConvertResourceString(const OUString &rString)
State GatherFolderList()
Collect all available top-level folders in an ordered list which can then be processed by ScanFolder(...
State ScanEntry()
Scan one entry.
css::uno::Reference< css::ucb::XCommandEnvironment > mxEntryEnvironment
State
The current state determines which step will be executed next by RunNextStep().
::ucbhelper::Content maFolderContent
virtual ~TemplateScanner()
The destructor deletes any remaining entries of the local list of templates.
std::unique_ptr< FolderDescriptorList > mpFolderDescriptors
TemplateScanner()
Create a new template scanner and prepare but do not execute the scanning.
virtual bool HasNextStep() override
Implementation of the AsynchronousTask interface method.
State InitializeFolderScanning()
Initialize the scanning of folders.
css::uno::Reference< css::ucb::XContent > mxTemplateRoot
Set of state variables used by the methods InitializeFolderScanning(), GatherFolderList(),...
State GetTemplateRoot()
Obtain the root folder of the template folder hierarchy.
css::uno::Reference< css::sdbc::XResultSet > mxFolderResultSet
State InitializeEntryScanning()
Initialize the scanning of entries of a top-level folder.
State ScanFolder()
From the list of top-level folders collected by GatherFolderList() the one with highest priority is p...
virtual void RunNextStep() override
Implementation of the AsynchronousTask interface method.
css::uno::Reference< css::sdbc::XResultSet > mxEntryResultSet
css::uno::Reference< css::ucb::XCommandEnvironment > mxFolderEnvironment
::std::vector< std::unique_ptr< TemplateEntry > > mpTemplateEntries
css::uno::Reference< css::sdbc::XResultSet > createCursor(const css::uno::Sequence< OUString > &rPropertyNames, ResultSetInclude eMode=INCLUDE_FOLDERS_AND_DOCUMENTS)
constexpr OUStringLiteral TITLE
constexpr OUStringLiteral MIMETYPE_VND_SUN_XML_IMPRESS_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII
float u
Reference< XComponentContext > getProcessComponentContext()
double mnPriority