diff options
-rw-r--r-- | sc/Library_scfilt.mk | 2 | ||||
-rw-r--r-- | sc/inc/orcusfilters.hxx | 15 | ||||
-rw-r--r-- | sc/source/filter/inc/orcusfiltersimpl.hxx | 19 | ||||
-rw-r--r-- | sc/source/filter/inc/orcusinterface.hxx | 63 | ||||
-rw-r--r-- | sc/source/filter/orcus/interface.cxx | 121 | ||||
-rw-r--r-- | sc/source/filter/orcus/orcusfiltersimpl.cxx | 359 | ||||
-rw-r--r-- | sc/source/filter/orcus/xmlcontext.cxx | 221 | ||||
-rw-r--r-- | sc/source/ui/inc/xmlsourcedlg.hxx | 3 | ||||
-rw-r--r-- | sc/source/ui/xmlsource/xmlsourcedlg.cxx | 14 |
9 files changed, 449 insertions, 368 deletions
diff --git a/sc/Library_scfilt.mk b/sc/Library_scfilt.mk index 18e302a6d198..c25ecb19c0a0 100644 --- a/sc/Library_scfilt.mk +++ b/sc/Library_scfilt.mk @@ -221,7 +221,9 @@ $(eval $(call gb_Library_add_exception_objects,scfilt,\ sc/source/filter/oox/worksheethelper \ sc/source/filter/oox/worksheetsettings \ sc/source/filter/orcus/orcusfiltersimpl \ + sc/source/filter/orcus/interface \ sc/source/filter/orcus/orcusxml \ + sc/source/filter/orcus/xmlcontext \ )) ifeq ($(SYSTEM_ZLIB),YES) diff --git a/sc/inc/orcusfilters.hxx b/sc/inc/orcusfilters.hxx index 1b94f67bed40..dd9778d3b263 100644 --- a/sc/inc/orcusfilters.hxx +++ b/sc/inc/orcusfilters.hxx @@ -17,6 +17,7 @@ class SvTreeListBox; class Image; struct ScOrcusXMLTreeParam; struct ScOrcusImportXMLParam; +class ScOrcusXMLContext; /** * Collection of orcus filter wrappers. @@ -28,11 +29,17 @@ public: virtual bool importCSV(ScDocument& rDoc, const rtl::OUString& rPath) const = 0; - virtual bool loadXMLStructure( - const rtl::OUString& rPath, SvTreeListBox& rTreeCtrl, ScOrcusXMLTreeParam& rParam) const = 0; + virtual ScOrcusXMLContext* createXMLContext(ScDocument& rDoc, const rtl::OUString& rPath) const = 0; +}; + +class ScOrcusXMLContext +{ +public: + virtual ~ScOrcusXMLContext() {} + + virtual bool loadXMLStructure(SvTreeListBox& rTreeCtrl, ScOrcusXMLTreeParam& rParam) const = 0; - virtual bool importXML( - ScDocument& rDoc, const rtl::OUString& rPath, const ScOrcusImportXMLParam& rParam) const = 0; + virtual bool importXML(const ScOrcusImportXMLParam& rParam) const = 0; }; #endif diff --git a/sc/source/filter/inc/orcusfiltersimpl.hxx b/sc/source/filter/inc/orcusfiltersimpl.hxx index f2d270355293..0b6ffa6997b3 100644 --- a/sc/source/filter/inc/orcusfiltersimpl.hxx +++ b/sc/source/filter/inc/orcusfiltersimpl.hxx @@ -15,13 +15,24 @@ class ScOrcusFiltersImpl : public ScOrcusFilters { public: + static rtl::OString toSystemPath(const rtl::OUString& rPath); + virtual bool importCSV(ScDocument& rDoc, const rtl::OUString& rPath) const; - virtual bool loadXMLStructure( - const rtl::OUString& rPath, SvTreeListBox& rTreeCtrl, ScOrcusXMLTreeParam& rParam) const; + virtual ScOrcusXMLContext* createXMLContext(ScDocument& rDoc, const rtl::OUString& rPath) const; +}; + +class ScOrcusXMLContextImpl : public ScOrcusXMLContext +{ + ScDocument& mrDoc; + rtl::OUString maPath; +public: + ScOrcusXMLContextImpl(ScDocument& rDoc, const rtl::OUString& rPath); + virtual ~ScOrcusXMLContextImpl(); + + virtual bool loadXMLStructure(SvTreeListBox& rTreeCtrl, ScOrcusXMLTreeParam& rParam) const; - virtual bool importXML( - ScDocument& rDoc, const rtl::OUString& rPath, const ScOrcusImportXMLParam& rParam) const; + virtual bool importXML(const ScOrcusImportXMLParam& rParam) const; }; #endif diff --git a/sc/source/filter/inc/orcusinterface.hxx b/sc/source/filter/inc/orcusinterface.hxx new file mode 100644 index 000000000000..e2c9c087f6fa --- /dev/null +++ b/sc/source/filter/inc/orcusinterface.hxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef __SC_ORCUSINTERFACE_HXX__ +#define __SC_ORCUSINTERFACE_HXX__ + +#include "address.hxx" + +#define __ORCUS_STATIC_LIB +#include <orcus/spreadsheet/import_interface.hpp> + +#include <boost/ptr_container/ptr_vector.hpp> + +class ScDocument; +class ScOrcusSheet; + +class ScOrcusFactory : public orcus::spreadsheet::iface::import_factory +{ + ScDocument& mrDoc; + boost::ptr_vector<ScOrcusSheet> maSheets; + +public: + ScOrcusFactory(ScDocument& rDoc); + + virtual orcus::spreadsheet::iface::import_sheet* append_sheet(const char *sheet_name, size_t sheet_name_length); + virtual orcus::spreadsheet::iface::import_sheet* get_sheet(const char *sheet_name, size_t sheet_name_length); + virtual orcus::spreadsheet::iface::import_shared_strings* get_shared_strings(); + virtual orcus::spreadsheet::iface::import_styles* get_styles(); +}; + +class ScOrcusSheet : public orcus::spreadsheet::iface::import_sheet +{ + ScDocument& mrDoc; + SCTAB mnTab; +public: + ScOrcusSheet(ScDocument& rDoc, SCTAB nTab); + + // Orcus import interface + virtual void set_auto(orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, const char* p, size_t n); + virtual void set_format(orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, size_t xf_index); + virtual void set_formula(orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, orcus::spreadsheet::formula_grammar_t grammar, const char* p, size_t n); + virtual void set_formula_result(orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, const char* p, size_t n); + virtual void set_shared_formula( + orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, orcus::spreadsheet::formula_grammar_t grammar, size_t sindex, + const char* p_formula, size_t n_formula); + virtual void set_shared_formula( + orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, orcus::spreadsheet::formula_grammar_t grammar, size_t sindex, + const char* p_formula, size_t n_formula, const char* p_range, size_t n_range); + virtual void set_shared_formula(orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, size_t sindex); + virtual void set_string(orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, size_t sindex); + virtual void set_value(orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, double value); + + SCTAB getIndex() const { return mnTab; } +}; + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/orcus/interface.cxx b/sc/source/filter/orcus/interface.cxx new file mode 100644 index 000000000000..d22c20844d36 --- /dev/null +++ b/sc/source/filter/orcus/interface.cxx @@ -0,0 +1,121 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcusinterface.hxx" + +#include "document.hxx" + +using orcus::spreadsheet::row_t; +using orcus::spreadsheet::col_t; +using orcus::spreadsheet::formula_grammar_t; + +ScOrcusFactory::ScOrcusFactory(ScDocument& rDoc) : mrDoc(rDoc) {} + +orcus::spreadsheet::iface::import_sheet* ScOrcusFactory::append_sheet(const char* sheet_name, size_t sheet_name_length) +{ + OUString aTabName(sheet_name, sheet_name_length, RTL_TEXTENCODING_UTF8); + if (!mrDoc.InsertTab(SC_TAB_APPEND, aTabName)) + return NULL; + + SCTAB nTab = mrDoc.GetTableCount() - 1; + maSheets.push_back(new ScOrcusSheet(mrDoc, nTab)); + return &maSheets.back(); +} + +class FindSheetByIndex : std::unary_function<ScOrcusSheet, bool> +{ + SCTAB mnTab; +public: + FindSheetByIndex(SCTAB nTab) : mnTab(nTab) {} + bool operator() (const ScOrcusSheet& rSheet) const + { + return rSheet.getIndex() == mnTab; + } +}; + +orcus::spreadsheet::iface::import_sheet* ScOrcusFactory::get_sheet(const char* sheet_name, size_t sheet_name_length) +{ + OUString aTabName(sheet_name, sheet_name_length, RTL_TEXTENCODING_UTF8); + SCTAB nTab = -1; + if (!mrDoc.GetTable(aTabName, nTab)) + // Sheet by that name not found. + return NULL; + + // See if we already have an orcus sheet instance by that index. + boost::ptr_vector<ScOrcusSheet>::iterator it = + std::find_if(maSheets.begin(), maSheets.end(), FindSheetByIndex(nTab)); + + if (it != maSheets.end()) + // We already have one. Return it. + return &(*it); + + // Create a new orcus sheet instance for this. + maSheets.push_back(new ScOrcusSheet(mrDoc, nTab)); + return &maSheets.back(); +} + +orcus::spreadsheet::iface::import_shared_strings* ScOrcusFactory::get_shared_strings() +{ + // We don't support it yet. + return NULL; +} + +orcus::spreadsheet::iface::import_styles* ScOrcusFactory::get_styles() +{ + // We don't support it yet. + return NULL; +} + +ScOrcusSheet::ScOrcusSheet(ScDocument& rDoc, SCTAB nTab) : + mrDoc(rDoc), mnTab(nTab) {} + +void ScOrcusSheet::set_auto(row_t row, col_t col, const char* p, size_t n) +{ + OUString aVal(p, n, RTL_TEXTENCODING_UTF8); + mrDoc.SetString(col, row, mnTab, aVal); +} + +void ScOrcusSheet::set_format(row_t /*row*/, col_t /*col*/, size_t /*xf_index*/) +{ +} + +void ScOrcusSheet::set_formula( + row_t /*row*/, col_t /*col*/, formula_grammar_t /*grammar*/, const char* /*p*/, size_t /*n*/) +{ +} + +void ScOrcusSheet::set_formula_result(row_t /*row*/, col_t /*col*/, const char* /*p*/, size_t /*n*/) +{ +} + +void ScOrcusSheet::set_shared_formula( + row_t /*row*/, col_t /*col*/, formula_grammar_t /*grammar*/, size_t /*sindex*/, + const char* /*p_formula*/, size_t /*n_formula*/) +{ +} + +void ScOrcusSheet::set_shared_formula( + row_t /*row*/, col_t /*col*/, formula_grammar_t /*grammar*/, size_t /*sindex*/, + const char* /*p_formula*/, size_t /*n_formula*/, const char* /*p_range*/, size_t /*n_range*/) +{ +} + +void ScOrcusSheet::set_shared_formula(row_t /*row*/, col_t /*col*/, size_t /*sindex*/) +{ +} + +void ScOrcusSheet::set_string(row_t /*row*/, col_t /*col*/, size_t /*sindex*/) +{ +} + +void ScOrcusSheet::set_value(row_t /*row*/, col_t /*col*/, double /*value*/) +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/orcus/orcusfiltersimpl.cxx b/sc/source/filter/orcus/orcusfiltersimpl.cxx index 3fa23e14f5f3..0f1c32984175 100644 --- a/sc/source/filter/orcus/orcusfiltersimpl.cxx +++ b/sc/source/filter/orcus/orcusfiltersimpl.cxx @@ -8,187 +8,29 @@ */ #include "orcusfiltersimpl.hxx" +#include "orcusinterface.hxx" #include "document.hxx" -#include "orcusxml.hxx" #include "tools/urlobj.hxx" -#include "svtools/treelistbox.hxx" #define __ORCUS_STATIC_LIB #include <orcus/spreadsheet/import_interface.hpp> #include <orcus/orcus_csv.hpp> -#include <orcus/xml_structure_tree.hpp> -#include <orcus/xml_namespace.hpp> -#include <orcus/orcus_xml.hpp> #include <orcus/global.hpp> -#include <boost/ptr_container/ptr_vector.hpp> - -using orcus::spreadsheet::row_t; -using orcus::spreadsheet::col_t; -using orcus::spreadsheet::formula_grammar_t; - #ifdef WNT #define SYSTEM_PATH INetURLObject::FSYS_DOS #else #define SYSTEM_PATH INetURLObject::FSYS_UNX #endif -namespace { - -OString toSystemPath(const OUString& rPath) +OString ScOrcusFiltersImpl::toSystemPath(const OUString& rPath) { INetURLObject aURL(rPath); return rtl::OUStringToOString(aURL.getFSysPath(SYSTEM_PATH), RTL_TEXTENCODING_UTF8); } -class ScOrcusSheet; - -class ScOrcusFactory : public orcus::spreadsheet::iface::import_factory -{ - ScDocument& mrDoc; - boost::ptr_vector<ScOrcusSheet> maSheets; - -public: - ScOrcusFactory(ScDocument& rDoc); - - virtual orcus::spreadsheet::iface::import_sheet* append_sheet(const char *sheet_name, size_t sheet_name_length); - virtual orcus::spreadsheet::iface::import_sheet* get_sheet(const char *sheet_name, size_t sheet_name_length); - virtual orcus::spreadsheet::iface::import_shared_strings* get_shared_strings(); - virtual orcus::spreadsheet::iface::import_styles* get_styles(); -}; - -class ScOrcusSheet : public orcus::spreadsheet::iface::import_sheet -{ - ScDocument& mrDoc; - SCTAB mnTab; -public: - ScOrcusSheet(ScDocument& rDoc, SCTAB nTab); - - // Orcus import interface - virtual void set_auto(row_t row, col_t col, const char* p, size_t n); - virtual void set_format(row_t row, col_t col, size_t xf_index); - virtual void set_formula(row_t row, col_t col, formula_grammar_t grammar, const char* p, size_t n); - virtual void set_formula_result(row_t row, col_t col, const char* p, size_t n); - virtual void set_shared_formula( - row_t row, col_t col, formula_grammar_t grammar, size_t sindex, - const char* p_formula, size_t n_formula); - virtual void set_shared_formula( - row_t row, col_t col, formula_grammar_t grammar, size_t sindex, - const char* p_formula, size_t n_formula, const char* p_range, size_t n_range); - virtual void set_shared_formula(row_t row, col_t col, size_t sindex); - virtual void set_string(row_t row, col_t col, size_t sindex); - virtual void set_value(row_t row, col_t col, double value); - - SCTAB getIndex() const { return mnTab; } -}; - -ScOrcusFactory::ScOrcusFactory(ScDocument& rDoc) : mrDoc(rDoc) {} - -orcus::spreadsheet::iface::import_sheet* ScOrcusFactory::append_sheet(const char* sheet_name, size_t sheet_name_length) -{ - OUString aTabName(sheet_name, sheet_name_length, RTL_TEXTENCODING_UTF8); - if (!mrDoc.InsertTab(SC_TAB_APPEND, aTabName)) - return NULL; - - SCTAB nTab = mrDoc.GetTableCount() - 1; - maSheets.push_back(new ScOrcusSheet(mrDoc, nTab)); - return &maSheets.back(); -} - -class FindSheetByIndex : std::unary_function<ScOrcusSheet, bool> -{ - SCTAB mnTab; -public: - FindSheetByIndex(SCTAB nTab) : mnTab(nTab) {} - bool operator() (const ScOrcusSheet& rSheet) const - { - return rSheet.getIndex() == mnTab; - } -}; - -orcus::spreadsheet::iface::import_sheet* ScOrcusFactory::get_sheet(const char* sheet_name, size_t sheet_name_length) -{ - OUString aTabName(sheet_name, sheet_name_length, RTL_TEXTENCODING_UTF8); - SCTAB nTab = -1; - if (!mrDoc.GetTable(aTabName, nTab)) - // Sheet by that name not found. - return NULL; - - // See if we already have an orcus sheet instance by that index. - boost::ptr_vector<ScOrcusSheet>::iterator it = - std::find_if(maSheets.begin(), maSheets.end(), FindSheetByIndex(nTab)); - - if (it != maSheets.end()) - // We already have one. Return it. - return &(*it); - - // Create a new orcus sheet instance for this. - maSheets.push_back(new ScOrcusSheet(mrDoc, nTab)); - return &maSheets.back(); -} - -orcus::spreadsheet::iface::import_shared_strings* ScOrcusFactory::get_shared_strings() -{ - // We don't support it yet. - return NULL; -} - -orcus::spreadsheet::iface::import_styles* ScOrcusFactory::get_styles() -{ - // We don't support it yet. - return NULL; -} - -ScOrcusSheet::ScOrcusSheet(ScDocument& rDoc, SCTAB nTab) : - mrDoc(rDoc), mnTab(nTab) {} - -void ScOrcusSheet::set_auto(row_t row, col_t col, const char* p, size_t n) -{ - OUString aVal(p, n, RTL_TEXTENCODING_UTF8); - mrDoc.SetString(col, row, mnTab, aVal); -} - -void ScOrcusSheet::set_format(row_t /*row*/, col_t /*col*/, size_t /*xf_index*/) -{ -} - -void ScOrcusSheet::set_formula( - row_t /*row*/, col_t /*col*/, formula_grammar_t /*grammar*/, const char* /*p*/, size_t /*n*/) -{ -} - -void ScOrcusSheet::set_formula_result(row_t /*row*/, col_t /*col*/, const char* /*p*/, size_t /*n*/) -{ -} - -void ScOrcusSheet::set_shared_formula( - row_t /*row*/, col_t /*col*/, formula_grammar_t /*grammar*/, size_t /*sindex*/, - const char* /*p_formula*/, size_t /*n_formula*/) -{ -} - -void ScOrcusSheet::set_shared_formula( - row_t /*row*/, col_t /*col*/, formula_grammar_t /*grammar*/, size_t /*sindex*/, - const char* /*p_formula*/, size_t /*n_formula*/, const char* /*p_range*/, size_t /*n_range*/) -{ -} - -void ScOrcusSheet::set_shared_formula(row_t /*row*/, col_t /*col*/, size_t /*sindex*/) -{ -} - -void ScOrcusSheet::set_string(row_t /*row*/, col_t /*col*/, size_t /*sindex*/) -{ -} - -void ScOrcusSheet::set_value(row_t /*row*/, col_t /*col*/, double /*value*/) -{ -} - -} // anonymous namespace - bool ScOrcusFiltersImpl::importCSV(ScDocument& rDoc, const OUString& rPath) const { ScOrcusFactory aFactory(rDoc); @@ -209,202 +51,9 @@ bool ScOrcusFiltersImpl::importCSV(ScDocument& rDoc, const OUString& rPath) cons return true; } -namespace { - -ScOrcusXMLTreeParam::EntryData& setUserDataToEntry( - SvTreeListEntry& rEntry, ScOrcusXMLTreeParam::UserDataStoreType& rStore, ScOrcusXMLTreeParam::EntryType eType) -{ - rStore.push_back(new ScOrcusXMLTreeParam::EntryData(eType)); - rEntry.SetUserData(&rStore.back()); - return rStore.back(); -} - -void populateTree( - SvTreeListBox& rTreeCtrl, orcus::xml_structure_tree::walker& rWalker, - const orcus::xml_structure_tree::entity_name& rElemName, bool bRepeat, - SvTreeListEntry* pParent, ScOrcusXMLTreeParam& rParam) -{ - OUString aName(rElemName.name.get(), rElemName.name.size(), RTL_TEXTENCODING_UTF8); - SvTreeListEntry* pEntry = rTreeCtrl.InsertEntry(aName, pParent); - if (!pEntry) - // Can this ever happen!? - return; - - ScOrcusXMLTreeParam::EntryData& rEntryData = setUserDataToEntry( - *pEntry, rParam.maUserDataStore, - bRepeat ? ScOrcusXMLTreeParam::ElementRepeat : ScOrcusXMLTreeParam::ElementDefault); - - if (bRepeat) - { - // Recurring elements use different icon. - rTreeCtrl.SetExpandedEntryBmp(pEntry, rParam.maImgElementRepeat); - rTreeCtrl.SetCollapsedEntryBmp(pEntry, rParam.maImgElementRepeat); - } - - if (pParent) - rTreeCtrl.Expand(pParent); - - orcus::xml_structure_tree::entity_names_type aNames; - - // Insert attributes. - rWalker.get_attributes(aNames); - orcus::xml_structure_tree::entity_names_type::const_iterator it = aNames.begin(); - orcus::xml_structure_tree::entity_names_type::const_iterator itEnd = aNames.end(); - for (; it != itEnd; ++it) - { - orcus::xml_structure_tree::entity_name aAttrName = *it; - SvTreeListEntry* pAttr = rTreeCtrl.InsertEntry( - OUString(aAttrName.name.get(), aAttrName.name.size(), RTL_TEXTENCODING_UTF8), pEntry); - - if (!pAttr) - continue; - - setUserDataToEntry(*pAttr, rParam.maUserDataStore, ScOrcusXMLTreeParam::Attribute); - rTreeCtrl.SetExpandedEntryBmp(pAttr, rParam.maImgAttribute); - rTreeCtrl.SetCollapsedEntryBmp(pAttr, rParam.maImgAttribute); - } - rTreeCtrl.Expand(pEntry); - - rWalker.get_children(aNames); - - // Non-leaf if it has child elements, leaf otherwise. - rEntryData.mbLeafNode = aNames.empty(); - - // Insert child elements recursively. - for (it = aNames.begin(), itEnd = aNames.end(); it != itEnd; ++it) - { - orcus::xml_structure_tree::element aElem = rWalker.descend(*it); - populateTree(rTreeCtrl, rWalker, *it, aElem.repeat, pEntry, rParam); - rWalker.ascend(); - } -} - -class TreeUpdateSwitch -{ - SvTreeListBox& mrTreeCtrl; -public: - TreeUpdateSwitch(SvTreeListBox& rTreeCtrl) : mrTreeCtrl(rTreeCtrl) - { - mrTreeCtrl.SetUpdateMode(false); - } - - ~TreeUpdateSwitch() - { - mrTreeCtrl.SetUpdateMode(true); - } -}; - -} - -bool ScOrcusFiltersImpl::loadXMLStructure( - const rtl::OUString& rPath, SvTreeListBox& rTreeCtrl, ScOrcusXMLTreeParam& rParam) const -{ - rParam.maUserDataStore.clear(); - - OString aSysPath = toSystemPath(rPath); - const char* path = aSysPath.getStr(); - - // TODO: Use our own stream loading call instead of one from orcus. - std::string aStrm; - orcus::load_file_content(path, aStrm); - - if (aStrm.empty()) - return false; - - orcus::xmlns_repository repo; // xml namespace repository. - orcus::xmlns_context cxt = repo.create_context(); - orcus::xml_structure_tree aXmlTree(cxt); - try - { - aXmlTree.parse(&aStrm[0], aStrm.size()); - - TreeUpdateSwitch aSwitch(rTreeCtrl); - rTreeCtrl.Clear(); - rTreeCtrl.SetDefaultCollapsedEntryBmp(rParam.maImgElementDefault); - rTreeCtrl.SetDefaultExpandedEntryBmp(rParam.maImgElementDefault); - - orcus::xml_structure_tree::walker aWalker = aXmlTree.get_walker(); - - // Root element. - orcus::xml_structure_tree::element aElem = aWalker.root(); - populateTree(rTreeCtrl, aWalker, aElem.name, aElem.repeat, NULL, rParam); - } - catch (const std::exception&) - { - // Parsing of this XML file failed. - return false; - } - - return true; -} - -namespace { - -class InsertFieldPath : std::unary_function<OString, void> -{ - orcus::orcus_xml& mrFilter; -public: - InsertFieldPath(orcus::orcus_xml& rFilter) : mrFilter(rFilter) {} - void operator() (const OString& rPath) - { - mrFilter.append_field_link(rPath.getStr()); - } -}; - -} - -bool ScOrcusFiltersImpl::importXML( - ScDocument& rDoc, const rtl::OUString& rPath, const ScOrcusImportXMLParam& rParam) const +ScOrcusXMLContext* ScOrcusFiltersImpl::createXMLContext(ScDocument& rDoc, const rtl::OUString& rPath) const { - ScOrcusFactory aFactory(rDoc); - OString aSysPath = toSystemPath(rPath); - const char* path = aSysPath.getStr(); - try - { - orcus::orcus_xml filter(&aFactory, NULL); - - // Set cell links. - { - ScOrcusImportXMLParam::CellLinksType::const_iterator it = rParam.maCellLinks.begin(); - ScOrcusImportXMLParam::CellLinksType::const_iterator itEnd = rParam.maCellLinks.end(); - for (; it != itEnd; ++it) - { - const ScOrcusImportXMLParam::CellLink& rLink = *it; - OUString aTabName; - rDoc.GetName(rLink.maPos.Tab(), aTabName); - filter.set_cell_link( - rLink.maPath.getStr(), - rtl::OUStringToOString(aTabName, RTL_TEXTENCODING_UTF8).getStr(), - rLink.maPos.Row(), rLink.maPos.Col()); - } - } - - // Set range links. - { - ScOrcusImportXMLParam::RangeLinksType::const_iterator it = rParam.maRangeLinks.begin(); - ScOrcusImportXMLParam::RangeLinksType::const_iterator itEnd = rParam.maRangeLinks.end(); - for (; it != itEnd; ++it) - { - const ScOrcusImportXMLParam::RangeLink& rLink = *it; - OUString aTabName; - rDoc.GetName(rLink.maPos.Tab(), aTabName); - filter.start_range( - rtl::OUStringToOString(aTabName, RTL_TEXTENCODING_UTF8).getStr(), - rLink.maPos.Row(), rLink.maPos.Col()); - - std::for_each(rLink.maFieldPaths.begin(), rLink.maFieldPaths.end(), InsertFieldPath(filter)); - - filter.commit_range(); - } - } - - filter.read_file(path); - } - catch (const std::exception&) - { - return false; - } - return true; + return new ScOrcusXMLContextImpl(rDoc, rPath); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/orcus/xmlcontext.cxx b/sc/source/filter/orcus/xmlcontext.cxx new file mode 100644 index 000000000000..d32a55c2882c --- /dev/null +++ b/sc/source/filter/orcus/xmlcontext.cxx @@ -0,0 +1,221 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcusfiltersimpl.hxx" +#include "orcusinterface.hxx" +#include "orcusxml.hxx" +#include "document.hxx" + +#include "svtools/treelistbox.hxx" + +#define __ORCUS_STATIC_LIB +#include <orcus/spreadsheet/import_interface.hpp> +#include <orcus/xml_structure_tree.hpp> +#include <orcus/xml_namespace.hpp> +#include <orcus/orcus_xml.hpp> +#include <orcus/global.hpp> + +namespace { + +ScOrcusXMLTreeParam::EntryData& setUserDataToEntry( + SvTreeListEntry& rEntry, ScOrcusXMLTreeParam::UserDataStoreType& rStore, ScOrcusXMLTreeParam::EntryType eType) +{ + rStore.push_back(new ScOrcusXMLTreeParam::EntryData(eType)); + rEntry.SetUserData(&rStore.back()); + return rStore.back(); +} + +void populateTree( + SvTreeListBox& rTreeCtrl, orcus::xml_structure_tree::walker& rWalker, + const orcus::xml_structure_tree::entity_name& rElemName, bool bRepeat, + SvTreeListEntry* pParent, ScOrcusXMLTreeParam& rParam) +{ + OUString aName(rElemName.name.get(), rElemName.name.size(), RTL_TEXTENCODING_UTF8); + SvTreeListEntry* pEntry = rTreeCtrl.InsertEntry(aName, pParent); + if (!pEntry) + // Can this ever happen!? + return; + + ScOrcusXMLTreeParam::EntryData& rEntryData = setUserDataToEntry( + *pEntry, rParam.maUserDataStore, + bRepeat ? ScOrcusXMLTreeParam::ElementRepeat : ScOrcusXMLTreeParam::ElementDefault); + + if (bRepeat) + { + // Recurring elements use different icon. + rTreeCtrl.SetExpandedEntryBmp(pEntry, rParam.maImgElementRepeat); + rTreeCtrl.SetCollapsedEntryBmp(pEntry, rParam.maImgElementRepeat); + } + + if (pParent) + rTreeCtrl.Expand(pParent); + + orcus::xml_structure_tree::entity_names_type aNames; + + // Insert attributes. + rWalker.get_attributes(aNames); + orcus::xml_structure_tree::entity_names_type::const_iterator it = aNames.begin(); + orcus::xml_structure_tree::entity_names_type::const_iterator itEnd = aNames.end(); + for (; it != itEnd; ++it) + { + orcus::xml_structure_tree::entity_name aAttrName = *it; + SvTreeListEntry* pAttr = rTreeCtrl.InsertEntry( + OUString(aAttrName.name.get(), aAttrName.name.size(), RTL_TEXTENCODING_UTF8), pEntry); + + if (!pAttr) + continue; + + setUserDataToEntry(*pAttr, rParam.maUserDataStore, ScOrcusXMLTreeParam::Attribute); + rTreeCtrl.SetExpandedEntryBmp(pAttr, rParam.maImgAttribute); + rTreeCtrl.SetCollapsedEntryBmp(pAttr, rParam.maImgAttribute); + } + rTreeCtrl.Expand(pEntry); + + rWalker.get_children(aNames); + + // Non-leaf if it has child elements, leaf otherwise. + rEntryData.mbLeafNode = aNames.empty(); + + // Insert child elements recursively. + for (it = aNames.begin(), itEnd = aNames.end(); it != itEnd; ++it) + { + orcus::xml_structure_tree::element aElem = rWalker.descend(*it); + populateTree(rTreeCtrl, rWalker, *it, aElem.repeat, pEntry, rParam); + rWalker.ascend(); + } +} + +class TreeUpdateSwitch +{ + SvTreeListBox& mrTreeCtrl; +public: + TreeUpdateSwitch(SvTreeListBox& rTreeCtrl) : mrTreeCtrl(rTreeCtrl) + { + mrTreeCtrl.SetUpdateMode(false); + } + + ~TreeUpdateSwitch() + { + mrTreeCtrl.SetUpdateMode(true); + } +}; + +class InsertFieldPath : std::unary_function<OString, void> +{ + orcus::orcus_xml& mrFilter; +public: + InsertFieldPath(orcus::orcus_xml& rFilter) : mrFilter(rFilter) {} + void operator() (const OString& rPath) + { + mrFilter.append_field_link(rPath.getStr()); + } +}; + +} + +ScOrcusXMLContextImpl::ScOrcusXMLContextImpl(ScDocument& rDoc, const OUString& rPath) : + ScOrcusXMLContext(), mrDoc(rDoc), maPath(rPath) {} + +ScOrcusXMLContextImpl::~ScOrcusXMLContextImpl() {} + +bool ScOrcusXMLContextImpl::loadXMLStructure(SvTreeListBox& rTreeCtrl, ScOrcusXMLTreeParam& rParam) const +{ + rParam.maUserDataStore.clear(); + + OString aSysPath = ScOrcusFiltersImpl::toSystemPath(maPath); + const char* path = aSysPath.getStr(); + + // TODO: Use our own stream loading call instead of one from orcus. + std::string aStrm; + orcus::load_file_content(path, aStrm); + + if (aStrm.empty()) + return false; + + orcus::xmlns_repository repo; // xml namespace repository. + orcus::xmlns_context cxt = repo.create_context(); + orcus::xml_structure_tree aXmlTree(cxt); + try + { + aXmlTree.parse(&aStrm[0], aStrm.size()); + + TreeUpdateSwitch aSwitch(rTreeCtrl); + rTreeCtrl.Clear(); + rTreeCtrl.SetDefaultCollapsedEntryBmp(rParam.maImgElementDefault); + rTreeCtrl.SetDefaultExpandedEntryBmp(rParam.maImgElementDefault); + + orcus::xml_structure_tree::walker aWalker = aXmlTree.get_walker(); + + // Root element. + orcus::xml_structure_tree::element aElem = aWalker.root(); + populateTree(rTreeCtrl, aWalker, aElem.name, aElem.repeat, NULL, rParam); + } + catch (const std::exception&) + { + // Parsing of this XML file failed. + return false; + } + + return true; +} + +bool ScOrcusXMLContextImpl::importXML(const ScOrcusImportXMLParam& rParam) const +{ + ScOrcusFactory aFactory(mrDoc); + OString aSysPath = ScOrcusFiltersImpl::toSystemPath(maPath); + const char* path = aSysPath.getStr(); + try + { + orcus::orcus_xml filter(&aFactory, NULL); + + // Set cell links. + { + ScOrcusImportXMLParam::CellLinksType::const_iterator it = rParam.maCellLinks.begin(); + ScOrcusImportXMLParam::CellLinksType::const_iterator itEnd = rParam.maCellLinks.end(); + for (; it != itEnd; ++it) + { + const ScOrcusImportXMLParam::CellLink& rLink = *it; + OUString aTabName; + mrDoc.GetName(rLink.maPos.Tab(), aTabName); + filter.set_cell_link( + rLink.maPath.getStr(), + rtl::OUStringToOString(aTabName, RTL_TEXTENCODING_UTF8).getStr(), + rLink.maPos.Row(), rLink.maPos.Col()); + } + } + + // Set range links. + { + ScOrcusImportXMLParam::RangeLinksType::const_iterator it = rParam.maRangeLinks.begin(); + ScOrcusImportXMLParam::RangeLinksType::const_iterator itEnd = rParam.maRangeLinks.end(); + for (; it != itEnd; ++it) + { + const ScOrcusImportXMLParam::RangeLink& rLink = *it; + OUString aTabName; + mrDoc.GetName(rLink.maPos.Tab(), aTabName); + filter.start_range( + rtl::OUStringToOString(aTabName, RTL_TEXTENCODING_UTF8).getStr(), + rLink.maPos.Row(), rLink.maPos.Col()); + + std::for_each(rLink.maFieldPaths.begin(), rLink.maFieldPaths.end(), InsertFieldPath(filter)); + + filter.commit_range(); + } + } + + filter.read_file(path); + } + catch (const std::exception&) + { + return false; + } + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/xmlsourcedlg.hxx b/sc/source/ui/inc/xmlsourcedlg.hxx index e16b52a17a6f..1540b294cf94 100644 --- a/sc/source/ui/inc/xmlsourcedlg.hxx +++ b/sc/source/ui/inc/xmlsourcedlg.hxx @@ -23,6 +23,7 @@ class ScDocument; class ScRange; +class ScOrcusXMLContext; class ScXMLSourceTree : public SvTreeListBox { @@ -55,6 +56,8 @@ class ScXMLSourceDlg : public ScAnyRefDlg std::set<const SvTreeListEntry*> maCellLinks; std::set<const SvTreeListEntry*> maRangeLinks; + boost::scoped_ptr<ScOrcusXMLContext> mpXMLContext; + ScDocument* mpDoc; formula::RefEdit* mpActiveEdit; diff --git a/sc/source/ui/xmlsource/xmlsourcedlg.cxx b/sc/source/ui/xmlsource/xmlsourcedlg.cxx index fa85970617ca..5019306d6e7f 100644 --- a/sc/source/ui/xmlsource/xmlsourcedlg.cxx +++ b/sc/source/ui/xmlsource/xmlsourcedlg.cxx @@ -208,7 +208,11 @@ void ScXMLSourceDlg::LoadSourceFileStructure(const OUString& rPath) if (!pOrcus) return; - pOrcus->loadXMLStructure(rPath, maLbTree, maXMLParam); + mpXMLContext.reset(pOrcus->createXMLContext(*mpDoc, rPath)); + if (!mpXMLContext) + return; + + mpXMLContext->loadXMLStructure(maLbTree, maXMLParam); } void ScXMLSourceDlg::HandleGetFocus(Control* pCtrl) @@ -454,6 +458,9 @@ void getFieldLinks(ScOrcusImportXMLParam::RangeLink& rRangeLink, const SvTreeLis void ScXMLSourceDlg::OkPressed() { + if (!mpXMLContext) + return; + // Begin import. ScOrcusImportXMLParam aParam; @@ -493,11 +500,8 @@ void ScXMLSourceDlg::OkPressed() } // Now do the import. - ScOrcusFilters* pOrcus = ScFormatFilter::Get().GetOrcusFilters(); - if (!pOrcus) - return; - pOrcus->importXML(*mpDoc, maSrcPath, aParam); + mpXMLContext->importXML(aParam); // Don't forget to broadcast the change. SfxObjectShell* pShell = mpDoc->GetDocumentShell(); |