TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

kateprinter.cpp 37KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  1. /*
  2. * This file is part of the KDE libraries
  3. * Copyright (c) 2001-2002 Michael Goffioul <tdeprint@swing.be>
  4. * Complete rewrite on Sat Jun 15 2002 (c) Anders Lund <anders@alweb.dk>
  5. * Copyright (c) 2002, 2003 Anders Lund <anders@alweb.dk>
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Library General Public
  9. * License version 2 as published by the Free Software Foundation.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Library General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Library General Public License
  17. * along with this library; see the file COPYING.LIB. If not, write to
  18. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  19. * Boston, MA 02110-1301, USA.
  20. **/
  21. #include "kateprinter.h"
  22. #include <kateconfig.h>
  23. #include <katedocument.h>
  24. #include <katefactory.h>
  25. #include <katehighlight.h>
  26. #include <katelinerange.h>
  27. #include <katerenderer.h>
  28. #include <kateschema.h>
  29. #include <katetextline.h>
  30. #include <tdeapplication.h>
  31. #include <kcolorbutton.h>
  32. #include <kdebug.h>
  33. #include <kdialog.h> // for spacingHint()
  34. #include <tdefontdialog.h>
  35. #include <tdelocale.h>
  36. #include <kprinter.h>
  37. #include <kurl.h>
  38. #include <kuser.h> // for loginName
  39. #include <tqpainter.h>
  40. #include <tqpopupmenu.h>
  41. #include <tqpaintdevicemetrics.h>
  42. #include <tqcheckbox.h>
  43. #include <tqcombobox.h>
  44. #include <tqgroupbox.h>
  45. #include <tqhbox.h>
  46. #include <tqlabel.h>
  47. #include <tqlayout.h>
  48. #include <tqlineedit.h>
  49. #include <tqspinbox.h>
  50. #include <tqstringlist.h>
  51. #include <tqwhatsthis.h>
  52. //BEGIN KatePrinter
  53. bool KatePrinter::print (KateDocument *doc)
  54. {
  55. #ifndef Q_WS_WIN //TODO: reenable
  56. KPrinter printer;
  57. // docname is now always there, including the right Untitled name
  58. printer.setDocName(doc->docName());
  59. KatePrintTextSettings *kpts = new KatePrintTextSettings(&printer, NULL);
  60. kpts->enableSelection( doc->hasSelection() );
  61. printer.addDialogPage( kpts );
  62. printer.addDialogPage( new KatePrintHeaderFooter(&printer, NULL) );
  63. printer.addDialogPage( new KatePrintLayout(&printer, NULL) );
  64. if ( printer.setup( kapp->mainWidget(), i18n("Print %1").arg(printer.docName()) ) )
  65. {
  66. KateRenderer renderer(doc);
  67. //renderer.config()->setSchema (1);
  68. renderer.setPrinterFriendly(true);
  69. TQPainter paint( &printer );
  70. TQPaintDeviceMetrics pdm( &printer );
  71. /*
  72. We work in tree cycles:
  73. 1) initialize variables and retrieve print settings
  74. 2) prepare data according to those settings
  75. 3) draw to the printer
  76. */
  77. uint pdmWidth = pdm.width();
  78. uint y = 0;
  79. uint xstart = 0; // beginning point for painting lines
  80. uint lineCount = 0;
  81. uint maxWidth = pdmWidth;
  82. uint headerWidth = pdmWidth;
  83. int startCol = 0;
  84. int endCol = 0;
  85. bool needWrap = true;
  86. bool pageStarted = true;
  87. // Text Settings Page
  88. bool selectionOnly = ( doc->hasSelection() &&
  89. ( printer.option("app-kate-printselection") == "true" ) );
  90. int selStartCol = 0;
  91. int selEndCol = 0;
  92. bool useGuide = ( printer.option("app-kate-printguide") == "true" );
  93. int guideHeight = 0;
  94. int guideCols = 0;
  95. bool printLineNumbers = ( printer.option("app-kate-printlinenumbers") == "true" );
  96. uint lineNumberWidth( 0 );
  97. // Header/Footer Page
  98. TQFont headerFont; // used for header/footer
  99. TQString f = printer.option("app-kate-hffont");
  100. if (!f.isEmpty())
  101. headerFont.fromString( f );
  102. bool useHeader = (printer.option("app-kate-useheader") == "true");
  103. TQColor headerBgColor(printer.option("app-kate-headerbg"));
  104. TQColor headerFgColor(printer.option("app-kate-headerfg"));
  105. uint headerHeight( 0 ); // further init only if needed
  106. TQStringList headerTagList; // do
  107. bool headerDrawBg = false; // do
  108. bool useFooter = (printer.option("app-kate-usefooter") == "true");
  109. TQColor footerBgColor(printer.option("app-kate-footerbg"));
  110. TQColor footerFgColor(printer.option("app-kate-footerfg"));
  111. uint footerHeight( 0 ); // further init only if needed
  112. TQStringList footerTagList = 0; // do
  113. bool footerDrawBg = 0; // do
  114. // Layout Page
  115. renderer.config()->setSchema( KateFactory::self()->schemaManager()->number(
  116. printer.option("app-kate-colorscheme") ) );
  117. bool useBackground = ( printer.option("app-kate-usebackground") == "true" );
  118. bool useBox = (printer.option("app-kate-usebox") == "true");
  119. int boxWidth(printer.option("app-kate-boxwidth").toInt());
  120. TQColor boxColor(printer.option("app-kate-boxcolor"));
  121. int innerMargin = useBox ? printer.option("app-kate-boxmargin").toInt() : 6;
  122. // Post initialization
  123. uint maxHeight = (useBox ? pdm.height()-innerMargin : pdm.height());
  124. uint currentPage( 1 );
  125. uint lastline = doc->lastLine(); // nessecary to print selection only
  126. uint firstline( 0 );
  127. KateHlItemDataList ilist;
  128. if (useGuide)
  129. doc->highlight()->getKateHlItemDataListCopy (renderer.config()->schema(), ilist);
  130. /*
  131. Now on for preparations...
  132. during preparations, variable names starting with a "_" means
  133. those variables are local to the enclosing block.
  134. */
  135. {
  136. if ( selectionOnly )
  137. {
  138. // set a line range from the first selected line to the last
  139. firstline = doc->selStartLine();
  140. selStartCol = doc->selStartCol();
  141. lastline = doc->selEndLine();
  142. selEndCol = doc->selEndCol();
  143. lineCount = firstline;
  144. }
  145. if ( printLineNumbers )
  146. {
  147. // figure out the horiizontal space required
  148. TQString s( TQString("%1 ").arg( doc->numLines() ) );
  149. s.fill('5', -1); // some non-fixed fonts haven't equally wide numbers
  150. // FIXME calculate which is actually the widest...
  151. lineNumberWidth = renderer.currentFontMetrics()->width( s );
  152. // a small space between the line numbers and the text
  153. int _adj = renderer.currentFontMetrics()->width( "5" );
  154. // adjust available width and set horizontal start point for data
  155. maxWidth -= (lineNumberWidth + _adj);
  156. xstart += lineNumberWidth + _adj;
  157. }
  158. if ( useHeader || useFooter )
  159. {
  160. // Set up a tag map
  161. // This retrieves all tags, ued or not, but
  162. // none of theese operations should be expensive,
  163. // and searcing each tag in the format strings is avoided.
  164. TQDateTime dt = TQDateTime::currentDateTime();
  165. TQMap<TQString,TQString> tags;
  166. KUser u (KUser::UseRealUserID);
  167. tags["u"] = u.loginName();
  168. tags["d"] = TDEGlobal::locale()->formatDateTime(dt, true, false);
  169. tags["D"] = TDEGlobal::locale()->formatDateTime(dt, false, false);
  170. tags["h"] = TDEGlobal::locale()->formatTime(TQT_TQTIME_OBJECT(dt.time()), false);
  171. tags["y"] = TDEGlobal::locale()->formatDate(TQT_TQDATE_OBJECT(dt.date()), true);
  172. tags["Y"] = TDEGlobal::locale()->formatDate(TQT_TQDATE_OBJECT(dt.date()), false);
  173. tags["f"] = doc->url().fileName();
  174. tags["U"] = doc->url().prettyURL();
  175. if ( selectionOnly )
  176. {
  177. TQString s( i18n("(Selection of) ") );
  178. tags["f"].prepend( s );
  179. tags["U"].prepend( s );
  180. }
  181. TQRegExp reTags( "%([dDfUhuyY])" ); // TODO tjeck for "%%<TAG>"
  182. if (useHeader)
  183. {
  184. headerDrawBg = ( printer.option("app-kate-headerusebg") == "true" );
  185. headerHeight = TQFontMetrics( headerFont ).height();
  186. if ( useBox || headerDrawBg )
  187. headerHeight += innerMargin * 2;
  188. else
  189. headerHeight += 1 + TQFontMetrics( headerFont ).leading();
  190. TQString headerTags = printer.option("app-kate-headerformat");
  191. int pos = reTags.search( headerTags );
  192. TQString rep;
  193. while ( pos > -1 )
  194. {
  195. rep = tags[reTags.cap( 1 )];
  196. headerTags.replace( (uint)pos, 2, rep );
  197. pos += rep.length();
  198. pos = reTags.search( headerTags, pos );
  199. }
  200. headerTagList = TQStringList::split('|', headerTags, true);
  201. if (!headerBgColor.isValid())
  202. headerBgColor = Qt::lightGray;
  203. if (!headerFgColor.isValid())
  204. headerFgColor = Qt::black;
  205. }
  206. if (useFooter)
  207. {
  208. footerDrawBg = ( printer.option("app-kate-footerusebg") == "true" );
  209. footerHeight = TQFontMetrics( headerFont ).height();
  210. if ( useBox || footerDrawBg )
  211. footerHeight += 2*innerMargin;
  212. else
  213. footerHeight += 1; // line only
  214. TQString footerTags = printer.option("app-kate-footerformat");
  215. int pos = reTags.search( footerTags );
  216. TQString rep;
  217. while ( pos > -1 )
  218. {
  219. rep = tags[reTags.cap( 1 )];
  220. footerTags.replace( (uint)pos, 2, rep );
  221. pos += rep.length();
  222. pos = reTags.search( footerTags, pos );
  223. }
  224. footerTagList = TQStringList::split('|', footerTags, true);
  225. if (!footerBgColor.isValid())
  226. footerBgColor = Qt::lightGray;
  227. if (!footerFgColor.isValid())
  228. footerFgColor = Qt::black;
  229. // adjust maxheight, so we can know when/where to print footer
  230. maxHeight -= footerHeight;
  231. }
  232. } // if ( useHeader || useFooter )
  233. if ( useBackground )
  234. {
  235. if ( ! useBox )
  236. {
  237. xstart += innerMargin;
  238. maxWidth -= innerMargin * 2;
  239. }
  240. }
  241. if ( useBox )
  242. {
  243. if (!boxColor.isValid())
  244. boxColor = Qt::black;
  245. if (boxWidth < 1) // shouldn't be pssible no more!
  246. boxWidth = 1;
  247. // set maxwidth to something sensible
  248. maxWidth -= ( ( boxWidth + innerMargin ) * 2 );
  249. xstart += boxWidth + innerMargin;
  250. // maxheight too..
  251. maxHeight -= boxWidth;
  252. }
  253. else
  254. boxWidth = 0;
  255. if ( useGuide )
  256. {
  257. // calculate the height required
  258. // the number of columns is a side effect, saved for drawing time
  259. // first width is needed
  260. int _w = pdmWidth - innerMargin * 2;
  261. if ( useBox )
  262. _w -= boxWidth * 2;
  263. else
  264. {
  265. if ( useBackground )
  266. _w -= ( innerMargin * 2 );
  267. _w -= 2; // 1 px line on each side
  268. }
  269. // base of height: margins top/bottom, above and below tetle sep line
  270. guideHeight = ( innerMargin * 4 ) + 1;
  271. // get a title and add the height required to draw it
  272. TQString _title = i18n("Typographical Conventions for %1").arg(doc->highlight()->name());
  273. guideHeight += paint.boundingRect( 0, 0, _w, 1000, Qt::AlignTop|Qt::AlignHCenter, _title ).height();
  274. // see how many columns we can fit in
  275. int _widest( 0 );
  276. TQPtrListIterator<KateHlItemData> it( ilist );
  277. KateHlItemData *_d;
  278. int _items ( 0 );
  279. while ( ( _d = it.current()) != 0 )
  280. {
  281. _widest = kMax( _widest, ((TQFontMetrics)(
  282. _d->bold() ?
  283. _d->italic() ?
  284. renderer.config()->fontStruct()->myFontMetricsBI :
  285. renderer.config()->fontStruct()->myFontMetricsBold :
  286. _d->italic() ?
  287. renderer.config()->fontStruct()->myFontMetricsItalic :
  288. renderer.config()->fontStruct()->myFontMetrics
  289. ) ).width( _d->name ) );
  290. _items++;
  291. ++it;
  292. }
  293. guideCols = _w/( _widest + innerMargin );
  294. // add height for required number of lines needed given columns
  295. guideHeight += renderer.fontHeight() * ( _items/guideCols );
  296. if ( _items%guideCols )
  297. guideHeight += renderer.fontHeight();
  298. }
  299. // now that we know the vertical amount of space needed,
  300. // it is possible to calculate the total number of pages
  301. // if needed, that is if any header/footer tag contains "%P".
  302. if ( headerTagList.grep("%P").count() || footerTagList.grep("%P").count() )
  303. {
  304. kdDebug(13020)<<"'%P' found! calculating number of pages..."<<endl;
  305. uint _pages = 0;
  306. uint _ph = maxHeight;
  307. if ( useHeader )
  308. _ph -= ( headerHeight + innerMargin );
  309. if ( useFooter )
  310. _ph -= innerMargin;
  311. int _lpp = _ph / renderer.fontHeight();
  312. uint _lt = 0, _c=0;
  313. // add space for guide if required
  314. if ( useGuide )
  315. _lt += (guideHeight + (renderer.fontHeight() /2)) / renderer.fontHeight();
  316. long _lw;
  317. for ( uint i = firstline; i < lastline; i++ )
  318. {
  319. _lw = renderer.textWidth( doc->kateTextLine( i ), -1 );
  320. while ( _lw >= 0 )
  321. {
  322. _c++;
  323. _lt++;
  324. if ( (int)_lt == _lpp )
  325. {
  326. _pages++;
  327. _lt = 0;
  328. }
  329. _lw -= maxWidth;
  330. if ( ! _lw ) _lw--; // skip lines matching exactly!
  331. }
  332. }
  333. if ( _lt ) _pages++; // last page
  334. // substitute both tag lists
  335. TQString re("%P");
  336. TQStringList::Iterator it;
  337. for ( it=headerTagList.begin(); it!=headerTagList.end(); ++it )
  338. (*it).replace( re, TQString( "%1" ).arg( _pages ) );
  339. for ( it=footerTagList.begin(); it!=footerTagList.end(); ++it )
  340. (*it).replace( re, TQString( "%1" ).arg( _pages ) );
  341. }
  342. } // end prepare block
  343. /*
  344. On to draw something :-)
  345. */
  346. uint _count = 0;
  347. while ( lineCount <= lastline )
  348. {
  349. startCol = 0;
  350. endCol = 0;
  351. needWrap = true;
  352. while (needWrap)
  353. {
  354. if ( y + renderer.fontHeight() >= (uint)(maxHeight) )
  355. {
  356. kdDebug(13020)<<"Starting new page, "<<_count<<" lines up to now."<<endl;
  357. printer.newPage();
  358. currentPage++;
  359. pageStarted = true;
  360. y=0;
  361. }
  362. if ( pageStarted )
  363. {
  364. if ( useHeader )
  365. {
  366. paint.setPen(headerFgColor);
  367. paint.setFont(headerFont);
  368. if ( headerDrawBg )
  369. paint.fillRect(0, 0, headerWidth, headerHeight, headerBgColor);
  370. if (headerTagList.count() == 3)
  371. {
  372. int valign = ( (useBox||headerDrawBg||useBackground) ?
  373. Qt::AlignVCenter : Qt::AlignTop );
  374. int align = valign|Qt::AlignLeft;
  375. int marg = ( useBox || headerDrawBg ) ? innerMargin : 0;
  376. if ( useBox ) marg += boxWidth;
  377. TQString s;
  378. for (int i=0; i<3; i++)
  379. {
  380. s = headerTagList[i];
  381. if (s.find("%p") != -1) s.replace("%p", TQString::number(currentPage));
  382. paint.drawText(marg, 0, headerWidth-(marg*2), headerHeight, align, s);
  383. align = valign|(i == 0 ? Qt::AlignHCenter : Qt::AlignRight);
  384. }
  385. }
  386. if ( ! ( headerDrawBg || useBox || useBackground ) ) // draw a 1 px (!?) line to separate header from contents
  387. {
  388. paint.drawLine( 0, headerHeight-1, headerWidth, headerHeight-1 );
  389. //y += 1; now included in headerHeight
  390. }
  391. y += headerHeight + innerMargin;
  392. }
  393. if ( useFooter )
  394. {
  395. if ( ! ( footerDrawBg || useBox || useBackground ) ) // draw a 1 px (!?) line to separate footer from contents
  396. paint.drawLine( 0, maxHeight + innerMargin - 1, headerWidth, maxHeight + innerMargin - 1 );
  397. if ( footerDrawBg )
  398. paint.fillRect(0, maxHeight+innerMargin+boxWidth, headerWidth, footerHeight, footerBgColor);
  399. if (footerTagList.count() == 3)
  400. {
  401. int align = Qt::AlignVCenter|Qt::AlignLeft;
  402. int marg = ( useBox || footerDrawBg ) ? innerMargin : 0;
  403. if ( useBox ) marg += boxWidth;
  404. TQString s;
  405. for (int i=0; i<3; i++)
  406. {
  407. s = footerTagList[i];
  408. if (s.find("%p") != -1) s.replace("%p", TQString::number(currentPage));
  409. paint.drawText(marg, maxHeight+innerMargin, headerWidth-(marg*2), footerHeight, align, s);
  410. align = Qt::AlignVCenter|(i == 0 ? Qt::AlignHCenter : Qt::AlignRight);
  411. }
  412. }
  413. } // done footer
  414. if ( useBackground )
  415. {
  416. // If we have a box, or the header/footer has backgrounds, we want to paint
  417. // to the border of those. Otherwise just the contents area.
  418. int _y = y, _h = maxHeight - y;
  419. if ( useBox )
  420. {
  421. _y -= innerMargin;
  422. _h += 2 * innerMargin;
  423. }
  424. else
  425. {
  426. if ( headerDrawBg )
  427. {
  428. _y -= innerMargin;
  429. _h += innerMargin;
  430. }
  431. if ( footerDrawBg )
  432. {
  433. _h += innerMargin;
  434. }
  435. }
  436. paint.fillRect( 0, _y, pdmWidth, _h, renderer.config()->backgroundColor());
  437. }
  438. if ( useBox )
  439. {
  440. paint.setPen(TQPen(boxColor, boxWidth));
  441. paint.drawRect(0, 0, pdmWidth, pdm.height());
  442. if (useHeader)
  443. paint.drawLine(0, headerHeight, headerWidth, headerHeight);
  444. else
  445. y += innerMargin;
  446. if ( useFooter ) // drawline is not trustable, grr.
  447. paint.fillRect( 0, maxHeight+innerMargin, headerWidth, boxWidth, boxColor );
  448. }
  449. if ( useGuide && currentPage == 1 )
  450. { // FIXME - this may span more pages...
  451. // draw a box unless we have boxes, in which case we end with a box line
  452. // use color of dsNormal for the title string and the hline
  453. KateAttributeList _dsList;
  454. KateHlManager::self()->getDefaults ( renderer.config()->schema(), _dsList );
  455. paint.setPen( _dsList.at(0)->textColor() );
  456. int _marg = 0; // this could be available globally!??
  457. if ( useBox )
  458. {
  459. _marg += (2*boxWidth) + (2*innerMargin);
  460. paint.fillRect( 0, y+guideHeight-innerMargin-boxWidth, headerWidth, boxWidth, boxColor );
  461. }
  462. else
  463. {
  464. if ( useBackground )
  465. _marg += 2*innerMargin;
  466. paint.drawRect( _marg, y, pdmWidth-(2*_marg), guideHeight );
  467. _marg += 1;
  468. y += 1 + innerMargin;
  469. }
  470. // draw a title string
  471. paint.setFont( renderer.config()->fontStruct()->myFontBold );
  472. TQRect _r;
  473. paint.drawText( _marg, y, pdmWidth-(2*_marg), maxHeight - y,
  474. Qt::AlignTop|Qt::AlignHCenter,
  475. i18n("Typographical Conventions for %1").arg(doc->highlight()->name()), -1, &_r );
  476. int _w = pdmWidth - (_marg*2) - (innerMargin*2);
  477. int _x = _marg + innerMargin;
  478. y += _r.height() + innerMargin;
  479. paint.drawLine( _x, y, _x + _w, y );
  480. y += 1 + innerMargin;
  481. // draw attrib names using their styles
  482. TQPtrListIterator<KateHlItemData> _it( ilist );
  483. KateHlItemData *_d;
  484. int _cw = _w/guideCols;
  485. int _i(0);
  486. while ( ( _d = _it.current() ) != 0 )
  487. {
  488. paint.setPen( renderer.attribute(_i)->textColor() );
  489. paint.setFont( renderer.attribute(_i)->font( *renderer.currentFont() ) );
  490. paint.drawText(( _x + ((_i%guideCols)*_cw)), y, _cw, renderer.fontHeight(),
  491. Qt::AlignVCenter|Qt::AlignLeft, _d->name, -1, &_r );
  492. _i++;
  493. if ( _i && ! ( _i%guideCols ) ) y += renderer.fontHeight();
  494. ++_it;
  495. }
  496. if ( _i%guideCols ) y += renderer.fontHeight();// last row not full
  497. y += ( useBox ? boxWidth : 1 ) + (innerMargin*2);
  498. }
  499. pageStarted = false;
  500. } // pageStarted; move on to contents:)
  501. if ( printLineNumbers && ! startCol ) // don't repeat!
  502. {
  503. paint.setFont( renderer.config()->fontStruct()->font( false, false ) );
  504. paint.setPen( renderer.config()->lineNumberColor() );
  505. paint.drawText( (( useBox || useBackground ) ? innerMargin : 0), y,
  506. lineNumberWidth, renderer.fontHeight(),
  507. Qt::AlignRight, TQString("%1").arg( lineCount + 1 ) );
  508. }
  509. endCol = renderer.textWidth(doc->kateTextLine(lineCount), startCol, maxWidth, &needWrap);
  510. if ( endCol < startCol )
  511. {
  512. //kdDebug(13020)<<"--- Skipping garbage, line: "<<lineCount<<" start: "<<startCol<<" end: "<<endCol<<" real EndCol; "<< buffer->line(lineCount)->length()<< " !?"<<endl;
  513. lineCount++;
  514. continue; // strange case...
  515. // Happens if the line fits exactly.
  516. // When it happens, a line of garbage would be printed.
  517. // FIXME Most likely this is an error in textWidth(),
  518. // failing to correctly set needWrap to false in this case?
  519. }
  520. // if we print only selection:
  521. // print only selected range of chars.
  522. bool skip = false;
  523. if ( selectionOnly )
  524. {
  525. bool inBlockSelection = ( doc->blockSelectionMode() && lineCount >= firstline && lineCount <= lastline );
  526. if ( lineCount == firstline || inBlockSelection )
  527. {
  528. if ( startCol < selStartCol )
  529. startCol = selStartCol;
  530. }
  531. if ( lineCount == lastline || inBlockSelection )
  532. {
  533. if ( endCol > selEndCol )
  534. {
  535. endCol = selEndCol;
  536. skip = true;
  537. }
  538. }
  539. }
  540. // HA! this is where we print [part of] a line ;]]
  541. // FIXME Convert this function + related functionality to a separate KatePrintView
  542. KateLineRange range;
  543. range.line = lineCount;
  544. range.startCol = startCol;
  545. range.endCol = endCol;
  546. range.wrap = needWrap;
  547. paint.translate(xstart, y);
  548. renderer.paintTextLine(paint, &range, 0, maxWidth);
  549. paint.resetXForm();
  550. if ( skip )
  551. {
  552. needWrap = false;
  553. startCol = 0;
  554. }
  555. else
  556. {
  557. startCol = endCol;
  558. }
  559. y += renderer.fontHeight();
  560. _count++;
  561. } // done while ( needWrap )
  562. lineCount++;
  563. } // done lineCount <= lastline
  564. return true;
  565. }
  566. #endif //!Q_WS_WIN
  567. return false;
  568. }
  569. //END KatePrinter
  570. #ifndef Q_WS_WIN //TODO: reenable
  571. //BEGIN KatePrintTextSettings
  572. KatePrintTextSettings::KatePrintTextSettings( KPrinter * /*printer*/, TQWidget *parent, const char *name )
  573. : KPrintDialogPage( parent, name )
  574. {
  575. setTitle( i18n("Te&xt Settings") );
  576. TQVBoxLayout *lo = new TQVBoxLayout ( this );
  577. lo->setSpacing( KDialog::spacingHint() );
  578. cbSelection = new TQCheckBox( i18n("Print &selected text only"), this );
  579. lo->addWidget( cbSelection );
  580. cbLineNumbers = new TQCheckBox( i18n("Print &line numbers"), this );
  581. lo->addWidget( cbLineNumbers );
  582. cbGuide = new TQCheckBox( i18n("Print syntax &guide"), this );
  583. lo->addWidget( cbGuide );
  584. lo->addStretch( 1 );
  585. // set defaults - nothing to do :-)
  586. // whatsthis
  587. TQWhatsThis::add( cbSelection, i18n(
  588. "<p>This option is only available if some text is selected in the document.</p>"
  589. "<p>If available and enabled, only the selected text is printed.</p>") );
  590. TQWhatsThis::add( cbLineNumbers, i18n(
  591. "<p>If enabled, line numbers will be printed on the left side of the page(s).</p>") );
  592. TQWhatsThis::add( cbGuide, i18n(
  593. "<p>Print a box displaying typographical conventions for the document type, as "
  594. "defined by the syntax highlighting being used.") );
  595. }
  596. void KatePrintTextSettings::getOptions( TQMap<TQString,TQString>& opts, bool )
  597. {
  598. opts["app-kate-printselection"] = cbSelection->isChecked() ? "true" : "false";
  599. opts["app-kate-printlinenumbers"] = cbLineNumbers->isChecked() ? "true" : "false";
  600. opts["app-kate-printguide"] = cbGuide->isChecked() ? "true" : "false" ;
  601. }
  602. void KatePrintTextSettings::setOptions( const TQMap<TQString,TQString>& opts )
  603. {
  604. TQString v;
  605. v = opts["app-kate-printselection"];
  606. if ( ! v.isEmpty() )
  607. cbSelection->setChecked( v == "true" );
  608. v = opts["app-kate-printlinenumbers"];
  609. if ( ! v.isEmpty() )
  610. cbLineNumbers->setChecked( v == "true" );
  611. v = opts["app-kate-printguide"];
  612. if ( ! v.isEmpty() )
  613. cbGuide->setChecked( v == "true" );
  614. }
  615. void KatePrintTextSettings::enableSelection( bool enable )
  616. {
  617. cbSelection->setEnabled( enable );
  618. }
  619. //END KatePrintTextSettings
  620. //BEGIN KatePrintHeaderFooter
  621. KatePrintHeaderFooter::KatePrintHeaderFooter( KPrinter * /*printer*/, TQWidget *parent, const char *name )
  622. : KPrintDialogPage( parent, name )
  623. {
  624. setTitle( i18n("Hea&der && Footer") );
  625. TQVBoxLayout *lo = new TQVBoxLayout ( this );
  626. uint sp = KDialog::spacingHint();
  627. lo->setSpacing( sp );
  628. // enable
  629. TQHBoxLayout *lo1 = new TQHBoxLayout ( lo );
  630. cbEnableHeader = new TQCheckBox( i18n("Pr&int header"), this );
  631. lo1->addWidget( cbEnableHeader );
  632. cbEnableFooter = new TQCheckBox( i18n("Pri&nt footer"), this );
  633. lo1->addWidget( cbEnableFooter );
  634. // font
  635. TQHBoxLayout *lo2 = new TQHBoxLayout( lo );
  636. lo2->addWidget( new TQLabel( i18n("Header/footer font:"), this ) );
  637. lFontPreview = new TQLabel( this );
  638. lFontPreview->setFrameStyle( TQFrame::Panel|TQFrame::Sunken );
  639. lo2->addWidget( lFontPreview );
  640. lo2->setStretchFactor( lFontPreview, 1 );
  641. TQPushButton *btnChooseFont = new TQPushButton( i18n("Choo&se Font..."), this );
  642. lo2->addWidget( btnChooseFont );
  643. connect( btnChooseFont, TQT_SIGNAL(clicked()), this, TQT_SLOT(setHFFont()) );
  644. // header
  645. gbHeader = new TQGroupBox( 2, Qt::Horizontal, i18n("Header Properties"), this );
  646. lo->addWidget( gbHeader );
  647. TQLabel *lHeaderFormat = new TQLabel( i18n("&Format:"), gbHeader );
  648. TQHBox *hbHeaderFormat = new TQHBox( gbHeader );
  649. hbHeaderFormat->setSpacing( sp );
  650. leHeaderLeft = new TQLineEdit( hbHeaderFormat );
  651. leHeaderCenter = new TQLineEdit( hbHeaderFormat );
  652. leHeaderRight = new TQLineEdit( hbHeaderFormat );
  653. lHeaderFormat->setBuddy( leHeaderLeft );
  654. new TQLabel( i18n("Colors:"), gbHeader );
  655. TQHBox *hbHeaderColors = new TQHBox( gbHeader );
  656. hbHeaderColors->setSpacing( sp );
  657. TQLabel *lHeaderFgCol = new TQLabel( i18n("Foreground:"), hbHeaderColors );
  658. kcbtnHeaderFg = new KColorButton( hbHeaderColors );
  659. lHeaderFgCol->setBuddy( kcbtnHeaderFg );
  660. cbHeaderEnableBgColor = new TQCheckBox( i18n("Bac&kground"), hbHeaderColors );
  661. kcbtnHeaderBg = new KColorButton( hbHeaderColors );
  662. gbFooter = new TQGroupBox( 2, Qt::Horizontal, i18n("Footer Properties"), this );
  663. lo->addWidget( gbFooter );
  664. // footer
  665. TQLabel *lFooterFormat = new TQLabel( i18n("For&mat:"), gbFooter );
  666. TQHBox *hbFooterFormat = new TQHBox( gbFooter );
  667. hbFooterFormat->setSpacing( sp );
  668. leFooterLeft = new TQLineEdit( hbFooterFormat );
  669. leFooterCenter = new TQLineEdit( hbFooterFormat );
  670. leFooterRight = new TQLineEdit( hbFooterFormat );
  671. lFooterFormat->setBuddy( leFooterLeft );
  672. new TQLabel( i18n("Colors:"), gbFooter );
  673. TQHBox *hbFooterColors = new TQHBox( gbFooter );
  674. hbFooterColors->setSpacing( sp );
  675. TQLabel *lFooterBgCol = new TQLabel( i18n("Foreground:"), hbFooterColors );
  676. kcbtnFooterFg = new KColorButton( hbFooterColors );
  677. lFooterBgCol->setBuddy( kcbtnFooterFg );
  678. cbFooterEnableBgColor = new TQCheckBox( i18n("&Background"), hbFooterColors );
  679. kcbtnFooterBg = new KColorButton( hbFooterColors );
  680. lo->addStretch( 1 );
  681. // user friendly
  682. connect( cbEnableHeader, TQT_SIGNAL(toggled(bool)), gbHeader, TQT_SLOT(setEnabled(bool)) );
  683. connect( cbEnableFooter, TQT_SIGNAL(toggled(bool)), gbFooter, TQT_SLOT(setEnabled(bool)) );
  684. connect( cbHeaderEnableBgColor, TQT_SIGNAL(toggled(bool)), kcbtnHeaderBg, TQT_SLOT(setEnabled(bool)) );
  685. connect( cbFooterEnableBgColor, TQT_SIGNAL(toggled(bool)), kcbtnFooterBg, TQT_SLOT(setEnabled(bool)) );
  686. // set defaults
  687. cbEnableHeader->setChecked( true );
  688. leHeaderLeft->setText( "%y" );
  689. leHeaderCenter->setText( "%f" );
  690. leHeaderRight->setText( "%p" );
  691. kcbtnHeaderFg->setColor( TQColor("black") );
  692. cbHeaderEnableBgColor->setChecked( true );
  693. kcbtnHeaderBg->setColor( TQColor("lightgrey") );
  694. cbEnableFooter->setChecked( true );
  695. leFooterRight->setText( "%U" );
  696. kcbtnFooterFg->setColor( TQColor("black") );
  697. cbFooterEnableBgColor->setChecked( true );
  698. kcbtnFooterBg->setColor( TQColor("lightgrey") );
  699. // whatsthis
  700. TQString s = i18n("<p>Format of the page header. The following tags are supported:</p>");
  701. TQString s1 = i18n(
  702. "<ul><li><tt>%u</tt>: current user name</li>"
  703. "<li><tt>%d</tt>: complete date/time in short format</li>"
  704. "<li><tt>%D</tt>: complete date/time in long format</li>"
  705. "<li><tt>%h</tt>: current time</li>"
  706. "<li><tt>%y</tt>: current date in short format</li>"
  707. "<li><tt>%Y</tt>: current date in long format</li>"
  708. "<li><tt>%f</tt>: file name</li>"
  709. "<li><tt>%U</tt>: full URL of the document</li>"
  710. "<li><tt>%p</tt>: page number</li>"
  711. "</ul><br>"
  712. "<u>Note:</u> Do <b>not</b> use the '|' (vertical bar) character.");
  713. TQWhatsThis::add(leHeaderRight, s + s1 );
  714. TQWhatsThis::add(leHeaderCenter, s + s1 );
  715. TQWhatsThis::add(leHeaderLeft, s + s1 );
  716. s = i18n("<p>Format of the page footer. The following tags are supported:</p>");
  717. TQWhatsThis::add(leFooterRight, s + s1 );
  718. TQWhatsThis::add(leFooterCenter, s + s1 );
  719. TQWhatsThis::add(leFooterLeft, s + s1 );
  720. }
  721. void KatePrintHeaderFooter::getOptions(TQMap<TQString,TQString>& opts, bool )
  722. {
  723. opts["app-kate-hffont"] = strFont;
  724. opts["app-kate-useheader"] = (cbEnableHeader->isChecked() ? "true" : "false");
  725. opts["app-kate-headerfg"] = kcbtnHeaderFg->color().name();
  726. opts["app-kate-headerusebg"] = (cbHeaderEnableBgColor->isChecked() ? "true" : "false");
  727. opts["app-kate-headerbg"] = kcbtnHeaderBg->color().name();
  728. opts["app-kate-headerformat"] = leHeaderLeft->text() + "|" + leHeaderCenter->text() + "|" + leHeaderRight->text();
  729. opts["app-kate-usefooter"] = (cbEnableFooter->isChecked() ? "true" : "false");
  730. opts["app-kate-footerfg"] = kcbtnFooterFg->color().name();
  731. opts["app-kate-footerusebg"] = (cbFooterEnableBgColor->isChecked() ? "true" : "false");
  732. opts["app-kate-footerbg"] = kcbtnFooterBg->color().name();
  733. opts["app-kate-footerformat"] = leFooterLeft->text() + "|" + leFooterCenter->text() + "|" + leFooterRight->text();
  734. }
  735. void KatePrintHeaderFooter::setOptions( const TQMap<TQString,TQString>& opts )
  736. {
  737. TQString v;
  738. v = opts["app-kate-hffont"];
  739. strFont = v;
  740. TQFont f = font();
  741. if ( ! v.isEmpty() )
  742. {
  743. if (!strFont.isEmpty())
  744. f.fromString( strFont );
  745. lFontPreview->setFont( f );
  746. }
  747. lFontPreview->setText( (f.family() + ", %1pt").arg( f.pointSize() ) );
  748. v = opts["app-kate-useheader"];
  749. if ( ! v.isEmpty() )
  750. cbEnableHeader->setChecked( v == "true" );
  751. v = opts["app-kate-headerfg"];
  752. if ( ! v.isEmpty() )
  753. kcbtnHeaderFg->setColor( TQColor( v ) );
  754. v = opts["app-kate-headerusebg"];
  755. if ( ! v.isEmpty() )
  756. cbHeaderEnableBgColor->setChecked( v == "true" );
  757. v = opts["app-kate-headerbg"];
  758. if ( ! v.isEmpty() )
  759. kcbtnHeaderBg->setColor( TQColor( v ) );
  760. TQStringList tags = TQStringList::split('|', opts["app-kate-headerformat"], "true");
  761. if (tags.count() == 3)
  762. {
  763. leHeaderLeft->setText(tags[0]);
  764. leHeaderCenter->setText(tags[1]);
  765. leHeaderRight->setText(tags[2]);
  766. }
  767. v = opts["app-kate-usefooter"];
  768. if ( ! v.isEmpty() )
  769. cbEnableFooter->setChecked( v == "true" );
  770. v = opts["app-kate-footerfg"];
  771. if ( ! v.isEmpty() )
  772. kcbtnFooterFg->setColor( TQColor( v ) );
  773. v = opts["app-kate-footerusebg"];
  774. if ( ! v.isEmpty() )
  775. cbFooterEnableBgColor->setChecked( v == "true" );
  776. v = opts["app-kate-footerbg"];
  777. if ( ! v.isEmpty() )
  778. kcbtnFooterBg->setColor( TQColor( v ) );
  779. tags = TQStringList::split('|', opts["app-kate-footerformat"], "true");
  780. if (tags.count() == 3)
  781. {
  782. leFooterLeft->setText(tags[0]);
  783. leFooterCenter->setText(tags[1]);
  784. leFooterRight->setText(tags[2]);
  785. }
  786. }
  787. void KatePrintHeaderFooter::setHFFont()
  788. {
  789. TQFont fnt( lFontPreview->font() );
  790. // display a font dialog
  791. if ( TDEFontDialog::getFont( fnt, false, this ) == TDEFontDialog::Accepted )
  792. {
  793. // change strFont
  794. strFont = fnt.toString();
  795. // set preview
  796. lFontPreview->setFont( fnt );
  797. lFontPreview->setText( (fnt.family() + ", %1pt").arg( fnt.pointSize() ) );
  798. }
  799. }
  800. //END KatePrintHeaderFooter
  801. //BEGIN KatePrintLayout
  802. KatePrintLayout::KatePrintLayout( KPrinter * /*printer*/, TQWidget *parent, const char *name )
  803. : KPrintDialogPage( parent, name )
  804. {
  805. setTitle( i18n("L&ayout") );
  806. TQVBoxLayout *lo = new TQVBoxLayout ( this );
  807. lo->setSpacing( KDialog::spacingHint() );
  808. TQHBox *hb = new TQHBox( this );
  809. lo->addWidget( hb );
  810. TQLabel *lSchema = new TQLabel( i18n("&Schema:"), hb );
  811. cmbSchema = new TQComboBox( false, hb );
  812. lSchema->setBuddy( cmbSchema );
  813. cbDrawBackground = new TQCheckBox( i18n("Draw bac&kground color"), this );
  814. lo->addWidget( cbDrawBackground );
  815. cbEnableBox = new TQCheckBox( i18n("Draw &boxes"), this );
  816. lo->addWidget( cbEnableBox );
  817. gbBoxProps = new TQGroupBox( 2, Qt::Horizontal, i18n("Box Properties"), this );
  818. lo->addWidget( gbBoxProps );
  819. TQLabel *lBoxWidth = new TQLabel( i18n("W&idth:"), gbBoxProps );
  820. sbBoxWidth = new TQSpinBox( 1, 100, 1, gbBoxProps );
  821. lBoxWidth->setBuddy( sbBoxWidth );
  822. TQLabel *lBoxMargin = new TQLabel( i18n("&Margin:"), gbBoxProps );
  823. sbBoxMargin = new TQSpinBox( 0, 100, 1, gbBoxProps );
  824. lBoxMargin->setBuddy( sbBoxMargin );
  825. TQLabel *lBoxColor = new TQLabel( i18n("Co&lor:"), gbBoxProps );
  826. kcbtnBoxColor = new KColorButton( gbBoxProps );
  827. lBoxColor->setBuddy( kcbtnBoxColor );
  828. connect( cbEnableBox, TQT_SIGNAL(toggled(bool)), gbBoxProps, TQT_SLOT(setEnabled(bool)) );
  829. lo->addStretch( 1 );
  830. // set defaults:
  831. sbBoxMargin->setValue( 6 );
  832. gbBoxProps->setEnabled( false );
  833. cmbSchema->insertStringList (KateFactory::self()->schemaManager()->list ());
  834. cmbSchema->setCurrentItem( 1 );
  835. // whatsthis
  836. // FIXME uncomment when string freeze is over
  837. // TQWhatsThis::add ( cmbSchema, i18n(
  838. // "Select the color scheme to use for the print." ) );
  839. TQWhatsThis::add( cbDrawBackground, i18n(
  840. "<p>If enabled, the background color of the editor will be used.</p>"
  841. "<p>This may be useful if your color scheme is designed for a dark background.</p>") );
  842. TQWhatsThis::add( cbEnableBox, i18n(
  843. "<p>If enabled, a box as defined in the properties below will be drawn "
  844. "around the contents of each page. The Header and Footer will be separated "
  845. "from the contents with a line as well.</p>") );
  846. TQWhatsThis::add( sbBoxWidth, i18n(
  847. "The width of the box outline" ) );
  848. TQWhatsThis::add( sbBoxMargin, i18n(
  849. "The margin inside boxes, in pixels") );
  850. TQWhatsThis::add( kcbtnBoxColor, i18n(
  851. "The line color to use for boxes") );
  852. }
  853. void KatePrintLayout::getOptions(TQMap<TQString,TQString>& opts, bool )
  854. {
  855. opts["app-kate-colorscheme"] = cmbSchema->currentText();
  856. opts["app-kate-usebackground"] = cbDrawBackground->isChecked() ? "true" : "false";
  857. opts["app-kate-usebox"] = cbEnableBox->isChecked() ? "true" : "false";
  858. opts["app-kate-boxwidth"] = sbBoxWidth->cleanText();
  859. opts["app-kate-boxmargin"] = sbBoxMargin->cleanText();
  860. opts["app-kate-boxcolor"] = kcbtnBoxColor->color().name();
  861. }
  862. void KatePrintLayout::setOptions( const TQMap<TQString,TQString>& opts )
  863. {
  864. TQString v;
  865. v = opts["app-kate-colorscheme"];
  866. if ( ! v.isEmpty() )
  867. cmbSchema->setCurrentItem( KateFactory::self()->schemaManager()->number( v ) );
  868. v = opts["app-kate-usebackground"];
  869. if ( ! v.isEmpty() )
  870. cbDrawBackground->setChecked( v == "true" );
  871. v = opts["app-kate-usebox"];
  872. if ( ! v.isEmpty() )
  873. cbEnableBox->setChecked( v == "true" );
  874. v = opts["app-kate-boxwidth"];
  875. if ( ! v.isEmpty() )
  876. sbBoxWidth->setValue( v.toInt() );
  877. v = opts["app-kate-boxmargin"];
  878. if ( ! v.isEmpty() )
  879. sbBoxMargin->setValue( v.toInt() );
  880. v = opts["app-kate-boxcolor"];
  881. if ( ! v.isEmpty() )
  882. kcbtnBoxColor->setColor( TQColor( v ) );
  883. }
  884. //END KatePrintLayout
  885. #include "kateprinter.moc"
  886. #endif //!Q_WS_WIN
  887. // kate: space-indent on; indent-width 2; replace-tabs on;