lib Library API Documentation

koparaglayout.cc

00001 /* This file is part of the KDE project 00002 Copyright (C) 2001 David Faure <faure@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00017 Boston, MA 02111-1307, USA. 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 // Create a default KoParagLayout. 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 //if ( style != layout.style ) 00095 // flags |= Style; 00096 if ( m_tabList != layout.m_tabList ) 00097 flags |= Tabulator; 00098 00099 // This method is used for the GUI stuff only, so we don't have a flag 00100 // for the Direction value. 00101 return flags; 00102 } 00103 00104 void KoParagLayout::initialise() 00105 { 00106 alignment = Qt::AlignAuto; 00107 for ( int i = 0 ; i < 5 ; ++i ) // use memset ? 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 // layout is an input and output parameter 00130 // It can have been initialized already, e.g. by copying from a style 00131 // (we don't do that anymore though). 00132 00133 // Load the paragraph tabs - we load into a clean list, not mixing with those already in "layout" 00134 // We can't apply the 'default comes from the style' in this case, because 00135 // there is no way to differentiate between "I want no tabs in the parag" 00136 // and "use default from style". 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(); // Flow is what is now called alignment internally 00160 if ( !element.isNull() ) 00161 { 00162 QString flow = element.attribute( "align" ); // KWord-1.0 DTD 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" ); // KWord-1.2 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" ); // KWord-0.8 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(); // used by KWord-0.8 00190 if ( !element.isNull() ) 00191 layout.margins[QStyleSheetItem::MarginTop] = KoStyle::getAttribute( element, "pt", 0.0 ); 00192 00193 element = parentElem.namedItem( "OFOOT" ).toElement(); // used by KWord-0.8 00194 if ( !element.isNull() ) 00195 layout.margins[QStyleSheetItem::MarginBottom] = KoStyle::getAttribute( element, "pt", 0.0 ); 00196 00197 element = parentElem.namedItem( "IFIRST" ).toElement(); // used by KWord-0.8 00198 if ( !element.isNull() ) 00199 layout.margins[QStyleSheetItem::MarginFirstLine] = KoStyle::getAttribute( element, "pt", 0.0 ); 00200 00201 element = parentElem.namedItem( "ILEFT" ).toElement(); // used by KWord-0.8 00202 if ( !element.isNull() ) 00203 layout.margins[QStyleSheetItem::MarginLeft] = KoStyle::getAttribute( element, "pt", 0.0 ); 00204 } 00205 00206 // KWord-1.0 DTD 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(); // used by KWord-0.8 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(); // KWord-1.0 DTD 00232 if ( !element.isNull() ) 00233 { 00234 //compatibility with koffice 1.1 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" ) // not used; just in case future versions use it. 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(); // KWord-0.8 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 // Compatibility with KOffice-1.2 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: // KoParagLayout::SD_LEFT_UP: 00361 case 2: // KoParagLayout::SD_UP: 00362 case 3: // KoParagLayout::SD_RIGHT_UP: 00363 distanceX = - shadowDistance; 00364 case 7: // KoParagLayout::SD_LEFT_BOTTOM: 00365 case 6: // KoParagLayout::SD_BOTTOM: 00366 case 5: // KoParagLayout::SD_RIGHT_BOTTOM: 00367 distanceX = shadowDistance; 00368 } 00369 switch ( shadowDirection ) 00370 { 00371 case 7: // KoParagLayout::SD_LEFT_BOTTOM: 00372 case 8: // KoParagLayout::SD_LEFT: 00373 case 1: //KoParagLayout::SD_LEFT_UP: 00374 distanceY = - shadowDistance; 00375 case 3: // KoParagLayout::SD_RIGHT_UP: 00376 case 4: // KoParagLayout::SD_RIGHT: 00377 case 5: // KoParagLayout::SD_RIGHT_BOTTOM: 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; // code moved from somewhere else;) 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 //else 00401 // kdWarning() << "KoParagLayout::saveParagLayout: style==0L!" << endl; 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" ); // Note: styles can have AlignAuto. Not paragraphs. 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" ); //compatibility with koffice 1.2 00448 } 00449 else if ( layout.lineSpacingType == KoParagLayout::LS_DOUBLE ) { 00450 element.setAttribute( "type", "double" ); 00451 element.setAttribute( "value", "double" ); //compatibility with koffice 1.2 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 ); //compatibility with koffice 1.2 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 }
KDE Logo
This file is part of the documentation for lib Library Version 1.3.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Sep 24 18:22:25 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003