Esempio n. 1
0
	/*!
	 * \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;
	}
Esempio n. 2
0
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();
}