/*! * \param Namespace (unused) * \param localName (unused) * \param tagid Qualified name * \param list Attributes */ bool startElement( const QString &, const QString &, const QString & tagid, const QXmlAttributes & list ) { if ( depth >= 8 ) err( tr("error maximum nesting level exceeded") ); Tag x = tags.value( tagid ); if ( x == tagNone ) err( tr("error unknown element '%1'").arg(tagid) ); if ( depth == 0 ) { if ( x != tagFile ) err( tr("this is not a niftoolsxml file") ); push( x ); return true; } switch ( current() ) { case tagFile: push( x ); switch ( x ) { case tagCompound: case tagBlock: { if ( ! list.value("nifskopetype").isEmpty() ) { QString alias = list.value( "name" ); QString type = list.value( "nifskopetype" ); if ( alias != type ) if ( ! NifValue::registerAlias( alias, type ) ) err( tr("failed to register alias %1 for type %2").arg(alias).arg(type) ); typId = alias; typTxt = QString(); } else { QString id = list.value( "name" ); if ( x == tagCompound && NifValue::isValid( NifValue::type( id ) ) ) err( tr("compound %1 is already registered as internal type").arg( list.value( "name" ) ) ); if ( id.isEmpty() ) err( tr("compound and niblocks must have a name") ); if ( NifModel::compounds.contains( id ) || NifModel::blocks.contains( id ) ) err( tr("multiple declarations of %1").arg(id) ); if ( ! blk ) blk = new NifBlock; blk->id = id; blk->abstract = ( list.value( "abstract" ) == "1" ); if ( x == tagBlock ) { blk->ancestor = list.value( "inherit" ); if ( ! blk->ancestor.isEmpty() ) { if ( ! NifModel::blocks.contains( blk->ancestor ) ) err( tr("forward declaration of block id %1").arg(blk->ancestor) ); } } }; } break; case tagBasic: { QString alias = list.value( "name" ); QString type = list.value( "nifskopetype" ); if ( alias.isEmpty() || type.isEmpty() ) err( tr("basic definition must have a name and a nifskopetype") ); if ( alias != type ) if ( ! NifValue::registerAlias( alias, type ) ) err( tr("failed to register alias %1 for type %2" ).arg(alias).arg(type) ); typId = alias; typTxt = QString(); } break; case tagEnum: case tagBitFlag: { typId = list.value( "name" ); typTxt = QString(); QString storage = list.value( "storage" ); if ( typId.isEmpty() || storage.isEmpty() ) err( tr("enum definition must have a name and a known storage type") ); if ( ! NifValue::registerAlias( typId, storage ) ) err( tr("failed to register alias %1 for enum type %2").arg(storage).arg(typId) ); NifValue::EnumType flags = (x == tagBitFlag) ? NifValue::eFlags : NifValue::eDefault; NifValue::registerEnumType(typId, flags); } break; case tagVersion: { int v = NifModel::version2number( list.value( "num" ).trimmed() ); if ( v != 0 && ! list.value( "num" ).isEmpty() ) NifModel::supportedVersions.append( v ); else err( tr("invalid version tag") ); } break; default: err( tr("expected basic, enum, compound, niobject or version got %1 instead").arg(tagid) ); } break; case tagVersion: //err( tr("version tag must not contain any sub tags") ); break; case tagCompound: if ( x != tagAdd ) err( tr("only add tags allowed in compound type declaration") ); case tagBlock: push( x ); switch ( x ) { case tagAdd: { // ns type optimizers come here // we really shouldn't be doing this // but it will work for now until we find a better solution QString type = list.value( "type" ); QString nstype = list.value( "nifskopetype" ); if (!nstype.isEmpty() && nstype != type) { if ( NifValue::type( nstype ) == NifValue::tNone ) err( "failed to locate alias " + nstype ); type = nstype; } if ( type == "KeyArray" ) type = "ns keyarray"; else if ( type == "VectorKeyArray" ) type = "ns keyvecarray"; else if ( type == "TypedVectorKeyArray" ) type = "ns keyvecarraytyp"; else if ( type == "RotationKeyArray" ) type = "ns keyrotarray"; // now allocate data = NifData( list.value( "name" ), type, list.value( "template" ), NifValue( NifValue::type( type ) ), list.value( "arg" ), list.value( "arr1" ), list.value( "arr2" ), list.value( "cond" ), NifModel::version2number( list.value( "ver1" ) ), NifModel::version2number( list.value( "ver2" ) ), ( list.value( "abstract" ) == "1" ) ); if ( data.isAbstract() ) { data.value.setAbstract( true ); } QString defval = list.value( "default" ); if ( ! defval.isEmpty() ) { bool ok; quint32 enumVal = NifValue::enumOptionValue( type, defval, &ok ); if( ok ) { data.value.setCount( enumVal ); } else { data.value.fromString( defval ); } } QString vercond = list.value( "vercond" ); QString userver = list.value( "userver" ); if ( ! userver.isEmpty() ) { if ( ! vercond.isEmpty() ) vercond += " && "; vercond += QString("(User Version == %1)").arg(userver); } QString userver2 = list.value( "userver2" ); if ( ! userver2.isEmpty() ) { if ( ! vercond.isEmpty() ) vercond += " && "; vercond += QString("(User Version 2 == %1)").arg(userver2); } if ( !vercond.isEmpty() ) { data.setVerCond( vercond ); } if ( data.name().isEmpty() || data.type().isEmpty() ) err( tr("add needs at least name and type attributes") ); } break; default: err( tr("only add tags allowed in block declaration") ); } break; case tagEnum: case tagBitFlag: push( x ); switch ( x ) { case tagOption: optId = list.value( "name" ); optVal = list.value( "value" ); optTxt = QString(); if ( optId.isEmpty() || optVal.isEmpty() ) err( tr("option defintion must have a name and a value") ); bool ok; optVal.toInt( &ok, 0 ); if ( ! ok ) err( tr("option value error (only integers please)") ); break; default: err( tr("only option tags allowed in enum declaration") ); } break; default: err( tr("error unhandled tag %1").arg(tagid) ); break; } return true; }
NifValue BaseModel::getValue( const QModelIndex & index ) const { NifItem * item = static_cast<NifItem*>( index.internalPointer() ); if ( ! ( index.isValid() && item && index.model() == this ) ) return NifValue(); return item->value(); }