00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <float.h>
00020
00021 #include <Q3ValueList>
00022
00023 #include <kdebug.h>
00024
00025 #include <KoXmlWriter.h>
00026 #include "KoGenStyles.h"
00027
00028 #include "KoGenStyle.h"
00029
00030
00031
00032 static int compareMap( const QMap<QString, QString>& map1, const QMap<QString, QString>& map2 )
00033 {
00034 QMap<QString, QString>::const_iterator it = map1.begin();
00035 QMap<QString, QString>::const_iterator oit = map2.begin();
00036 for ( ; it != map1.end(); ++it, ++oit ) {
00037 if ( it.key() != oit.key() )
00038 return it.key() < oit.key() ? -1 : +1;
00039 if ( it.value() != oit.value() )
00040 return it.value() < oit.value() ? -1 : +1;
00041 }
00042 return 0;
00043 }
00044
00045
00046 KoGenStyle::KoGenStyle( int type, const char* familyName,
00047 const QString& parentName )
00048 : m_type( type ), m_familyName( familyName ), m_parentName( parentName ),
00049 m_autoStyleInStylesDotXml( false ), m_defaultStyle( false )
00050 {
00051 }
00052
00053 KoGenStyle::~KoGenStyle()
00054 {
00055 }
00056
00057 void KoGenStyle::writeStyleProperties( KoXmlWriter* writer, PropertyType i,
00058 const char* elementName, const KoGenStyle* parentStyle ) const
00059 {
00060 if ( !m_properties[i].isEmpty() ) {
00061 writer->startElement( elementName );
00062 QMap<QString, QString>::const_iterator it = m_properties[i].begin();
00063 const QMap<QString, QString>::const_iterator end = m_properties[i].end();
00064 for ( ; it != end; ++it ) {
00065 if ( !parentStyle || parentStyle->property( it.key(), i ) != it.value() )
00066 writer->addAttribute( it.key().toUtf8(), it.value().toUtf8() );
00067 }
00068 writer->endElement();
00069 }
00070 }
00071
00072 void KoGenStyle::writeStyle( KoXmlWriter* writer, KoGenStyles& styles, const char* elementName, const QString& name, const char* propertiesElementName, bool closeElement, bool drawElement ) const
00073 {
00074
00075 writer->startElement( elementName );
00076 const KoGenStyle* parentStyle = 0;
00077 if ( !m_defaultStyle ) {
00078 if ( !drawElement )
00079 writer->addAttribute( "style:name", name );
00080 else
00081 writer->addAttribute( "draw:name", name );
00082 if ( !m_parentName.isEmpty() ) {
00083 parentStyle = styles.style( m_parentName );
00084 if ( parentStyle && m_familyName.isEmpty() ) {
00085
00086
00087 const_cast<KoGenStyle *>( this )->
00088 m_familyName = parentStyle->attribute( "style:family" ).toLatin1();
00089
00090 }
00091 writer->addAttribute( "style:parent-style-name", m_parentName );
00092 }
00093 } else {
00094 Q_ASSERT( qstrcmp( elementName, "style:default-style" ) == 0 );
00095 Q_ASSERT( m_parentName.isEmpty() );
00096 }
00097 if ( !m_familyName.isEmpty() )
00098 const_cast<KoGenStyle *>( this )->
00099 addAttribute( "style:family", QString::fromLatin1( m_familyName ) );
00100 else {
00101 if ( qstrcmp( elementName, "style:style" ) == 0 )
00102 kWarning(30003) << "User style " << name << " is without family - invalid. m_type=" << m_type << endl;
00103 }
00104
00105 #if 0 // #ifndef NDEBUG
00106 kDebug() << "style: " << name << endl;
00107 printDebug();
00108 if ( parentStyle ) {
00109 kDebug() << " parent: " << m_parentName << endl;
00110 parentStyle->printDebug();
00111 }
00112 #endif
00113
00114
00115
00116
00117
00118 QMap<QString, QString>::const_iterator it = m_attributes.begin();
00119 for ( ; it != m_attributes.end(); ++it ) {
00120 bool writeit = true;
00121 if ( parentStyle && it.key() != "style:family"
00122 && parentStyle->attribute( it.key() ) == it.value() )
00123 writeit = false;
00124 if ( writeit )
00125 writer->addAttribute( it.key().toUtf8(), it.value().toUtf8() );
00126 }
00127 bool createPropertiesTag = propertiesElementName && propertiesElementName[0] != '\0';
00128 KoGenStyle::PropertyType i = KoGenStyle::DefaultType;
00129 if ( !m_properties[i].isEmpty() ||
00130 !m_properties[KoGenStyle::ChildElement].isEmpty() ) {
00131 if ( createPropertiesTag )
00132 writer->startElement( propertiesElementName );
00133 it = m_properties[i].begin();
00134 for ( ; it != m_properties[i].end(); ++it ) {
00135 if ( !parentStyle || parentStyle->property( it.key(), i ) != it.value() )
00136 writer->addAttribute( it.key().toUtf8(), it.value().toUtf8() );
00137 }
00138 i = KoGenStyle::ChildElement;
00139 it = m_properties[i].begin();
00140 for ( ; it != m_properties[i].end(); ++it ) {
00141 if ( !parentStyle || parentStyle->property( it.key(), i ) != it.value() ) {
00142 writer->addCompleteElement( it.value().toUtf8() );
00143 }
00144 }
00145 if ( createPropertiesTag )
00146 writer->endElement();
00147 }
00148 writeStyleProperties( writer, KoGenStyle::GraphicType, "style:graphic-properties", parentStyle );
00149 writeStyleProperties( writer, KoGenStyle::ParagraphType, "style:paragraph-properties", parentStyle );
00150 writeStyleProperties( writer, KoGenStyle::TextType, "style:text-properties", parentStyle );
00151
00152
00153 for ( int i = 0; i < m_maps.count(); ++i ) {
00154 bool writeit = true;
00155 if ( parentStyle && compareMap( m_maps[i], parentStyle->m_maps[i] ) == 0 )
00156 writeit = false;
00157 if ( writeit ) {
00158 writer->startElement( "style:map" );
00159 QMap<QString, QString>::const_iterator it = m_maps[i].begin();
00160 for ( ; it != m_maps[i].end(); ++it ) {
00161 writer->addAttribute( it.key().toUtf8(), it.value().toUtf8() );
00162 }
00163 writer->endElement();
00164 }
00165 }
00166 if ( closeElement )
00167 writer->endElement();
00168 }
00169
00170 void KoGenStyle::addPropertyPt( const QString& propName, double propValue, PropertyType type )
00171 {
00172 QString str;
00173 str.setNum( propValue, 'g', DBL_DIG );
00174 str += "pt";
00175 m_properties[type].insert( propName, str );
00176 }
00177
00178 void KoGenStyle::addAttributePt( const QString& attrName, double attrValue )
00179 {
00180 QString str;
00181 str.setNum( attrValue, 'g', DBL_DIG );
00182 str += "pt";
00183 m_attributes.insert( attrName, str );
00184 }
00185
00186 #ifndef NDEBUG
00187 void KoGenStyle::printDebug() const
00188 {
00189 int i = DefaultType;
00190 kDebug() << m_properties[i].count() << " properties." << endl;
00191 for( QMap<QString,QString>::ConstIterator it = m_properties[i].begin(); it != m_properties[i].end(); ++it ) {
00192 kDebug() << " " << it.key() << " = " << it.value() << endl;
00193 }
00194 i = TextType;
00195 kDebug() << m_properties[i].count() << " text properties." << endl;
00196 for( QMap<QString,QString>::ConstIterator it = m_properties[i].begin(); it != m_properties[i].end(); ++it ) {
00197 kDebug() << " " << it.key() << " = " << it.value() << endl;
00198 }
00199 i = ParagraphType;
00200 kDebug() << m_properties[i].count() << " paragraph properties." << endl;
00201 for( QMap<QString,QString>::ConstIterator it = m_properties[i].begin(); it != m_properties[i].end(); ++it ) {
00202 kDebug() << " " << it.key() << " = " << it.value() << endl;
00203 }
00204 i = ChildElement;
00205 kDebug() << m_properties[i].count() << " child elements." << endl;
00206 for( QMap<QString,QString>::ConstIterator it = m_properties[i].begin(); it != m_properties[i].end(); ++it ) {
00207 kDebug() << " " << it.key() << " = " << it.value() << endl;
00208 }
00209 kDebug() << m_attributes.count() << " attributes." << endl;
00210 for( QMap<QString,QString>::ConstIterator it = m_attributes.begin(); it != m_attributes.end(); ++it ) {
00211 kDebug() << " " << it.key() << " = " << it.value() << endl;
00212 }
00213 kDebug() << m_maps.count() << " maps." << endl;
00214 for ( int i = 0; i < m_maps.count(); ++i ) {
00215 kDebug() << "map " << i << ":" << endl;
00216 for( QMap<QString,QString>::ConstIterator it = m_maps[i].begin(); it != m_maps[i].end(); ++it ) {
00217 kDebug() << " " << it.key() << " = " << it.value() << endl;
00218 }
00219 }
00220 kDebug() << endl;
00221 }
00222 #endif
00223
00224 bool KoGenStyle::operator<( const KoGenStyle &other ) const
00225 {
00226 if ( m_type != other.m_type ) return m_type < other.m_type;
00227 if ( m_parentName != other.m_parentName ) return m_parentName < other.m_parentName;
00228 if ( m_autoStyleInStylesDotXml != other.m_autoStyleInStylesDotXml ) return m_autoStyleInStylesDotXml;
00229 for ( uint i = 0 ; i < N_NumTypes ; ++i )
00230 if ( m_properties[i].count() != other.m_properties[i].count() )
00231 return m_properties[i].count() < other.m_properties[i].count();
00232 if ( m_attributes.count() != other.m_attributes.count() ) return m_attributes.count() < other.m_attributes.count();
00233 if ( m_maps.count() != other.m_maps.count() ) return m_maps.count() < other.m_maps.count();
00234
00235 for ( uint i = 0 ; i < N_NumTypes ; ++i ) {
00236 int comp = compareMap( m_properties[i], other.m_properties[i] );
00237 if ( comp != 0 )
00238 return comp < 0;
00239 }
00240 int comp = compareMap( m_attributes, other.m_attributes );
00241 if ( comp != 0 )
00242 return comp < 0;
00243 for ( int i = 0 ; i < m_maps.count() ; ++i ) {
00244 int comp = compareMap( m_maps[i], other.m_maps[i] );
00245 if ( comp != 0 )
00246 return comp < 0;
00247 }
00248 return false;
00249 }
00250
00251 bool KoGenStyle::operator==( const KoGenStyle &other ) const
00252 {
00253 if ( m_type != other.m_type ) return false;
00254 if ( m_parentName != other.m_parentName ) return false;
00255 if ( m_autoStyleInStylesDotXml != other.m_autoStyleInStylesDotXml ) return false;
00256 for ( uint i = 0 ; i < N_NumTypes ; ++i )
00257 if ( m_properties[i].count() != other.m_properties[i].count() )
00258 return false;
00259 if ( m_attributes.count() != other.m_attributes.count() ) return false;
00260 if ( m_maps.count() != other.m_maps.count() ) return false;
00261
00262 for ( uint i = 0 ; i < N_NumTypes ; ++i ) {
00263 int comp = compareMap( m_properties[i], other.m_properties[i] );
00264 if ( comp != 0 )
00265 return false;
00266 }
00267 int comp = compareMap( m_attributes, other.m_attributes );
00268 if ( comp != 0 )
00269 return false;
00270 for ( int i = 0 ; i < m_maps.count() ; ++i ) {
00271 int comp = compareMap( m_maps[i], other.m_maps[i] );
00272 if ( comp != 0 )
00273 return false;
00274 }
00275 return true;
00276 }