QString ElementWrapper::xmlBase() const { if (!d->xmlBaseParsed) // xmlBase not computed yet { QDomElement current = d->element; while (!current.isNull()) { if (current.hasAttributeNS(xmlNamespace(), QLatin1String("base"))) { d->xmlBase = current.attributeNS(xmlNamespace(), QLatin1String("base")); return d->xmlBase; } QDomNode parent = current.parentNode(); if (!parent.isNull() && parent.isElement()) current = parent.toElement(); else current = QDomElement(); } d->xmlBaseParsed = true; } return d->xmlBase; }
bool KoStyleStack::hasAttributeNS( const char* nsURI, const char* name, const char* detail ) const { QString fullName( name ); if ( detail ) { fullName += '-'; fullName += detail; } QValueList<QDomElement>::ConstIterator it = m_stack.end(); while ( it != m_stack.begin() ) { --it; QDomElement properties = KoDom::namedItemNS( *it, m_styleNSURI, m_propertiesTagName ); if ( properties.hasAttributeNS( nsURI, name ) || ( detail && properties.hasAttributeNS( nsURI, fullName ) ) ) return true; } return false; }
Parser::Parser() { d = new Private; // check for evil bug in Qt <= 3.2.1 if(!qt_bug_check) { qt_bug_check = true; QDomElement e = d->doc->createElementNS("someuri", "somename"); if(e.hasAttributeNS("someuri", "somename")) qt_bug_have = true; else qt_bug_have = false; } }
bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts) { if(depth == 0) { Parser::Event *e = new Parser::Event; QXmlAttributes a; for(int n = 0; n < atts.length(); ++n) { QString uri = atts.uri(n); QString ln = atts.localName(n); if(a.index(uri, ln) == -1) a.append(atts.qName(n), uri, ln, atts.value(n)); } e->setDocumentOpen(namespaceURI, localName, qName, a, nsnames, nsvalues); nsnames.clear(); nsvalues.clear(); e->setActualString(in->lastString()); in->resetLastData(); eventList.append(e); in->pause(true); } else { QDomElement e = doc->createElementNS(namespaceURI, qName); for(int n = 0; n < atts.length(); ++n) { QString uri = atts.uri(n); QString ln = atts.localName(n); bool have; if(!uri.isEmpty()) { have = e.hasAttributeNS(uri, ln); if(qt_bug_have) have = !have; } else have = e.hasAttribute(ln); if(!have) e.setAttributeNS(uri, atts.qName(n), atts.value(n)); } if(depth == 1) { elem = e; current = e; } else { current.appendChild(e); current = e; } } ++depth; return true; }
// Font size is a bit special. "115%" applies to "the fontsize of the parent style". // This can be generalized though (hasAttributeThatCanBePercentOfParent() ? :) // Although, if we also add support for fo:font-size-rel here then it's not general anymore. double KoStyleStack::fontSize() const { const QString name = "font-size"; double percent = 1; QValueList<QDomElement>::ConstIterator it = m_stack.end(); // reverse iterator while ( it != m_stack.begin() ) { --it; QDomElement properties = KoDom::namedItemNS( *it, m_styleNSURI, m_propertiesTagName ).toElement(); if ( properties.hasAttributeNS( m_foNSURI, name ) ) { const QString value = properties.attributeNS( m_foNSURI, name, QString::null ); if ( value.endsWith( "%" ) ) percent *= value.left( value.length() - 1 ).toDouble() / 100.0; else return percent * KoUnit::parseValue( value ); // e.g. 12pt } } return 0; }
void KoOasisLoadingContext::fillStyleStack( const QDomElement& object, const char* nsURI, const char* attrName, const char* family ) { // find all styles associated with an object and push them on the stack if ( object.hasAttributeNS( nsURI, attrName ) ) { const QString styleName = object.attributeNS( nsURI, attrName, QString::null ); const QDomElement* style = 0; bool isStyleAutoStyle = false; if ( m_useStylesAutoStyles ) { // When loading something from styles.xml, look into the styles.xml auto styles first style = m_styles.findStyleAutoStyle( styleName, family ); // and fallback to looking at styles(), which includes the user styles from styles.xml if ( style ) isStyleAutoStyle = true; } if ( !style ) style = m_styles.findStyle( styleName, family ); if ( style ) addStyles( style, family, isStyleAutoStyle ); else kdWarning(32500) << "fillStyleStack: no style named " << styleName << " found." << endl; } }
void KoParagStyle::loadStyle( QDomElement & styleElem, KoOasisContext& context ) { // Load name m_name = styleElem.attributeNS( KoXmlNS::style, "name", QString::null ); m_displayName = styleElem.attributeNS( KoXmlNS::style, "display-name", QString::null ); if ( m_displayName.isEmpty() ) m_displayName = m_name; // OOo hack //m_bOutline = m_name.startsWith( "Heading" ); // real OASIS solution: m_bOutline = styleElem.hasAttributeNS( KoXmlNS::style, "default-outline-level" ); context.styleStack().save(); context.addStyles( &styleElem, "paragraph" ); // Load all parents - only because we don't support inheritance. KoParagLayout layout; KoParagLayout::loadOasisParagLayout( layout, context ); // loadOasisParagLayout doesn't load the counter. It's modelled differently for parags and for styles. int level = 0; bool listOK = false; const QString listStyleName = styleElem.attributeNS( KoXmlNS::style, "list-style-name", QString::null ); if ( m_bOutline ) { level = styleElem.attributeNS( KoXmlNS::style, "default-outline-level", QString::null ).toInt(); // 1-based listOK = context.pushOutlineListLevelStyle( level ); // allow overriding the outline numbering, see http://lists.oasis-open.org/archives/office/200310/msg00033.html if ( !listStyleName.isEmpty() ) context.pushListLevelStyle( listStyleName, level ); } else { // ######## BIG difference here. In the OOo/OASIS format, one list style has infos for 10 list levels... // ###### so we can't know a level at this point... // The only solution I can think of, to preserve document content when importing OO but // not necessarily the styles used when editing, is: // 1) when importing from OOo, convert each non-heading style with numbering // into 10 kotext styles (at least those used by the document) [TODO] // 2) for KWord's own loading/saving, to add a hack into the file format, say // style:default-level. // Note that default-level defaults to "1", i.e. works for non-nested OOo lists too. level = styleElem.attributeNS( KoXmlNS::style, "default-level", "1" ).toInt(); // 1-based listOK = !listStyleName.isEmpty(); if ( listOK ) listOK = context.pushListLevelStyle( listStyleName, level ); } if ( listOK ) { const QDomElement listStyle = context.listStyleStack().currentListStyle(); // The tag is either text:list-level-style-number or text:list-level-style-bullet const bool ordered = listStyle.localName() == "list-level-style-number"; Q_ASSERT( !layout.counter ); layout.counter = new KoParagCounter; layout.counter->loadOasis( context, -1, ordered, m_bOutline, level, true ); context.listStyleStack().pop(); } // This way, KoTextParag::setParagLayout also sets the style pointer, to this style layout.style = this; m_paragLayout = layout; m_format.load( context ); context.styleStack().restore(); }