lib

KoStyleCollection.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2001 David Faure <faure@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include "KoStyleCollection.h"
21#include "KoOasisContext.h"
22#include "KoParagCounter.h"
23
24#include <KoOasisStyles.h>
25#include <KoGenStyles.h>
26#include <KoXmlWriter.h>
27#include <KoXmlNS.h>
28
29#include <kdebug.h>
30#include <tdelocale.h>
31
32#include <tqdom.h>
33
34KoStyleCollection::KoStyleCollection()
35 : KoUserStyleCollection( "paragsty" )
36{
37}
38
39KoStyleCollection::~KoStyleCollection()
40{
41}
42
44{
45 TQStringList followingStyles;
46 TQValueVector<TQDomElement> userStyles = context.oasisStyles().userStyles();
47 bool defaultStyleDeleted = false;
48 int stylesLoaded = 0;
49 const unsigned int nStyles = userStyles.count();
50 for (unsigned int item = 0; item < nStyles; item++) {
51 TQDomElement styleElem = userStyles[item];
52 Q_ASSERT( !styleElem.isNull() );
53
54 if ( styleElem.attributeNS( KoXmlNS::style, "family", TQString() ) != "paragraph" )
55 continue;
56
57 if( !defaultStyleDeleted ) { // we are going to import at least one style.
59 //kdDebug() << "loadOasisStyles looking for Standard, to delete it. Found " << s << endl;
60 if(s) // delete the standard style.
61 removeStyle(s);
62 defaultStyleDeleted = true;
63 }
64
65 KoParagStyle *sty = new KoParagStyle( TQString() );
66 // Load the style
67 sty->loadStyle( styleElem, context );
68 // Style created, now let's try to add it
69 const int oldStyleCount = count();
70 sty = addStyle( sty );
71 // the real value of followingStyle is set below after loading all styles
72 sty->setFollowingStyle( sty );
73
74 kdDebug() << " Loaded style " << sty->name() << endl;
75
76 if ( count() > oldStyleCount )
77 {
78 const TQString following = styleElem.attributeNS( KoXmlNS::style, "next-style-name", TQString() );
79 followingStyles.append( following );
80 ++stylesLoaded;
81 }
82 else
83 kdWarning() << "Found duplicate style declaration, overwriting former " << sty->name() << endl;
84 }
85
86 if( followingStyles.count() != styleList().count() ) {
87 kdDebug() << "Ouch, " << followingStyles.count() << " following-styles, but "
88 << styleList().count() << " styles in styleList" << endl;
89 }
90
91 unsigned int i=0;
92 for( TQValueList<TQString>::ConstIterator it = followingStyles.begin(); it != followingStyles.end(); ++it, ++i ) {
93 const TQString followingStyleName = *it;
94 if ( !followingStyleName.isEmpty() ) {
95 KoParagStyle * style = findStyle( followingStyleName );
96 if ( style )
97 styleAt(i)->setFollowingStyle( style );
98 }
99 }
100
101 // TODO the same thing for style inheritance (style:parent-style-name) and setParentStyle()
102
103 Q_ASSERT( defaultStyle() );
104 return stylesLoaded;
105}
106
107void KoStyleCollection::saveOasis( KoGenStyles& styles, int styleType, KoSavingContext& context ) const
108{
109 // In order to reduce the bloat, we define that the first style (usually Standard)
110 // is the "parent" (reference) for the others.
111 // ## This is mostly a hack due to lack of proper style inheritance.
112 // Once that's implemented, default to 'styles derive from Standard', but save normally.
113 TQString refStyleName;
114
115 for ( TQValueList<KoUserStyle *>::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) {
116 KoParagStyle* style = static_cast<KoParagStyle *>( *styleIt );
117 style->saveStyle( styles, styleType, refStyleName, context );
118 kdDebug() << k_funcinfo << "Saved style " << style->displayName() << " to OASIS format as " << style->name() << endl;
119 if ( refStyleName.isEmpty() ) // i.e. first style
120 refStyleName = style->name();
121 }
122 // Now edit the kogenstyle and set the next-style-name. This works here
123 // because the style's m_name is already unique so there's no risk of
124 // "two styles being only different due to their following-style"; the
125 // display-name will also be different, and will ensure they get two kogenstyles.
126 for ( TQValueList<KoUserStyle *>::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) {
127 KoParagStyle* style = static_cast<KoParagStyle *>( *styleIt );
128 if ( style->followingStyle() && style->followingStyle() != style ) {
129 const TQString fsname = style->followingStyle()->name();
130 KoGenStyle* gs = styles.styleForModification( style->name() );
131 Q_ASSERT( gs );
132 if ( gs )
133 gs->addAttribute( "style:next-style-name", fsname );
134 }
135 }
136}
137
139{
140 const TQValueList<KoUserStyle *> styles = styleCollection.styleList();
141 TQMap<TQString, TQString> followStyle;
142 for ( TQValueList<KoUserStyle *>::const_iterator styleIt = styles.begin(), styleEnd = styles.end() ; styleIt != styleEnd ; ++styleIt ) {
143 KoParagStyle* p = static_cast<KoParagStyle *>( *styleIt );
144 KoParagStyle* style = new KoParagStyle( *p );
145 if ( style->followingStyle() ) {
146 followStyle.insert( style->name(), style->followingStyle()->name() );
147 }
148 style = addStyle( style );
149 }
150
151 TQMapIterator<TQString, TQString> itFollow = followStyle.begin();
152 for ( ; itFollow != followStyle.end(); ++itFollow )
153 {
154 KoParagStyle * style = findStyle(itFollow.key());
155 const TQString followingStyleName = followStyle[ itFollow.key() ];
156 KoParagStyle * styleFollow = findStyle(followingStyleName);
157 //kdDebug() << " " << style << " " << itFollow.key() << ": followed by " << styleFollow << " (" << followingStyleName << ")" << endl;
158 Q_ASSERT(styleFollow);
159 if ( styleFollow )
160 style->setFollowingStyle( styleFollow );
161 else
162 style->setFollowingStyle( style );
163 }
164}
165
167{
168 bool first = true;
169 TQValueVector<KoParagStyle *> styles = outlineStyles();
170 for ( int i = 0 ; i < 10 ; ++i ) {
171 if ( styles[i] ) {
172 if ( first ) {
173 writer.startElement( "text:outline-style" );
174 first = false;
175 }
176 writer.startElement( "text:outline-level-style" );
177 styles[i]->paragLayout().counter->saveOasisListLevel( writer, true, true );
178 writer.endElement();
179 }
180 }
181 if ( !first )
182 writer.endElement(); // text:outline-style
183}
184
185TQValueVector<KoParagStyle *> KoStyleCollection::outlineStyles() const
186{
187 TQValueVector<KoParagStyle *> lst( 10, 0 );
188 for ( int i = 0 ; i < 10 ; ++i ) {
190 if ( style )
191 lst[i] = style;
192 }
193 return lst;
194}
195
196
198{
199 for ( TQValueList<KoUserStyle *>::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) {
200 KoParagStyle* style = static_cast<KoParagStyle *>( *styleIt );
201 if ( style->isOutline() && style->paragLayout().counter )
202 {
203 int styleLevel = style->paragLayout().counter->depth();
204 if ( styleLevel == level )
205 return style;
206 }
207 }
208 return 0;
209}
210
212{
213 for ( TQValueList<KoUserStyle *>::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) {
214 KoParagStyle* style = static_cast<KoParagStyle *>( *styleIt );
215 KoParagCounter* counter = style->paragLayout().counter;
216 if ( !style->isOutline() && counter
217 && counter->numbering() != KoParagCounter::NUM_NONE
218 && !counter->isBullet() )
219 {
220 int styleLevel = counter->depth();
221 if ( styleLevel == level )
222 return style;
223 }
224 }
225 return 0;
226}
227
229{
230 return findStyle( "Standard" ); // includes the fallback to first style
231}
232
233#ifndef NDEBUG
234void KoStyleCollection::printDebug() const
235{
236 for ( TQValueList<KoUserStyle *>::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) {
237 KoParagStyle* style = static_cast<KoParagStyle *>( *styleIt );
238
239 // short version:
240 // kdDebug() << style << " " << style->name() << " " << style->displayName() << " followingStyle=" << style->followingStyle() << endl;
241
242 kdDebug() << "Style " << style << " " << style->name() << " isOutline=" << style->isOutline() << endl;
243 kdDebug() << " format: " << style->format().key() <<endl;
244 static const char * const s_align[] = { "Auto", "Left", "Right", "ERROR", "HCenter", "ERR", "ERR", "ERR", "Justify", };
245 kdDebug() << " align: " << s_align[(TQt::AlignmentFlags)style->paragLayout().alignment] << endl;
246 if ( style->paragLayout().counter )
247 kdDebug() << " counter level=" << style->paragLayout().counter->depth() << endl;
248
249 kdDebug() << " following style: " << style->followingStyle() << " "
250 << ( style->followingStyle() ? style->followingStyle()->name() : TQString() ) << endl;
251
252 }
253}
254#endif
const KoTextFormat & format() const
Return a format.
A generic style, i.e.
void addAttribute(const TQString &attrName, const TQString &attrValue)
Add an attribute to the style The difference between property and attributes is a bit oasis-format-sp...
Repository of styles used during saving of OASIS/OOo file.
Definition KoGenStyles.h:60
KoGenStyle * styleForModification(const TQString &name)
Used during loading of Oasis format (and discarded at the end of the loading).
TQValueVector< TQDomElement > userStyles() const
This is the structure associated with a paragraph (KoTextParag), to define the bullet or numbering of...
unsigned int depth() const
The level of the numbering.
Numbering numbering() const
Numbering type and style.
bool isBullet() const
Does this counter have a bullet style?
KoParagCounter * counter
can be 0 if no counter set
char alignment
Alignment flag (AlignAuto/AlignLeft/AlignRight/AlignJustify)
A paragraph style is a combination of a character style and paragraph-layout attributes,...
void saveStyle(TQDomElement &parentElem)
Saves the name, layout, the following style and the outline bool.
void loadStyle(TQDomElement &parentElem, int docVersion=2)
Loads the name, layout and the outline bool.
Used during saving to Oasis format (and discarded at the end of the saving).
TODO rename to KoParagStyleCollection - or should char styles be part of it too?
TQValueVector< KoParagStyle * > outlineStyles() const
KoParagStyle * outlineStyleForLevel(int level) const
KoParagStyle * defaultStyle() const
KoParagStyle * addStyle(KoParagStyle *sty)
See KoUserStyleCollection::addStyle.
KoParagStyle * styleAt(int i)
Return style number i.
KoParagStyle * findStyle(const TQString &name) const
Find style based on the internal name name.
void importStyles(const KoStyleCollection &styleList)
Import a number of styles (e.g. loaded from another document)
void saveOasis(KoGenStyles &styles, int styleType, KoSavingContext &context) const
Save the entire style collection in the OASIS OpenDocument format styleType is the STYLE_* value for ...
KoParagStyle * numberedStyleForLevel(int level) const
int loadOasisStyles(KoOasisContext &context)
Loads the entire style collection, in the OASIS OpenDocument format.
void saveOasisOutlineStyles(KoXmlWriter &writer) const
Save the text:outline-style element, mostly for OOo.
Generic style collection class, for all "user styles" (see KoUserStyle).
TQValueList< KoUserStyle * > styleList() const
Return the list of all styles in the collection.
void removeStyle(KoUserStyle *style)
Remove style from the collection.
TQString displayName() const
The user-visible name (e.g. translated, or set by the user)
TQString name() const
The internal name (used for loading/saving, but not shown to the user) Should be unique in a given st...
Definition KoUserStyle.h:40
A class for writing out XML (to any TQIODevice), with a special attention on performance.
Definition KoXmlWriter.h:37
void startElement(const char *tagName, bool indentInside=true)
Start a new element, as a child of the current element.
void endElement()
Terminate the current element.