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); }
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; }
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; }
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; }
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; }
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")); }
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; } } }
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; }
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; }
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; }
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); } } }
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; } } }
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; }
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") {
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"