Update ooo320-m1
[ooovba.git] / sd / source / ui / dlg / TemplateScanner.cxx
blob7f4db6f6a32a52e338e548c8639efe4268eaae03
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: TemplateScanner.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
34 #include "TemplateScanner.hxx"
36 #ifndef _COMPHELPER_SERVICEFACTORY_HXX
37 #include <comphelper/processfactory.hxx>
38 #endif
39 #include <comphelper/documentconstants.hxx>
41 #include <tools/debug.hxx>
42 #include <vos/mutex.hxx>
43 #include <vcl/svapp.hxx>
44 #include <com/sun/star/frame/XDocumentTemplates.hpp>
45 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
46 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
47 #include <com/sun/star/ucb/XContentAccess.hpp>
48 #include <com/sun/star/sdbc/XResultSet.hpp>
49 #include <com/sun/star/sdbc/XRow.hpp>
51 #include <set>
53 using namespace ::com::sun::star;
54 using namespace ::com::sun::star::uno;
56 namespace {
58 const ::rtl::OUString TITLE = ::rtl::OUString::createFromAscii ("Title");
59 const ::rtl::OUString TARGET_DIR_URL = ::rtl::OUString::createFromAscii ("TargetDirURL");
60 const ::rtl::OUString DESCRIPTION = ::rtl::OUString::createFromAscii ("TypeDescription");
61 const ::rtl::OUString TARGET_URL = ::rtl::OUString::createFromAscii ("TargetURL");
63 const ::rtl::OUString DOCTEMPLATES = ::rtl::OUString::createFromAscii ("com.sun.star.frame.DocumentTemplates");
65 // These strings are used to find impress templates in the tree of
66 // template files. Should probably be determined dynamically.
67 const ::rtl::OUString IMPRESS_BIN_TEMPLATE = ::rtl::OUString::createFromAscii ("application/vnd.stardivision.impress");
68 const ::rtl::OUString IMPRESS_XML_TEMPLATE = MIMETYPE_VND_SUN_XML_IMPRESS;
69 // The following id comes from the bugdoc in #i2764#.
70 const ::rtl::OUString IMPRESS_XML_TEMPLATE_B = ::rtl::OUString::createFromAscii ("Impress 2.0");
71 const ::rtl::OUString IMPRESS_XML_TEMPLATE_OASIS = MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION;
74 class FolderDescriptor
76 public:
77 FolderDescriptor (
78 int nPriority,
79 const ::rtl::OUString& rsTitle,
80 const ::rtl::OUString& rsTargetDir,
81 const ::rtl::OUString& rsContentIdentifier,
82 const Reference<com::sun::star::ucb::XCommandEnvironment>& rxFolderEnvironment)
83 : mnPriority(nPriority),
84 msTitle(rsTitle),
85 msTargetDir(rsTargetDir),
86 msContentIdentifier(rsContentIdentifier),
87 mxFolderEnvironment(rxFolderEnvironment)
88 { }
89 int mnPriority;
90 ::rtl::OUString msTitle;
91 ::rtl::OUString msTargetDir;
92 ::rtl::OUString msContentIdentifier;
93 // Reference<sdbc::XResultSet> mxFolderResultSet;
94 Reference<com::sun::star::ucb::XCommandEnvironment> mxFolderEnvironment;
96 class Comparator { public:
97 bool operator() (const FolderDescriptor& r1, const FolderDescriptor& r2)
98 { return r1.mnPriority < r2.mnPriority; }
102 /** Use a heuristic based on the URL of a top-level template folder to
103 assign a priority that is used to sort the folders.
105 int Classify (const ::rtl::OUString&, const ::rtl::OUString& rsURL)
107 int nPriority (0);
109 if (rsURL.getLength() == 0)
110 nPriority = 100;
111 else if (rsURL.indexOf(::rtl::OUString::createFromAscii("presnt"))>=0)
113 nPriority = 30;
115 else if (rsURL.indexOf(::rtl::OUString::createFromAscii("layout"))>=0)
117 nPriority = 20;
119 else if (rsURL.indexOf(::rtl::OUString::createFromAscii("educate"))>=0)
121 nPriority = 40;
123 else if (rsURL.indexOf(::rtl::OUString::createFromAscii("finance"))>=0)
125 nPriority = 40;
127 else
129 // All other folders are taken for user supplied and have the
130 // highest priority.
131 nPriority = 10;
134 return nPriority;
137 } // end of anonymous namespace
142 namespace sd
145 class TemplateScanner::FolderDescriptorList
146 : public ::std::multiset<FolderDescriptor,FolderDescriptor::Comparator>
150 TemplateScanner::TemplateScanner (void)
151 : meState(INITIALIZE_SCANNING),
152 maFolderContent(),
153 mpTemplateDirectory(NULL),
154 maFolderList(),
155 mpLastAddedEntry(NULL),
156 mpFolderDescriptors(new FolderDescriptorList()),
157 mxTemplateRoot(),
158 mxFolderEnvironment(),
159 mxEntryEnvironment(),
160 mxFolderResultSet(),
161 mxEntryResultSet()
163 // empty;
169 TemplateScanner::~TemplateScanner (void)
171 mpFolderDescriptors.reset();
173 // Delete all entries of the template list that have not been
174 // transferred to another object.
175 std::vector<TemplateDir*>::iterator I;
176 for (I=maFolderList.begin(); I!=maFolderList.end(); I++)
177 if (*I != NULL)
178 delete *I;
184 TemplateScanner::State TemplateScanner::GetTemplateRoot (void)
186 State eNextState (INITIALIZE_FOLDER_SCANNING);
188 Reference<lang::XMultiServiceFactory> xFactory = ::comphelper::getProcessServiceFactory ();
189 DBG_ASSERT (xFactory.is(), "TemplateScanner::GetTemplateRoot: xFactory is NULL");
191 if (xFactory.is())
193 Reference<frame::XDocumentTemplates> xTemplates (
194 xFactory->createInstance (DOCTEMPLATES), UNO_QUERY);
195 DBG_ASSERT (xTemplates.is(), "TemplateScanner::GetTemplateRoot: xTemplates is NULL");
197 if (xTemplates.is())
198 mxTemplateRoot = xTemplates->getContent();
199 else
200 eNextState = ERROR;
202 else
203 eNextState = ERROR;
205 return eNextState;
211 TemplateScanner::State TemplateScanner::InitializeEntryScanning (void)
213 State eNextState (SCAN_ENTRY);
215 if (maFolderContent.isFolder())
217 mxEntryEnvironment = Reference<com::sun::star::ucb::XCommandEnvironment>();
219 // We are interested only in three properties: the entry's name,
220 // its URL, and its content type.
221 Sequence<rtl::OUString> aProps (3);
222 aProps[0] = TITLE;
223 aProps[1] = TARGET_URL;
224 aProps[2] = DESCRIPTION;
226 // Create a cursor to iterate over the templates in this folders.
227 ::ucbhelper::ResultSetInclude eInclude = ::ucbhelper::INCLUDE_DOCUMENTS_ONLY;
228 mxEntryResultSet = Reference<com::sun::star::sdbc::XResultSet>(
229 maFolderContent.createCursor(aProps, eInclude));
231 else
232 eNextState = ERROR;
234 return eNextState;
240 TemplateScanner::State TemplateScanner::ScanEntry (void)
242 State eNextState (ERROR);
244 Reference<com::sun::star::ucb::XContentAccess> xContentAccess (mxEntryResultSet, UNO_QUERY);
245 Reference<com::sun::star::sdbc::XRow> xRow (mxEntryResultSet, UNO_QUERY);
247 if (xContentAccess.is() && xRow.is() && mxEntryResultSet.is())
249 if (mxEntryResultSet->next())
251 ::rtl::OUString sTitle (xRow->getString (1));
252 ::rtl::OUString sTargetURL (xRow->getString (2));
253 ::rtl::OUString sContentType (xRow->getString (3));
255 ::rtl::OUString aId = xContentAccess->queryContentIdentifierString();
256 ::ucbhelper::Content aContent = ::ucbhelper::Content (aId, mxEntryEnvironment);
257 if (aContent.isDocument ())
259 // Check wether the entry is an impress template. If so
260 // add a new entry to the resulting list (which is created
261 // first if necessary).
262 if ( (sContentType == MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE)
263 || (sContentType == IMPRESS_XML_TEMPLATE_OASIS)
264 || (sContentType == IMPRESS_BIN_TEMPLATE)
265 || (sContentType == IMPRESS_XML_TEMPLATE)
266 || (sContentType == IMPRESS_XML_TEMPLATE_B))
268 mpLastAddedEntry = new TemplateEntry(sTitle, sTargetURL);
269 mpTemplateDirectory->maEntries.push_back(mpLastAddedEntry);
273 // Continue scanning entries.
274 eNextState = SCAN_ENTRY;
276 else
278 if (mpTemplateDirectory->maEntries.empty())
280 delete mpTemplateDirectory;
281 mpTemplateDirectory = NULL;
283 else
285 ::vos::OGuard aGuard(Application::GetSolarMutex());
286 maFolderList.push_back(mpTemplateDirectory);
289 // Continue with scanning the next folder.
290 eNextState = SCAN_FOLDER;
294 return eNextState;
300 TemplateScanner::State TemplateScanner::InitializeFolderScanning (void)
302 State eNextState (ERROR);
304 mxFolderResultSet = Reference<sdbc::XResultSet>();
308 // Create content for template folders.
309 mxFolderEnvironment = Reference<com::sun::star::ucb::XCommandEnvironment>();
310 ::ucbhelper::Content aTemplateDir (mxTemplateRoot, mxFolderEnvironment);
312 // Define the list of properties we are interested in.
313 Sequence<rtl::OUString> aProps (2);
314 aProps[0] = TITLE;
315 aProps[1] = TARGET_DIR_URL;
317 // Create an cursor to iterate over the template folders.
318 ::ucbhelper::ResultSetInclude eInclude = ::ucbhelper::INCLUDE_FOLDERS_ONLY;
319 mxFolderResultSet = Reference<sdbc::XResultSet>(
320 aTemplateDir.createCursor(aProps, eInclude));
321 if (mxFolderResultSet.is())
322 eNextState = GATHER_FOLDER_LIST;
324 catch (::com::sun::star::uno::Exception&)
326 eNextState = ERROR;
329 return eNextState;
335 TemplateScanner::State TemplateScanner::GatherFolderList (void)
337 State eNextState (ERROR);
339 Reference<com::sun::star::ucb::XContentAccess> xContentAccess (mxFolderResultSet, UNO_QUERY);
340 if (xContentAccess.is() && mxFolderResultSet.is())
342 while (mxFolderResultSet->next())
344 Reference<sdbc::XRow> xRow (mxFolderResultSet, UNO_QUERY);
345 if (xRow.is())
347 ::rtl::OUString sTitle (xRow->getString (1));
348 ::rtl::OUString sTargetDir (xRow->getString (2));
349 ::rtl::OUString aId = xContentAccess->queryContentIdentifierString();
351 mpFolderDescriptors->insert(
352 FolderDescriptor(
353 Classify(sTitle,sTargetDir),
354 sTitle,
355 sTargetDir,
356 aId,
357 mxFolderEnvironment));
361 eNextState = SCAN_FOLDER;
364 return eNextState;
370 TemplateScanner::State TemplateScanner::ScanFolder (void)
372 State eNextState (ERROR);
374 if (mpFolderDescriptors->size() > 0)
376 FolderDescriptor aDescriptor (*mpFolderDescriptors->begin());
377 mpFolderDescriptors->erase(mpFolderDescriptors->begin());
379 ::rtl::OUString sTitle (aDescriptor.msTitle);
380 ::rtl::OUString sTargetDir (aDescriptor.msTargetDir);
381 ::rtl::OUString aId (aDescriptor.msContentIdentifier);
383 maFolderContent = ::ucbhelper::Content (aId, aDescriptor.mxFolderEnvironment);
384 if (maFolderContent.isFolder())
386 // Scan the folder and insert it into the list of template
387 // folders.
388 mpTemplateDirectory = new TemplateDir (sTitle, sTargetDir);
389 if (mpTemplateDirectory != NULL)
391 // Continue with scanning all entries in the folder.
392 eNextState = INITIALIZE_ENTRY_SCAN;
396 else
398 eNextState = DONE;
401 return eNextState;
407 void TemplateScanner::Scan (void)
409 while (HasNextStep())
410 RunNextStep();
416 std::vector<TemplateDir*>& TemplateScanner::GetFolderList (void)
418 return maFolderList;
424 void TemplateScanner::RunNextStep (void)
426 switch (meState)
428 case INITIALIZE_SCANNING:
429 meState = GetTemplateRoot();
430 break;
432 case INITIALIZE_FOLDER_SCANNING:
433 meState = InitializeFolderScanning();
434 break;
436 case SCAN_FOLDER:
437 meState = ScanFolder();
438 break;
440 case GATHER_FOLDER_LIST:
441 meState = GatherFolderList();
442 break;
444 case INITIALIZE_ENTRY_SCAN:
445 meState = InitializeEntryScanning();
446 break;
448 case SCAN_ENTRY:
449 meState = ScanEntry();
450 break;
451 default:
452 break;
455 switch (meState)
457 case DONE:
458 case ERROR:
459 mxTemplateRoot.clear();
460 mxTemplateRoot.clear();
461 mxFolderEnvironment.clear();
462 mxEntryEnvironment.clear();
463 mxFolderResultSet.clear();
464 mxEntryResultSet.clear();
465 mpLastAddedEntry = NULL;
466 break;
467 default:
468 break;
475 bool TemplateScanner::HasNextStep (void)
477 switch (meState)
479 case DONE:
480 case ERROR:
481 return false;
483 default:
484 return true;
491 const TemplateEntry* TemplateScanner::GetLastAddedEntry (void) const
493 return mpLastAddedEntry;