kate Library API Documentation

kateprinter.cpp

00001 /* 00002 * This file is part of the KDE libraries 00003 * Copyright (c) 2001-2002 Michael Goffioul <kdeprint@swing.be> 00004 * Complete rewrite on Sat Jun 15 2002 (c) Anders Lund <anders@alweb.dk> 00005 * Copyright (c) 2002, 2003 Anders Lund <anders@alweb.dk> 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Library General Public 00009 * License version 2 as published by the Free Software Foundation. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Library General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Library General Public License 00017 * along with this library; see the file COPYING.LIB. If not, write to 00018 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00019 * Boston, MA 02111-1307, USA. 00020 **/ 00021 00022 #include "kateprinter.h" 00023 00024 #include <kateconfig.h> 00025 #include <katedocument.h> 00026 #include <katefactory.h> 00027 #include <katehighlight.h> 00028 #include <katelinerange.h> 00029 #include <katerenderer.h> 00030 #include <kateschema.h> 00031 #include <katetextline.h> 00032 00033 #include <kapplication.h> 00034 #include <kcolorbutton.h> 00035 #include <kdebug.h> 00036 #include <kdialog.h> // for spacingHint() 00037 #include <kfontdialog.h> 00038 #include <klocale.h> 00039 #include <kprinter.h> 00040 #include <kurl.h> 00041 #include <kuser.h> // for loginName 00042 00043 #include <qpainter.h> 00044 #include <qpopupmenu.h> 00045 #include <qpaintdevicemetrics.h> 00046 #include <qcheckbox.h> 00047 #include <qcombobox.h> 00048 #include <qgroupbox.h> 00049 #include <qhbox.h> 00050 #include <qlabel.h> 00051 #include <qlayout.h> 00052 #include <qlineedit.h> 00053 #include <qspinbox.h> 00054 #include <qstringlist.h> 00055 #include <qwhatsthis.h> 00056 00057 //BEGIN KatePrinter 00058 bool KatePrinter::print (KateDocument *doc) 00059 { 00060 #ifndef Q_WS_WIN //TODO: reenable 00061 KPrinter printer; 00062 00063 // docname is now always there, including the right Untitled name 00064 printer.setDocName(doc->docName()); 00065 00066 KatePrintTextSettings *kpts = new KatePrintTextSettings(&printer, NULL); 00067 kpts->enableSelection( doc->hasSelection() ); 00068 printer.addDialogPage( kpts ); 00069 printer.addDialogPage( new KatePrintHeaderFooter(&printer, NULL) ); 00070 printer.addDialogPage( new KatePrintLayout(&printer, NULL) ); 00071 00072 if ( printer.setup( kapp->mainWidget(), i18n("Print %1").arg(printer.docName()) ) ) 00073 { 00074 KateRenderer renderer(doc); 00075 //renderer.config()->setSchema (1); 00076 renderer.setPrinterFriendly(true); 00077 00078 QPainter paint( &printer ); 00079 QPaintDeviceMetrics pdm( &printer ); 00080 /* 00081 We work in tree cycles: 00082 1) initialize variables and retrieve print settings 00083 2) prepare data according to those settings 00084 3) draw to the printer 00085 */ 00086 uint pdmWidth = pdm.width(); 00087 uint y = 0; 00088 uint xstart = 0; // beginning point for painting lines 00089 uint lineCount = 0; 00090 uint maxWidth = pdmWidth; 00091 uint headerWidth = pdmWidth; 00092 int startCol = 0; 00093 int endCol = 0; 00094 bool needWrap = true; 00095 bool pageStarted = true; 00096 00097 // Text Settings Page 00098 bool selectionOnly = ( doc->hasSelection() && 00099 ( printer.option("app-kate-printselection") == "true" ) ); 00100 int selStartCol = 0; 00101 int selEndCol = 0; 00102 00103 bool useGuide = ( printer.option("app-kate-printguide") == "true" ); 00104 int guideHeight = 0; 00105 int guideCols = 0; 00106 00107 bool printLineNumbers = ( printer.option("app-kate-printlinenumbers") == "true" ); 00108 uint lineNumberWidth( 0 ); 00109 00110 // Header/Footer Page 00111 QFont headerFont; // used for header/footer 00112 QString f = printer.option("app-kate-hffont"); 00113 if (!f.isEmpty()) 00114 headerFont.fromString( f ); 00115 00116 bool useHeader = (printer.option("app-kate-useheader") == "true"); 00117 QColor headerBgColor(printer.option("app-kate-headerbg")); 00118 QColor headerFgColor(printer.option("app-kate-headerfg")); 00119 uint headerHeight( 0 ); // further init only if needed 00120 QStringList headerTagList; // do 00121 bool headerDrawBg = false; // do 00122 00123 bool useFooter = (printer.option("app-kate-usefooter") == "true"); 00124 QColor footerBgColor(printer.option("app-kate-footerbg")); 00125 QColor footerFgColor(printer.option("app-kate-footerfg")); 00126 uint footerHeight( 0 ); // further init only if needed 00127 QStringList footerTagList = 0; // do 00128 bool footerDrawBg = 0; // do 00129 00130 // Layout Page 00131 renderer.config()->setSchema( KateFactory::self()->schemaManager()->number( 00132 printer.option("app-kate-colorscheme") ) ); 00133 bool useBackground = ( printer.option("app-kate-usebackground") == "true" ); 00134 bool useBox = (printer.option("app-kate-usebox") == "true"); 00135 int boxWidth(printer.option("app-kate-boxwidth").toInt()); 00136 QColor boxColor(printer.option("app-kate-boxcolor")); 00137 int innerMargin = useBox ? printer.option("app-kate-boxmargin").toInt() : 6; 00138 00139 // Post initialization 00140 uint maxHeight = (useBox ? pdm.height()-innerMargin : pdm.height()); 00141 uint currentPage( 1 ); 00142 uint lastline = doc->lastLine(); // nessecary to print selection only 00143 uint firstline( 0 ); 00144 00145 KateHlItemDataList ilist; 00146 00147 if (useGuide) 00148 doc->highlight()->getKateHlItemDataListCopy (renderer.config()->schema(), ilist); 00149 00150 /* 00151 Now on for preparations... 00152 during preparations, variable names starting with a "_" means 00153 those variables are local to the enclosing block. 00154 */ 00155 { 00156 if ( selectionOnly ) 00157 { 00158 // set a line range from the first selected line to the last 00159 firstline = doc->selStartLine(); 00160 selStartCol = doc->selStartCol(); 00161 lastline = doc->selEndLine(); 00162 selEndCol = doc->selEndCol(); 00163 00164 lineCount = firstline; 00165 } 00166 00167 if ( printLineNumbers ) 00168 { 00169 // figure out the horiizontal space required 00170 QString s( QString("%1 ").arg( doc->numLines() ) ); 00171 s.fill('5', -1); // some non-fixed fonts haven't equally wide numbers 00172 // FIXME calculate which is actually the widest... 00173 lineNumberWidth = renderer.currentFontMetrics()->width( s ); 00174 // a small space between the line numbers and the text 00175 int _adj = renderer.currentFontMetrics()->width( "5" ); 00176 // adjust available width and set horizontal start point for data 00177 maxWidth -= (lineNumberWidth + _adj); 00178 xstart += lineNumberWidth + _adj; 00179 } 00180 00181 if ( useHeader || useFooter ) 00182 { 00183 // Set up a tag map 00184 // This retrieves all tags, ued or not, but 00185 // none of theese operations should be expensive, 00186 // and searcing each tag in the format strings is avoided. 00187 QDateTime dt = QDateTime::currentDateTime(); 00188 QMap<QString,QString> tags; 00189 00190 KUser u (KUser::UseRealUserID); 00191 tags["u"] = u.loginName(); 00192 00193 tags["d"] = KGlobal::locale()->formatDateTime(dt, true, false); 00194 tags["D"] = KGlobal::locale()->formatDateTime(dt, false, false); 00195 tags["h"] = KGlobal::locale()->formatTime(dt.time(), false); 00196 tags["y"] = KGlobal::locale()->formatDate(dt.date(), true); 00197 tags["Y"] = KGlobal::locale()->formatDate(dt.date(), false); 00198 tags["f"] = doc->url().fileName(); 00199 tags["U"] = doc->url().prettyURL(); 00200 if ( selectionOnly ) 00201 { 00202 QString s( i18n("(Selection of) ") ); 00203 tags["f"].prepend( s ); 00204 tags["U"].prepend( s ); 00205 } 00206 00207 QRegExp reTags( "%([dDfUhuyY])" ); // TODO tjeck for "%%<TAG>" 00208 00209 if (useHeader) 00210 { 00211 headerDrawBg = ( printer.option("app-kate-headerusebg") == "true" ); 00212 headerHeight = QFontMetrics( headerFont ).height(); 00213 if ( useBox || headerDrawBg ) 00214 headerHeight += innerMargin * 2; 00215 else 00216 headerHeight += 1 + QFontMetrics( headerFont ).leading(); 00217 00218 QString headerTags = printer.option("app-kate-headerformat"); 00219 int pos = reTags.search( headerTags ); 00220 QString rep; 00221 while ( pos > -1 ) 00222 { 00223 rep = tags[reTags.cap( 1 )]; 00224 headerTags.replace( (uint)pos, 2, rep ); 00225 pos += rep.length(); 00226 pos = reTags.search( headerTags, pos ); 00227 } 00228 headerTagList = QStringList::split('|', headerTags, true); 00229 00230 if (!headerBgColor.isValid()) 00231 headerBgColor = Qt::lightGray; 00232 if (!headerFgColor.isValid()) 00233 headerFgColor = Qt::black; 00234 } 00235 00236 if (useFooter) 00237 { 00238 footerDrawBg = ( printer.option("app-kate-footerusebg") == "true" ); 00239 footerHeight = QFontMetrics( headerFont ).height(); 00240 if ( useBox || footerDrawBg ) 00241 footerHeight += 2*innerMargin; 00242 else 00243 footerHeight += 1; // line only 00244 00245 QString footerTags = printer.option("app-kate-footerformat"); 00246 int pos = reTags.search( footerTags ); 00247 QString rep; 00248 while ( pos > -1 ) 00249 { 00250 rep = tags[reTags.cap( 1 )]; 00251 footerTags.replace( (uint)pos, 2, rep ); 00252 pos += rep.length(); 00253 pos = reTags.search( footerTags, pos ); 00254 } 00255 00256 footerTagList = QStringList::split('|', footerTags, true); 00257 if (!footerBgColor.isValid()) 00258 footerBgColor = Qt::lightGray; 00259 if (!footerFgColor.isValid()) 00260 footerFgColor = Qt::black; 00261 // adjust maxheight, so we can know when/where to print footer 00262 maxHeight -= footerHeight; 00263 } 00264 } // if ( useHeader || useFooter ) 00265 00266 if ( useBackground ) 00267 { 00268 if ( ! useBox ) 00269 { 00270 xstart += innerMargin; 00271 maxWidth -= innerMargin * 2; 00272 } 00273 } 00274 00275 if ( useBox ) 00276 { 00277 if (!boxColor.isValid()) 00278 boxColor = Qt::black; 00279 if (boxWidth < 1) // shouldn't be pssible no more! 00280 boxWidth = 1; 00281 // set maxwidth to something sensible 00282 maxWidth -= ( ( boxWidth + innerMargin ) * 2 ); 00283 xstart += boxWidth + innerMargin; 00284 // maxheight too.. 00285 maxHeight -= boxWidth; 00286 } 00287 else 00288 boxWidth = 0; 00289 00290 if ( useGuide ) 00291 { 00292 // calculate the height required 00293 // the number of columns is a side effect, saved for drawing time 00294 // first width is needed 00295 int _w = pdmWidth - innerMargin * 2; 00296 if ( useBox ) 00297 _w -= boxWidth * 2; 00298 else 00299 { 00300 if ( useBackground ) 00301 _w -= ( innerMargin * 2 ); 00302 _w -= 2; // 1 px line on each side 00303 } 00304 00305 // base of height: margins top/bottom, above and below tetle sep line 00306 guideHeight = ( innerMargin * 4 ) + 1; 00307 00308 // get a title and add the height required to draw it 00309 QString _title = i18n("Typographical Conventions for %1").arg(doc->highlight()->name()); 00310 guideHeight += paint.boundingRect( 0, 0, _w, 1000, Qt::AlignTop|Qt::AlignHCenter, _title ).height(); 00311 00312 // see how many columns we can fit in 00313 int _widest( 0 ); 00314 00315 QPtrListIterator<KateHlItemData> it( ilist ); 00316 KateHlItemData *_d; 00317 00318 int _items ( 0 ); 00319 while ( ( _d = it.current()) != 0 ) 00320 { 00321 _widest = QMAX( _widest, ((QFontMetrics)( 00322 _d->bold() ? 00323 _d->italic() ? 00324 renderer.config()->fontStruct()->myFontMetricsBI : 00325 renderer.config()->fontStruct()->myFontMetricsBold : 00326 _d->italic() ? 00327 renderer.config()->fontStruct()->myFontMetricsItalic : 00328 renderer.config()->fontStruct()->myFontMetrics 00329 ) ).width( _d->name ) ); 00330 _items++; 00331 ++it; 00332 } 00333 guideCols = _w/( _widest + innerMargin ); 00334 // add height for required number of lines needed given columns 00335 guideHeight += renderer.fontHeight() * ( _items/guideCols ); 00336 if ( _items%guideCols ) 00337 guideHeight += renderer.fontHeight(); 00338 } 00339 00340 // now that we know the vertical amount of space needed, 00341 // it is possible to calculate the total number of pages 00342 // if needed, that is if any header/footer tag contains "%P". 00343 if ( headerTagList.grep("%P").count() || footerTagList.grep("%P").count() ) 00344 { 00345 kdDebug(13020)<<"'%P' found! calculating number of pages..."<<endl; 00346 uint _pages = 0; 00347 uint _ph = maxHeight; 00348 if ( useHeader ) 00349 _ph -= ( headerHeight + innerMargin ); 00350 if ( useFooter ) 00351 _ph -= innerMargin; 00352 int _lpp = _ph / renderer.fontHeight(); 00353 uint _lt = 0, _c=0; 00354 00355 // add space for guide if required 00356 if ( useGuide ) 00357 _lt += (guideHeight + (renderer.fontHeight() /2)) / renderer.fontHeight(); 00358 long _lw; 00359 for ( uint i = firstline; i < lastline; i++ ) 00360 { 00361 _lw = renderer.textWidth( doc->kateTextLine( i ), -1 ); 00362 while ( _lw >= 0 ) 00363 { 00364 _c++; 00365 _lt++; 00366 if ( (int)_lt == _lpp ) 00367 { 00368 _pages++; 00369 _lt = 0; 00370 } 00371 _lw -= maxWidth; 00372 if ( ! _lw ) _lw--; // skip lines matching exactly! 00373 } 00374 } 00375 if ( _lt ) _pages++; // last page 00376 00377 // substitute both tag lists 00378 QString re("%P"); 00379 QStringList::Iterator it; 00380 for ( it=headerTagList.begin(); it!=headerTagList.end(); ++it ) 00381 (*it).replace( re, QString( "%1" ).arg( _pages ) ); 00382 for ( it=footerTagList.begin(); it!=footerTagList.end(); ++it ) 00383 (*it).replace( re, QString( "%1" ).arg( _pages ) ); 00384 } 00385 } // end prepare block 00386 00387 /* 00388 On to draw something :-) 00389 */ 00390 uint _count = 0; 00391 while ( lineCount <= lastline ) 00392 { 00393 startCol = 0; 00394 endCol = 0; 00395 needWrap = true; 00396 00397 while (needWrap) 00398 { 00399 if ( y + renderer.fontHeight() >= (uint)(maxHeight) ) 00400 { 00401 kdDebug(13020)<<"Starting new page, "<<_count<<" lines up to now."<<endl; 00402 printer.newPage(); 00403 currentPage++; 00404 pageStarted = true; 00405 y=0; 00406 } 00407 00408 if ( pageStarted ) 00409 { 00410 00411 if ( useHeader ) 00412 { 00413 paint.setPen(headerFgColor); 00414 paint.setFont(headerFont); 00415 if ( headerDrawBg ) 00416 paint.fillRect(0, 0, headerWidth, headerHeight, headerBgColor); 00417 if (headerTagList.count() == 3) 00418 { 00419 int valign = ( (useBox||headerDrawBg||useBackground) ? 00420 Qt::AlignVCenter : Qt::AlignTop ); 00421 int align = valign|Qt::AlignLeft; 00422 int marg = ( useBox || headerDrawBg ) ? innerMargin : 0; 00423 if ( useBox ) marg += boxWidth; 00424 QString s; 00425 for (int i=0; i<3; i++) 00426 { 00427 s = headerTagList[i]; 00428 if (s.find("%p") != -1) s.replace("%p", QString::number(currentPage)); 00429 paint.drawText(marg, 0, headerWidth-(marg*2), headerHeight, align, s); 00430 align = valign|(i == 0 ? Qt::AlignHCenter : Qt::AlignRight); 00431 } 00432 } 00433 if ( ! ( headerDrawBg || useBox || useBackground ) ) // draw a 1 px (!?) line to separate header from contents 00434 { 00435 paint.drawLine( 0, headerHeight-1, headerWidth, headerHeight-1 ); 00436 //y += 1; now included in headerHeight 00437 } 00438 y += headerHeight + innerMargin; 00439 } 00440 00441 if ( useFooter ) 00442 { 00443 if ( ! ( footerDrawBg || useBox || useBackground ) ) // draw a 1 px (!?) line to separate footer from contents 00444 paint.drawLine( 0, maxHeight + innerMargin - 1, headerWidth, maxHeight + innerMargin - 1 ); 00445 if ( footerDrawBg ) 00446 paint.fillRect(0, maxHeight+innerMargin+boxWidth, headerWidth, footerHeight, footerBgColor); 00447 if (footerTagList.count() == 3) 00448 { 00449 int align = Qt::AlignVCenter|Qt::AlignLeft; 00450 int marg = ( useBox || footerDrawBg ) ? innerMargin : 0; 00451 if ( useBox ) marg += boxWidth; 00452 QString s; 00453 for (int i=0; i<3; i++) 00454 { 00455 s = footerTagList[i]; 00456 if (s.find("%p") != -1) s.replace("%p", QString::number(currentPage)); 00457 paint.drawText(marg, maxHeight+innerMargin, headerWidth-(marg*2), footerHeight, align, s); 00458 align = Qt::AlignVCenter|(i == 0 ? Qt::AlignHCenter : Qt::AlignRight); 00459 } 00460 } 00461 } // done footer 00462 00463 if ( useBackground ) 00464 { 00465 // If we have a box, or the header/footer has backgrounds, we want to paint 00466 // to the border of those. Otherwise just the contents area. 00467 int _y = y, _h = maxHeight - y; 00468 if ( useBox ) 00469 { 00470 _y -= innerMargin; 00471 _h += 2 * innerMargin; 00472 } 00473 else 00474 { 00475 if ( headerDrawBg ) 00476 { 00477 _y -= innerMargin; 00478 _h += innerMargin; 00479 } 00480 if ( footerDrawBg ) 00481 { 00482 _h += innerMargin; 00483 } 00484 } 00485 paint.fillRect( 0, _y, pdmWidth, _h, renderer.config()->backgroundColor()); 00486 } 00487 00488 if ( useBox ) 00489 { 00490 paint.setPen(QPen(boxColor, boxWidth)); 00491 paint.drawRect(0, 0, pdmWidth, pdm.height()); 00492 if (useHeader) 00493 paint.drawLine(0, headerHeight, headerWidth, headerHeight); 00494 else 00495 y += innerMargin; 00496 00497 if ( useFooter ) // drawline is not trustable, grr. 00498 paint.fillRect( 0, maxHeight+innerMargin, headerWidth, boxWidth, boxColor ); 00499 } 00500 00501 if ( useGuide && currentPage == 1 ) 00502 { // FIXME - this may span more pages... 00503 // draw a box unless we have boxes, in which case we end with a box line 00504 00505 // use color of dsNormal for the title string and the hline 00506 KateAttributeList _dsList; 00507 KateHlManager::self()->getDefaults ( renderer.config()->schema(), _dsList ); 00508 paint.setPen( _dsList.at(0)->textColor() ); 00509 int _marg = 0; // this could be available globally!?? 00510 if ( useBox ) 00511 { 00512 _marg += (2*boxWidth) + (2*innerMargin); 00513 paint.fillRect( 0, y+guideHeight-innerMargin-boxWidth, headerWidth, boxWidth, boxColor ); 00514 } 00515 else 00516 { 00517 if ( useBackground ) 00518 _marg += 2*innerMargin; 00519 paint.drawRect( _marg, y, pdmWidth-(2*_marg), guideHeight ); 00520 _marg += 1; 00521 y += 1 + innerMargin; 00522 } 00523 // draw a title string 00524 paint.setFont( renderer.config()->fontStruct()->myFontBold ); 00525 QRect _r; 00526 paint.drawText( _marg, y, pdmWidth-(2*_marg), maxHeight - y, 00527 Qt::AlignTop|Qt::AlignHCenter, 00528 i18n("Typographical Conventions for %1").arg(doc->highlight()->name()), -1, &_r ); 00529 int _w = pdmWidth - (_marg*2) - (innerMargin*2); 00530 int _x = _marg + innerMargin; 00531 y += _r.height() + innerMargin; 00532 paint.drawLine( _x, y, _x + _w, y ); 00533 y += 1 + innerMargin; 00534 // draw attrib names using their styles 00535 00536 QPtrListIterator<KateHlItemData> _it( ilist ); 00537 KateHlItemData *_d; 00538 int _cw = _w/guideCols; 00539 int _i(0); 00540 00541 while ( ( _d = _it.current() ) != 0 ) 00542 { 00543 paint.setPen( renderer.attribute(_i)->textColor() ); 00544 paint.setFont( renderer.attribute(_i)->font( *renderer.currentFont() ) ); 00545 paint.drawText(( _x + ((_i%guideCols)*_cw)), y, _cw, renderer.fontHeight(), 00546 Qt::AlignVCenter|Qt::AlignLeft, _d->name, -1, &_r ); 00547 _i++; 00548 if ( _i && ! ( _i%guideCols ) ) y += renderer.fontHeight(); 00549 ++_it; 00550 } 00551 if ( _i%guideCols ) y += renderer.fontHeight();// last row not full 00552 y += ( useBox ? boxWidth : 1 ) + (innerMargin*2); 00553 } 00554 00555 pageStarted = false; 00556 } // pageStarted; move on to contents:) 00557 00558 if ( printLineNumbers && ! startCol ) // don't repeat! 00559 { 00560 paint.setFont( renderer.config()->fontStruct()->font( false, false ) ); 00561 paint.setPen( renderer.config()->lineNumberColor() ); 00562 paint.drawText( (( useBox || useBackground ) ? innerMargin : 0), y, 00563 lineNumberWidth, renderer.fontHeight(), 00564 Qt::AlignRight, QString("%1").arg( lineCount + 1 ) ); 00565 } 00566 endCol = renderer.textWidth(doc->kateTextLine(lineCount), startCol, maxWidth, &needWrap); 00567 00568 if ( endCol < startCol ) 00569 { 00570 //kdDebug(13020)<<"--- Skipping garbage, line: "<<lineCount<<" start: "<<startCol<<" end: "<<endCol<<" real EndCol; "<< buffer->line(lineCount)->length()<< " !?"<<endl; 00571 lineCount++; 00572 continue; // strange case... 00573 // Happens if the line fits exactly. 00574 // When it happens, a line of garbage would be printed. 00575 // FIXME Most likely this is an error in textWidth(), 00576 // failing to correctly set needWrap to false in this case? 00577 } 00578 00579 // if we print only selection: 00580 // print only selected range of chars. 00581 bool skip = false; 00582 if ( selectionOnly ) 00583 { 00584 bool inBlockSelection = ( doc->blockSelectionMode() && lineCount >= firstline && lineCount <= lastline ); 00585 if ( lineCount == firstline || inBlockSelection ) 00586 { 00587 if ( startCol < selStartCol ) 00588 startCol = selStartCol; 00589 } 00590 if ( lineCount == lastline || inBlockSelection ) 00591 { 00592 if ( endCol > selEndCol ) 00593 { 00594 endCol = selEndCol; 00595 skip = true; 00596 } 00597 } 00598 } 00599 00600 // HA! this is where we print [part of] a line ;]] 00601 // FIXME Convert this function + related functionality to a separate KatePrintView 00602 KateLineRange range; 00603 range.line = lineCount; 00604 range.startCol = startCol; 00605 range.endCol = endCol; 00606 range.wrap = needWrap; 00607 paint.translate(xstart, y); 00608 renderer.paintTextLine(paint, &range, 0, maxWidth); 00609 paint.resetXForm(); 00610 if ( skip ) 00611 { 00612 needWrap = false; 00613 startCol = 0; 00614 } 00615 else 00616 { 00617 startCol = endCol; 00618 } 00619 00620 y += renderer.fontHeight(); 00621 _count++; 00622 } // done while ( needWrap ) 00623 00624 lineCount++; 00625 } // done lineCount <= lastline 00626 return true; 00627 } 00628 00629 #endif 00630 return false; 00631 } 00632 //END KatePrinter 00633 00634 #ifndef Q_WS_WIN //TODO: reenable 00635 //BEGIN KatePrintTextSettings 00636 KatePrintTextSettings::KatePrintTextSettings( KPrinter * /*printer*/, QWidget *parent, const char *name ) 00637 : KPrintDialogPage( parent, name ) 00638 { 00639 setTitle( i18n("Te&xt Settings") ); 00640 00641 QVBoxLayout *lo = new QVBoxLayout ( this ); 00642 lo->setSpacing( KDialog::spacingHint() ); 00643 00644 cbSelection = new QCheckBox( i18n("Print &selected text only"), this ); 00645 lo->addWidget( cbSelection ); 00646 00647 cbLineNumbers = new QCheckBox( i18n("Print &line numbers"), this ); 00648 lo->addWidget( cbLineNumbers ); 00649 00650 cbGuide = new QCheckBox( i18n("Print syntax &guide"), this ); 00651 lo->addWidget( cbGuide ); 00652 00653 lo->addStretch( 1 ); 00654 00655 // set defaults - nothing to do :-) 00656 00657 // whatsthis 00658 QWhatsThis::add( cbSelection, i18n( 00659 "<p>This option is only available if some text is selected in the document.</p>" 00660 "<p>If available and enabled, only the selected text is printed.</p>") ); 00661 QWhatsThis::add( cbLineNumbers, i18n( 00662 "<p>If enabled, line numbers will be printed on the left side of the page(s).</p>") ); 00663 QWhatsThis::add( cbGuide, i18n( 00664 "<p>Print a box displaying typographical conventions for the document type, as " 00665 "defined by the syntax highlighting being used.") ); 00666 } 00667 00668 void KatePrintTextSettings::getOptions( QMap<QString,QString>& opts, bool ) 00669 { 00670 opts["app-kate-printselection"] = cbSelection->isChecked() ? "true" : "false"; 00671 opts["app-kate-printlinenumbers"] = cbLineNumbers->isChecked() ? "true" : "false"; 00672 opts["app-kate-printguide"] = cbGuide->isChecked() ? "true" : "false" ; 00673 } 00674 00675 void KatePrintTextSettings::setOptions( const QMap<QString,QString>& opts ) 00676 { 00677 QString v; 00678 v = opts["app-kate-printselection"]; 00679 if ( ! v.isEmpty() ) 00680 cbSelection->setChecked( v == "true" ); 00681 v = opts["app-kate-printlinenumbers"]; 00682 if ( ! v.isEmpty() ) 00683 cbLineNumbers->setChecked( v == "true" ); 00684 v = opts["app-kate-printguide"]; 00685 if ( ! v.isEmpty() ) 00686 cbGuide->setChecked( v == "true" ); 00687 } 00688 00689 void KatePrintTextSettings::enableSelection( bool enable ) 00690 { 00691 cbSelection->setEnabled( enable ); 00692 } 00693 00694 //END KatePrintTextSettings 00695 00696 //BEGIN KatePrintHeaderFooter 00697 KatePrintHeaderFooter::KatePrintHeaderFooter( KPrinter * /*printer*/, QWidget *parent, const char *name ) 00698 : KPrintDialogPage( parent, name ) 00699 { 00700 setTitle( i18n("Hea&der && Footer") ); 00701 00702 QVBoxLayout *lo = new QVBoxLayout ( this ); 00703 uint sp = KDialog::spacingHint(); 00704 lo->setSpacing( sp ); 00705 00706 // enable 00707 QHBoxLayout *lo1 = new QHBoxLayout ( lo ); 00708 cbEnableHeader = new QCheckBox( i18n("Pr&int header"), this ); 00709 lo1->addWidget( cbEnableHeader ); 00710 cbEnableFooter = new QCheckBox( i18n("Pri&nt footer"), this ); 00711 lo1->addWidget( cbEnableFooter ); 00712 00713 // font 00714 QHBoxLayout *lo2 = new QHBoxLayout( lo ); 00715 lo2->addWidget( new QLabel( i18n("Header/footer font:"), this ) ); 00716 lFontPreview = new QLabel( this ); 00717 lFontPreview->setFrameStyle( QFrame::Panel|QFrame::Sunken ); 00718 lo2->addWidget( lFontPreview ); 00719 lo2->setStretchFactor( lFontPreview, 1 ); 00720 QPushButton *btnChooseFont = new QPushButton( i18n("Choo&se Font..."), this ); 00721 lo2->addWidget( btnChooseFont ); 00722 connect( btnChooseFont, SIGNAL(clicked()), this, SLOT(setHFFont()) ); 00723 // header 00724 gbHeader = new QGroupBox( 2, Qt::Horizontal, i18n("Header Properties"), this ); 00725 lo->addWidget( gbHeader ); 00726 00727 QLabel *lHeaderFormat = new QLabel( i18n("&Format:"), gbHeader ); 00728 QHBox *hbHeaderFormat = new QHBox( gbHeader ); 00729 hbHeaderFormat->setSpacing( sp ); 00730 leHeaderLeft = new QLineEdit( hbHeaderFormat ); 00731 leHeaderCenter = new QLineEdit( hbHeaderFormat ); 00732 leHeaderRight = new QLineEdit( hbHeaderFormat ); 00733 lHeaderFormat->setBuddy( leHeaderLeft ); 00734 new QLabel( i18n("Colors:"), gbHeader ); 00735 QHBox *hbHeaderColors = new QHBox( gbHeader ); 00736 hbHeaderColors->setSpacing( sp ); 00737 QLabel *lHeaderFgCol = new QLabel( i18n("Foreground:"), hbHeaderColors ); 00738 kcbtnHeaderFg = new KColorButton( hbHeaderColors ); 00739 lHeaderFgCol->setBuddy( kcbtnHeaderFg ); 00740 cbHeaderEnableBgColor = new QCheckBox( i18n("Bac&kground"), hbHeaderColors ); 00741 kcbtnHeaderBg = new KColorButton( hbHeaderColors ); 00742 00743 gbFooter = new QGroupBox( 2, Qt::Horizontal, i18n("Footer Properties"), this ); 00744 lo->addWidget( gbFooter ); 00745 00746 // footer 00747 QLabel *lFooterFormat = new QLabel( i18n("For&mat:"), gbFooter ); 00748 QHBox *hbFooterFormat = new QHBox( gbFooter ); 00749 hbFooterFormat->setSpacing( sp ); 00750 leFooterLeft = new QLineEdit( hbFooterFormat ); 00751 leFooterCenter = new QLineEdit( hbFooterFormat ); 00752 leFooterRight = new QLineEdit( hbFooterFormat ); 00753 lFooterFormat->setBuddy( leFooterLeft ); 00754 00755 new QLabel( i18n("Colors:"), gbFooter ); 00756 QHBox *hbFooterColors = new QHBox( gbFooter ); 00757 hbFooterColors->setSpacing( sp ); 00758 QLabel *lFooterBgCol = new QLabel( i18n("Foreground:"), hbFooterColors ); 00759 kcbtnFooterFg = new KColorButton( hbFooterColors ); 00760 lFooterBgCol->setBuddy( kcbtnFooterFg ); 00761 cbFooterEnableBgColor = new QCheckBox( i18n("&Background"), hbFooterColors ); 00762 kcbtnFooterBg = new KColorButton( hbFooterColors ); 00763 00764 lo->addStretch( 1 ); 00765 00766 // user friendly 00767 connect( cbEnableHeader, SIGNAL(toggled(bool)), gbHeader, SLOT(setEnabled(bool)) ); 00768 connect( cbEnableFooter, SIGNAL(toggled(bool)), gbFooter, SLOT(setEnabled(bool)) ); 00769 connect( cbHeaderEnableBgColor, SIGNAL(toggled(bool)), kcbtnHeaderBg, SLOT(setEnabled(bool)) ); 00770 connect( cbFooterEnableBgColor, SIGNAL(toggled(bool)), kcbtnFooterBg, SLOT(setEnabled(bool)) ); 00771 00772 // set defaults 00773 cbEnableHeader->setChecked( true ); 00774 leHeaderLeft->setText( "%y" ); 00775 leHeaderCenter->setText( "%f" ); 00776 leHeaderRight->setText( "%p" ); 00777 kcbtnHeaderFg->setColor( QColor("black") ); 00778 cbHeaderEnableBgColor->setChecked( true ); 00779 kcbtnHeaderBg->setColor( QColor("lightgrey") ); 00780 00781 cbEnableFooter->setChecked( true ); 00782 leFooterRight->setText( "%U" ); 00783 kcbtnFooterFg->setColor( QColor("black") ); 00784 cbFooterEnableBgColor->setChecked( true ); 00785 kcbtnFooterBg->setColor( QColor("lightgrey") ); 00786 00787 // whatsthis 00788 QString s = i18n("<p>Format of the page header. The following tags are supported:</p>"); 00789 QString s1 = i18n( 00790 "<ul><li><tt>%u</tt>: current user name</li>" 00791 "<li><tt>%d</tt>: complete date/time in short format</li>" 00792 "<li><tt>%D</tt>: complete date/time in long format</li>" 00793 "<li><tt>%h</tt>: current time</li>" 00794 "<li><tt>%y</tt>: current date in short format</li>" 00795 "<li><tt>%Y</tt>: current date in long format</li>" 00796 "<li><tt>%f</tt>: file name</li>" 00797 "<li><tt>%U</tt>: full URL of the document</li>" 00798 "<li><tt>%p</tt>: page number</li>" 00799 "</ul><br>" 00800 "<u>Note:</u> Do <b>not</b> use the '|' (vertical bar) character."); 00801 QWhatsThis::add(leHeaderRight, s + s1 ); 00802 QWhatsThis::add(leHeaderCenter, s + s1 ); 00803 QWhatsThis::add(leHeaderLeft, s + s1 ); 00804 s = i18n("<p>Format of the page footer. The following tags are supported:</p>"); 00805 QWhatsThis::add(leFooterRight, s + s1 ); 00806 QWhatsThis::add(leFooterCenter, s + s1 ); 00807 QWhatsThis::add(leFooterLeft, s + s1 ); 00808 00809 00810 } 00811 00812 void KatePrintHeaderFooter::getOptions(QMap<QString,QString>& opts, bool ) 00813 { 00814 opts["app-kate-hffont"] = strFont; 00815 00816 opts["app-kate-useheader"] = (cbEnableHeader->isChecked() ? "true" : "false"); 00817 opts["app-kate-headerfg"] = kcbtnHeaderFg->color().name(); 00818 opts["app-kate-headerusebg"] = (cbHeaderEnableBgColor->isChecked() ? "true" : "false"); 00819 opts["app-kate-headerbg"] = kcbtnHeaderBg->color().name(); 00820 opts["app-kate-headerformat"] = leHeaderLeft->text() + "|" + leHeaderCenter->text() + "|" + leHeaderRight->text(); 00821 00822 opts["app-kate-usefooter"] = (cbEnableFooter->isChecked() ? "true" : "false"); 00823 opts["app-kate-footerfg"] = kcbtnFooterFg->color().name(); 00824 opts["app-kate-footerusebg"] = (cbFooterEnableBgColor->isChecked() ? "true" : "false"); 00825 opts["app-kate-footerbg"] = kcbtnFooterBg->color().name(); 00826 opts["app-kate-footerformat"] = leFooterLeft->text() + "|" + leFooterCenter->text() + "|" + leFooterRight->text(); 00827 } 00828 00829 void KatePrintHeaderFooter::setOptions( const QMap<QString,QString>& opts ) 00830 { 00831 QString v; 00832 v = opts["app-kate-hffont"]; 00833 strFont = v; 00834 QFont f = font(); 00835 if ( ! v.isEmpty() ) 00836 { 00837 if (!strFont.isEmpty()) 00838 f.fromString( strFont ); 00839 00840 lFontPreview->setFont( f ); 00841 } 00842 lFontPreview->setText( (f.family() + ", %1pt").arg( f.pointSize() ) ); 00843 00844 v = opts["app-kate-useheader"]; 00845 if ( ! v.isEmpty() ) 00846 cbEnableHeader->setChecked( v == "true" ); 00847 v = opts["app-kate-headerfg"]; 00848 if ( ! v.isEmpty() ) 00849 kcbtnHeaderFg->setColor( QColor( v ) ); 00850 v = opts["app-kate-headerusebg"]; 00851 if ( ! v.isEmpty() ) 00852 cbHeaderEnableBgColor->setChecked( v == "true" ); 00853 v = opts["app-kate-headerbg"]; 00854 if ( ! v.isEmpty() ) 00855 kcbtnHeaderBg->setColor( QColor( v ) ); 00856 00857 QStringList tags = QStringList::split('|', opts["app-kate-headerformat"], "true"); 00858 if (tags.count() == 3) 00859 { 00860 leHeaderLeft->setText(tags[0]); 00861 leHeaderCenter->setText(tags[1]); 00862 leHeaderRight->setText(tags[2]); 00863 } 00864 00865 v = opts["app-kate-usefooter"]; 00866 if ( ! v.isEmpty() ) 00867 cbEnableFooter->setChecked( v == "true" ); 00868 v = opts["app-kate-footerfg"]; 00869 if ( ! v.isEmpty() ) 00870 kcbtnFooterFg->setColor( QColor( v ) ); 00871 v = opts["app-kate-footerusebg"]; 00872 if ( ! v.isEmpty() ) 00873 cbFooterEnableBgColor->setChecked( v == "true" ); 00874 v = opts["app-kate-footerbg"]; 00875 if ( ! v.isEmpty() ) 00876 kcbtnFooterBg->setColor( QColor( v ) ); 00877 00878 tags = QStringList::split('|', opts["app-kate-footerformat"], "true"); 00879 if (tags.count() == 3) 00880 { 00881 leFooterLeft->setText(tags[0]); 00882 leFooterCenter->setText(tags[1]); 00883 leFooterRight->setText(tags[2]); 00884 } 00885 } 00886 00887 void KatePrintHeaderFooter::setHFFont() 00888 { 00889 QFont fnt( lFontPreview->font() ); 00890 // display a font dialog 00891 if ( KFontDialog::getFont( fnt, false, this ) == KFontDialog::Accepted ) 00892 { 00893 // change strFont 00894 strFont = fnt.toString(); 00895 // set preview 00896 lFontPreview->setFont( fnt ); 00897 lFontPreview->setText( (fnt.family() + ", %1pt").arg( fnt.pointSize() ) ); 00898 } 00899 } 00900 00901 //END KatePrintHeaderFooter 00902 00903 //BEGIN KatePrintLayout 00904 00905 KatePrintLayout::KatePrintLayout( KPrinter * /*printer*/, QWidget *parent, const char *name ) 00906 : KPrintDialogPage( parent, name ) 00907 { 00908 setTitle( i18n("L&ayout") ); 00909 00910 QVBoxLayout *lo = new QVBoxLayout ( this ); 00911 lo->setSpacing( KDialog::spacingHint() ); 00912 00913 QHBox *hb = new QHBox( this ); 00914 lo->addWidget( hb ); 00915 QLabel *lSchema = new QLabel( i18n("&Schema:"), hb ); 00916 cmbSchema = new QComboBox( false, hb ); 00917 lSchema->setBuddy( cmbSchema ); 00918 00919 cbDrawBackground = new QCheckBox( i18n("Draw bac&kground color"), this ); 00920 lo->addWidget( cbDrawBackground ); 00921 00922 cbEnableBox = new QCheckBox( i18n("Draw &boxes"), this ); 00923 lo->addWidget( cbEnableBox ); 00924 00925 gbBoxProps = new QGroupBox( 2, Qt::Horizontal, i18n("Box Properties"), this ); 00926 lo->addWidget( gbBoxProps ); 00927 00928 QLabel *lBoxWidth = new QLabel( i18n("W&idth:"), gbBoxProps ); 00929 sbBoxWidth = new QSpinBox( 1, 100, 1, gbBoxProps ); 00930 lBoxWidth->setBuddy( sbBoxWidth ); 00931 00932 QLabel *lBoxMargin = new QLabel( i18n("&Margin:"), gbBoxProps ); 00933 sbBoxMargin = new QSpinBox( 0, 100, 1, gbBoxProps ); 00934 lBoxMargin->setBuddy( sbBoxMargin ); 00935 00936 QLabel *lBoxColor = new QLabel( i18n("Co&lor:"), gbBoxProps ); 00937 kcbtnBoxColor = new KColorButton( gbBoxProps ); 00938 lBoxColor->setBuddy( kcbtnBoxColor ); 00939 00940 connect( cbEnableBox, SIGNAL(toggled(bool)), gbBoxProps, SLOT(setEnabled(bool)) ); 00941 00942 lo->addStretch( 1 ); 00943 // set defaults: 00944 sbBoxMargin->setValue( 6 ); 00945 gbBoxProps->setEnabled( false ); 00946 cmbSchema->insertStringList (KateFactory::self()->schemaManager()->list ()); 00947 cmbSchema->setCurrentItem( 1 ); 00948 00949 // whatsthis 00950 // FIXME uncomment when string freeze is over 00951 // QWhatsThis::add ( cmbSchema, i18n( 00952 // "Select the color scheme to use for the print." ) ); 00953 QWhatsThis::add( cbDrawBackground, i18n( 00954 "<p>If enabled, the background color of the editor will be used.</p>" 00955 "<p>This may be useful if your color scheme is designed for a dark background.</p>") ); 00956 QWhatsThis::add( cbEnableBox, i18n( 00957 "<p>If enabled, a box as defined in the properties below will be drawn " 00958 "around the contents of each page. The Header and Footer will be separated " 00959 "from the contents with a line as well.</p>") ); 00960 QWhatsThis::add( sbBoxWidth, i18n( 00961 "The width of the box outline" ) ); 00962 QWhatsThis::add( sbBoxMargin, i18n( 00963 "The margin inside boxes, in pixels") ); 00964 QWhatsThis::add( kcbtnBoxColor, i18n( 00965 "The line color to use for boxes") ); 00966 } 00967 00968 void KatePrintLayout::getOptions(QMap<QString,QString>& opts, bool ) 00969 { 00970 opts["app-kate-colorscheme"] = cmbSchema->currentText(); 00971 opts["app-kate-usebackground"] = cbDrawBackground->isChecked() ? "true" : "false"; 00972 opts["app-kate-usebox"] = cbEnableBox->isChecked() ? "true" : "false"; 00973 opts["app-kate-boxwidth"] = sbBoxWidth->cleanText(); 00974 opts["app-kate-boxmargin"] = sbBoxMargin->cleanText(); 00975 opts["app-kate-boxcolor"] = kcbtnBoxColor->color().name(); 00976 } 00977 00978 void KatePrintLayout::setOptions( const QMap<QString,QString>& opts ) 00979 { 00980 QString v; 00981 v = opts["app-kate-colorscheme"]; 00982 if ( ! v.isEmpty() ) 00983 cmbSchema->setCurrentItem( KateFactory::self()->schemaManager()->number( v ) ); 00984 v = opts["app-kate-usebackground"]; 00985 if ( ! v.isEmpty() ) 00986 cbDrawBackground->setChecked( v == "true" ); 00987 v = opts["app-kate-usebox"]; 00988 if ( ! v.isEmpty() ) 00989 cbEnableBox->setChecked( v == "true" ); 00990 v = opts["app-kate-boxwidth"]; 00991 if ( ! v.isEmpty() ) 00992 sbBoxWidth->setValue( v.toInt() ); 00993 v = opts["app-kate-boxmargin"]; 00994 if ( ! v.isEmpty() ) 00995 sbBoxMargin->setValue( v.toInt() ); 00996 v = opts["app-kate-boxcolor"]; 00997 if ( ! v.isEmpty() ) 00998 kcbtnBoxColor->setColor( QColor( v ) ); 00999 } 01000 //END KatePrintLayout 01001 01002 #include "kateprinter.moc" 01003 #endif 01004 01005 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE Logo
This file is part of the documentation for kate Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 14 00:46:07 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003