Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sd / source / ui / dlg / TemplateScanner.cxx
blob96a8516f72494b1ea3ee2d746deb26c8dc7434f5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
37 #include <set>
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::uno;
42 namespace {
44 const char TITLE[] = "Title";
46 class FolderDescriptor
48 public:
49 FolderDescriptor (
50 int nPriority,
51 const OUString& rsContentIdentifier,
52 const Reference<css::ucb::XCommandEnvironment>& rxFolderEnvironment)
53 : mnPriority(nPriority),
54 msContentIdentifier(rsContentIdentifier),
55 mxFolderEnvironment(rxFolderEnvironment)
56 { }
57 int mnPriority;
58 OUString msContentIdentifier;
59 // Reference<sdbc::XResultSet> mxFolderResultSet;
60 Reference<css::ucb::XCommandEnvironment> mxFolderEnvironment;
62 class Comparator
64 public:
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)
75 int nPriority (0);
77 if (rsURL.isEmpty())
78 nPriority = 100;
79 else if (rsURL.indexOf("presnt")>=0)
81 nPriority = 30;
83 else if (rsURL.indexOf("layout")>=0)
85 nPriority = 20;
87 else if (rsURL.indexOf("educate")>=0)
89 nPriority = 40;
91 else if (rsURL.indexOf("finance")>=0)
93 nPriority = 40;
95 else
97 // All other folders are taken for user supplied and have the
98 // highest priority.
99 nPriority = 10;
102 return nPriority;
105 } // end of anonymous namespace
107 namespace sd
110 class TemplateScanner::FolderDescriptorList
111 : public ::std::multiset<FolderDescriptor,FolderDescriptor::Comparator>
115 TemplateScanner::TemplateScanner()
116 : meState(INITIALIZE_SCANNING),
117 maFolderContent(),
118 mpFolderDescriptors(new FolderDescriptorList),
119 mxTemplateRoot(),
120 mxFolderEnvironment(),
121 mxEntryEnvironment(),
122 mxFolderResultSet(),
123 mxEntryResultSet()
125 // empty;
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);
152 aProps[0] = TITLE;
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));
159 else
160 eNextState = ERROR;
162 return eNextState;
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;
204 else
206 // Continue with scanning the next folder.
207 eNextState = SCAN_FOLDER;
211 return eNextState;
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);
228 aProps[0] = TITLE;
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&)
238 eNextState = ERROR;
241 return eNextState;
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);
254 if (xRow.is())
256 OUString sTitle (xRow->getString (1));
257 OUString sTargetDir (xRow->getString (2));
258 OUString aId = xContentAccess->queryContentIdentifierString();
260 mpFolderDescriptors->insert(
261 FolderDescriptor(
262 Classify(sTitle,sTargetDir),
263 aId,
264 mxFolderEnvironment));
268 eNextState = SCAN_FOLDER;
271 return eNextState;
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
289 // folders.
290 // Continue with scanning all entries in the folder.
291 mpTemplateEntries.clear();
292 eNextState = INITIALIZE_ENTRY_SCAN;
295 else
297 eNextState = DONE;
300 return eNextState;
303 void TemplateScanner::RunNextStep()
305 switch (meState)
307 case INITIALIZE_SCANNING:
308 meState = GetTemplateRoot();
309 break;
311 case INITIALIZE_FOLDER_SCANNING:
312 meState = InitializeFolderScanning();
313 break;
315 case SCAN_FOLDER:
316 meState = ScanFolder();
317 break;
319 case GATHER_FOLDER_LIST:
320 meState = GatherFolderList();
321 break;
323 case INITIALIZE_ENTRY_SCAN:
324 meState = InitializeEntryScanning();
325 break;
327 case SCAN_ENTRY:
328 meState = ScanEntry();
329 break;
330 default:
331 break;
334 switch (meState)
336 case DONE:
337 case ERROR:
338 mxTemplateRoot.clear();
339 mxFolderEnvironment.clear();
340 mxEntryEnvironment.clear();
341 mxFolderResultSet.clear();
342 mxEntryResultSet.clear();
343 break;
344 default:
345 break;
349 bool TemplateScanner::HasNextStep()
351 switch (meState)
353 case DONE:
354 case ERROR:
355 return false;
357 default:
358 return true;
364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */