kate Library: kateprinter.cpp Source File (kate Library)

| # kate Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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;

This file is part of the documentation for kate Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:36:36 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003