lib

KoTextCommand.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 "KoTextCommand.h"
21#include "KoTextObject.h"
22#include "KoTextParag.h"
23#include "KoVariable.h"
24#include <kdebug.h>
25#include <tdelocale.h>
26
27// This is automatically called by KCommandHistory's redo action when redo is activated
29{
30 m_textobj->redo();
31}
32
33// This is automatically called by KCommandHistory's undo action when undo is activated
35{
36 m_textobj->undo();
37}
38
39KoTextDeleteCommand::KoTextDeleteCommand(
40 KoTextDocument *d, int i, int idx, const TQMemArray<KoTextStringChar> &str,
41 const CustomItemsMap & customItemsMap,
42 const TQValueList<KoParagLayout> &oldParagLayouts )
43 : KoTextDocDeleteCommand( d, i, idx, str ),
44 m_oldParagLayouts( oldParagLayouts ),
45 m_customItemsMap( customItemsMap )
46{
47 Q_ASSERT( id >= 0 );
48}
49
50KoTextCursor * KoTextDeleteCommand::execute( KoTextCursor *c )
51{
52 KoTextParag *s = doc ? doc->paragAt( id ) : parag;
53 if ( !s ) {
54 kdWarning() << "can't locate parag at " << id << ", last parag: " << doc->lastParag()->paragId() << endl;
55 return 0;
56 }
57 cursor.setParag( s );
58 cursor.setIndex( index );
59 int len = text.size();
60 // Detach from custom items. They are already in the map, and we don't
61 // want them to be deleted
62 for ( int i = 0; i < len; ++i )
63 {
64 KoTextStringChar * ch = cursor.parag()->at( cursor.index() );
65 if ( ch->isCustom() )
66 {
67 ch->customItem()->setDeleted( true );
68 cursor.parag()->removeCustomItem(cursor.index());
69 }
70 cursor.gotoRight();
71 }
72
73 return KoTextDocDeleteCommand::execute(c);
74}
75
76KoTextCursor * KoTextDeleteCommand::unexecute( KoTextCursor *c )
77{
78 // Let TQRichText re-create the text and formatting
79 KoTextCursor * cr = KoTextDocDeleteCommand::unexecute(c);
80
81 KoTextParag *s = doc ? doc->paragAt( id ) : parag;
82 if ( !s ) {
83 kdWarning() << "can't locate parag at " << id << ", last parag: " << (doc ? doc->lastParag()->paragId() : -1) << endl;
84 return 0;
85 }
86 cursor.setParag( s );
87 cursor.setIndex( index );
88 // Set any custom item that we had
89 m_customItemsMap.insertItems( cursor, text.size() );
90
91 // Now restore the parag layouts (i.e. libkotext specific stuff)
92 TQValueList<KoParagLayout>::Iterator lit = m_oldParagLayouts.begin();
93 kdDebug(32500) << "KoTextDeleteCommand::unexecute " << m_oldParagLayouts.count() << " parag layouts. First parag=" << s->paragId() << endl;
94 Q_ASSERT( id == s->paragId() );
95 KoTextParag *p = s;
96 while ( p ) {
97 if ( lit != m_oldParagLayouts.end() )
98 {
99 kdDebug(32500) << "KoTextDeleteCommand::unexecute applying paraglayout to parag " << p->paragId() << endl;
100 p->setParagLayout( *lit );
101 }
102 else
103 break;
104 //if ( s == cr->parag() )
105 // break;
106 p = p->next();
107 ++lit;
108 }
109 return cr;
110}
111
112KoTextParagCommand::KoTextParagCommand( KoTextDocument *d, int fParag, int lParag,
113 const TQValueList<KoParagLayout> &oldParagLayouts,
114 KoParagLayout newParagLayout,
115 int flags,
116 TQStyleSheetItem::Margin margin )
117 : KoTextDocCommand( d ), firstParag( fParag ), lastParag( lParag ), m_oldParagLayouts( oldParagLayouts ),
118 m_newParagLayout( newParagLayout ), m_flags( flags ), m_margin( margin )
119{
120 Q_ASSERT( fParag >= 0 );
121 Q_ASSERT( lParag >= 0 );
122}
123
124KoTextCursor * KoTextParagCommand::execute( KoTextCursor *c )
125{
126 //kdDebug(32500) << "KoTextParagCommand::execute" << endl;
127 KoTextParag *p = doc->paragAt( firstParag );
128 if ( !p )
129 {
130 kdWarning() << "KoTextParagCommand::execute paragraph " << firstParag << "not found" << endl;
131 return c;
132 }
133 while ( p ) {
134 if ( ( m_flags & KoParagLayout::Margins ) && m_margin != (TQStyleSheetItem::Margin)-1 ) // all
135 p->setMargin( static_cast<TQStyleSheetItem::Margin>(m_margin), m_newParagLayout.margins[m_margin] );
136 else
137 {
138 p->setParagLayout( m_newParagLayout, m_flags );
139 }
140 if ( p->paragId() == lastParag )
141 break;
142 p = p->next();
143 }
144 //kdDebug(32500) << "KoTextParagCommand::execute done" << endl;
145 // Set cursor to end of selection. Like in KoTextFormatCommand::[un]execute...
146 c->setParag( p );
147 c->setIndex( p->length()-1 );
148 return c;
149}
150
151KoTextCursor * KoTextParagCommand::unexecute( KoTextCursor *c )
152{
153 kdDebug(32500) << "KoTextParagCommand::unexecute" << endl;
154 KoTextParag *p = doc->paragAt( firstParag );
155 if ( !p )
156 {
157 kdDebug(32500) << "KoTextParagCommand::unexecute paragraph " << firstParag << "not found" << endl;
158 return c;
159 }
160 TQValueList<KoParagLayout>::Iterator lit = m_oldParagLayouts.begin();
161 while ( p ) {
162 if ( lit == m_oldParagLayouts.end() )
163 {
164 kdDebug(32500) << "KoTextParagCommand::unexecute m_oldParagLayouts not big enough!" << endl;
165 break;
166 }
167 if ( m_flags & KoParagLayout::Margins && m_margin != (TQStyleSheetItem::Margin)-1 ) // just one
168 p->setMargin( static_cast<TQStyleSheetItem::Margin>(m_margin), (*lit).margins[m_margin] );
169 else
170 {
171 p->setParagLayout( *lit, m_flags );
172 }
173 if ( p->paragId() == lastParag )
174 break;
175 p = p->next();
176 ++lit;
177 }
178 // Set cursor to end of selection. Like in KoTextFormatCommand::[un]execute...
179 c->setParag( p );
180 c->setIndex( p->length()-1 );
181 return c;
182}
183
185
186KoParagFormatCommand::KoParagFormatCommand( KoTextDocument *d, int fParag, int lParag,
187 const TQValueList<KoTextFormat *> &oldFormats,
188 KoTextFormat * newFormat )
189 : KoTextDocCommand( d ), firstParag( fParag ), lastParag( lParag ), m_oldFormats( oldFormats ),
190 m_newFormat( newFormat )
191{
192 TQValueList<KoTextFormat *>::Iterator lit = m_oldFormats.begin();
193 for ( ; lit != m_oldFormats.end() ; ++lit )
194 (*lit)->addRef();
195}
196
197KoParagFormatCommand::~KoParagFormatCommand()
198{
199 TQValueList<KoTextFormat *>::Iterator lit = m_oldFormats.begin();
200 for ( ; lit != m_oldFormats.end() ; ++lit )
201 (*lit)->removeRef();
202}
203
204KoTextCursor * KoParagFormatCommand::execute( KoTextCursor *c )
205{
206 KoTextParag *p = doc->paragAt( firstParag );
207 if ( !p )
208 {
209 kdDebug(32500) << "KoTextParagCommand::execute paragraph " << firstParag << "not found" << endl;
210 return c;
211 }
212 while ( p ) {
213 p->setFormat( m_newFormat );
214 p->invalidate(0);
215 if ( p->paragId() == lastParag )
216 break;
217 p = p->next();
218 }
219 return c;
220}
221
222KoTextCursor * KoParagFormatCommand::unexecute( KoTextCursor *c )
223{
224 kdDebug(32500) << "KoParagFormatCommand::unexecute" << endl;
225 KoTextParag *p = doc->paragAt( firstParag );
226 if ( !p )
227 {
228 kdDebug(32500) << "KoParagFormatCommand::unexecute paragraph " << firstParag << "not found" << endl;
229 return c;
230 }
231 TQValueList<KoTextFormat *>::Iterator lit = m_oldFormats.begin();
232 while ( p ) {
233 if ( lit == m_oldFormats.end() )
234 {
235 kdDebug(32500) << "KoParagFormatCommand::unexecute m_oldFormats not big enough!" << endl;
236 break;
237 }
238 p->setFormat( (*lit) );
239 if ( p->paragId() == lastParag )
240 break;
241 p = p->next();
242 ++lit;
243 }
244 return c;
245}
246
247KoTextFormatCommand::KoTextFormatCommand(KoTextDocument *d, int sid, int sidx, int eid, int eidx, const TQMemArray<KoTextStringChar> &old, const KoTextFormat *f, int fl )
248 : KoTextDocFormatCommand(d, sid, sidx, eid, eidx, old, f, fl)
249{
250}
251
252
253KoTextFormatCommand::~KoTextFormatCommand()
254{
255}
256
257void KoTextFormatCommand::resizeCustomItems()
258{
259 KoTextParag *sp = doc->paragAt( startId );
260 KoTextParag *ep = doc->paragAt( endId );
261 if ( !sp || !ep )
262 return;
263
264 KoTextCursor start( doc );
265 start.setParag( sp );
266 start.setIndex( startIndex );
267 KoTextCursor end( doc );
268 end.setParag( ep );
269 end.setIndex( endIndex );
270
271 doc->setSelectionStart( KoTextDocument::Temp, &start );
272 doc->setSelectionEnd( KoTextDocument::Temp, &end );
273
274 // TODO use the visitor pattern (some 'ResizeCustomItemVisitor')
275
276 if ( start.parag() == end.parag() )
277 {
278 TQString text = start.parag()->string()->toString().mid( start.index(), end.index() - start.index() );
279 for ( int i = start.index(); i < end.index(); ++i )
280 {
281 if( start.parag()->at(i)->isCustom())
282 {
283 start.parag()->at(i)->customItem()->resize();
284 }
285 }
286 }
287 else
288 {
289 int i;
290 TQString text = start.parag()->string()->toString().mid( start.index(), start.parag()->length() - 1 - start.index() );
291 for ( i = start.index(); i < start.parag()->length(); ++i )
292 if( start.parag()->at(i)->isCustom())
293 {
294 start.parag()->at(i)->customItem()->resize();
295 }
296
297 KoTextParag *p = start.parag()->next();
298 while ( p && p != end.parag() )
299 {
300 text = p->string()->toString().left( p->length() - 1 );
301 for ( i = 0; i < p->length(); ++i )
302 {
303 if( p->at(i)->isCustom())
304 {
305 p->at(i)->customItem()->resize();
306 }
307 }
308 p = p->next();
309 }
310 text = end.parag()->string()->toString().left( end.index() );
311 for ( i = 0; i < end.index(); ++i )
312 {
313 if( end.parag()->at(i)->isCustom())
314 {
315 end.parag()->at(i)->customItem()->resize();
316 }
317 }
318 }
319}
320
321KoTextCursor *KoTextFormatCommand::execute( KoTextCursor *c )
322{
323 c = KoTextDocFormatCommand::execute( c );
324 resizeCustomItems();
325 return c;
326}
327
328KoTextCursor *KoTextFormatCommand::unexecute( KoTextCursor *c )
329{
330 kdDebug(32500) << "KoTextFormatCommand::unexecute c:" << c << " index:" << c->index() << endl;
331 c = KoTextDocFormatCommand::unexecute( c );
332 kdDebug(32500) << "KoTextFormatCommand::unexecute after KoTextFormatCommand c:" << c << " index:" << c->index() << endl;
333 resizeCustomItems();
334 return c;
335}
336
338
339KoChangeVariableSubType::KoChangeVariableSubType(
340 short int _oldValue, short int _newValue,
341 KoVariable *var):
342 KCommand(),
343 m_newValue(_newValue),
344 m_oldValue(_oldValue),
345 m_var(var)
346{
347}
348
350{
351 Q_ASSERT(m_var);
352 m_var->setVariableSubType(m_newValue);
353 m_var->recalcAndRepaint();
354}
355
357{
358 Q_ASSERT(m_var);
359 m_var->setVariableSubType(m_oldValue);
360 m_var->recalcAndRepaint();
361}
362
363TQString KoChangeVariableSubType::name() const
364{
365 return i18n( "Change Variable Subtype" );
366}
367
369
370KoChangeVariableFormatProperties::KoChangeVariableFormatProperties(
371 const TQString &_oldValue, const TQString &_newValue,
372 KoVariable *var)
373 : KCommand(),
374 m_newValue(_newValue),
375 m_oldValue(_oldValue),
376 m_var(var)
377{
378}
379
381{
382 Q_ASSERT(m_var);
383 // Wrong! m_var->variableFormat()->setFormatProperties( m_newValue );
384 KoVariableFormatCollection* coll = m_var->variableColl()->formatCollection();
385 m_var->setVariableFormat( coll->format( m_var->variableFormat()->getKey( m_newValue ) ) );
386 m_var->recalcAndRepaint();
387}
388
390{
391 Q_ASSERT(m_var);
392 // Wrong! m_var->variableFormat()->setFormatProperties( m_oldValue );
393 KoVariableFormatCollection* coll = m_var->variableColl()->formatCollection();
394 m_var->setVariableFormat( coll->format( m_var->variableFormat()->getKey( m_oldValue ) ) );
395 m_var->recalcAndRepaint();
396}
397
399{
400 return i18n( "Change Variable Format" );
401}
A CustomItemsMap associates a custom item to an index Used in the undo/redo info for insert/delete te...
virtual TQString name() const=0
virtual void unexecute()=0
virtual void execute()=0
This class holds the paragraph-specific formatting information It's separated from KoTextParag so tha...
Each character (KoTextStringChar) points to a KoTextFormat that defines the formatting of that charac...
KoVariableFormat * format(const TQCString &key)
Find or create the format for the given key.
A KoVariable is a custom item, i.e.
Definition KoVariable.h:364