File indexing completed on 2024-05-12 16:29:06

0001 /*
0002  * This file is part of Office 2007 Filters for Calligra
0003  *
0004  * Copyright (C) 2010 Sebastian Sauer <sebsauer@kdab.com>
0005  * Copyright (c) 2010 Carlos Licea <carlos@kdab.com>
0006  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
0007  *
0008  * Contact: Suresh Chande suresh.chande@nokia.com
0009  *
0010  * This library is free software; you can redistribute it and/or
0011  * modify it under the terms of the GNU Lesser General Public License
0012  * version 2.1 as published by the Free Software Foundation.
0013  *
0014  * This library is distributed in the hope that it will be useful, but
0015  * WITHOUT ANY WARRANTY; without even the implied warranty of
0016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0017  * Lesser General Public License for more details.
0018  *
0019  * You should have received a copy of the GNU Lesser General Public
0020  * License along with this library; if not, write to the Free Software
0021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0022  * 02110-1301 USA
0023  *
0024  */
0025 
0026 #include "MsooXmlDiagramReader.h"
0027 
0028 #define MSOOXML_CURRENT_NS "dgm"
0029 #define MSOOXML_CURRENT_CLASS MsooXmlDiagramReader
0030 #define BIND_READ_CLASS MSOOXML_CURRENT_CLASS
0031 
0032 #include <MsooXmlReader_p.h>
0033 #include <MsooXmlUtils.h>
0034 #include <KoXmlWriter.h>
0035 #include <KoGenStyles.h>
0036 #include <QExplicitlySharedDataPointer>
0037 #include <typeinfo>
0038 
0039 #include "MsooXmlDiagramReader_p.h"
0040 
0041 using namespace MSOOXML;
0042 
0043 MsooXmlDiagramReaderContext::MsooXmlDiagramReaderContext(KoGenStyles* styles)
0044     : MSOOXML::MsooXmlReaderContext()
0045     , m_styles(styles)
0046     , m_context(new Diagram::Context)
0047 {
0048 }
0049 
0050 MsooXmlDiagramReaderContext::~MsooXmlDiagramReaderContext()
0051 {
0052     delete m_context;
0053 }
0054 
0055 int MsooXmlDiagramReaderContext::shapeListSize() const
0056 {
0057     return m_context->m_shapeList.size();
0058 }
0059 
0060 void MsooXmlDiagramReaderContext::saveIndex(KoXmlWriter* xmlWriter, const QRect &rect)
0061 {
0062     // The root layout node always inherits the canvas dimensions by default.
0063     m_context->m_rootLayout->m_values["l"] = rect.x();
0064     m_context->m_rootLayout->m_values["t"] = rect.y();
0065     m_context->m_rootLayout->m_values["w"] = rect.width();
0066     m_context->m_rootLayout->m_values["h"] = rect.height();
0067     debugMsooXml << "drawingRect" << rect;
0068 
0069     // Do the (re-)layout.
0070     m_context->m_rootLayout->layoutAtom(m_context);    
0071     // Write the content.
0072     m_context->m_rootLayout->writeAtom(m_context, xmlWriter, m_styles);  
0073 }
0074 
0075 MsooXmlDiagramReader::MsooXmlDiagramReader(KoOdfWriters *writers)
0076     : MSOOXML::MsooXmlCommonReader(writers)
0077     , m_type(InvalidType)
0078 {
0079 }
0080 
0081 MsooXmlDiagramReader::~MsooXmlDiagramReader()
0082 {
0083 }
0084 
0085 KoFilter::ConversionStatus MsooXmlDiagramReader::read(MSOOXML::MsooXmlReaderContext* context)
0086 {
0087     m_context = dynamic_cast<MsooXmlDiagramReaderContext*>(context);
0088     Q_ASSERT(m_context);
0089 
0090     readNext();
0091     if (!isStartDocument()) {
0092         return KoFilter::WrongFormat;
0093     }
0094 
0095     readNext();
0096     if (qualifiedName() == QLatin1String("dgm:dataModel")) {
0097         m_type = DataModelType;
0098         
0099         Diagram::PointListNode rootList;
0100         while (!atEnd()) {
0101             QXmlStreamReader::TokenType tokenType = readNext();
0102             if (tokenType == QXmlStreamReader::Invalid || tokenType == QXmlStreamReader::EndDocument) break;
0103             if (isStartElement()) {
0104                 if (qualifiedName() == QLatin1String("dgm:ptLst")) { // list of points
0105                     rootList.readAll(m_context->m_context, this);
0106                 } else if (qualifiedName() == QLatin1String("dgm:cxnLst")) { // list of connections
0107                     m_context->m_context->m_connections->readAll(m_context->m_context, this);
0108                 }
0109             }
0110         }
0111         
0112         QMap<QString, Diagram::PointNode*> pointMap;
0113         foreach(Diagram::AbstractNode* node, rootList.children()) {
0114             if (Diagram::PointNode* point = dynamic_cast<Diagram::PointNode*>(node))
0115                 if (!point->m_modelId.isEmpty())
0116                     pointMap[point->m_modelId] = point;
0117         }
0118 
0119         foreach(Diagram::AbstractNode* node, m_context->m_context->m_connections->children()) {
0120             if (Diagram::ConnectionNode* connection = dynamic_cast<Diagram::ConnectionNode*>(node)) {
0121                 Q_ASSERT(pointMap.contains(connection->m_srcId));
0122                 Q_ASSERT(pointMap.contains(connection->m_destId));
0123                 Q_ASSERT(connection->m_parTransId.isEmpty() || pointMap.contains(connection->m_parTransId));
0124                 Q_ASSERT(connection->m_sibTransId.isEmpty() || pointMap.contains(connection->m_sibTransId));
0125                 Diagram::PointNode* source = pointMap.value(connection->m_srcId);
0126                 Diagram::PointNode* destination = pointMap.value(connection->m_destId);
0127                 Diagram::PointNode* parent = connection->m_parTransId.isEmpty() ? 0 : pointMap.value(connection->m_parTransId);
0128                 Diagram::PointNode* sibling = connection->m_sibTransId.isEmpty() ? 0 : pointMap.value(connection->m_sibTransId);
0129 
0130                 const int srcOrd = connection->m_srcOrd;
0131                 const int destOrd = connection->m_destOrd;
0132                 Q_UNUSED(destOrd); //TODO how to apply that one?
0133 
0134                 if (parent) {
0135                     // add a transition between parent and child
0136                     Q_ASSERT(parent->m_type == "parTrans");
0137                     Q_ASSERT(rootList.children().contains(parent));
0138                     rootList.removeChild(parent);
0139                     source->insertChild(srcOrd, parent);
0140                 }
0141 
0142                 if (sibling) {
0143                      // add a transition between siblings
0144                     Q_ASSERT(sibling->m_type == "sibTrans");
0145                     Q_ASSERT(rootList.children().contains(sibling));
0146                     rootList.removeChild(sibling);
0147                     source->insertChild(srcOrd, sibling);
0148                 }
0149 
0150                 if (connection->m_type == QLatin1String("parOf")) {
0151                     // This defines a parent-child relationship in the sense that node X is a parent of node Y.
0152                     Q_ASSERT(rootList.children().contains(destination));
0153                     //Q_ASSERT(rootList.children().at(destOrd) == destination);
0154                     rootList.removeChild(destination);
0155                     source->insertChild(srcOrd, destination);
0156                 } else if (connection->m_type == QLatin1String("presOf")) {
0157                     // A presentation type relationship. This type of relationship exists to actually present data.
0158                     //TODO
0159                 } else if (connection->m_type == QLatin1String("presParOf")) {
0160                     // A relationship defining a parent of a presentation node.
0161                     //TODO
0162                 }
0163             }
0164         }
0165 
0166         delete m_context->m_context->m_rootPoint;
0167         foreach(Diagram::AbstractNode* node, rootList.children()) {
0168             if (Diagram::PointNode* pt = dynamic_cast<Diagram::PointNode*>(node)) {
0169                 if (pt->m_type == QLatin1String("doc")) {
0170                     m_context->m_context->m_rootPoint = pt;
0171                     break;
0172                 }
0173             }
0174         }
0175         if (!m_context->m_context->m_rootPoint) {
0176             warnMsooXml << "Data-definition doesn't specify a root-node";
0177             return KoFilter::WrongFormat;
0178         }
0179         Q_ASSERT(rootList.children().contains(m_context->m_context->m_rootPoint));
0180         rootList.removeChild(m_context->m_context->m_rootPoint);
0181         //Q_ASSERT(rootList.children().isEmpty());
0182         m_context->m_context->setCurrentNode(m_context->m_context->m_rootPoint);
0183 
0184 #if 0
0185         QFile visGraphFile( "graphDump" );
0186         visGraphFile.open( QFile::WriteOnly | QFile::Truncate );
0187         QTextStream visGraph( &visGraphFile );
0188         visGraph << "digraph { \n";
0189         m_context->m_context->m_rootPoint->dump( visGraph );
0190         visGraph << "}\n";
0191         visGraphFile.close();
0192 #endif
0193         //m_context->m_context->m_rootPoint->dump(m_context->m_context, 0);
0194         //Q_ASSERT( false );
0195     }
0196     else if (qualifiedName() == QLatin1String("dgm:layoutDef")) {
0197         m_type = LayoutDefType;
0198 
0199         while (!atEnd()) {
0200             QXmlStreamReader::TokenType tokenType = readNext();
0201             if(tokenType == QXmlStreamReader::Invalid || tokenType == QXmlStreamReader::EndDocument) break;
0202             if (isStartElement()) {
0203                 if (qualifiedName() == QLatin1String("dgm:layoutNode")) {
0204                     m_context->m_context->m_rootLayout->readAll(m_context->m_context, this);
0205                 }
0206                 //ELSE_TRY_READ_IF(title)
0207                 //ELSE_TRY_READ_IF(sampData)
0208                 //ELSE_TRY_READ_IF(styleData)
0209             }
0210         }
0211         if (!m_context->m_context->m_rootPoint) {
0212             warnMsooXml << "Layout-definition doesn't specify a root-point";
0213             return KoFilter::WrongFormat;
0214         }
0215 
0216         // build the layout-tree. This solves ForEachAtom, ChooseAtom and other things that need to be executed.
0217         m_context->m_context->m_rootLayout->build(m_context->m_context);
0218         // once done we start a second build-process that does additional things once the layout-tree is fully available.
0219         m_context->m_context->m_rootLayout->finishBuild(m_context->m_context);
0220 
0221         //m_context->m_context->m_rootLayout->dump(m_context->m_context,0);
0222         //Q_ASSERT( false );
0223     }
0224     else if (qualifiedName() == QLatin1String("dgm:styleDef")) {
0225         m_type = StyleDefType;
0226         //TODO
0227     }
0228     else if (qualifiedName() == QLatin1String("dgm:colorsDef")) {
0229         m_type = ColorsDefType;
0230         //TODO
0231     }
0232     else {
0233         return KoFilter::WrongFormat;
0234     }
0235 
0236     m_context = 0;
0237     m_type = InvalidType;
0238     return KoFilter::OK;
0239 }
0240