00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "koparaglayout.h"
00021 #include "korichtext.h"
00022 #include "koparagcounter.h"
00023 #include "kostyle.h"
00024 #include <qdom.h>
00025 #include <kglobal.h>
00026 #include <klocale.h>
00027 #include <kdebug.h>
00028
00029 QString* KoParagLayout::shadowCssCompat = 0L;
00030
00031
00032 KoParagLayout::KoParagLayout()
00033 {
00034 initialise();
00035 }
00036
00037 void KoParagLayout::operator=( const KoParagLayout &layout )
00038 {
00039 alignment = layout.alignment;
00040 for ( int i = 0 ; i < 5 ; ++i )
00041 margins[i] = layout.margins[i];
00042 pageBreaking = layout.pageBreaking;
00043 leftBorder = layout.leftBorder;
00044 rightBorder = layout.rightBorder;
00045 topBorder = layout.topBorder;
00046 bottomBorder = layout.bottomBorder;
00047 if ( layout.counter )
00048 counter = new KoParagCounter( *layout.counter );
00049 else
00050 counter = 0L;
00051 lineSpacing = layout.lineSpacing;
00052 lineSpacingType = layout.lineSpacingType;
00053 style = layout.style;
00054 direction = layout.direction;
00055 setTabList( layout.tabList() );
00056 }
00057
00058 int KoParagLayout::compare( const KoParagLayout & layout ) const
00059 {
00060 int flags = 0;
00061 if ( alignment != layout.alignment )
00062 flags |= Alignment;
00063 for ( int i = 0 ; i < 5 ; ++i )
00064 if ( margins[i] != layout.margins[i] )
00065 {
00066 flags |= Margins;
00067 break;
00068 }
00069 if ( pageBreaking != layout.pageBreaking )
00070 flags |= PageBreaking;
00071 if ( leftBorder != layout.leftBorder
00072 || rightBorder != layout.rightBorder
00073 || topBorder != layout.topBorder
00074 || bottomBorder != layout.bottomBorder )
00075 flags |= Borders;
00076
00077 if ( layout.counter )
00078 {
00079 if ( counter )
00080 {
00081 if ( ! ( *layout.counter == *counter ) )
00082 flags |= BulletNumber;
00083 } else
00084 if ( layout.counter->numbering() != KoParagCounter::NUM_NONE )
00085 flags |= BulletNumber;
00086 }
00087 else
00088 if ( counter && counter->numbering() != KoParagCounter::NUM_NONE )
00089 flags |= BulletNumber;
00090
00091 if ( lineSpacing != layout.lineSpacing
00092 || lineSpacingType != layout.lineSpacingType )
00093 flags |= LineSpacing;
00094
00095
00096 if ( m_tabList != layout.m_tabList )
00097 flags |= Tabulator;
00098
00099
00100
00101 return flags;
00102 }
00103
00104 void KoParagLayout::initialise()
00105 {
00106 alignment = Qt::AlignAuto;
00107 for ( int i = 0 ; i < 5 ; ++i )
00108 margins[i] = 0;
00109 lineSpacingType = LS_SINGLE;
00110 lineSpacing = 0;
00111 counter = 0L;
00112 leftBorder.setPenWidth( 0);
00113 rightBorder.setPenWidth( 0);
00114 topBorder.setPenWidth( 0);
00115 bottomBorder.setPenWidth( 0);
00116 pageBreaking = 0;
00117 style = 0L;
00118 direction = QChar::DirON;
00119 m_tabList.clear();
00120 }
00121
00122 KoParagLayout::~KoParagLayout()
00123 {
00124 delete counter;
00125 }
00126
00127 void KoParagLayout::loadParagLayout( KoParagLayout& layout, const QDomElement& parentElem, int docVersion )
00128 {
00129
00130
00131
00132
00133
00134
00135
00136
00137 KoTabulatorList tabList;
00138 QDomElement element = parentElem.firstChild().toElement();
00139 for ( ; !element.isNull() ; element = element.nextSibling().toElement() )
00140 {
00141 if ( element.tagName() == "TABULATOR" )
00142 {
00143 KoTabulator tab;
00144 tab.type = static_cast<KoTabulators>( KoStyle::getAttribute( element, "type", T_LEFT ) );
00145 tab.ptPos = KoStyle::getAttribute( element, "ptpos", 0.0 );
00146 tab.filling = static_cast<KoTabulatorFilling>( KoStyle::getAttribute( element, "filling", TF_BLANK ) );
00147 tab.ptWidth = KoStyle::getAttribute( element, "width", 0.5 );
00148 QString alignCharStr = element.attribute("alignchar");
00149 if ( alignCharStr.isEmpty() )
00150 tab.alignChar = KGlobal::locale()->decimalSymbol()[0];
00151 else
00152 tab.alignChar = alignCharStr[0];
00153 tabList.append( tab );
00154 }
00155 }
00156 qHeapSort( tabList );
00157 layout.setTabList( tabList );
00158 layout.alignment = Qt::AlignAuto;
00159 element = parentElem.namedItem( "FLOW" ).toElement();
00160 if ( !element.isNull() )
00161 {
00162 QString flow = element.attribute( "align" );
00163 if ( !flow.isEmpty() )
00164 {
00165 layout.alignment = flow=="right" ? Qt::AlignRight :
00166 flow=="center" ? Qt::AlignHCenter :
00167 flow=="justify" ? Qt::AlignJustify :
00168 flow=="left" ? Qt::AlignLeft : Qt::AlignAuto;
00169
00170 QString dir = element.attribute( "dir" );
00171 if ( !dir.isEmpty() ) {
00172 if ( dir == "L" )
00173 layout.direction = QChar::DirL;
00174 else if ( dir == "R" )
00175 layout.direction = QChar::DirR;
00176 else
00177 kdWarning() << "Unexpected value for paragraph direction: " << dir << endl;
00178 }
00179 } else {
00180 flow = element.attribute( "value" );
00181 static const int flow2align[] = { Qt::AlignAuto, Qt::AlignRight, Qt::AlignHCenter, Qt::AlignJustify };
00182 if ( !flow.isEmpty() && flow.toInt() < 4 )
00183 layout.alignment = flow2align[flow.toInt()];
00184 }
00185 }
00186
00187 if ( docVersion < 2 )
00188 {
00189 element = parentElem.namedItem( "OHEAD" ).toElement();
00190 if ( !element.isNull() )
00191 layout.margins[QStyleSheetItem::MarginTop] = KoStyle::getAttribute( element, "pt", 0.0 );
00192
00193 element = parentElem.namedItem( "OFOOT" ).toElement();
00194 if ( !element.isNull() )
00195 layout.margins[QStyleSheetItem::MarginBottom] = KoStyle::getAttribute( element, "pt", 0.0 );
00196
00197 element = parentElem.namedItem( "IFIRST" ).toElement();
00198 if ( !element.isNull() )
00199 layout.margins[QStyleSheetItem::MarginFirstLine] = KoStyle::getAttribute( element, "pt", 0.0 );
00200
00201 element = parentElem.namedItem( "ILEFT" ).toElement();
00202 if ( !element.isNull() )
00203 layout.margins[QStyleSheetItem::MarginLeft] = KoStyle::getAttribute( element, "pt", 0.0 );
00204 }
00205
00206
00207 element = parentElem.namedItem( "INDENTS" ).toElement();
00208 if ( !element.isNull() )
00209 {
00210 layout.margins[QStyleSheetItem::MarginFirstLine] = KoStyle::getAttribute( element, "first", 0.0 );
00211 layout.margins[QStyleSheetItem::MarginLeft] = KoStyle::getAttribute( element, "left", 0.0 );
00212 layout.margins[QStyleSheetItem::MarginRight] = KoStyle::getAttribute( element, "right", 0.0 );
00213 }
00214 element = parentElem.namedItem( "OFFSETS" ).toElement();
00215 if ( !element.isNull() )
00216 {
00217 layout.margins[QStyleSheetItem::MarginTop] = KoStyle::getAttribute( element, "before", 0.0 );
00218 layout.margins[QStyleSheetItem::MarginBottom] = KoStyle::getAttribute( element, "after", 0.0 );
00219 }
00220
00221 if ( docVersion < 2 )
00222 {
00223 element = parentElem.namedItem( "LINESPACE" ).toElement();
00224 if ( !element.isNull() )
00225 {
00226 layout.lineSpacingType = KoParagLayout::LS_CUSTOM;
00227 layout.lineSpacing = KoStyle::getAttribute( element, "pt", 0.0 );
00228 }
00229 }
00230
00231 element = parentElem.namedItem( "LINESPACING" ).toElement();
00232 if ( !element.isNull() )
00233 {
00234
00235 if ( element.hasAttribute( "value" ))
00236 {
00237 QString value = element.attribute( "value" );
00238 if ( value == "oneandhalf" )
00239 {
00240 layout.lineSpacingType = KoParagLayout::LS_ONEANDHALF;
00241 layout.lineSpacing = 0;
00242 }
00243 else if ( value == "double" )
00244 {
00245 layout.lineSpacingType = KoParagLayout::LS_DOUBLE;
00246 layout.lineSpacing = 0;
00247 }
00248 else
00249 {
00250 layout.lineSpacingType = KoParagLayout::LS_CUSTOM;
00251 layout.lineSpacing = value.toDouble();
00252 }
00253 }
00254 else
00255 {
00256 QString type = element.attribute( "type" );
00257 if ( type == "oneandhalf" )
00258 {
00259 layout.lineSpacingType = KoParagLayout::LS_ONEANDHALF;
00260 layout.lineSpacing = 0;
00261 }
00262 else if ( type == "double" )
00263 {
00264 layout.lineSpacingType = KoParagLayout::LS_DOUBLE;
00265 layout.lineSpacing = 0;
00266 }
00267 else if ( type == "custom" )
00268 {
00269 layout.lineSpacingType = KoParagLayout::LS_CUSTOM;
00270 layout.lineSpacing = element.attribute( "spacingvalue" ).toDouble();
00271 }
00272 else if ( type == "atleast" )
00273 {
00274 layout.lineSpacingType = KoParagLayout::LS_AT_LEAST;
00275 layout.lineSpacing = element.attribute( "spacingvalue" ).toDouble();
00276 }
00277 else if ( type == "multiple" )
00278 {
00279 layout.lineSpacingType = KoParagLayout::LS_MULTIPLE;
00280 layout.lineSpacing = element.attribute( "spacingvalue" ).toDouble();
00281 }
00282 else if ( type == "fixed" )
00283 {
00284 layout.lineSpacingType = KoParagLayout::LS_FIXED;
00285 layout.lineSpacing = element.attribute( "spacingvalue" ).toDouble();
00286 }
00287 else if ( type == "single" )
00288 layout.lineSpacingType = KoParagLayout::LS_SINGLE;
00289 }
00290 }
00291
00292 int pageBreaking = 0;
00293 element = parentElem.namedItem( "PAGEBREAKING" ).toElement();
00294 if ( !element.isNull() )
00295 {
00296 if ( element.attribute( "linesTogether" ) == "true" )
00297 pageBreaking |= KoParagLayout::KeepLinesTogether;
00298 if ( element.attribute( "hardFrameBreak" ) == "true" )
00299 pageBreaking |= KoParagLayout::HardFrameBreakBefore;
00300 if ( element.attribute( "hardFrameBreakAfter" ) == "true" )
00301 pageBreaking |= KoParagLayout::HardFrameBreakAfter;
00302 }
00303 if ( docVersion < 2 )
00304 {
00305 element = parentElem.namedItem( "HARDBRK" ).toElement();
00306 if ( !element.isNull() )
00307 pageBreaking |= KoParagLayout::HardFrameBreakBefore;
00308 }
00309 layout.pageBreaking = pageBreaking;
00310
00311 element = parentElem.namedItem( "LEFTBORDER" ).toElement();
00312 if ( !element.isNull() )
00313 layout.leftBorder = KoBorder::loadBorder( element );
00314 else
00315 layout.leftBorder.setPenWidth(0);
00316
00317 element = parentElem.namedItem( "RIGHTBORDER" ).toElement();
00318 if ( !element.isNull() )
00319 layout.rightBorder = KoBorder::loadBorder( element );
00320 else
00321 layout.rightBorder.setPenWidth(0);
00322
00323 element = parentElem.namedItem( "TOPBORDER" ).toElement();
00324 if ( !element.isNull() )
00325 layout.topBorder = KoBorder::loadBorder( element );
00326 else
00327 layout.topBorder.setPenWidth(0);
00328
00329 element = parentElem.namedItem( "BOTTOMBORDER" ).toElement();
00330 if ( !element.isNull() )
00331 layout.bottomBorder = KoBorder::loadBorder( element );
00332 else
00333 layout.bottomBorder.setPenWidth(0);
00334
00335 element = parentElem.namedItem( "COUNTER" ).toElement();
00336 if ( !element.isNull() )
00337 {
00338 layout.counter = new KoParagCounter;
00339 layout.counter->load( element );
00340 }
00341
00342
00343 element = parentElem.namedItem( "SHADOW" ).toElement();
00344 if ( !element.isNull() && element.hasAttribute("direction") )
00345 {
00346 int shadowDistance = element.attribute("distance").toInt();
00347 int shadowDirection = element.attribute("direction").toInt();
00348 QColor shadowColor;
00349 if ( element.hasAttribute("red") )
00350 {
00351 int r = element.attribute("red").toInt();
00352 int g = element.attribute("green").toInt();
00353 int b = element.attribute("blue").toInt();
00354 shadowColor.setRgb( r, g, b );
00355 }
00356 int distanceX = 0;
00357 int distanceY = 0;
00358 switch ( shadowDirection )
00359 {
00360 case 1:
00361 case 2:
00362 case 3:
00363 distanceX = - shadowDistance;
00364 case 7:
00365 case 6:
00366 case 5:
00367 distanceX = shadowDistance;
00368 }
00369 switch ( shadowDirection )
00370 {
00371 case 7:
00372 case 8:
00373 case 1:
00374 distanceY = - shadowDistance;
00375 case 3:
00376 case 4:
00377 case 5:
00378 distanceY = shadowDistance;
00379 }
00380 if ( !shadowCssCompat )
00381 shadowCssCompat = new QString;
00382 *shadowCssCompat = KoTextFormat::shadowAsCss( distanceX, distanceY, shadowColor );
00383 kdDebug(32500) << "setting shadow compat to " << ( *shadowCssCompat ) << endl;
00384 }
00385 else
00386 {
00387 delete shadowCssCompat;
00388 shadowCssCompat = 0L;
00389 }
00390 }
00391
00392 void KoParagLayout::saveParagLayout( QDomElement & parentElem, int alignment ) const
00393 {
00394 const KoParagLayout& layout = *this;
00395 QDomDocument doc = parentElem.ownerDocument();
00396 QDomElement element = doc.createElement( "NAME" );
00397 parentElem.appendChild( element );
00398 if ( layout.style )
00399 element.setAttribute( "value", layout.style->name() );
00400
00401
00402
00403 element = doc.createElement( "FLOW" );
00404 parentElem.appendChild( element );
00405
00406 element.setAttribute( "align", alignment==Qt::AlignRight ? "right" :
00407 alignment==Qt::AlignHCenter ? "center" :
00408 alignment==Qt::AlignJustify ? "justify" :
00409 alignment==Qt::AlignAuto ? "auto" : "left" );
00410
00411 if ( static_cast<QChar::Direction>(layout.direction) == QChar::DirR )
00412 element.setAttribute( "dir", "R" );
00413 else
00414 if ( static_cast<QChar::Direction>(layout.direction) == QChar::DirL )
00415 element.setAttribute( "dir", "L" );
00416
00417 if ( layout.margins[QStyleSheetItem::MarginFirstLine] != 0 ||
00418 layout.margins[QStyleSheetItem::MarginLeft] != 0 ||
00419 layout.margins[QStyleSheetItem::MarginRight] != 0 )
00420 {
00421 element = doc.createElement( "INDENTS" );
00422 parentElem.appendChild( element );
00423 if ( layout.margins[QStyleSheetItem::MarginFirstLine] != 0 )
00424 element.setAttribute( "first", layout.margins[QStyleSheetItem::MarginFirstLine] );
00425 if ( layout.margins[QStyleSheetItem::MarginLeft] != 0 )
00426 element.setAttribute( "left", layout.margins[QStyleSheetItem::MarginLeft] );
00427 if ( layout.margins[QStyleSheetItem::MarginRight] != 0 )
00428 element.setAttribute( "right", layout.margins[QStyleSheetItem::MarginRight] );
00429 }
00430
00431 if ( layout.margins[QStyleSheetItem::MarginTop] != 0 ||
00432 layout.margins[QStyleSheetItem::MarginBottom] != 0 )
00433 {
00434 element = doc.createElement( "OFFSETS" );
00435 parentElem.appendChild( element );
00436 if ( layout.margins[QStyleSheetItem::MarginTop] != 0 )
00437 element.setAttribute( "before", layout.margins[QStyleSheetItem::MarginTop] );
00438 if ( layout.margins[QStyleSheetItem::MarginBottom] != 0 )
00439 element.setAttribute( "after", layout.margins[QStyleSheetItem::MarginBottom] );
00440 }
00441 if ( layout.lineSpacingType != LS_SINGLE )
00442 {
00443 element = doc.createElement( "LINESPACING" );
00444 parentElem.appendChild( element );
00445 if ( layout.lineSpacingType == KoParagLayout::LS_ONEANDHALF ) {
00446 element.setAttribute( "type", "oneandhalf" );
00447 element.setAttribute( "value", "oneandhalf" );
00448 }
00449 else if ( layout.lineSpacingType == KoParagLayout::LS_DOUBLE ) {
00450 element.setAttribute( "type", "double" );
00451 element.setAttribute( "value", "double" );
00452 }
00453 else if ( layout.lineSpacingType == KoParagLayout::LS_CUSTOM )
00454 {
00455 element.setAttribute( "type", "custom" );
00456 element.setAttribute( "spacingvalue", layout.lineSpacing);
00457 element.setAttribute( "value", layout.lineSpacing );
00458 }
00459 else if ( layout.lineSpacingType == KoParagLayout::LS_AT_LEAST )
00460 {
00461 element.setAttribute( "type", "atleast" );
00462 element.setAttribute( "spacingvalue", layout.lineSpacing);
00463 }
00464 else if ( layout.lineSpacingType == KoParagLayout::LS_MULTIPLE )
00465 {
00466 element.setAttribute( "type", "multiple" );
00467 element.setAttribute( "spacingvalue", layout.lineSpacing);
00468 }
00469 else if ( layout.lineSpacingType == KoParagLayout::LS_FIXED )
00470 {
00471 element.setAttribute( "type", "fixed" );
00472 element.setAttribute( "spacingvalue", layout.lineSpacing);
00473 }
00474 else
00475 kdDebug()<<" error in lineSpacing Type\n";
00476 }
00477
00478 if ( layout.pageBreaking != 0 )
00479 {
00480 element = doc.createElement( "PAGEBREAKING" );
00481 parentElem.appendChild( element );
00482 if ( layout.pageBreaking & KoParagLayout::KeepLinesTogether )
00483 element.setAttribute( "linesTogether", "true" );
00484 if ( layout.pageBreaking & KoParagLayout::HardFrameBreakBefore )
00485 element.setAttribute( "hardFrameBreak", "true" );
00486 if ( layout.pageBreaking & KoParagLayout::HardFrameBreakAfter )
00487 element.setAttribute( "hardFrameBreakAfter", "true" );
00488 }
00489
00490 if ( layout.leftBorder.penWidth() > 0 )
00491 {
00492 element = doc.createElement( "LEFTBORDER" );
00493 parentElem.appendChild( element );
00494 layout.leftBorder.save( element );
00495 }
00496 if ( layout.rightBorder.penWidth() > 0 )
00497 {
00498 element = doc.createElement( "RIGHTBORDER" );
00499 parentElem.appendChild( element );
00500 layout.rightBorder.save( element );
00501 }
00502 if ( layout.topBorder.penWidth() > 0 )
00503 {
00504 element = doc.createElement( "TOPBORDER" );
00505 parentElem.appendChild( element );
00506 layout.topBorder.save( element );
00507 }
00508 if ( layout.bottomBorder.penWidth() > 0 )
00509 {
00510 element = doc.createElement( "BOTTOMBORDER" );
00511 parentElem.appendChild( element );
00512 layout.bottomBorder.save( element );
00513 }
00514 if ( layout.counter && layout.counter->numbering() != KoParagCounter::NUM_NONE )
00515 {
00516 element = doc.createElement( "COUNTER" );
00517 parentElem.appendChild( element );
00518 if ( layout.counter )
00519 layout.counter->save( element );
00520 }
00521
00522 KoTabulatorList tabList = layout.tabList();
00523 KoTabulatorList::ConstIterator it = tabList.begin();
00524 for ( ; it != tabList.end() ; it++ )
00525 {
00526 element = doc.createElement( "TABULATOR" );
00527 parentElem.appendChild( element );
00528 element.setAttribute( "type", (*it).type );
00529 element.setAttribute( "ptpos", (*it).ptPos );
00530 element.setAttribute( "filling", (*it).filling );
00531 element.setAttribute( "width", (*it).ptWidth );
00532 if ( !(*it).alignChar.isNull() )
00533 element.setAttribute( "alignchar", QString((*it).alignChar) );
00534 }
00535 }