summaryrefslogtreecommitdiff
path: root/sd/source/ui/dlg/TemplateScanner.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/dlg/TemplateScanner.cxx')
-rw-r--r--sd/source/ui/dlg/TemplateScanner.cxx493
1 files changed, 493 insertions, 0 deletions
diff --git a/sd/source/ui/dlg/TemplateScanner.cxx b/sd/source/ui/dlg/TemplateScanner.cxx
new file mode 100644
index 000000000000..9f510f20c55d
--- /dev/null
+++ b/sd/source/ui/dlg/TemplateScanner.cxx
@@ -0,0 +1,493 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "TemplateScanner.hxx"
+
+#ifndef _COMPHELPER_SERVICEFACTORY_HXX
+#include <comphelper/processfactory.hxx>
+#endif
+#include <comphelper/documentconstants.hxx>
+
+#include <tools/debug.hxx>
+#include <vos/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/frame/XDocumentTemplates.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/ucb/XContentAccess.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+
+#include <set>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace {
+
+const ::rtl::OUString TITLE = ::rtl::OUString::createFromAscii ("Title");
+const ::rtl::OUString TARGET_DIR_URL = ::rtl::OUString::createFromAscii ("TargetDirURL");
+const ::rtl::OUString DESCRIPTION = ::rtl::OUString::createFromAscii ("TypeDescription");
+const ::rtl::OUString TARGET_URL = ::rtl::OUString::createFromAscii ("TargetURL");
+
+const ::rtl::OUString DOCTEMPLATES = ::rtl::OUString::createFromAscii ("com.sun.star.frame.DocumentTemplates");
+
+// These strings are used to find impress templates in the tree of
+// template files. Should probably be determined dynamically.
+const ::rtl::OUString IMPRESS_BIN_TEMPLATE = ::rtl::OUString::createFromAscii ("application/vnd.stardivision.impress");
+const ::rtl::OUString IMPRESS_XML_TEMPLATE = MIMETYPE_VND_SUN_XML_IMPRESS;
+// The following id comes from the bugdoc in #i2764#.
+const ::rtl::OUString IMPRESS_XML_TEMPLATE_B = ::rtl::OUString::createFromAscii ("Impress 2.0");
+const ::rtl::OUString IMPRESS_XML_TEMPLATE_OASIS = MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION;
+
+
+class FolderDescriptor
+{
+public:
+ FolderDescriptor (
+ int nPriority,
+ const ::rtl::OUString& rsTitle,
+ const ::rtl::OUString& rsTargetDir,
+ const ::rtl::OUString& rsContentIdentifier,
+ const Reference<com::sun::star::ucb::XCommandEnvironment>& rxFolderEnvironment)
+ : mnPriority(nPriority),
+ msTitle(rsTitle),
+ msTargetDir(rsTargetDir),
+ msContentIdentifier(rsContentIdentifier),
+ mxFolderEnvironment(rxFolderEnvironment)
+ { }
+ int mnPriority;
+ ::rtl::OUString msTitle;
+ ::rtl::OUString msTargetDir;
+ ::rtl::OUString msContentIdentifier;
+ // Reference<sdbc::XResultSet> mxFolderResultSet;
+ Reference<com::sun::star::ucb::XCommandEnvironment> mxFolderEnvironment;
+
+ class Comparator { public:
+ bool operator() (const FolderDescriptor& r1, const FolderDescriptor& r2)
+ { return r1.mnPriority < r2.mnPriority; }
+ };
+};
+
+/** Use a heuristic based on the URL of a top-level template folder to
+ assign a priority that is used to sort the folders.
+*/
+int Classify (const ::rtl::OUString&, const ::rtl::OUString& rsURL)
+{
+ int nPriority (0);
+
+ if (rsURL.getLength() == 0)
+ nPriority = 100;
+ else if (rsURL.indexOf(::rtl::OUString::createFromAscii("presnt"))>=0)
+ {
+ nPriority = 30;
+ }
+ else if (rsURL.indexOf(::rtl::OUString::createFromAscii("layout"))>=0)
+ {
+ nPriority = 20;
+ }
+ else if (rsURL.indexOf(::rtl::OUString::createFromAscii("educate"))>=0)
+ {
+ nPriority = 40;
+ }
+ else if (rsURL.indexOf(::rtl::OUString::createFromAscii("finance"))>=0)
+ {
+ nPriority = 40;
+ }
+ else
+ {
+ // All other folders are taken for user supplied and have the
+ // highest priority.
+ nPriority = 10;
+ }
+
+ return nPriority;
+}
+
+} // end of anonymous namespace
+
+
+
+
+namespace sd
+{
+
+class TemplateScanner::FolderDescriptorList
+ : public ::std::multiset<FolderDescriptor,FolderDescriptor::Comparator>
+{
+};
+
+TemplateScanner::TemplateScanner (void)
+ : meState(INITIALIZE_SCANNING),
+ maFolderContent(),
+ mpTemplateDirectory(NULL),
+ maFolderList(),
+ mpLastAddedEntry(NULL),
+ mpFolderDescriptors(new FolderDescriptorList()),
+ mxTemplateRoot(),
+ mxFolderEnvironment(),
+ mxEntryEnvironment(),
+ mxFolderResultSet(),
+ mxEntryResultSet()
+{
+ // empty;
+}
+
+
+
+
+TemplateScanner::~TemplateScanner (void)
+{
+ mpFolderDescriptors.reset();
+
+ // Delete all entries of the template list that have not been
+ // transferred to another object.
+ std::vector<TemplateDir*>::iterator I;
+ for (I=maFolderList.begin(); I!=maFolderList.end(); I++)
+ if (*I != NULL)
+ delete *I;
+}
+
+
+
+
+TemplateScanner::State TemplateScanner::GetTemplateRoot (void)
+{
+ State eNextState (INITIALIZE_FOLDER_SCANNING);
+
+ Reference<lang::XMultiServiceFactory> xFactory = ::comphelper::getProcessServiceFactory ();
+ DBG_ASSERT (xFactory.is(), "TemplateScanner::GetTemplateRoot: xFactory is NULL");
+
+ if (xFactory.is())
+ {
+ Reference<frame::XDocumentTemplates> xTemplates (
+ xFactory->createInstance (DOCTEMPLATES), UNO_QUERY);
+ DBG_ASSERT (xTemplates.is(), "TemplateScanner::GetTemplateRoot: xTemplates is NULL");
+
+ if (xTemplates.is())
+ mxTemplateRoot = xTemplates->getContent();
+ else
+ eNextState = ERROR;
+ }
+ else
+ eNextState = ERROR;
+
+ return eNextState;
+}
+
+
+
+
+TemplateScanner::State TemplateScanner::InitializeEntryScanning (void)
+{
+ State eNextState (SCAN_ENTRY);
+
+ if (maFolderContent.isFolder())
+ {
+ mxEntryEnvironment = Reference<com::sun::star::ucb::XCommandEnvironment>();
+
+ // We are interested only in three properties: the entry's name,
+ // its URL, and its content type.
+ Sequence<rtl::OUString> aProps (3);
+ aProps[0] = TITLE;
+ aProps[1] = TARGET_URL;
+ aProps[2] = DESCRIPTION;
+
+ // Create a cursor to iterate over the templates in this folders.
+ ::ucbhelper::ResultSetInclude eInclude = ::ucbhelper::INCLUDE_DOCUMENTS_ONLY;
+ mxEntryResultSet = Reference<com::sun::star::sdbc::XResultSet>(
+ maFolderContent.createCursor(aProps, eInclude));
+ }
+ else
+ eNextState = ERROR;
+
+ return eNextState;
+}
+
+
+
+
+TemplateScanner::State TemplateScanner::ScanEntry (void)
+{
+ State eNextState (ERROR);
+
+ Reference<com::sun::star::ucb::XContentAccess> xContentAccess (mxEntryResultSet, UNO_QUERY);
+ Reference<com::sun::star::sdbc::XRow> xRow (mxEntryResultSet, UNO_QUERY);
+
+ if (xContentAccess.is() && xRow.is() && mxEntryResultSet.is())
+ {
+ if (mxEntryResultSet->next())
+ {
+ ::rtl::OUString sTitle (xRow->getString (1));
+ ::rtl::OUString sTargetURL (xRow->getString (2));
+ ::rtl::OUString sContentType (xRow->getString (3));
+
+ ::rtl::OUString aId = xContentAccess->queryContentIdentifierString();
+ ::ucbhelper::Content aContent = ::ucbhelper::Content (aId, mxEntryEnvironment);
+ if (aContent.isDocument ())
+ {
+ // Check wether the entry is an impress template. If so
+ // add a new entry to the resulting list (which is created
+ // first if necessary).
+ if ( (sContentType == MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE)
+ || (sContentType == IMPRESS_XML_TEMPLATE_OASIS)
+ || (sContentType == IMPRESS_BIN_TEMPLATE)
+ || (sContentType == IMPRESS_XML_TEMPLATE)
+ || (sContentType == IMPRESS_XML_TEMPLATE_B))
+ {
+ mpLastAddedEntry = new TemplateEntry(sTitle, sTargetURL);
+ mpTemplateDirectory->maEntries.push_back(mpLastAddedEntry);
+ }
+ }
+
+ // Continue scanning entries.
+ eNextState = SCAN_ENTRY;
+ }
+ else
+ {
+ if (mpTemplateDirectory->maEntries.empty())
+ {
+ delete mpTemplateDirectory;
+ mpTemplateDirectory = NULL;
+ }
+ else
+ {
+ ::vos::OGuard aGuard(Application::GetSolarMutex());
+ maFolderList.push_back(mpTemplateDirectory);
+ }
+
+ // Continue with scanning the next folder.
+ eNextState = SCAN_FOLDER;
+ }
+ }
+
+ return eNextState;
+}
+
+
+
+
+TemplateScanner::State TemplateScanner::InitializeFolderScanning (void)
+{
+ State eNextState (ERROR);
+
+ mxFolderResultSet = Reference<sdbc::XResultSet>();
+
+ try
+ {
+ // Create content for template folders.
+ mxFolderEnvironment = Reference<com::sun::star::ucb::XCommandEnvironment>();
+ ::ucbhelper::Content aTemplateDir (mxTemplateRoot, mxFolderEnvironment);
+
+ // Define the list of properties we are interested in.
+ Sequence<rtl::OUString> aProps (2);
+ aProps[0] = TITLE;
+ aProps[1] = TARGET_DIR_URL;
+
+ // Create an cursor to iterate over the template folders.
+ ::ucbhelper::ResultSetInclude eInclude = ::ucbhelper::INCLUDE_FOLDERS_ONLY;
+ mxFolderResultSet = Reference<sdbc::XResultSet>(
+ aTemplateDir.createCursor(aProps, eInclude));
+ if (mxFolderResultSet.is())
+ eNextState = GATHER_FOLDER_LIST;
+ }
+ catch (::com::sun::star::uno::Exception&)
+ {
+ eNextState = ERROR;
+ }
+
+ return eNextState;
+}
+
+
+
+
+TemplateScanner::State TemplateScanner::GatherFolderList (void)
+{
+ State eNextState (ERROR);
+
+ Reference<com::sun::star::ucb::XContentAccess> xContentAccess (mxFolderResultSet, UNO_QUERY);
+ if (xContentAccess.is() && mxFolderResultSet.is())
+ {
+ while (mxFolderResultSet->next())
+ {
+ Reference<sdbc::XRow> xRow (mxFolderResultSet, UNO_QUERY);
+ if (xRow.is())
+ {
+ ::rtl::OUString sTitle (xRow->getString (1));
+ ::rtl::OUString sTargetDir (xRow->getString (2));
+ ::rtl::OUString aId = xContentAccess->queryContentIdentifierString();
+
+ mpFolderDescriptors->insert(
+ FolderDescriptor(
+ Classify(sTitle,sTargetDir),
+ sTitle,
+ sTargetDir,
+ aId,
+ mxFolderEnvironment));
+ }
+ }
+
+ eNextState = SCAN_FOLDER;
+ }
+
+ return eNextState;
+}
+
+
+
+
+TemplateScanner::State TemplateScanner::ScanFolder (void)
+{
+ State eNextState (ERROR);
+
+ if (mpFolderDescriptors->size() > 0)
+ {
+ FolderDescriptor aDescriptor (*mpFolderDescriptors->begin());
+ mpFolderDescriptors->erase(mpFolderDescriptors->begin());
+
+ ::rtl::OUString sTitle (aDescriptor.msTitle);
+ ::rtl::OUString sTargetDir (aDescriptor.msTargetDir);
+ ::rtl::OUString aId (aDescriptor.msContentIdentifier);
+
+ maFolderContent = ::ucbhelper::Content (aId, aDescriptor.mxFolderEnvironment);
+ if (maFolderContent.isFolder())
+ {
+ // Scan the folder and insert it into the list of template
+ // folders.
+ mpTemplateDirectory = new TemplateDir (sTitle, sTargetDir);
+ if (mpTemplateDirectory != NULL)
+ {
+ // Continue with scanning all entries in the folder.
+ eNextState = INITIALIZE_ENTRY_SCAN;
+ }
+ }
+ }
+ else
+ {
+ eNextState = DONE;
+ }
+
+ return eNextState;
+}
+
+
+
+
+void TemplateScanner::Scan (void)
+{
+ while (HasNextStep())
+ RunNextStep();
+}
+
+
+
+
+std::vector<TemplateDir*>& TemplateScanner::GetFolderList (void)
+{
+ return maFolderList;
+}
+
+
+
+
+void TemplateScanner::RunNextStep (void)
+{
+ switch (meState)
+ {
+ case INITIALIZE_SCANNING:
+ meState = GetTemplateRoot();
+ break;
+
+ case INITIALIZE_FOLDER_SCANNING:
+ meState = InitializeFolderScanning();
+ break;
+
+ case SCAN_FOLDER:
+ meState = ScanFolder();
+ break;
+
+ case GATHER_FOLDER_LIST:
+ meState = GatherFolderList();
+ break;
+
+ case INITIALIZE_ENTRY_SCAN:
+ meState = InitializeEntryScanning();
+ break;
+
+ case SCAN_ENTRY:
+ meState = ScanEntry();
+ break;
+ default:
+ break;
+ }
+
+ switch (meState)
+ {
+ case DONE:
+ case ERROR:
+ mxTemplateRoot.clear();
+ mxTemplateRoot.clear();
+ mxFolderEnvironment.clear();
+ mxEntryEnvironment.clear();
+ mxFolderResultSet.clear();
+ mxEntryResultSet.clear();
+ mpLastAddedEntry = NULL;
+ break;
+ default:
+ break;
+ }
+}
+
+
+
+
+bool TemplateScanner::HasNextStep (void)
+{
+ switch (meState)
+ {
+ case DONE:
+ case ERROR:
+ return false;
+
+ default:
+ return true;
+ }
+}
+
+
+
+
+const TemplateEntry* TemplateScanner::GetLastAddedEntry (void) const
+{
+ return mpLastAddedEntry;
+}
+
+}