fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / sd / source / ui / dlg / TemplateScanner.cxx
blob5b18349a0f1e46cd4059c4286f1d17352ec54474
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 .
21 #include "TemplateScanner.hxx"
23 #include <comphelper/processfactory.hxx>
24 #include <comphelper/componentcontext.hxx>
25 #include <comphelper/documentconstants.hxx>
26 #include <comphelper/string.hxx>
28 #include <tools/debug.hxx>
29 #include <osl/mutex.hxx>
30 #include <vcl/svapp.hxx>
31 #include <sfx2/doctempl.hxx>
32 #include <sfx2/templatelocnames.hrc>
33 #include <com/sun/star/frame/DocumentTemplates.hpp>
34 #include <com/sun/star/frame/XDocumentTemplates.hpp>
35 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
37 #include <com/sun/star/ucb/XContentAccess.hpp>
38 #include <com/sun/star/sdbc/XResultSet.hpp>
39 #include <com/sun/star/sdbc/XRow.hpp>
41 #include <set>
43 using namespace ::com::sun::star;
44 using namespace ::com::sun::star::uno;
46 namespace {
48 const char TITLE[] = "Title";
49 const char TARGET_DIR_URL[] = "TargetDirURL";
50 const char DESCRIPTION[] = "TypeDescription";
51 const char TARGET_URL[] = "TargetURL";
53 const char DOCTEMPLATES[] = "com.sun.star.frame.DocumentTemplates";
55 // These strings are used to find impress templates in the tree of
56 // template files. Should probably be determined dynamically.
57 const char IMPRESS_BIN_TEMPLATE[] = "application/vnd.stardivision.impress";
58 const char IMPRESS_XML_TEMPLATE[] = MIMETYPE_VND_SUN_XML_IMPRESS_ASCII;
59 // The following id comes from the bugdoc in #i2764#.
60 const char IMPRESS_XML_TEMPLATE_B[] = "Impress 2.0";
61 const char IMPRESS_XML_TEMPLATE_OASIS[] = MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII;
64 class FolderDescriptor
66 public:
67 FolderDescriptor (
68 int nPriority,
69 const OUString& rsTitle,
70 const OUString& rsTargetDir,
71 const OUString& rsContentIdentifier,
72 const Reference<com::sun::star::ucb::XCommandEnvironment>& rxFolderEnvironment)
73 : mnPriority(nPriority),
74 msTitle(rsTitle),
75 msTargetDir(rsTargetDir),
76 msContentIdentifier(rsContentIdentifier),
77 mxFolderEnvironment(rxFolderEnvironment)
78 { }
79 int mnPriority;
80 OUString msTitle;
81 OUString msTargetDir;
82 OUString msContentIdentifier;
83 // Reference<sdbc::XResultSet> mxFolderResultSet;
84 Reference<com::sun::star::ucb::XCommandEnvironment> mxFolderEnvironment;
86 class Comparator
88 public:
89 bool operator() (const FolderDescriptor& r1, const FolderDescriptor& r2) const
90 { return r1.mnPriority < r2.mnPriority; }
94 /** Use a heuristic based on the URL of a top-level template folder to
95 assign a priority that is used to sort the folders.
97 int Classify (const OUString&, const OUString& rsURL)
99 int nPriority (0);
101 if (rsURL.isEmpty())
102 nPriority = 100;
103 else if (rsURL.indexOf("presnt")>=0)
105 nPriority = 30;
107 else if (rsURL.indexOf("layout")>=0)
109 nPriority = 20;
111 else if (rsURL.indexOf("educate")>=0)
113 nPriority = 40;
115 else if (rsURL.indexOf("finance")>=0)
117 nPriority = 40;
119 else
121 // All other folders are taken for user supplied and have the
122 // highest priority.
123 nPriority = 10;
126 return nPriority;
129 } // end of anonymous namespace
134 namespace sd
137 TemplateEntryCompare::TemplateEntryCompare():
138 mpStringSorter(new comphelper::string::NaturalStringSorter(
139 ::comphelper::getProcessComponentContext(),
140 Application::GetSettings().GetLanguageTag().getLocale())) {}
142 bool TemplateEntryCompare::operator()(TemplateEntry* pA, TemplateEntry* pB) const
144 return 0 > mpStringSorter->compare(pA->msTitle, pB->msTitle);
147 void TemplateDir::EnableSorting(bool bSortingEnabled)
149 mbSortingEnabled = bSortingEnabled;
150 if (mbSortingEnabled)
152 if (mpEntryCompare.get() == NULL)
153 mpEntryCompare.reset(new TemplateEntryCompare);
155 ::std::sort(maEntries.begin(), maEntries.end(), *mpEntryCompare);
159 void TemplateDir::InsertEntry(TemplateEntry* pNewEntry)
161 if (mbSortingEnabled)
163 ::std::vector<TemplateEntry*>::iterator aPlaceToInsert =
164 ::std::upper_bound(maEntries.begin(), maEntries.end(), pNewEntry, *mpEntryCompare);
165 maEntries.insert(aPlaceToInsert, pNewEntry);
167 else
168 maEntries.push_back(pNewEntry);
171 class TemplateScanner::FolderDescriptorList
172 : public ::std::multiset<FolderDescriptor,FolderDescriptor::Comparator>
176 TemplateScanner::TemplateScanner (void)
177 : meState(INITIALIZE_SCANNING),
178 maFolderContent(),
179 mpTemplateDirectory(NULL),
180 maFolderList(),
181 mbEntrySortingEnabled(false),
182 mpLastAddedEntry(NULL),
183 mpFolderDescriptors(new FolderDescriptorList()),
184 mxTemplateRoot(),
185 mxFolderEnvironment(),
186 mxEntryEnvironment(),
187 mxFolderResultSet(),
188 mxEntryResultSet()
190 // empty;
196 TemplateScanner::~TemplateScanner (void)
198 mpFolderDescriptors.reset();
200 // Delete all entries of the template list that have not been
201 // transferred to another object.
202 std::vector<TemplateDir*>::iterator I;
203 for (I=maFolderList.begin(); I!=maFolderList.end(); ++I)
204 if (*I != NULL)
205 delete *I;
211 TemplateScanner::State TemplateScanner::GetTemplateRoot (void)
213 State eNextState (INITIALIZE_FOLDER_SCANNING);
215 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
216 Reference<frame::XDocumentTemplates> xTemplates = frame::DocumentTemplates::create(xContext);
217 mxTemplateRoot = xTemplates->getContent();
219 return eNextState;
225 TemplateScanner::State TemplateScanner::InitializeEntryScanning (void)
227 State eNextState (SCAN_ENTRY);
229 if (maFolderContent.isFolder())
231 mxEntryEnvironment = Reference<com::sun::star::ucb::XCommandEnvironment>();
233 // We are interested only in three properties: the entry's name,
234 // its URL, and its content type.
235 Sequence<OUString> aProps (3);
236 aProps[0] = OUString(TITLE);
237 aProps[1] = OUString(TARGET_URL);
238 aProps[2] = OUString(DESCRIPTION);
240 // Create a cursor to iterate over the templates in this folders.
241 ::ucbhelper::ResultSetInclude eInclude = ::ucbhelper::INCLUDE_DOCUMENTS_ONLY;
242 mxEntryResultSet = Reference<com::sun::star::sdbc::XResultSet>(
243 maFolderContent.createCursor(aProps, eInclude));
245 else
246 eNextState = ERROR;
248 return eNextState;
254 TemplateScanner::State TemplateScanner::ScanEntry (void)
256 State eNextState (ERROR);
258 Reference<com::sun::star::ucb::XContentAccess> xContentAccess (mxEntryResultSet, UNO_QUERY);
259 Reference<com::sun::star::sdbc::XRow> xRow (mxEntryResultSet, UNO_QUERY);
261 if (xContentAccess.is() && xRow.is() && mxEntryResultSet.is())
263 if (mxEntryResultSet->next())
265 OUString sTitle (xRow->getString (1));
266 OUString sTargetURL (xRow->getString (2));
267 OUString sContentType (xRow->getString (3));
269 OUString aId = xContentAccess->queryContentIdentifierString();
270 ::ucbhelper::Content aContent = ::ucbhelper::Content (aId, mxEntryEnvironment, comphelper::getProcessComponentContext());
271 if (aContent.isDocument ())
273 // Check whether the entry is an impress template. If so
274 // add a new entry to the resulting list (which is created
275 // first if necessary).
276 if ( (sContentType == MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE)
277 || (sContentType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(IMPRESS_XML_TEMPLATE_OASIS)))
278 || (sContentType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(IMPRESS_BIN_TEMPLATE)))
279 || (sContentType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(IMPRESS_XML_TEMPLATE)))
280 || (sContentType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(IMPRESS_XML_TEMPLATE_B))))
282 OUString sLocalisedTitle = SfxDocumentTemplates::ConvertResourceString(
283 STR_TEMPLATE_NAME1_DEF, STR_TEMPLATE_NAME1, NUM_TEMPLATE_NAMES, sTitle );
284 mpLastAddedEntry = new TemplateEntry(sLocalisedTitle, sTargetURL);
285 mpTemplateDirectory->InsertEntry(mpLastAddedEntry);
289 // Continue scanning entries.
290 eNextState = SCAN_ENTRY;
292 else
294 if (mpTemplateDirectory->maEntries.empty())
296 delete mpTemplateDirectory;
297 mpTemplateDirectory = NULL;
299 else
301 SolarMutexGuard aGuard;
302 maFolderList.push_back(mpTemplateDirectory);
305 // Continue with scanning the next folder.
306 eNextState = SCAN_FOLDER;
310 return eNextState;
316 TemplateScanner::State TemplateScanner::InitializeFolderScanning (void)
318 State eNextState (ERROR);
320 mxFolderResultSet = Reference<sdbc::XResultSet>();
324 // Create content for template folders.
325 mxFolderEnvironment = Reference<com::sun::star::ucb::XCommandEnvironment>();
326 ::ucbhelper::Content aTemplateDir (mxTemplateRoot, mxFolderEnvironment, comphelper::getProcessComponentContext());
328 // Define the list of properties we are interested in.
329 Sequence<OUString> aProps (2);
330 aProps[0] = OUString(TITLE);
331 aProps[1] = OUString(TARGET_DIR_URL);
333 // Create an cursor to iterate over the template folders.
334 ::ucbhelper::ResultSetInclude eInclude = ::ucbhelper::INCLUDE_FOLDERS_ONLY;
335 mxFolderResultSet = Reference<sdbc::XResultSet>(
336 aTemplateDir.createCursor(aProps, eInclude));
337 if (mxFolderResultSet.is())
338 eNextState = GATHER_FOLDER_LIST;
340 catch (::com::sun::star::uno::Exception&)
342 eNextState = ERROR;
345 return eNextState;
351 TemplateScanner::State TemplateScanner::GatherFolderList (void)
353 State eNextState (ERROR);
355 Reference<com::sun::star::ucb::XContentAccess> xContentAccess (mxFolderResultSet, UNO_QUERY);
356 if (xContentAccess.is() && mxFolderResultSet.is())
358 while (mxFolderResultSet->next())
360 Reference<sdbc::XRow> xRow (mxFolderResultSet, UNO_QUERY);
361 if (xRow.is())
363 OUString sTitle (xRow->getString (1));
364 OUString sTargetDir (xRow->getString (2));
365 OUString aId = xContentAccess->queryContentIdentifierString();
367 mpFolderDescriptors->insert(
368 FolderDescriptor(
369 Classify(sTitle,sTargetDir),
370 sTitle,
371 sTargetDir,
372 aId,
373 mxFolderEnvironment));
377 eNextState = SCAN_FOLDER;
380 return eNextState;
386 TemplateScanner::State TemplateScanner::ScanFolder (void)
388 State eNextState (ERROR);
390 if (mpFolderDescriptors->size() > 0)
392 FolderDescriptor aDescriptor (*mpFolderDescriptors->begin());
393 mpFolderDescriptors->erase(mpFolderDescriptors->begin());
395 OUString sTitle (aDescriptor.msTitle);
396 OUString sTargetDir (aDescriptor.msTargetDir);
397 OUString aId (aDescriptor.msContentIdentifier);
399 maFolderContent = ::ucbhelper::Content (aId, aDescriptor.mxFolderEnvironment, comphelper::getProcessComponentContext());
400 if (maFolderContent.isFolder())
402 // Scan the folder and insert it into the list of template
403 // folders.
404 mpTemplateDirectory = new TemplateDir (sTitle, sTargetDir);
405 if (mpTemplateDirectory != NULL)
407 mpTemplateDirectory->EnableSorting(mbEntrySortingEnabled);
408 // Continue with scanning all entries in the folder.
409 eNextState = INITIALIZE_ENTRY_SCAN;
413 else
415 eNextState = DONE;
418 return eNextState;
424 void TemplateScanner::Scan (void)
426 while (HasNextStep())
427 RunNextStep();
433 std::vector<TemplateDir*>& TemplateScanner::GetFolderList (void)
435 return maFolderList;
441 void TemplateScanner::RunNextStep (void)
443 switch (meState)
445 case INITIALIZE_SCANNING:
446 meState = GetTemplateRoot();
447 break;
449 case INITIALIZE_FOLDER_SCANNING:
450 meState = InitializeFolderScanning();
451 break;
453 case SCAN_FOLDER:
454 meState = ScanFolder();
455 break;
457 case GATHER_FOLDER_LIST:
458 meState = GatherFolderList();
459 break;
461 case INITIALIZE_ENTRY_SCAN:
462 meState = InitializeEntryScanning();
463 break;
465 case SCAN_ENTRY:
466 meState = ScanEntry();
467 break;
468 default:
469 break;
472 switch (meState)
474 case DONE:
475 case ERROR:
476 mxTemplateRoot.clear();
477 mxTemplateRoot.clear();
478 mxFolderEnvironment.clear();
479 mxEntryEnvironment.clear();
480 mxFolderResultSet.clear();
481 mxEntryResultSet.clear();
482 mpLastAddedEntry = NULL;
483 break;
484 default:
485 break;
492 bool TemplateScanner::HasNextStep (void)
494 switch (meState)
496 case DONE:
497 case ERROR:
498 return false;
500 default:
501 return true;
508 const TemplateEntry* TemplateScanner::GetLastAddedEntry (void) const
510 return mpLastAddedEntry;
515 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */