merged tag LIBREOFFICE_3_2_99_3
[LibreOffice.git] / sd / source / ui / dlg / TemplateScanner.cxx
blob78bc6eb087664f4ece479c812ad645114dce4225
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 // MARKER(update_precomp.py): autogen include statement, do not remove
30 #include "precompiled_sd.hxx"
32 #include "TemplateScanner.hxx"
34 #include <comphelper/processfactory.hxx>
35 #include <comphelper/documentconstants.hxx>
37 #include <tools/debug.hxx>
38 #include <osl/mutex.hxx>
39 #include <vcl/svapp.hxx>
40 #include <com/sun/star/frame/XDocumentTemplates.hpp>
41 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
42 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
43 #include <com/sun/star/ucb/XContentAccess.hpp>
44 #include <com/sun/star/sdbc/XResultSet.hpp>
45 #include <com/sun/star/sdbc/XRow.hpp>
47 #include <set>
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::uno;
52 namespace {
54 const ::rtl::OUString TITLE = ::rtl::OUString::createFromAscii ("Title");
55 const ::rtl::OUString TARGET_DIR_URL = ::rtl::OUString::createFromAscii ("TargetDirURL");
56 const ::rtl::OUString DESCRIPTION = ::rtl::OUString::createFromAscii ("TypeDescription");
57 const ::rtl::OUString TARGET_URL = ::rtl::OUString::createFromAscii ("TargetURL");
59 const ::rtl::OUString DOCTEMPLATES = ::rtl::OUString::createFromAscii ("com.sun.star.frame.DocumentTemplates");
61 // These strings are used to find impress templates in the tree of
62 // template files. Should probably be determined dynamically.
63 const ::rtl::OUString IMPRESS_BIN_TEMPLATE = ::rtl::OUString::createFromAscii ("application/vnd.stardivision.impress");
64 const ::rtl::OUString IMPRESS_XML_TEMPLATE = MIMETYPE_VND_SUN_XML_IMPRESS;
65 // The following id comes from the bugdoc in #i2764#.
66 const ::rtl::OUString IMPRESS_XML_TEMPLATE_B = ::rtl::OUString::createFromAscii ("Impress 2.0");
67 const ::rtl::OUString IMPRESS_XML_TEMPLATE_OASIS = MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION;
70 class FolderDescriptor
72 public:
73 FolderDescriptor (
74 int nPriority,
75 const ::rtl::OUString& rsTitle,
76 const ::rtl::OUString& rsTargetDir,
77 const ::rtl::OUString& rsContentIdentifier,
78 const Reference<com::sun::star::ucb::XCommandEnvironment>& rxFolderEnvironment)
79 : mnPriority(nPriority),
80 msTitle(rsTitle),
81 msTargetDir(rsTargetDir),
82 msContentIdentifier(rsContentIdentifier),
83 mxFolderEnvironment(rxFolderEnvironment)
84 { }
85 int mnPriority;
86 ::rtl::OUString msTitle;
87 ::rtl::OUString msTargetDir;
88 ::rtl::OUString msContentIdentifier;
89 // Reference<sdbc::XResultSet> mxFolderResultSet;
90 Reference<com::sun::star::ucb::XCommandEnvironment> mxFolderEnvironment;
92 class Comparator { public:
93 bool operator() (const FolderDescriptor& r1, const FolderDescriptor& r2)
94 { return r1.mnPriority < r2.mnPriority; }
98 /** Use a heuristic based on the URL of a top-level template folder to
99 assign a priority that is used to sort the folders.
101 int Classify (const ::rtl::OUString&, const ::rtl::OUString& rsURL)
103 int nPriority (0);
105 if (rsURL.getLength() == 0)
106 nPriority = 100;
107 else if (rsURL.indexOf(::rtl::OUString::createFromAscii("presnt"))>=0)
109 nPriority = 30;
111 else if (rsURL.indexOf(::rtl::OUString::createFromAscii("layout"))>=0)
113 nPriority = 20;
115 else if (rsURL.indexOf(::rtl::OUString::createFromAscii("educate"))>=0)
117 nPriority = 40;
119 else if (rsURL.indexOf(::rtl::OUString::createFromAscii("finance"))>=0)
121 nPriority = 40;
123 else
125 // All other folders are taken for user supplied and have the
126 // highest priority.
127 nPriority = 10;
130 return nPriority;
133 } // end of anonymous namespace
138 namespace sd
141 class TemplateScanner::FolderDescriptorList
142 : public ::std::multiset<FolderDescriptor,FolderDescriptor::Comparator>
146 TemplateScanner::TemplateScanner (void)
147 : meState(INITIALIZE_SCANNING),
148 maFolderContent(),
149 mpTemplateDirectory(NULL),
150 maFolderList(),
151 mpLastAddedEntry(NULL),
152 mpFolderDescriptors(new FolderDescriptorList()),
153 mxTemplateRoot(),
154 mxFolderEnvironment(),
155 mxEntryEnvironment(),
156 mxFolderResultSet(),
157 mxEntryResultSet()
159 // empty;
165 TemplateScanner::~TemplateScanner (void)
167 mpFolderDescriptors.reset();
169 // Delete all entries of the template list that have not been
170 // transferred to another object.
171 std::vector<TemplateDir*>::iterator I;
172 for (I=maFolderList.begin(); I!=maFolderList.end(); I++)
173 if (*I != NULL)
174 delete *I;
180 TemplateScanner::State TemplateScanner::GetTemplateRoot (void)
182 State eNextState (INITIALIZE_FOLDER_SCANNING);
184 Reference<lang::XMultiServiceFactory> xFactory = ::comphelper::getProcessServiceFactory ();
185 DBG_ASSERT (xFactory.is(), "TemplateScanner::GetTemplateRoot: xFactory is NULL");
187 if (xFactory.is())
189 Reference<frame::XDocumentTemplates> xTemplates (
190 xFactory->createInstance (DOCTEMPLATES), UNO_QUERY);
191 DBG_ASSERT (xTemplates.is(), "TemplateScanner::GetTemplateRoot: xTemplates is NULL");
193 if (xTemplates.is())
194 mxTemplateRoot = xTemplates->getContent();
195 else
196 eNextState = ERROR;
198 else
199 eNextState = ERROR;
201 return eNextState;
207 TemplateScanner::State TemplateScanner::InitializeEntryScanning (void)
209 State eNextState (SCAN_ENTRY);
211 if (maFolderContent.isFolder())
213 mxEntryEnvironment = Reference<com::sun::star::ucb::XCommandEnvironment>();
215 // We are interested only in three properties: the entry's name,
216 // its URL, and its content type.
217 Sequence<rtl::OUString> aProps (3);
218 aProps[0] = TITLE;
219 aProps[1] = TARGET_URL;
220 aProps[2] = DESCRIPTION;
222 // Create a cursor to iterate over the templates in this folders.
223 ::ucbhelper::ResultSetInclude eInclude = ::ucbhelper::INCLUDE_DOCUMENTS_ONLY;
224 mxEntryResultSet = Reference<com::sun::star::sdbc::XResultSet>(
225 maFolderContent.createCursor(aProps, eInclude));
227 else
228 eNextState = ERROR;
230 return eNextState;
236 TemplateScanner::State TemplateScanner::ScanEntry (void)
238 State eNextState (ERROR);
240 Reference<com::sun::star::ucb::XContentAccess> xContentAccess (mxEntryResultSet, UNO_QUERY);
241 Reference<com::sun::star::sdbc::XRow> xRow (mxEntryResultSet, UNO_QUERY);
243 if (xContentAccess.is() && xRow.is() && mxEntryResultSet.is())
245 if (mxEntryResultSet->next())
247 ::rtl::OUString sTitle (xRow->getString (1));
248 ::rtl::OUString sTargetURL (xRow->getString (2));
249 ::rtl::OUString sContentType (xRow->getString (3));
251 ::rtl::OUString aId = xContentAccess->queryContentIdentifierString();
252 ::ucbhelper::Content aContent = ::ucbhelper::Content (aId, mxEntryEnvironment);
253 if (aContent.isDocument ())
255 // Check wether the entry is an impress template. If so
256 // add a new entry to the resulting list (which is created
257 // first if necessary).
258 if ( (sContentType == MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE)
259 || (sContentType == IMPRESS_XML_TEMPLATE_OASIS)
260 || (sContentType == IMPRESS_BIN_TEMPLATE)
261 || (sContentType == IMPRESS_XML_TEMPLATE)
262 || (sContentType == IMPRESS_XML_TEMPLATE_B))
264 mpLastAddedEntry = new TemplateEntry(sTitle, sTargetURL);
265 mpTemplateDirectory->maEntries.push_back(mpLastAddedEntry);
269 // Continue scanning entries.
270 eNextState = SCAN_ENTRY;
272 else
274 if (mpTemplateDirectory->maEntries.empty())
276 delete mpTemplateDirectory;
277 mpTemplateDirectory = NULL;
279 else
281 SolarMutexGuard aGuard;
282 maFolderList.push_back(mpTemplateDirectory);
285 // Continue with scanning the next folder.
286 eNextState = SCAN_FOLDER;
290 return eNextState;
296 TemplateScanner::State TemplateScanner::InitializeFolderScanning (void)
298 State eNextState (ERROR);
300 mxFolderResultSet = Reference<sdbc::XResultSet>();
304 // Create content for template folders.
305 mxFolderEnvironment = Reference<com::sun::star::ucb::XCommandEnvironment>();
306 ::ucbhelper::Content aTemplateDir (mxTemplateRoot, mxFolderEnvironment);
308 // Define the list of properties we are interested in.
309 Sequence<rtl::OUString> aProps (2);
310 aProps[0] = TITLE;
311 aProps[1] = TARGET_DIR_URL;
313 // Create an cursor to iterate over the template folders.
314 ::ucbhelper::ResultSetInclude eInclude = ::ucbhelper::INCLUDE_FOLDERS_ONLY;
315 mxFolderResultSet = Reference<sdbc::XResultSet>(
316 aTemplateDir.createCursor(aProps, eInclude));
317 if (mxFolderResultSet.is())
318 eNextState = GATHER_FOLDER_LIST;
320 catch (::com::sun::star::uno::Exception&)
322 eNextState = ERROR;
325 return eNextState;
331 TemplateScanner::State TemplateScanner::GatherFolderList (void)
333 State eNextState (ERROR);
335 Reference<com::sun::star::ucb::XContentAccess> xContentAccess (mxFolderResultSet, UNO_QUERY);
336 if (xContentAccess.is() && mxFolderResultSet.is())
338 while (mxFolderResultSet->next())
340 Reference<sdbc::XRow> xRow (mxFolderResultSet, UNO_QUERY);
341 if (xRow.is())
343 ::rtl::OUString sTitle (xRow->getString (1));
344 ::rtl::OUString sTargetDir (xRow->getString (2));
345 ::rtl::OUString aId = xContentAccess->queryContentIdentifierString();
347 mpFolderDescriptors->insert(
348 FolderDescriptor(
349 Classify(sTitle,sTargetDir),
350 sTitle,
351 sTargetDir,
352 aId,
353 mxFolderEnvironment));
357 eNextState = SCAN_FOLDER;
360 return eNextState;
366 TemplateScanner::State TemplateScanner::ScanFolder (void)
368 State eNextState (ERROR);
370 if (mpFolderDescriptors->size() > 0)
372 FolderDescriptor aDescriptor (*mpFolderDescriptors->begin());
373 mpFolderDescriptors->erase(mpFolderDescriptors->begin());
375 ::rtl::OUString sTitle (aDescriptor.msTitle);
376 ::rtl::OUString sTargetDir (aDescriptor.msTargetDir);
377 ::rtl::OUString aId (aDescriptor.msContentIdentifier);
379 maFolderContent = ::ucbhelper::Content (aId, aDescriptor.mxFolderEnvironment);
380 if (maFolderContent.isFolder())
382 // Scan the folder and insert it into the list of template
383 // folders.
384 mpTemplateDirectory = new TemplateDir (sTitle, sTargetDir);
385 if (mpTemplateDirectory != NULL)
387 // Continue with scanning all entries in the folder.
388 eNextState = INITIALIZE_ENTRY_SCAN;
392 else
394 eNextState = DONE;
397 return eNextState;
403 void TemplateScanner::Scan (void)
405 while (HasNextStep())
406 RunNextStep();
412 std::vector<TemplateDir*>& TemplateScanner::GetFolderList (void)
414 return maFolderList;
420 void TemplateScanner::RunNextStep (void)
422 switch (meState)
424 case INITIALIZE_SCANNING:
425 meState = GetTemplateRoot();
426 break;
428 case INITIALIZE_FOLDER_SCANNING:
429 meState = InitializeFolderScanning();
430 break;
432 case SCAN_FOLDER:
433 meState = ScanFolder();
434 break;
436 case GATHER_FOLDER_LIST:
437 meState = GatherFolderList();
438 break;
440 case INITIALIZE_ENTRY_SCAN:
441 meState = InitializeEntryScanning();
442 break;
444 case SCAN_ENTRY:
445 meState = ScanEntry();
446 break;
447 default:
448 break;
451 switch (meState)
453 case DONE:
454 case ERROR:
455 mxTemplateRoot.clear();
456 mxTemplateRoot.clear();
457 mxFolderEnvironment.clear();
458 mxEntryEnvironment.clear();
459 mxFolderResultSet.clear();
460 mxEntryResultSet.clear();
461 mpLastAddedEntry = NULL;
462 break;
463 default:
464 break;
471 bool TemplateScanner::HasNextStep (void)
473 switch (meState)
475 case DONE:
476 case ERROR:
477 return false;
479 default:
480 return true;
487 const TemplateEntry* TemplateScanner::GetLastAddedEntry (void) const
489 return mpLastAddedEntry;
494 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */