Commit 4b5080d6 authored by Boudewijn Rempt's avatar Boudewijn Rempt

All the code for loading odf using shapes is now in place: only the shapes themselves

still need to implement the loading. So unittests fail, which is okay.

svn path=/trunk/koffice/; revision=664392
parent 1017ee9b
......@@ -51,7 +51,6 @@ KoShape * KoPathShapeFactory::createShape(const KoProperties * params) const {
bool KoPathShapeFactory::supports(const KoXmlElement & e) const
{
Q_UNUSED( e );
return false;
return ( e.tagName() == "path" );
}
......@@ -141,9 +141,11 @@ public:
* @param context the KoShapeLoadingContext used for loading
* @param element element which represents the shape in odf
*
* @return false if loading failed
*
* TODO make it pure virtual
*/
virtual bool loadOdf( const KoXmlElement & element, KoShapeLoadingContext &context ) { Q_UNUSED(element); Q_UNUSED(context); return true; }
virtual bool loadOdf( const KoXmlElement & element, KoShapeLoadingContext &context ) { Q_UNUSED(element); Q_UNUSED(context); return false; }
/**
* @brief store the shape data as ODF XML.
......@@ -596,7 +598,7 @@ protected:
* @param attributes a number of OdfAttribute items to state which attributes to load.
*/
bool loadOdfAttributes( const KoXmlElement & element, KoShapeLoadingContext &context, int attributes );
/**
* This method can be used while saving the shape as ODF to add the data
* stored on this shape to the current element.
......
......@@ -23,12 +23,19 @@
class KoShapeFactory::Private {
public:
Private(const QString &i, const QString &n) : id(i), name(n) {}
Private( const QString &i, const QString &n )
: id(i)
, name(n)
, loadingPriority( 0 )
{
}
~Private() {
foreach(KoShapeTemplate t, templates)
delete t.properties;
templates.clear();
}
QList<KoShapeTemplate> templates;
QList<KoShapeConfigFactory*> configPanels;
const QString id;
......
......@@ -183,11 +183,11 @@ public:
/// the name used for quick checking if this shapeFactory is able to
/// load Odf data identified by the element name.
virtual QString odfElementName() const;
QString odfElementName() const;
/// returns true if this shapeFactory is able to load the ODF type
/// started at argument element. ('draw:line' / 'draw:frame' / etc)
bool supports(const KoXmlElement & e) const;
virtual bool supports(const KoXmlElement & e) const;
protected:
......
......@@ -19,6 +19,7 @@
* Boston, MA 02110-1301, USA.
*/
#include <QString>
#include <QHash>
#include <QMultiMap>
#include <kdebug.h>
......@@ -30,29 +31,68 @@
#include "KoShapeLoadingContext.h"
#include "KoXmlReader.h"
class KoShapeRegistry::Private
{
public:
// Map namespace,tagname to priority:factory
QHash<QPair<QString, QString>, QMultiMap<int, KoShapeFactory*> > factoryMap;
};
KoShapeRegistry::KoShapeRegistry()
{
}
void KoShapeRegistry::init() {
d = new Private();
KoPluginLoader::PluginsConfig config;
config.whiteList = "FlakePlugins";
config.blacklist = "FlakePluginsDisabled";
config.group = "koffice";
KoPluginLoader::instance()->load( QString::fromLatin1("KOffice/Flake"),
QString::fromLatin1("[X-Flake-Version] == 1"), config);
QString::fromLatin1("[X-Flake-Version] == 1"),
config);
config.whiteList = "ShapePlugins";
config.blacklist = "ShapePluginsDisabled";
KoPluginLoader::instance()->load(QString::fromLatin1("KOffice/Shape"),
QString::fromLatin1("[X-Flake-Version] == 1"), config);
QString::fromLatin1("[X-Flake-Version] == 1"),
config);
// Also add our hard-coded basic shape
add( new KoPathShapeFactory(this, QStringList()) );
// Now all shape factories are registered with us, determine their
// assocated odf tagname & priority and prepare ourselves for
// loading ODF.
QList<KoShapeFactory*> factories = values();
for ( int i = 0; i < factories.size(); ++i ) {
KoShapeFactory * factory = factories[i];
if ( factory->odfNameSpace().isEmpty() || factory->odfElementName().isEmpty() )
{
kDebug() << "Booh! Shape factory " << factory->id() << " sucks!" << endl;
}
else {
QPair<QString, QString> p ( factory->odfNameSpace(), factory->odfElementName() );
QMultiMap<int, KoShapeFactory*> priorityMap = d->factoryMap[p];
d->factoryMap[p].insert( factory->loadingPriority(), factory );
kDebug() << "Inserting factory " << factory->id() << " for "
<< p << " with priority "
<< factory->loadingPriority() << " into factoryMap making "
<< d->factoryMap[p].size() << " entries. " << endl;
}
}
}
KoShapeRegistry::~KoShapeRegistry()
{
delete d;
}
KoShapeRegistry *KoShapeRegistry::m_singleton = 0;
......@@ -68,10 +108,38 @@ KoShapeRegistry* KoShapeRegistry::instance()
return KoShapeRegistry::m_singleton;
}
KoShape * KoShapeRegistry::createShapeFromOdf(const KoXmlElement & e, KoShapeLoadingContext *context) const
KoShape * KoShapeRegistry::createShapeFromOdf(const KoXmlElement & e, KoShapeLoadingContext & context) const
{
Q_UNUSED( context );
Q_UNUSED( e );
kDebug() << "Going to check for " << e.namespaceURI() << ":" << e.tagName() << endl;
QPair<QString, QString> p = QPair<QString, QString>(e.namespaceURI(), e.tagName());
kDebug() << p << endl;
if ( !d->factoryMap.contains( p ) ) return 0;
QMultiMap<int,KoShapeFactory*> priorityMap = d->factoryMap[p];
QList<KoShapeFactory*> factories = priorityMap.values();
// Higher numbers are more specific, map is sorted by keys
for ( int i = factories.size() - 1; i >= 0; --i ) {
KoShapeFactory * factory = factories[i];
if ( factory->supports( e ) ) {
KoShape * shape = factory->createDefaultShape();
if( shape->shapeId().isEmpty() )
shape->setShapeId(factory->id());
if ( shape->loadOdf( e, context ) )
return shape;
// Maybe a shape with a lower priority can load our
// element, but this attempt has failed.
delete shape;
}
}
return 0;
}
......
......@@ -60,7 +60,7 @@ public:
*
* @returns the shape or 0 if no shape could be created
*/
KoShape * createShapeFromOdf(const KoXmlElement & e, KoShapeLoadingContext *context) const;
KoShape * createShapeFromOdf(const KoXmlElement & e, KoShapeLoadingContext & context) const;
private:
KoShapeRegistry();
......@@ -70,6 +70,10 @@ private:
private:
static KoShapeRegistry *m_singleton;
class Private;
Private * d;
};
#endif
......@@ -27,6 +27,10 @@
#include <QtXml>
#include <QStringList>
#include <KoOasisLoadingContext.h>
#include <KoOasisStyles.h>
#include "KoShapeLoadingContext.h"
#include "KoShapeRegistry.h"
#include "KoPathShapeFactory.h"
#include "KoShape.h"
......@@ -85,19 +89,10 @@ void TestKoShapeFactory::testOdfElement()
xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
xmlstream << "<office:document-content xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\" xmlns:config=\"urn:oasis:names:tc:opendocument:xmlns:config:1.0\" xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\" xmlns:draw=\"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0\" xmlns:presentation=\"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0\" xmlns:dr3d=\"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0\" xmlns:chart=\"urn:oasis:names:tc:opendocument:xmlns:chart:1.0\" xmlns:form=\"urn:oasis:names:tc:opendocument:xmlns:form:1.0\" xmlns:script=\"urn:oasis:names:tc:opendocument:xmlns:script:1.0\" xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\" xmlns:number=\"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0\" xmlns:math=\"http://www.w3.org/1998/Math/MathML\" xmlns:svg=\"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0\" xmlns:fo=\"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0\" xmlns:koffice=\"http://www.koffice.org/2005/\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">";
xmlstream << "<office:font-face-decls>";
xmlstream << "<style:font-face style:name=\"Georgia\" svg:font-family=\"Georgia\"/>";
xmlstream << "</office:font-face-decls>";
xmlstream << "<office:automatic-styles>";
xmlstream << "<style:style style:name=\"P1\" style:parent-style-name=\"Standard\" style:family=\"paragraph\" style:master-page-name=\"Standard\">";
xmlstream << "<style:paragraph-properties style:page-number=\"1\" style:writing-mode=\"lr-tb\"/>";
xmlstream << "<style:text-properties/>";
xmlstream << "</style:style>";
xmlstream << "</office:automatic-styles>";
xmlstream << "<office:body>";
xmlstream << "<office:text>";
xmlstream << "<text:p text:style-name=\"P1\"><?opendocument cursor-position?></text:p>";
xmlstream << "<draw:path svg:d=\"M0,0L100,100\"></draw:path>";
xmlstream << "<draw:path svg:d=\"M10,10L100,100\"></draw:path>";
xmlstream << "</office:text>";
xmlstream << "</office:body>";
xmlstream << "</office:document-content>";
......@@ -116,17 +111,24 @@ void TestKoShapeFactory::testOdfElement()
KoXmlElement contentElement = doc.documentElement();
KoXmlElement bodyElement = contentElement.firstChild().toElement();
QTEST( factory->supports( bodyElement ), false );
KoXmlElement textElement = bodyElement.firstChild().toElement();
QTEST( factory->supports( textElement ), false );
KoXmlElement textElement = bodyElement.firstChild().firstChild().toElement();
QVERIFY( textElement.tagName() == "p" );
QCOMPARE( factory->supports( textElement ), false );
KoXmlElement pathElement = bodyElement.firstChild().nextSibling().toElement();
KoXmlElement pathElement = bodyElement.firstChild().lastChild().toElement();
QVERIFY( pathElement.tagName() == "path" );
QCOMPARE( factory->supports( pathElement ), true );
KoShape * shape = factory->createDefaultShape( );
QVERIFY( shape );
//XXX: test loading
// XXX: When loading is implemented, these no doubt have to be
// sensibly filled.
KoOasisStyles styles;
KoOasisLoadingContext oasisContext(0, styles, 0);
KoShapeLoadingContext shapeContext( oasisContext );
QVERIFY( shape->loadOdf( pathElement, shapeContext ) );
delete shape;
delete factory;
......
......@@ -26,8 +26,12 @@
#include <QTextStream>
#include <QtXml>
#include <KoOasisLoadingContext.h>
#include <KoOasisStyles.h>
#include "KoShapeRegistry.h"
#include "KoShape.h"
#include "KoPathShape.h"
#include "KoShapeLoadingContext.h"
#include <KoXmlReader.h>
......@@ -48,18 +52,9 @@ void TestKoShapeRegistry::testCreateEmptyShape()
xmlstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
xmlstream << "<office:document-content xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\" xmlns:config=\"urn:oasis:names:tc:opendocument:xmlns:config:1.0\" xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\" xmlns:draw=\"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0\" xmlns:presentation=\"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0\" xmlns:dr3d=\"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0\" xmlns:chart=\"urn:oasis:names:tc:opendocument:xmlns:chart:1.0\" xmlns:form=\"urn:oasis:names:tc:opendocument:xmlns:form:1.0\" xmlns:script=\"urn:oasis:names:tc:opendocument:xmlns:script:1.0\" xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\" xmlns:number=\"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0\" xmlns:math=\"http://www.w3.org/1998/Math/MathML\" xmlns:svg=\"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0\" xmlns:fo=\"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0\" xmlns:koffice=\"http://www.koffice.org/2005/\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">";
xmlstream << "<office:font-face-decls>";
xmlstream << "<style:font-face style:name=\"Georgia\" svg:font-family=\"Georgia\"/>";
xmlstream << "</office:font-face-decls>";
xmlstream << "<office:automatic-styles>";
xmlstream << "<style:style style:name=\"P1\" style:parent-style-name=\"Standard\" style:family=\"paragraph\" style:master-page-name=\"Standard\">";
xmlstream << "<style:paragraph-properties style:page-number=\"1\" style:writing-mode=\"lr-tb\"/>";
xmlstream << "<style:text-properties/>";
xmlstream << "</style:style>";
xmlstream << "</office:automatic-styles>";
xmlstream << "<office:body>";
xmlstream << "<office:text>";
xmlstream << "<text:p text:style-name=\"P1\"><?opendocument cursor-position?></text:p>";
xmlstream << "<draw:path svg:d=\"M0,0L100,100\"></draw:path>";
xmlstream << "</office:text>";
xmlstream << "</office:body>";
xmlstream << "</office:document-content>";
......@@ -79,11 +74,20 @@ void TestKoShapeRegistry::testCreateEmptyShape()
KoXmlElement bodyElement = contentElement.firstChild().toElement();
KoShapeRegistry * registry = KoShapeRegistry::instance();
// KoShapeLoadingContext * context = new KoShapeLoadingContext();
// KoShape * shape = registry->createShapeFromOdf(bodyElement, context);
// QVERIFY( shape == 0 );
// XXX: When loading is implemented, these no doubt have to be
// sensibly filled.
KoOasisStyles styles;
KoOasisLoadingContext oasisContext(0, styles, 0);
KoShapeLoadingContext shapeContext( oasisContext );
KoShape * shape = registry->createShapeFromOdf(bodyElement, shapeContext);
QVERIFY( shape == 0 );
KoXmlElement pathElement = bodyElement.firstChild().firstChild().toElement();
shape = registry->createShapeFromOdf( pathElement, shapeContext );
QVERIFY( shape != 0 );
QVERIFY( shape->shapeId() == KoPathShapeId );
}
......
......@@ -114,6 +114,10 @@ public:
return m_hash.count();
}
QList<T> values() const {
return m_hash.values();
}
private:
QHash<QString, T> m_hash;
};
......
......@@ -41,9 +41,10 @@ class KOMAIN_EXPORT KoOasisLoadingContext
{
public:
/**
* Stores reference to the KoOasisStyles and stored passed by KoDocument.
* Make sure that the KoOasisStyles instance outlives this KoOasisLoadingContext instance.
* (This is the case during loading, when using the KoOasisStyles given by KoDocument)
* Stores reference to the KoOasisStyles and stored passed by
* KoDocument. Make sure that the KoOasisStyles instance outlives
* this KoOasisLoadingContext instance. (This is the case during
* loading, when using the KoOasisStyles given by KoDocument)
*
* @param doc the KoDocument being loaded
* @param styles reference to the KoOasisStyles parsed by KoDocument
......
......@@ -142,17 +142,23 @@ bool KoOasisStore::closeManifestWriter()
bool KoOasisStore::loadAndParse( const QString& fileName, KoXmlDocument& doc, QString& errorMessage )
{
//kDebug(30003) << "loadAndParse: Trying to open " << fileName << endl;
if ( !m_store ) {
kWarning( 30003 ) << "No store backend" << endl;
errorMessage = i18n( "No store backend" );
return false;
}
if (!m_store->open(fileName))
if ( !m_store->open(fileName) )
{
kWarning(30003) << "Entry " << fileName << " not found!" << endl;
errorMessage = i18n( "Could not find %1", fileName );
return false;
}
bool ok = loadAndParse( m_store->device(), doc, errorMessage, fileName );
m_store->close();
return ok;
}
}
bool KoOasisStore::loadAndParse( QIODevice* fileDevice, KoXmlDocument& doc, QString& errorMessage, const QString& fileName )
{
......@@ -175,7 +181,7 @@ bool KoOasisStore::loadAndParse( QIODevice* fileDevice, KoXmlDocument& doc, QStr
kError(30003) << "Parsing error in " << fileName << "! Aborting!" << endl
<< " In line: " << errorLine << ", column: " << errorColumn << endl
<< " Error message: " << errorMsg << endl;
errorMessage = i18n( "Parsing error in the main document at line %1, column %2\nError message: %3"
errorMessage = i18n( "Parsing error in the main document at line %1, column %2\nError message: %3"
,errorLine ,errorColumn ,i18n ( "QXml", errorMsg ) );
}
else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment