kate Library API Documentation

kateprinter.cpp

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