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 }