bool KoFormulaShape::loadOdfFrameElement(const KoXmlElement &element,
                                         KoShapeLoadingContext &context)
{
    // If this formula is embedded and not inline, then load the embedded document.
    if ( element.tagName() == "object" && element.hasAttributeNS( KoXmlNS::xlink, "href" )) {
        m_isInline = false;

        // This calls loadOdfEmbedded().
        return loadEmbeddedDocument( context.odfLoadingContext().store(),
                                     element,
                                     context.odfLoadingContext() );
    }

    // It's not a frame:object, so it must be inline.
    const KoXmlElement& topLevelElement = KoXml::namedItemNS(element, KoXmlNS::math, "math");
    if (topLevelElement.isNull()) {
        kWarning() << "no math element as first child";
        return false;
    }

    // Create a new root element, load the formula and replace the old one.
    FormulaElement* formulaElement = new FormulaElement();
    formulaElement->readMathML( topLevelElement );
    delete m_formulaData->formulaElement();
    m_formulaData->setFormulaElement(formulaElement);
    m_formulaData->notifyDataChange(0, false);

    m_isInline = true;

    return true;
}
bool KoTextOnShapeContainer::loadOdf(const KoXmlElement &element, KoShapeLoadingContext &context)
{
    Q_D(KoTextOnShapeContainer);
    if (d->textShape == 0)
        return false; // probably because the factory was not found.

    KoTextShapeDataBase *shapeData = qobject_cast<KoTextShapeDataBase*>(d->textShape->userData());
    Q_ASSERT(shapeData); // would be a bug in kotext

    QString styleName = element.attributeNS(KoXmlNS::draw, "style-name");
    if (!styleName.isEmpty()) {
        KoStyleStack &styleStack = context.odfLoadingContext().styleStack();
        styleStack.save();
        context.odfLoadingContext().fillStyleStack(element, KoXmlNS::draw, "style-name", "graphic");
        styleStack.setTypeProperties("graphic");
        QString valign = styleStack.property(KoXmlNS::draw, "textarea-vertical-align");
        if (valign == "top") {
            shapeData->setVerticalAlignment(Qt::AlignTop);
        } else if (valign == "middle") {
            shapeData->setVerticalAlignment(Qt::AlignVCenter);
        } else if (valign == "bottom") {
            shapeData->setVerticalAlignment(Qt::AlignBottom);
        }
        styleStack.restore();
    }

    return shapeData->loadOdf(element, context);
}
Exemple #3
0
bool Surface::loadOdf( const KoXmlElement &surfaceElement, KoShapeLoadingContext &context )
{
    KoStyleStack &styleStack = context.odfLoadingContext().styleStack();
    styleStack.save();
    
    if ( surfaceElement.hasAttributeNS( KoXmlNS::chart, "style-name" ) )
    {
        KDChart::BackgroundAttributes backgroundAttributes = d->kdPlane->backgroundAttributes();
        KDChart::FrameAttributes frameAttributes = d->kdPlane->frameAttributes();
        
        styleStack.clear();
        context.odfLoadingContext().fillStyleStack( surfaceElement, KoXmlNS::chart, "style-name", "chart" );
        
        styleStack.setTypeProperties( "graphic" );
        
        if ( styleStack.hasProperty( KoXmlNS::draw, "stroke" ) )
        {
            frameAttributes.setVisible( true );
            QString stroke = styleStack.property( KoXmlNS::draw, "stroke" );
            if( stroke == "solid" || stroke == "dash" )
            {
                QPen pen = KoOdfGraphicStyles::loadOdfStrokeStyle( styleStack, stroke, context.odfLoadingContext().stylesReader() );
                frameAttributes.setPen( pen );
            }
        }
        
        if ( styleStack.hasProperty( KoXmlNS::draw, "fill" ) )
        {
            backgroundAttributes.setVisible( true );
            QBrush brush;
            QString fill = styleStack.property( KoXmlNS::draw, "fill" );
            if ( fill == "solid" || fill == "hatch" )
                brush = KoOdfGraphicStyles::loadOdfFillStyle( styleStack, fill, context.odfLoadingContext().stylesReader() );
            else if ( fill == "gradient" )
            {
                brush = KoOdfGraphicStyles::loadOdfGradientStyle( styleStack, context.odfLoadingContext().stylesReader(), QSizeF( 5.0, 60.0 ) );
            }
            else if ( fill == "bitmap" )
                brush = KoOdfGraphicStyles::loadOdfPatternStyle( styleStack, context.odfLoadingContext(), QSizeF( 5.0, 60.0 ) );
            backgroundAttributes.setBrush( brush );
        }
        
        d->kdPlane->setBackgroundAttributes( backgroundAttributes );
        d->kdPlane->setFrameAttributes( frameAttributes );
    }

    styleStack.restore();
    
    return true;
}
bool PictureShapeFactory::supports(const KoXmlElement &e, KoShapeLoadingContext &context) const
{
    if (e.localName() == "image" && e.namespaceURI() == KoXmlNS::draw) {
        QString href = e.attribute("href");
        if (!href.isEmpty()) {
            // check the mimetype
            if (href.startsWith(QLatin1String("./"))) {
                href.remove(0, 2);
            }
            QString mimetype = context.odfLoadingContext().mimeTypeForPath(href);
            if (!mimetype.isEmpty()) {
                return mimetype.startsWith("image");
            }
            else {
                return ( href.endsWith("bmp") ||
                         href.endsWith("jpg") ||
                         href.endsWith("gif") ||
                         href.endsWith("eps") ||
                         href.endsWith("png") ||
                         href.endsWith("tif") ||
                         href.endsWith("tiff"));
            }
        }
        else {
            return !KoXml::namedItemNS(e, KoXmlNS::office, "binary-data").isNull();
        }
    }
    return false;
}
Exemple #5
0
void KoTosContainer::loadStyle(const KoXmlElement &element, KoShapeLoadingContext &context)
{
    Q_D(KoTosContainer);

    KoShapeContainer::loadStyle(element, context);

    KoStyleStack &styleStack = context.odfLoadingContext().styleStack();
    styleStack.setTypeProperties("graphic");

    QString verticalAlign(styleStack.property(KoXmlNS::draw, "textarea-vertical-align"));
    Qt::Alignment vAlignment(Qt::AlignTop);
    if (verticalAlign == "bottom") {
        vAlignment = Qt::AlignBottom;
    } else if (verticalAlign == "justify") {
        // not yet supported
        vAlignment = Qt::AlignVCenter;
    } else if (verticalAlign == "middle") {
        vAlignment = Qt::AlignVCenter;
    }

    QString horizontalAlign(styleStack.property(KoXmlNS::draw, "textarea-horizontal-align"));
    Qt::Alignment hAlignment(Qt::AlignLeft);
    if (horizontalAlign == "center") {
        hAlignment = Qt::AlignCenter;
    } else if (horizontalAlign == "justify") {
        // not yet supported
        hAlignment = Qt::AlignCenter;
    } else if (horizontalAlign == "right") {
        hAlignment = Qt::AlignRight;
    }

    d->alignment = vAlignment | hAlignment;
}
Exemple #6
0
bool PictureShape::loadOdfFrameElement(const KoXmlElement &element, KoShapeLoadingContext &context)
{
    if (m_imageCollection) {
        const QString href = element.attribute("href");
        // this can happen in case it is a presentation:placeholder
        if (!href.isEmpty()) {
            KoStore *store = context.odfLoadingContext().store();
            KoImageData *data = m_imageCollection->createImageData(href, store);
            setUserData(data);
        } else {
            // check if we have an office:binary data element containing the image data
            const KoXmlElement &binaryData(KoXml::namedItemNS(element, KoXmlNS::office, "binary-data"));
            if (!binaryData.isNull()) {
                QImage image;
                if (image.loadFromData(QByteArray::fromBase64(binaryData.text().toLatin1()))) {
                    KoImageData *data = m_imageCollection->createImageData(image);
                    setUserData(data);
                }
            }
        }
    }

    loadText(element, context);

    return true;
}
Exemple #7
0
bool VectorShapeFactory::supports(const KoXmlElement & e, KoShapeLoadingContext &context) const
{
    if (e.localName() == "image" && e.namespaceURI() == KoXmlNS::draw) {
        QString href = e.attribute("href");
        if (!href.isEmpty()) {
            // check the mimetype
            if (href.startsWith(QLatin1String("./"))) {
                href.remove(0, 2);
            }
            // LO 3.5 does not write a mimetype for embedded wmf files, so guess also from content
            const QString mimetype = context.odfLoadingContext().mimeTypeForPath(href, true);

            return
                mimetype == QLatin1String("image/x-svm") ||
                mimetype == QLatin1String("image/x-emf") ||
                mimetype == QLatin1String("image/x-wmf") ||
                // Note: the Vector Shape supports SVG, but _NOT_ in this method, otherwise it will stomp all over loading the artistic text shape's svg
                //mimetype == QLatin1String("image/svg+xml") ||
                // next three for backward compatibility with Calligra
                mimetype == QLatin1String("application/x-svm") ||
                mimetype == QLatin1String("application/x-emf") ||
                mimetype == QLatin1String("application/x-wmf") ||
                // seems like MSO does not always write a mimetype
                // see jeffcoweb.jeffco.k12.co.us%2Fhigh%2Fchatfield%2Fdepartments%2Fbusiness%2Fbanking_finance%2Funit_Plan_Budget.odp
                mimetype.isEmpty() ||
                // next for compatibility with OO/LO and our filters
                // see drwho.virtadpt.net%2Ffiles%2FNOVALUG-Tor.odp
                mimetype.startsWith(QLatin1String("application/x-openoffice"));
        }
        return true;
    }

    return false;
}
Exemple #8
0
void PictureShape::loadStyle(const KoXmlElement& element, KoShapeLoadingContext& context)
{
    // Load the common parts of the style.
    KoTosContainer::loadStyle(element, context);

    KoStyleStack &styleStack = context.odfLoadingContext().styleStack();
    styleStack.setTypeProperties("graphic");

    // Mirroring
    if (styleStack.hasProperty(KoXmlNS::style, "mirror")) {
        QString mirrorMode = styleStack.property(KoXmlNS::style, "mirror");

        QFlags<PictureShape::MirrorMode>  mode = 0;

        // Only one of the horizontal modes
        if (mirrorMode.contains("horizontal-on-even")) {
            mode |= MirrorHorizontalOnEven;
        }
        else if (mirrorMode.contains("horizontal-on-odd")) {
            mode |= MirrorHorizontalOnOdd;
        }
        else if (mirrorMode.contains("horizontal")) {
            mode |= MirrorHorizontal;
        }

        if (mirrorMode.contains("vertical")) {
            mode |= MirrorVertical;
        }

        m_mirrorMode = mode;
    }

    // Color-mode (effects)
    if (styleStack.hasProperty(KoXmlNS::draw, "color-mode")) {
        QString colorMode = styleStack.property(KoXmlNS::draw, "color-mode");
        if (colorMode == "greyscale") {
            setColorMode(Greyscale);
        }
        else if (colorMode == "mono") {
            setColorMode(Mono);
        }
        else if (colorMode == "watermark") {
            setColorMode(Watermark);
        }
    }

    // image opacity
    QString opacity(styleStack.property(KoXmlNS::draw, "image-opacity"));
    if (! opacity.isEmpty() && opacity.right(1) == "%") {
        setTransparency(1.0 - (opacity.left(opacity.length() - 1).toFloat() / 100.0));
    }

    // clip rect
    m_clippingRect = parseClippingRectString(styleStack.property(KoXmlNS::fo, "clip"));
}
Exemple #9
0
void Rotate::loadStyle(const KoXmlElement& element, KoShapeLoadingContext& context)
{
    // Load the common parts of the style.
    KoShape::loadStyle(element, context);

    KoStyleStack &styleStack = context.odfLoadingContext().styleStack();
    styleStack.setTypeProperties("graphic");

    QString dummy;

    if (styleStack.hasProperty(KoXmlNS::dr3d, "horizontal-segments")) {
        dummy = styleStack.property(KoXmlNS::dr3d, "horizontal-segments");
        bool ok;
        int hs = dummy.toInt(&ok);
        if (ok) {
            m_horizontalSegments = hs;
        }
    }
    if (styleStack.hasProperty(KoXmlNS::dr3d, "vertical-segments")) {
        dummy = styleStack.property(KoXmlNS::dr3d, "vertical-segments");
        bool ok;
        int vs = dummy.toInt(&ok);
        if (ok) {
            m_verticalSegments = vs;
        }
    }

    if (styleStack.hasProperty(KoXmlNS::dr3d, "end-angle")) {
        dummy = styleStack.property(KoXmlNS::dr3d, "end-angle");
        bool ok;
        qreal ea = dummy.toDouble(&ok);
        if (ok) {
            m_endAngle = ea;
        }
    }

    if (styleStack.hasProperty(KoXmlNS::dr3d, "close-front")) {
        dummy = styleStack.property(KoXmlNS::dr3d, "close-front");
        m_closeFront = (dummy == "true");
    }
    if (styleStack.hasProperty(KoXmlNS::dr3d, "close-back")) {
        dummy = styleStack.property(KoXmlNS::dr3d, "close-back");
        m_closeBack = (dummy == "true");
    }

    // FIXME: Note that this can be a percentage (our test file has "80%").
    if (styleStack.hasProperty(KoXmlNS::dr3d, "back-scale")) {
        dummy = styleStack.property(KoXmlNS::dr3d, "back-scale");
        bool ok;
        qreal bs = dummy.toDouble(&ok);
        if (ok) {
            m_backScale = bs;
        }
    }
}
Exemple #10
0
void KoPathShape::loadStyle(const KoXmlElement & element, KoShapeLoadingContext &context)
{
    KoShape::loadStyle(element, context);

    KoStyleStack &styleStack = context.odfLoadingContext().styleStack();
    styleStack.save();

    // fill the style stack with the shapes style
    if (element.hasAttributeNS(KoXmlNS::draw, "style-name")) {
        context.odfLoadingContext().fillStyleStack(element, KoXmlNS::draw, "style-name", "graphic");
    } else if (element.hasAttributeNS(KoXmlNS::presentation, "style-name")) {
        context.odfLoadingContext().fillStyleStack(element, KoXmlNS::presentation, "style-name", "presentation");
    }
    styleStack.setTypeProperties("graphic");

    if (styleStack.hasProperty(KoXmlNS::svg, "fill-rule")) {
        QString rule = styleStack.property(KoXmlNS::svg, "fill-rule");
        d->fillRule = rule == "nonzero" ?  Qt::WindingFill : Qt::OddEvenFill;
    }
    styleStack.restore();
}
bool KPrPlaceholderTextStrategy::loadOdf( const KoXmlElement & element, KoShapeLoadingContext & context )
{
    if (KoTextSharedLoadingData *textSharedData = dynamic_cast<KoTextSharedLoadingData *>(context.sharedData(KOTEXT_SHARED_LOADING_ID))) {
        KoShapeFactoryBase *factory = KoShapeRegistry::instance()->value("TextShapeID");
        Q_ASSERT(factory);
        delete m_textShape;
        m_textShape = factory->createDefaultShape(context.documentResourceManager());

        KoTextShapeData *shapeData = qobject_cast<KoTextShapeData*>(m_textShape->userData());
        shapeData->document()->setUndoRedoEnabled(false);

        QTextDocument *document = shapeData->document();
        QTextCursor cursor(document);
        QTextBlock block = cursor.block();

        const QString styleName = element.attributeNS(KoXmlNS::presentation, "style-name");
        if (!styleName.isEmpty()) {
            const KoXmlElement *style = context.odfLoadingContext().stylesReader().findStyle(styleName, "presentation", context.odfLoadingContext().useStylesAutoStyles());

            if (style) {
                KoParagraphStyle paragraphStyle;
                paragraphStyle.loadOdf(style, context);
                paragraphStyle.applyStyle(block, false); // TODO t.zachmann is the false correct?
            }
        }

        const QString textStyleName = element.attributeNS(KoXmlNS::draw, "text-style-name");
        if (!textStyleName.isEmpty()) {
            KoParagraphStyle *style = textSharedData->paragraphStyle(textStyleName, context.odfLoadingContext().useStylesAutoStyles());
            if (style) {
                style->applyStyle(block, false); // TODO t.zachmann is the false correct?
            }
        }

        cursor.insertText(text());
        shapeData->setDirty();
        shapeData->document()->setUndoRedoEnabled(true);
    }
    return true;
}
Exemple #12
0
bool VideoShape::loadOdfFrameElement(const KoXmlElement &element, KoShapeLoadingContext &context)
{
    /* the loading of the attributes might set the event actions which removes the m_videoEventAction
     * when there are other eventactions for the shape. Therefore we need to add it again. It is no
     * problem to add it again as internally a set is used and so it is not problematic when it is 
     * already set. */
    addEventAction(m_videoEventAction);

    if (m_videoCollection) {
        const QString href = element.attribute("href");
        // this can happen in case it is a presentation:placeholder
        if (!href.isEmpty()) {
            QUrl url = QUrl::fromUserInput(href);
            VideoData *data=0;

            if(href.startsWith("../")) {
                // file is outside store
                QUrl url = context.odfLoadingContext().store()->urlOfStore();
                QString path = url.path();
                if (!path.endsWith(QLatin1Char('/'))) {
                    path.append(QLatin1Char('/'));
                }
                path.append(href.mid(3));
                url.setPath(path);
                data = m_videoCollection->createExternalVideoData(url, false);
            } else if(!url.isRelative()) {
                // file is outside store and absolute
                data = m_videoCollection->createExternalVideoData(QUrl::fromUserInput(href), false);
            } else {
                // file is inside store
                KoStore *store = context.odfLoadingContext().store();
                data = m_videoCollection->createVideoData(href, store);
            }
            setUserData(data);
        }
    }

    return true;
}
bool SvgShapeFactory::supports(const KoXmlElement &element, KoShapeLoadingContext &context) const
{
    if (element.localName() == "image" && element.namespaceURI() == KoXmlNS::draw) {
        QString href = element.attribute("href");
        if (href.isEmpty())
            return false;

        // check the mimetype
        if (href.startsWith("./")) {
            href.remove(0,2);
        }

        QString mimetype = context.odfLoadingContext().mimeTypeForPath(href, true);
        return (mimetype == "image/svg+xml");
    }

    return false;
}
Exemple #14
0
 explicit Private(KoShapeLoadingContext &context)
         : context(context),
           textSharedData(0),
         // stylesDotXml says from where the office:automatic-styles are to be picked from:
         // the content.xml or the styles.xml (in a multidocument scenario). It does not
         // decide from where the office:styles are to be picked (always picked from styles.xml).
         // For our use here, stylesDotXml is always false (see ODF1.1 spec §2.1).
           stylesDotXml(context.odfLoadingContext().useStylesAutoStyles()),
           bodyProgressTotal(0),
           bodyProgressValue(0),
           lastElapsed(0),
           currentList(0),
           currentListStyle(0),
           currentListLevel(1),
           styleManager(0),
           changeTracker(0),
           loadSpanLevel(0),
           loadSpanInitialPos(0),
           currentChangeId(0) {
     dt.start();
 }
bool TableShape::loadOdf(const KoXmlElement &element, KoShapeLoadingContext &context)
{
    //kDebug() << "LOADING TABLE SHAPE";
    if (sheet() && element.namespaceURI() == KoXmlNS::table && element.localName() == "table") {
        // pre-load auto styles
        KoOdfLoadingContext& odfContext = context.odfLoadingContext();
        OdfLoadingContext tableContext(odfContext);
        QHash<QString, Conditions> conditionalStyles;
        Map *const map = sheet()->map();
        StyleManager *const styleManager = map->styleManager();
        ValueParser *const parser = map->parser();
        Styles autoStyles = styleManager->loadOdfAutoStyles(odfContext.stylesReader(), conditionalStyles, parser);

        if (!element.attributeNS(KoXmlNS::table, "name", QString()).isEmpty()) {
            sheet()->setSheetName(element.attributeNS(KoXmlNS::table, "name", QString()), true);
        }
        const bool result = sheet()->loadOdf(element, tableContext, autoStyles, conditionalStyles);

        // delete any styles which were not used
        sheet()->map()->styleManager()->releaseUnusedAutoStyles(autoStyles);

        if (!result) {
            return false;
        }

        const QRect usedArea = sheet()->usedArea();
        d->columns = usedArea.width();
        d->rows = usedArea.height();

        QSizeF size(0.0, 0.0);
        for (int col = 1; col <= d->columns; ++col) {
            size.rwidth() += sheet()->columnFormat(col)->visibleWidth();
        }
        size.rheight() = sheet()->rowFormats()->totalVisibleRowHeight(1, d->rows);
        KoShape::setSize(size);
        return true;
    }
    return false;
}
Exemple #16
0
KoTextLoader::KoTextLoader(KoShapeLoadingContext &context)
        : QObject()
        , d(new Private(context))
{
    KoSharedLoadingData *sharedData = context.sharedData(KOTEXT_SHARED_LOADING_ID);
    if (sharedData) {
        d->textSharedData = dynamic_cast<KoTextSharedLoadingData *>(sharedData);
    }

    kDebug(32500) << "sharedData" << sharedData << "textSharedData" << d->textSharedData;

    if (!d->textSharedData) {
        d->textSharedData = new KoTextSharedLoadingData();
        // TODO pass style manager so that on copy and paste we can recognice the same styles
        d->textSharedData->loadOdfStyles(context.odfLoadingContext(), 0);
        if (!sharedData) {
            context.addSharedData(KOTEXT_SHARED_LOADING_ID, d->textSharedData);
        } else {
            kWarning(32500) << "A different type of sharedData was found under the" << KOTEXT_SHARED_LOADING_ID;
            Q_ASSERT(false);
        }
    }
}
Exemple #17
0
void Extrude::loadStyle(const KoXmlElement& element, KoShapeLoadingContext& context)
{
    // Load the common parts of the style.
    KoShape::loadStyle(element, context);

    KoStyleStack &styleStack = context.odfLoadingContext().styleStack();
    styleStack.setTypeProperties("graphic");

    QString dummy;

    if (styleStack.hasProperty(KoXmlNS::dr3d, "depth")) {
        dummy = styleStack.property(KoXmlNS::dr3d, "depth");
        bool ok;
        qreal depth = dummy.toDouble(&ok);
        if (ok) {
            m_depth = depth;
        }
    }

    if (styleStack.hasProperty(KoXmlNS::dr3d, "close-front")) {
        dummy = styleStack.property(KoXmlNS::dr3d, "close-front");
        m_closeFront = (dummy == "true");
    }
    if (styleStack.hasProperty(KoXmlNS::dr3d, "close-back")) {
        dummy = styleStack.property(KoXmlNS::dr3d, "close-back");
        m_closeBack = (dummy == "true");
    }

    if (styleStack.hasProperty(KoXmlNS::dr3d, "back-scale")) {
        dummy = styleStack.property(KoXmlNS::dr3d, "back-scale");
        bool ok;
        qreal bs = dummy.toDouble(&ok);
        if (ok) {
            m_backScale = bs;
        }
    }
}
Exemple #18
0
bool Surface::loadOdf(const KoXmlElement &surfaceElement,
                       KoShapeLoadingContext &context)
{
    // Get the current style stack and save it's state.
    KoStyleStack &styleStack = context.odfLoadingContext().styleStack();

    bool brushLoaded = false;
    
    if (surfaceElement.hasAttributeNS(KoXmlNS::chart, "style-name")) {
        KDChart::BackgroundAttributes backgroundAttributes = d->kdPlane->backgroundAttributes();
        KDChart::FrameAttributes frameAttributes = d->kdPlane->frameAttributes();
        
        // Add the chart style to the style stack.
        styleStack.clear();
        context.odfLoadingContext().fillStyleStack(surfaceElement, KoXmlNS::chart, "style-name", "chart");
        
        styleStack.setTypeProperties("graphic");
        
        // If there is a "stroke" property, then get the stroke style
        // and set the pen accordingly.
        if (styleStack.hasProperty(KoXmlNS::draw, "stroke")) {
            frameAttributes.setVisible(true);

            QString  stroke = styleStack.property(KoXmlNS::draw, "stroke");
            QPen pen(Qt::NoPen);
            if (stroke == "solid" || stroke == "dash")
                pen = KoOdfGraphicStyles::loadOdfStrokeStyle(styleStack, stroke,
                                                             context.odfLoadingContext().stylesReader());

            frameAttributes.setPen(pen);
        }
        
        // If there is a "fill" property, then get the fill style, and
        // set the brush for the surface accordingly.
        if (styleStack.hasProperty(KoXmlNS::draw, "fill")) {
            backgroundAttributes.setVisible(true);

            QBrush   brush;
            QString  fill = styleStack.property(KoXmlNS::draw, "fill");
            if (fill == "solid" || fill == "hatch") {
                brushLoaded = true;
                brush = KoOdfGraphicStyles::loadOdfFillStyle(styleStack, fill,
                                                             context.odfLoadingContext().stylesReader());
            }
            else if (fill == "gradient") {
                brushLoaded = true;
                brush = KoOdfGraphicStyles::loadOdfGradientStyle(styleStack, context.odfLoadingContext().stylesReader(), QSizeF(5.0, 60.0));
            }
            else if (fill == "bitmap") {
                brushLoaded = true;
                brush = loadOdfPatternStyle(styleStack, context.odfLoadingContext(), QSizeF(5.0, 60.0));
            }

            backgroundAttributes.setBrush(brush);
        }
        
        // Finally actually set the attributes.
        d->kdPlane->setBackgroundAttributes(backgroundAttributes);
        d->kdPlane->setFrameAttributes(frameAttributes);
    }

#ifndef NWORKAROUND_ODF_BUGS
    if (!brushLoaded) {
        KDChart::BackgroundAttributes backgroundAttributes = d->kdPlane->backgroundAttributes();
        QColor fillColor = KoOdfWorkaround::fixMissingFillColor(surfaceElement, context);
        if (fillColor.isValid()) {
            backgroundAttributes.setVisible(true);
            backgroundAttributes.setBrush(fillColor);
            d->kdPlane->setBackgroundAttributes(backgroundAttributes);
        }
    }
#endif
    
    return true;
}
Exemple #19
0
bool Legend::loadOdf(const KoXmlElement &legendElement,
                     KoShapeLoadingContext &context)
{
    KoStyleStack &styleStack = context.odfLoadingContext().styleStack();
    styleStack.clear();
    
    // FIXME: If the style isn't present we shouldn't care about it at all
    // and move everything related to the legend style in this if clause
    if (legendElement.hasAttributeNS(KoXmlNS::chart, "style-name")) {
        context.odfLoadingContext().fillStyleStack(legendElement, KoXmlNS::chart, "style-name", "chart");
        styleStack.setTypeProperties("graphic");
    }

    if (!legendElement.isNull()) {
        int attributesToLoad = OdfAllAttributes;
        QString lp = legendElement.attributeNS(KoXmlNS::chart, "legend-position", QString());
        if (!lp.isEmpty()) {
            attributesToLoad ^= OdfPosition;
        }

        // FIXME according to odf if legend-position is provided the x
        // and y value should not be used.
        //
        // FIXME also width and height are not supported at this place
        if (legendElement.hasAttributeNS(KoXmlNS::svg, "x") ||
            legendElement.hasAttributeNS(KoXmlNS::svg, "y") ||
            legendElement.hasAttributeNS(KoXmlNS::svg, "width") ||
            legendElement.hasAttributeNS(KoXmlNS::svg, "height"))
        {
            d->shape->layout()->setPosition(this, FloatingPosition);
        }

        loadOdfAttributes(legendElement, context, attributesToLoad);

        QString lalign = legendElement.attributeNS(KoXmlNS::chart, "legend-align", QString());

        if (legendElement.hasAttributeNS(KoXmlNS::style, "legend-expansion")) {
            QString lexpansion = legendElement.attributeNS(KoXmlNS::style, "legend-expansion", QString());
            if (lexpansion == "wide")
                setExpansion(WideLegendExpansion);
            else if (lexpansion == "high")
                setExpansion(HighLegendExpansion);
            else
                setExpansion(BalancedLegendExpansion);
        }

        if (lalign == "start") {
            setAlignment(Qt::AlignLeft);
        }
        else if (lalign == "end") {
            setAlignment(Qt::AlignRight);
        }
        else {
            setAlignment(Qt::AlignCenter);
        }

        if (lp == "start") {
            setLegendPosition(StartPosition);
        }
        else if (lp == "top") {
            setLegendPosition(TopPosition);
        }
        else if (lp == "bottom") {
            setLegendPosition(BottomPosition);
        }
        else if (lp == "top-start") {
            setLegendPosition(TopStartPosition);
        }
        else if (lp == "bottom-start") {
            setLegendPosition(BottomStartPosition);
        }
        else if (lp == "top-end") {
            setLegendPosition(TopEndPosition);
        }
        else if (lp == "bottom-end") {
            setLegendPosition(BottomEndPosition);
        }
        else {
            setLegendPosition(EndPosition);
        }

        if (legendElement.hasAttributeNS(KoXmlNS::office, "title")) {
            setTitle(legendElement.attributeNS(KoXmlNS::office, "title", QString()));
        }

        styleStack.setTypeProperties("text");

        if (styleStack.hasProperty(KoXmlNS::fo, "font-family")) {
            QString fontFamily = styleStack.property(KoXmlNS::fo, "font-family");
            QFont font = d->font;
            font.setFamily(fontFamily);
            setFont(font);
        }
        if (styleStack.hasProperty(KoXmlNS::fo, "font-size")) {
            qreal fontSize = KoUnit::parseValue(styleStack.property(KoXmlNS::fo, "font-size"));
            setFontSize(fontSize);
        }
        if (styleStack.hasProperty(KoXmlNS::fo, "font-color")) {
            QColor color = styleStack.property(KoXmlNS::fo, "font-color");
            if (color.isValid()) {
                setFontColor(color);
            }
        }
    }
    else {
        // No legend element, use default legend.
        // FIXME: North??  Isn't that a bit strange as default? /IW
        setLegendPosition(TopPosition);
        setAlignment(Qt::AlignCenter);
    }

    d->pixmapRepaintRequested = true;

    return true;
}
bool DateVariable::loadOdf(const KoXmlElement & element, KoShapeLoadingContext & context)
{
    const QString localName(element.localName());
    QString dateFormat = "";
    QString dataStyle = element.attributeNS(KoXmlNS::style, "data-style-name");
    if (!dataStyle.isEmpty()) {
        if (context.odfLoadingContext().stylesReader().dataFormats().contains(dataStyle)) {
            KoOdfNumberStyles::NumericStyleFormat dataFormat = context.odfLoadingContext().stylesReader().dataFormats().value(dataStyle).first;
            dateFormat = dataFormat.prefix + dataFormat.formatStr + dataFormat.suffix;
        }
    }

    //dateProperties.setProperty("fixed", QVariant(element.attributeNS(KoXmlNS::text, "fixed") == "true"));
    if (element.attributeNS(KoXmlNS::text, "fixed", "false") == "true") {
        m_type = Fixed;
    } else {
        m_type = AutoUpdate;
    }

    if (localName == "time") {
        m_displayType = Time;
    } else {
        m_displayType = Date;
    }

    //dateProperties.setProperty("time", element.attributeNS(KoXmlNS::text, localName + "-value"));
    QString value(element.attributeNS(KoXmlNS::text, localName + "-value", ""));
    if (!value.isEmpty()) {
#ifndef NWORKAROUND_ODF_BUGS
        KoOdfWorkaround::fixBadDateForTextTime(value);
#endif
        // hopefully this simple detection works in all cases
        const bool isDateTime = (value.indexOf(QLatin1Char('T')) != -1);

        if (isDateTime) {
            m_datetime = QDateTime::fromString(value, Qt::ISODate);
            m_valueType = DateTime;
        } else {
            if (m_displayType == Time) {
                const QTime time = QTime::fromString(value, Qt::ISODate);
                m_datetime = QDateTime(QDate::currentDate(), time);
            } else {
                const QDate date = QDate::fromString(value, Qt::ISODate);
                m_datetime = QDateTime(date);
            }
            m_valueType = DateOrTime;
        }
    } else {
        // if value is not set current time is assumed  ODF 19.881 text:time-value
        m_type = AutoUpdate;
    }

    //dateProperties.setProperty("definition", dateFormat);
    m_definition = dateFormat;

    //dateProperties.setProperty("adjust", element.attributeNS(KoXmlNS::text, localName + "-adjust"));
    const QString adjust(element.attributeNS(KoXmlNS::text, localName + "-adjust", ""));
    adjustTime(adjust);
    update();
    return true;
}
bool KoShapeAnchor::loadOdf(const KoXmlElement &element, KoShapeLoadingContext &context)
{
    d->offset = shape()->position();

    if (! shape()->hasAdditionalAttribute("text:anchor-type"))
        return false;
    QString anchorType = shape()->additionalAttribute("text:anchor-type");
    if (anchorType == "char") {
        d->anchorType = AnchorToCharacter;
    } else if (anchorType == "as-char") {
        d->anchorType = AnchorAsCharacter;
    } else if (anchorType == "paragraph") {
        d->anchorType = AnchorParagraph;
    } else if (anchorType == "page") {
        d->anchorType = AnchorPage;
        // it has different defaults at least LO thinks so - ODF doesn't define defaults for this
        d->horizontalPos = HFromLeft;
        d->verticalPos = VFromTop;
        d->horizontalRel = HPage;
        d->verticalRel = VPage;
    }

    if (anchorType == "page" && shape()->hasAdditionalAttribute("text:anchor-page-number")) {
        d->pageNumber = shape()->additionalAttribute("text:anchor-page-number").toInt();
        if (d->pageNumber <= 0) {
            // invalid if the page-number is invalid (OO.org does the same)
            // see http://bugs.kde.org/show_bug.cgi?id=281869
            d->pageNumber = -1;
        }
    } else {
        d->pageNumber = -1;
    }
    // always make it invisible or it will create empty rects on the first page
    // during initial layout. This is because only when we layout it's final page is
    // the shape moved away from page 1
    // in KWRootAreaProvider of textlayout it's set back to visible
    shape()->setVisible(false);

    // load settings from graphic style
    KoStyleStack &styleStack = context.odfLoadingContext().styleStack();
    styleStack.save();
    if (element.hasAttributeNS(KoXmlNS::draw, "style-name")) {
        context.odfLoadingContext().fillStyleStack(element, KoXmlNS::draw, "style-name", "graphic");
        styleStack.setTypeProperties("graphic");
    }
    QString verticalPos = styleStack.property(KoXmlNS::style, "vertical-pos");
    QString verticalRel = styleStack.property(KoXmlNS::style, "vertical-rel");
    QString horizontalPos = styleStack.property(KoXmlNS::style, "horizontal-pos");
    QString horizontalRel = styleStack.property(KoXmlNS::style, "horizontal-rel");
    d->wrapInfluenceOnPosition = styleStack.property(KoXmlNS::draw, "wrap-influence-on-position");
    QString flowWithText = styleStack.property(KoXmlNS::style, "flow-with-text");
    d->flowWithText = flowWithText.isEmpty() ? false : flowWithText == "true";
    styleStack.restore();

    // vertical-pos
    if (verticalPos == "below") {//svg:y attribute is ignored
        d->verticalPos = VBelow;
        d->offset.setY(0);
    } else if (verticalPos == "bottom") {//svg:y attribute is ignored
        d->verticalPos = VBottom;
        d->offset.setY(-shape()->size().height());
    } else if (verticalPos == "from-top") {
        d->verticalPos = VFromTop;
    } else if (verticalPos == "middle") {//svg:y attribute is ignored
        d->verticalPos = VMiddle;
        d->offset.setY(-(shape()->size().height()/2));
    } else if (verticalPos == "top") {//svg:y attribute is ignored
        d->verticalPos = VTop;
        d->offset.setY(0);
    }

    // vertical-rel
    if (verticalRel == "baseline")
        d->verticalRel = VBaseline;
    else if (verticalRel == "char")
        d->verticalRel = VChar;
    else if (verticalRel == "frame")
        d->verticalRel = VFrame;
    else if (verticalRel == "frame-content")
        d->verticalRel = VFrameContent;
    else if (verticalRel == "line")
        d->verticalRel = VLine;
    else if (verticalRel == "page")
        d->verticalRel = VPage;
    else if (verticalRel == "page-content")
        d->verticalRel = VPageContent;
    else if (verticalRel == "paragraph")
        d->verticalRel = VParagraph;
    else if (verticalRel == "paragraph-content")
        d->verticalRel = VParagraphContent;
    else if (verticalRel == "text")
        d->verticalRel = VText;

    // horizontal-pos
    if (horizontalPos == "center") {//svg:x attribute is ignored
        d->horizontalPos = HCenter;
        d->offset.setX(-(shape()->size().width()/2));
    } else if (horizontalPos == "from-inside") {
        d->horizontalPos = HFromInside;
    } else if (horizontalPos == "from-left") {
        d->horizontalPos = HFromLeft;
    } else if (horizontalPos == "inside") {//svg:x attribute is ignored
        d->horizontalPos = HInside;
        d->offset.setX(0);
    } else if (horizontalPos == "left") {//svg:x attribute is ignored
        d->horizontalPos = HLeft;
        d->offset.setX(0);
    }else if (horizontalPos == "outside") {//svg:x attribute is ignored
        d->horizontalPos = HOutside;
        d->offset.setX(-shape()->size().width());
    }else if (horizontalPos == "right") {//svg:x attribute is ignored
        d->horizontalPos = HRight;
        d->offset.setX(-shape()->size().width());
    }

    // horizontal-rel
    if (horizontalRel == "char")
        d->horizontalRel = HChar;
    else if (horizontalRel == "page")
        d->horizontalRel = HPage;
    else if (horizontalRel == "page-content")
        d->horizontalRel = HPageContent;
    else if (horizontalRel == "page-start-margin")
        d->horizontalRel = HPageStartMargin;
    else if (horizontalRel == "page-end-margin")
        d->horizontalRel = HPageEndMargin;
    else if (horizontalRel == "frame")
        d->horizontalRel = HFrame;
    else if (horizontalRel == "frame-content")
        d->horizontalRel = HFrameContent;
    else if (horizontalRel == "frame-end-margin")
        d->horizontalRel = HFrameEndMargin;
    else if (horizontalRel == "frame-start-margin")
        d->horizontalRel = HFrameStartMargin;
    else if (horizontalRel == "paragraph")
        d->horizontalRel = HParagraph;
    else if (horizontalRel == "paragraph-content")
        d->horizontalRel = HParagraphContent;
    else if (horizontalRel == "paragraph-end-margin")
        d->horizontalRel = HParagraphEndMargin;
    else if (horizontalRel == "paragraph-start-margin")
        d->horizontalRel = HParagraphStartMargin;

    // if svg:x or svg:y should be ignored set new position
    shape()->setPosition(d->offset);

    if (element.hasAttributeNS(KoXmlNS::calligra, "anchor-type")) {
        QString anchorType = element.attributeNS(KoXmlNS::calligra, "anchor-type"); // our enriched properties
        QStringList types = anchorType.split('|');
        if (types.count() > 1) {
            QString vertical = types[0];
            QString horizontal = types[1];
            if (vertical == "TopOfFrame") {
                d->verticalRel = VPageContent;
                d->verticalPos = VTop;
            } else if (vertical == "TopOfParagraph") {
                d->verticalRel = VParagraph;
                d->verticalPos = VTop;
            } else if (vertical == "AboveCurrentLine") {
                d->verticalRel = VLine;
                d->verticalPos = VTop;
            } else if (vertical == "BelowCurrentLine") {
                d->verticalRel = VLine;
                d->verticalPos = VBottom;
            } else if (vertical == "BottomOfParagraph") {
                d->verticalRel = VParagraph;
                d->verticalPos = VBottom;
            } else if (vertical == "BottomOfFrame") {
                d->verticalRel = VPageContent;
                d->verticalPos = VBottom;
            } else if (vertical == "VerticalOffset") {
                d->verticalRel = VLine;
                d->verticalPos = VTop;
            }

            if (horizontal == "Left") {
                d->horizontalRel = HPageContent;
                d->horizontalPos = HLeft;
            } else if (horizontal == "Right") {
                d->horizontalRel = HPageContent;
                d->horizontalPos = HRight;
            } else if (horizontal == "Center") {
                d->horizontalRel = HPageContent;
                d->horizontalPos = HCenter;
            } else if (horizontal == "ClosestToBinding") {
                d->horizontalRel = HPageContent;
                d->horizontalPos = HInside;
            } else if (horizontal == "FurtherFromBinding") {
                d->horizontalRel = HPageContent;
                d->horizontalPos = HOutside;
            } else if (horizontal == "HorizontalOffset") {
                d->horizontalRel = HChar;
                d->horizontalPos = HLeft;
            }
        }
        d->offset = QPointF();
     }

    if (d->anchorType == AnchorAsCharacter) {
        d->horizontalRel = HChar;
        d->horizontalPos = HLeft;
    }


    return true;
}
void KoListLevelProperties::loadOdf(KoShapeLoadingContext& scontext, const KoXmlElement& style)
{
    KoOdfLoadingContext &context = scontext.odfLoadingContext();

    // The text:level attribute specifies the level of the number list
    // style. It can be used on all list-level styles.
    const int level = qMax(1, style.attributeNS(KoXmlNS::text, "level", QString()).toInt());
    // The text:display-levels attribute specifies the number of
    // levels whose numbers are displayed at the current level.
    const QString displayLevel = style.attributeNS(KoXmlNS::text,
                                 "display-levels", QString());

    const QString styleName = style.attributeNS(KoXmlNS::text, "style-name", QString());
    KoCharacterStyle *cs = 0;
    if (!styleName.isEmpty()) {
//         kDebug(32500) << "Should use the style =>" << styleName << "<=";

        KoSharedLoadingData *sharedData = scontext.sharedData(KOTEXT_SHARED_LOADING_ID);
        KoTextSharedLoadingData *textSharedData = 0;
        if (sharedData) {
            textSharedData = dynamic_cast<KoTextSharedLoadingData *>(sharedData);
        }
        if (textSharedData) {
            cs = textSharedData->characterStyle(styleName, context.useStylesAutoStyles());
            if (!cs) {
               kWarning(32500) << "Missing KoCharacterStyle!";
            }
            else {
//                kDebug(32500) << "==> cs.name:" << cs->name();
//                kDebug(32500) << "==> cs.styleId:" << cs->styleId();
                setCharacterStyleId(cs->styleId());
            }
        }
    }

    if (style.localName() == "list-level-style-bullet") {   // list with bullets
        // special case bullets:
        //qDebug() << QChar(0x2202) << QChar(0x25CF) << QChar(0xF0B7) << QChar(0xE00C)
        //<< QChar(0xE00A) << QChar(0x27A2)<< QChar(0x2794) << QChar(0x2714) << QChar(0x2d) << QChar(0x2717);

        //1.6: KoParagCounter::loadOasisListStyle
        QString bulletChar = style.attributeNS(KoXmlNS::text, "bullet-char", QString());
//         kDebug(32500) << "style.localName()=" << style.localName() << "level=" << level << "displayLevel=" << displayLevel << "bulletChar=" << bulletChar;
        if (bulletChar.isEmpty()) {  // list without any visible bullets
            setStyle(KoListStyle::CustomCharItem);
            setBulletCharacter(QChar());
        } else { // try to determinate the bullet we should use
            switch (bulletChar[0].unicode()) {
            case 0x2022: // bullet, a small disc -> circle
                setStyle(KoListStyle::Bullet);
                break;
            case 0x25CF: // black circle, large disc -> disc
                setStyle(KoListStyle::BlackCircle);
                break;
            case 0x25CB:           //white circle, no fill
                setStyle(KoListStyle::CircleItem);
                break;
            case 0x25C6: // losange => rhombus
                setStyle(KoListStyle::RhombusItem);
                break;
            case 0x25A0: // square. Not in OASIS (reserved Unicode area!), but used in both OOo and kotext.
                setStyle(KoListStyle::SquareItem);
                break;
            case 0x27A2: // two-colors right-pointing triangle
                setStyle(KoListStyle::RightArrowHeadItem);
                break;
            case 0x2794: // arrow to right
                setStyle(KoListStyle::RightArrowItem);
                break;
            case 0x2714: // checkmark
                setStyle(KoListStyle::HeavyCheckMarkItem);
                break;
            case 0x2d: // minus
                setStyle(KoListStyle::CustomCharItem);
                break;
            case 0x2717: // cross
                setStyle(KoListStyle::BallotXItem);
                break;
            default:
                QChar customBulletChar = bulletChar[0];
                kDebug(32500) << "Unhandled bullet code 0x" << QString::number((uint)customBulletChar.unicode(), 16) << bulletChar;
                kDebug(32500) << "Should use the style =>" << style.attributeNS(KoXmlNS::text, "style-name", QString()) << "<=";
                setStyle(KoListStyle::CustomCharItem);
                /*
                QString customBulletFont;
                // often StarSymbol when it comes from OO; doesn't matter, Qt finds it in another font if needed.
                if ( listStyleProperties.hasAttributeNS( KoXmlNS::style, "font-name" ) )
                {
                    customBulletFont = listStyleProperties.attributeNS( KoXmlNS::style, "font-name", QString() );
                    kDebug(32500) <<"customBulletFont style:font-name =" << listStyleProperties.attributeNS( KoXmlNS::style,"font-name", QString() );
                }
                else if ( listStyleTextProperties.hasAttributeNS( KoXmlNS::fo, "font-family" ) )
                {
                    customBulletFont = listStyleTextProperties.attributeNS( KoXmlNS::fo, "font-family", QString() );
                    kDebug(32500) <<"customBulletFont fo:font-family =" << listStyleTextProperties.attributeNS( KoXmlNS::fo,"font-family", QString() );
                }
                // ## TODO in fact we're supposed to read it from the style pointed to by text:style-name
                */
//                     setStyle(KoListStyle::BoxItem); //fallback
                break;
            } // switch
            setBulletCharacter(bulletChar[0]);
        }
        QString size = style.attributeNS(KoXmlNS::text, "bullet-relative-size", QString());
        if (!size.isEmpty()) {
            setRelativeBulletSize(size.remove('%').toInt());
        }

    } else if (style.localName() == "list-level-style-number" || style.localName() == "outline-level-style") { // it's a numbered list

        if (style.localName() == "outline-level-style") {
            setOutlineList(true);
        }
        setRelativeBulletSize(100); //arbitrary value for numbered list

        KoOdfNumberDefinition numberDefinition;
        numberDefinition.loadOdf(style);

        switch(numberDefinition.formatSpecification()) {
        case KoOdfNumberDefinition::Empty:
            setStyle(KoListStyle::None);
            break;
        case KoOdfNumberDefinition::AlphabeticLowerCase:
            setStyle(KoListStyle::AlphaLowerItem);
            break;
        case KoOdfNumberDefinition::AlphabeticUpperCase:
            setStyle(KoListStyle::UpperAlphaItem);
            break;
        case KoOdfNumberDefinition::RomanLowerCase:
            setStyle(KoListStyle::RomanLowerItem);
            break;
        case KoOdfNumberDefinition::RomanUpperCase:
            setStyle(KoListStyle::UpperRomanItem);
            break;
        case KoOdfNumberDefinition::ArabicAlphabet:
                    setStyle(KoListStyle::ArabicAlphabet);
                    break;
        case KoOdfNumberDefinition::Thai:
            setStyle(KoListStyle::Thai);
            break;
        case KoOdfNumberDefinition::Abjad:
            setStyle(KoListStyle::Abjad);
            break;
        case KoOdfNumberDefinition::AbjadMinor:
            setStyle(KoListStyle::AbjadMinor);
            break;
        case KoOdfNumberDefinition::Tibetan:
            setStyle(KoListStyle::Tibetan);
            break;
        case KoOdfNumberDefinition::Telugu:
            setStyle(KoListStyle::Telugu);
            break;
        case KoOdfNumberDefinition::Tamil:
            setStyle(KoListStyle::Tamil);
            break;
        case KoOdfNumberDefinition::Oriya:
            setStyle(KoListStyle::Oriya);
            break;
        case KoOdfNumberDefinition::Malayalam:
            setStyle(KoListStyle::Malayalam);
            break;
        case KoOdfNumberDefinition::Kannada:
            setStyle(KoListStyle::Kannada);
            break;
        case KoOdfNumberDefinition::Gurumukhi:
            setStyle(KoListStyle::Gurumukhi);
            break;
        case KoOdfNumberDefinition::Gujarati:
            setStyle(KoListStyle::Gujarati);
            break;
        case KoOdfNumberDefinition::Bengali:
            setStyle(KoListStyle::Bengali);
            break;
        case KoOdfNumberDefinition::Numeric:
        default:
            setStyle(KoListStyle::DecimalItem);
        }

        if (!numberDefinition.prefix().isNull()) {
            setListItemPrefix(numberDefinition.prefix());
        }

        if (!numberDefinition.suffix().isNull()) {
            setListItemSuffix(numberDefinition.suffix());
        }
        const QString startValue = style.attributeNS(KoXmlNS::text, "start-value", QString("1"));
        setStartValue(startValue.toInt());
    }
    else if (style.localName() == "list-level-style-image") {   // list with image
        setStyle(KoListStyle::ImageItem);
        KoImageCollection *imageCollection = scontext.imageCollection();
        const QString href = style.attribute("href");
        if(imageCollection) {
            if (!href.isEmpty()) {
                KoStore *store = context.store();
                setBulletImage(imageCollection->createImageData(href, store));
            } else {
                // check if we have an office:binary data element containing the image data
                const KoXmlElement &binaryData(KoXml::namedItemNS(style, KoXmlNS::office, "binary-data"));
                if (!binaryData.isNull()) {
                    QImage image;
                    if (image.loadFromData(QByteArray::fromBase64(binaryData.text().toLatin1()))) {
                        setBulletImage(imageCollection->createImageData(image));
                    }
                }
            }
        }
    }
    else { // if not defined, we have do nothing
//         kDebug(32500) << "stylename else:" << style.localName() << "level=" << level << "displayLevel=" << displayLevel;
        setStyle(KoListStyle::DecimalItem);
        setListItemSuffix(".");
    }

    setLevel(level);
    if (!displayLevel.isEmpty())
        setDisplayLevel(displayLevel.toInt());

    KoXmlElement property;
    forEachElement(property, style) {
        if (property.namespaceURI() != KoXmlNS::style)
            continue;
        const QString localName = property.localName();
        if (localName == "list-level-properties") {
            QString mode(property.attributeNS(KoXmlNS::text, "list-level-position-and-space-mode"));
            if (mode == "label-alignment") {
                QString textAlign(property.attributeNS(KoXmlNS::fo, "text-align"));
                setAlignment(textAlign.isEmpty() ? Qt::AlignLeft : KoText::alignmentFromString(textAlign));

                KoXmlElement p;
                forEachElement(p, property) {
                     if (p.namespaceURI() == KoXmlNS::style && p.localName() == "list-level-label-alignment") {
                        // The <style:list-level-label-alignment> element and the fo:text-align attribute are used to define
                        // the position and spacing of the list label and the list item. The values of the attributes for
                        // text:space-before, text:min-label-width and text:min-label-distance are assumed to be 0.
                        setAlignmentMode(true);

                        QString textindent(p.attributeNS(KoXmlNS::fo, "text-indent"));
                        QString marginleft(p.attributeNS(KoXmlNS::fo, "margin-left"));
                        qreal ti = textindent.isEmpty() ? 0 : KoUnit::parseValue(textindent);
                        qreal ml = marginleft.isEmpty() ? 0 : KoUnit::parseValue(marginleft);
                        setTextIndent(ti);
                        setMargin(ml);

                        QString labelFollowedBy(p.attributeNS(KoXmlNS::text, "label-followed-by","space"));
                        if(labelFollowedBy.compare("listtab",Qt::CaseInsensitive)==0) {

                            setLabelFollowedBy(KoListStyle::ListTab);

                            // list tab position is evaluated only if label is followed by listtab
                            // the it is only evaluated if there is a list-tab-stop-position specified
                            // if not specified use the fo:margin-left:
                            QString tabStop(p.attributeNS(KoXmlNS::text, "list-tab-stop-position"));
                            if (!tabStop.isEmpty()) {
                                qreal tabStopPos = KoUnit::parseValue(tabStop);
                                setTabStopPosition(qMax<qreal>(0.0, tabStopPos));
                            }

                        }else if(labelFollowedBy.compare("nothing",Qt::CaseInsensitive)==0) {

                            setLabelFollowedBy(KoListStyle::Nothing);

                        }else {

                            setLabelFollowedBy(KoListStyle::Space);

                        }

                        setMinimumWidth(0);
                        setMinimumDistance(0);

                        //TODO support ODF 18.829 text:label-followed-by and 18.832 text:list-tab-stop-position
                     }
                }
            }

            if(alignmentMode()!=true ){ // default is mode == "label-width-and-position"
                // The text:space-before, text:min-label-width, text:minimum-label-distance and fo:text-align attributes
                // are used to define the position and spacing of the list label and the list item.

                setAlignmentMode(false);

                QString spaceBefore(property.attributeNS(KoXmlNS::text, "space-before"));
                if (!spaceBefore.isEmpty())
                    setIndent(KoUnit::parseValue(spaceBefore));

                QString minLableWidth(property.attributeNS(KoXmlNS::text, "min-label-width"));
                if (!minLableWidth.isEmpty())
                    setMinimumWidth(KoUnit::parseValue(minLableWidth));

                QString textAlign(property.attributeNS(KoXmlNS::fo, "text-align"));
                if (!textAlign.isEmpty())
                    setAlignment(KoText::alignmentFromString(textAlign));

                QString minLableDistance(property.attributeNS(KoXmlNS::text, "min-label-distance"));
                if (!minLableDistance.isEmpty())
                    setMinimumDistance(KoUnit::parseValue(minLableDistance));               
            }

            QString width(property.attributeNS(KoXmlNS::fo, "width"));
            if (!width.isEmpty())
                setWidth(KoUnit::parseValue(width));

            QString height(property.attributeNS(KoXmlNS::fo, "height"));
            if (!height.isEmpty())
                setHeight(KoUnit::parseValue(height));

        } else if (localName == "text-properties") {
Exemple #23
0
bool ChartShape::Private::loadOdfLabel(KoShape *label, KoXmlElement &labelElement, KoShapeLoadingContext &context)
{
    TextLabelData *labelData = qobject_cast<TextLabelData*>(label->userData());
    if (!labelData)
        return false;

    // Following will always return false cause KoTextShapeData::loadOdf will try to load
    // a frame while our text:p is not within a frame. So, let's just not call loadOdf then...
    //label->loadOdf(labelElement, context);

    // 1. set the text
    KoXmlElement  pElement = KoXml::namedItemNS(labelElement, KoXmlNS::text, "p");

    QTextDocument* doc = labelData->document();
    doc->setPlainText(pElement.text());

    // 2. set the position
    QPointF pos = label->position();
    bool posChanged = false;
    if (labelElement.hasAttributeNS(KoXmlNS::svg, "x")) {
        pos.setX(KoUnit::parseValue(labelElement.attributeNS(KoXmlNS::svg, "x", QString())));
        posChanged = true;
    }
    if (labelElement.hasAttributeNS(KoXmlNS::svg, "y")) {
        pos.setY(KoUnit::parseValue(labelElement.attributeNS(KoXmlNS::svg, "y", QString())));
        posChanged = true;
    }
    if (posChanged) {
        label->setPosition(pos);
    }

    // 3. set the styles
    if (labelElement.hasAttributeNS(KoXmlNS::chart, "style-name")) {
        KoStyleStack &styleStack = context.odfLoadingContext().styleStack();
        styleStack.clear();
        context.odfLoadingContext().fillStyleStack(labelElement, KoXmlNS::chart, "style-name", "chart");

        styleStack.setTypeProperties("chart");
        if (styleStack.hasProperty(KoXmlNS::style, "rotation-angle")) {
            qreal rotationAngle = 360 - KoUnit::parseValue(styleStack.property(KoXmlNS::style, "rotation-angle"));
            label->rotate(rotationAngle);
        }

        styleStack.setTypeProperties("text");

        if (styleStack.hasProperty(KoXmlNS::fo, "font-size")) {
            const qreal fontSize = KoUnit::parseValue(styleStack.property(KoXmlNS::fo, "font-size"));
            QFont font = doc->defaultFont();
            font.setPointSizeF(fontSize);
            doc->setDefaultFont(font);
        }

        if (styleStack.hasProperty(KoXmlNS::fo, "font-family")) {
            const QString fontFamily = styleStack.property(KoXmlNS::fo, "font-family");
            QFont font = doc->defaultFont();
            font.setFamily(fontFamily);
            doc->setDefaultFont(font);
        }
    }

    // 4. set the size
    if (labelElement.hasAttributeNS(KoXmlNS::svg, "width")
        && labelElement.hasAttributeNS(KoXmlNS::svg, "height"))
    {
        const qreal width = KoUnit::parseValue(labelElement.attributeNS(KoXmlNS::svg, "width"));
        const qreal height = KoUnit::parseValue(labelElement.attributeNS(KoXmlNS::svg, "height"));
        label->setSize(QSizeF(width, height));
    } else {
        QSizeF size = shape->size();
        QRect r = QFontMetrics(doc->defaultFont()).boundingRect(
                        labelData->shapeMargins().left, labelData->shapeMargins().top,
                        qMax(CM_TO_POINT(5), qreal(size.width() - pos.x() * 2.0 - labelData->shapeMargins().right)),
                        qMax(CM_TO_POINT(0.6), qreal(size.height() - labelData->shapeMargins().bottom)),
                        Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, doc->toPlainText());
        label->setSize(r.size());
    }

    return true;
}
void KoListLevelProperties::loadOdf(KoShapeLoadingContext& scontext, const KoXmlElement& style)
{
    KoOdfLoadingContext &context = scontext.odfLoadingContext();

    // The text:level attribute specifies the level of the number list
    // style. It can be used on all list-level styles.
    const int level = qMax(1, style.attributeNS(KoXmlNS::text, "level", QString()).toInt());
    // The text:display-levels attribute specifies the number of
    // levels whose numbers are displayed at the current level.
    const QString displayLevel = style.attributeNS(KoXmlNS::text,
                                 "display-levels", QString());

    if (style.localName() == "list-level-style-bullet") {   // list with bullets

        //1.6: KoParagCounter::loadOasisListStyle
        QString bulletChar = style.isNull() ? QString() : style.attributeNS(KoXmlNS::text, "bullet-char", QString());
        kDebug(32500) << "style.localName()=" << style.localName() << "level=" << level << "displayLevel=" << displayLevel << "bulletChar=" << bulletChar;
        if (bulletChar.isEmpty()) {  // list without any visible bullets
            setStyle(KoListStyle::CustomCharItem);
            setBulletCharacter(QChar());
        } else { // try to determinate the bullet we should use
            switch (bulletChar[0].unicode()) {
            case 0x2022: // bullet, a small disc -> circle
                //TODO use BulletSize to differ between small and large discs
                setStyle(KoListStyle::DiscItem);
                break;
            case 0x25CF: // black circle, large disc -> disc
            case 0xF0B7: // #113361
                setStyle(KoListStyle::DiscItem);
                break;
            case 0xE00C: // losange => rhombus
                setStyle(KoListStyle::RhombusItem);
                break;
            case 0xE00A: // square. Not in OASIS (reserved Unicode area!), but used in both OOo and kotext.
                setStyle(KoListStyle::SquareItem);
                break;
            case 0x27A2: // two-colors right-pointing triangle
                setStyle(KoListStyle::RightArrowHeadItem);
                break;
            case 0x2794: // arrow to right
                setStyle(KoListStyle::RightArrowItem);
                break;
            case 0x2714: // checkmark
                setStyle(KoListStyle::HeavyCheckMarkItem);
                break;
            case 0x2d: // minus
                setStyle(KoListStyle::CustomCharItem);
                break;
            case 0x2717: // cross
                setStyle(KoListStyle::BallotXItem);
                break;
            default:
                QChar customBulletChar = bulletChar[0];
                kDebug(32500) << "Unhandled bullet code 0x" << QString::number((uint)customBulletChar.unicode(), 16);
                kDebug(32500) << "Should use the style =>" << style.attributeNS(KoXmlNS::text, "style-name", QString()) << "<=";
                setStyle(KoListStyle::CustomCharItem);
                /*
                QString customBulletFont;
                // often StarSymbol when it comes from OO; doesn't matter, Qt finds it in another font if needed.
                if ( listStyleProperties.hasAttributeNS( KoXmlNS::style, "font-name" ) )
                {
                    customBulletFont = listStyleProperties.attributeNS( KoXmlNS::style, "font-name", QString::null );
                    kDebug(32500) <<"customBulletFont style:font-name =" << listStyleProperties.attributeNS( KoXmlNS::style,"font-name", QString::null );
                }
                else if ( listStyleTextProperties.hasAttributeNS( KoXmlNS::fo, "font-family" ) )
                {
                    customBulletFont = listStyleTextProperties.attributeNS( KoXmlNS::fo, "font-family", QString::null );
                    kDebug(32500) <<"customBulletFont fo:font-family =" << listStyleTextProperties.attributeNS( KoXmlNS::fo,"font-family", QString::null );
                }
                // ## TODO in fact we're supposed to read it from the style pointed to by text:style-name
                */
//                     setStyle(KoListStyle::BoxItem); //fallback
                break;
            } // switch
            setBulletCharacter(bulletChar[0]);
        }

    } else if (style.localName() == "list-level-style-number" || style.localName() == "outline-level-style") { // it's a numbered list

        KoOdfNumberDefinition numberDefinition;
        numberDefinition.loadOdf(style);

        switch(numberDefinition.formatSpecification()) {
        case KoOdfNumberDefinition::Empty:
            setStyle(KoListStyle::CustomCharItem);
            setBulletCharacter(QChar());
            break;
        case KoOdfNumberDefinition::AlphabeticLowerCase:
            setStyle(KoListStyle::AlphaLowerItem);
            break;
        case KoOdfNumberDefinition::AlphabeticUpperCase:
            setStyle(KoListStyle::UpperAlphaItem);
            break;
        case KoOdfNumberDefinition::RomanLowerCase:
            setStyle(KoListStyle::RomanLowerItem);
            break;
        case KoOdfNumberDefinition::RomanUpperCase:
            setStyle(KoListStyle::UpperRomanItem);
            break;
        case KoOdfNumberDefinition::Numeric:
        default:
            setStyle(KoListStyle::DecimalItem);
        }

        if (!numberDefinition.prefix().isNull()) {
            setListItemPrefix(numberDefinition.prefix());
        }

        if (!numberDefinition.suffix().isNull()) {
            setListItemSuffix(numberDefinition.suffix());
        }
        const QString startValue = style.attributeNS(KoXmlNS::text, "start-value", QString("1"));
        setStartValue(startValue.toInt());
    }
    else if (style.localName() == "list-level-style-image") {   // list with image
        setStyle(KoListStyle::ImageItem);
        KoImageCollection *imageCollection = scontext.imageCollection();
        const QString href = style.attribute("href");
        if(imageCollection) {
            if (!href.isEmpty()) {
                KoStore *store = context.store();
                setBulletImage(imageCollection->createImageData(href, store));
            } else {
                // check if we have an office:binary data element containing the image data
                const KoXmlElement &binaryData(KoXml::namedItemNS(style, KoXmlNS::office, "binary-data"));
                if (!binaryData.isNull()) {
                    QImage image;
                    if (image.loadFromData(QByteArray::fromBase64(binaryData.text().toLatin1()))) {
                        setBulletImage(imageCollection->createImageData(image));
                    }
                }
            }
        }
    }
    else { // if not defined, we have do nothing
        kDebug(32500) << "stylename else:" << style.localName() << "level=" << level << "displayLevel=" << displayLevel;
        setStyle(KoListStyle::DecimalItem);
        setListItemSuffix(".");
    }

    setLevel(level);
    if (!displayLevel.isEmpty())
        setDisplayLevel(displayLevel.toInt());

    KoXmlElement property;
    forEachElement(property, style) {
        if (property.namespaceURI() != KoXmlNS::style)
            continue;
        const QString localName = property.localName();
        if (localName == "list-level-properties") {
            QString mode(property.attributeNS(KoXmlNS::text, "list-level-position-and-space-mode"));
            if (mode == "label-alignment") {
                KoXmlElement p;
                forEachElement(p, property) {
                     if (p.namespaceURI() == KoXmlNS::style && p.localName() == "list-level-label-alignment") {
                        // The <style:list-level-label-alignment> element and the fo:text-align attribute are used to define
                        // the position and spacing of the list label and the list item. The values of the attributes for
                        // text:space-before, text:min-label-width and text:min-label-distance are assumed to be 0.

                        QString textAlign(p.attributeNS(KoXmlNS::fo, "text-align"));
                        setAlignment(textAlign.isEmpty() ? Qt::AlignLeft : KoText::alignmentFromString(textAlign));

                        QString textindent(p.attributeNS(KoXmlNS::fo, "text-indent"));
                        QString marginleft(p.attributeNS(KoXmlNS::fo, "margin-left"));
                        qreal ti = textindent.isEmpty() ? 0 : KoUnit::parseValue(textindent);
                        qreal ml = marginleft.isEmpty() ? 0 : KoUnit::parseValue(marginleft);
                        setIndent(qMax(0.0, ti + ml));
                
                        setMinimumWidth(0);
                        setMinimumDistance(0);
                        
                        //TODO support ODF 18.829 text:label-followed-by and 18.832 text:list-tab-stop-position
                     }   
                }
            } else { // default is mode == "label-width-and-position"