kexisimpleprintingengine.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2005-2007 Jaroslaw Staniek <js@iidea.pl>
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this program; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#include "kexisimpleprintingengine.h"
21
22#include <core/keximainwindow.h>
23#include <kexiutils/utils.h>
24
25#include <tdeapplication.h>
26#include <kiconloader.h>
27#include <tdelocale.h>
28#include <tdefontdialog.h>
29#include <kurllabel.h>
30#include <kdebug.h>
31
32#include <tqlabel.h>
33#include <tqlayout.h>
34#include <tqpainter.h>
35#include <tqcheckbox.h>
36#include <tqwhatsthis.h>
37#include <tqpaintdevicemetrics.h>
38#include <tqimage.h>
39
40#include <kexiutils/tristate.h>
41#include <kexidb/connection.h>
42#include <kexidb/tableschema.h>
43#include <kexidb/cursor.h>
44#include <kexidb/utils.h>
45#include <kexidb/queryschema.h>
46
47KexiSimplePrintingSettings::KexiSimplePrintingSettings()
48{
49 pageLayout = KoPageLayout::standardLayout();
50 addPageNumbers = true;
51 addDateAndTime = true;
52 addTableBorders = false;
53 pageTitleFont = kapp->font();
54 pageTitleFont.setPointSizeFloat( (double)TQFontInfo(pageTitleFont).pointSize()*1.5 );
55 pageTitleFont.setBold(true);
56}
57
58KexiSimplePrintingSettings::~KexiSimplePrintingSettings()
59{
60}
61
63{
64 KexiSimplePrintingSettings settings; //this will set defaults
65
66 TDEConfig *config = kapp->config();
67 config->setGroup("Simple Printing");
68 if (config->hasKey("pageTitleFont"))
69 settings.pageTitleFont = config->readFontEntry("pageTitleFont");
71 if (config->hasKey("pageFormat"))
72 settings.pageLayout.format = KoPageFormat::formatFromString(
73 config->readEntry("pageFormat" ) );
74 if (config->readEntry("pageOrientation", "portrait").lower()=="landscape")
75 settings.pageLayout.orientation = PG_LANDSCAPE;
76 else
77 settings.pageLayout.orientation = PG_PORTRAIT;
78 if (config->hasKey("pageWidth"))
79 settings.pageLayout.ptWidth = config->readDoubleNumEntry("pageWidth");
80 if (config->hasKey("pageHeight"))
81 settings.pageLayout.ptHeight = config->readDoubleNumEntry("pageHeight");
82 if (config->hasKey("pageLeftMargin"))
83 settings.pageLayout.ptLeft = config->readDoubleNumEntry("pageLeftMargin");
84 if (config->hasKey("pageRightMargin"))
85 settings.pageLayout.ptRight = config->readDoubleNumEntry("pageRightMargin");
86 if (config->hasKey("pageTopMargin"))
87 settings.pageLayout.ptTop = config->readDoubleNumEntry("pageTopMargin");
88 if (config->hasKey("pageBottomMargin"))
89 settings.pageLayout.ptBottom = config->readDoubleNumEntry("pageBottomMargin");
90 settings.addPageNumbers = config->readBoolEntry("addPageNumbersToPage", true);
91 settings.addDateAndTime = config->readBoolEntry("addDateAndTimePage", true);
92 settings.addTableBorders = config->readBoolEntry("addTableBorders", false);
93 return settings;
94}
95
96void KexiSimplePrintingSettings::save()
97{
98 TDEConfig *config = kapp->config();
99 config->setGroup("Simple Printing");
100 config->writeEntry( "pageTitleFont", pageTitleFont );
101 config->writeEntry( "pageFormat", KoPageFormat::formatString( pageLayout.format ) );
102 config->writeEntry("pageOrientation",
103 pageLayout.orientation == PG_PORTRAIT ? "portrait" : "landscape");
104 config->writeEntry("pageWidth", pageLayout.ptWidth);
105 config->writeEntry("pageHeight", pageLayout.ptHeight);
106 config->writeEntry("pageLeftMargin", pageLayout.ptLeft);
107 config->writeEntry("pageRightMargin", pageLayout.ptRight);
108 config->writeEntry("pageTopMargin", pageLayout.ptTop);
109 config->writeEntry("pageBottomMargin", pageLayout.ptBottom);
110 config->writeEntry("addPageNumbersToPage", addPageNumbers);
111 config->writeEntry("addDateAndTimePage", addDateAndTime);
112 config->writeEntry("addTableBorders", addTableBorders);
113 config->sync();
114}
115
116//------------------------
117
118KexiSimplePrintingEngine::KexiSimplePrintingEngine(
119 const KexiSimplePrintingSettings& settings, TQObject* parent)
120 : TQObject(parent, "KexiSimplePrintingEngine")
121 , m_settings(&settings)
122 , m_pdm(0)
123{
124 m_cursor = 0;
125 m_data = 0;
126 m_visibleFieldsCount = 0;
127 m_dataOffsets.setAutoDelete(true);
128 clear();
129}
130
131KexiSimplePrintingEngine::~KexiSimplePrintingEngine()
132{
133 done();
134}
135
137 KexiDB::TableOrQuerySchema& tableOrQuery, const TQString& titleText, TQString& errorMessage)
138{
139 errorMessage = TQString();
140 done();
141 m_headerText = titleText; //tableOrQuery.captionOrName();
142
143 //open data source
144 KexiDB::QuerySchema *query = 0;
145 if (tableOrQuery.table())
146 query = tableOrQuery.table()->query(); //all rows
147 else
148 query = tableOrQuery.query();
149 if (!query) {
150 errorMessage = i18n("Could not load data from table or query.");
151 return false;
152 }
153
154 m_cursor = conn.executeQuery(*query);
155 if (!m_cursor) {
156 conn.debugError();
157 return false;
158 }
159 bool ok = !m_cursor->error();
160 if (ok) {
161 m_data = new KexiTableViewData(m_cursor);
163 m_data->preloadAllRows();
164 m_fieldsExpanded = query->fieldsExpanded( KexiDB::QuerySchema::WithInternalFields );
165 m_visibleFieldsCount = m_cursor->query()->fieldsExpanded().count(); //real fields count without internals
166 }
167 else {
168 conn.debugError();
169 }
170 m_eof = !ok || m_data->count() == 0;
171 conn.deleteCursor(m_cursor);
172 m_cursor = 0;
173 return ok;
174}
175
176bool KexiSimplePrintingEngine::done()
177{
178 bool result = true;
179 if (m_cursor && (m_cursor->error() || !m_cursor->connection()->deleteCursor(m_cursor))) {
180 m_cursor->debugError();
181 result = false;
182 }
183 m_cursor = 0;
184 delete m_data;
185 m_data = 0;
186 m_pagesCount = 0;
187 m_paintInitialized = false;
188 m_fieldsExpanded.clear();
189 m_visibleFieldsCount = 0;
190 return result;
191}
192
193void KexiSimplePrintingEngine::clear()
194{
195 m_eof = false;
196 m_pagesCount = 0;
197 m_dataOffsets.clear();
198 m_dataOffsets.append(new uint(0));
199 m_paintInitialized = false;
200}
201
202void KexiSimplePrintingEngine::paintPage(int pageNumber, TQPainter& painter, bool paint)
203{
204 uint offset = 0;
205 if (pageNumber < (int)m_dataOffsets.count()) {
206 offset = *m_dataOffsets.at(pageNumber);
207 }
208
209 double y = 0.0;
210
211 const bool printing = painter.device()->devType() == TQInternal::Printer;
212 m_SCALE = printing ? 1 : 20;
213
214 double w, h;
215 m_pdm = TQPaintDeviceMetrics( painter.device() );
216
217 if (dynamic_cast<TQWidget*>(painter.device())) {
218 w = dynamic_cast<TQWidget*>(painter.device())->width() * m_SCALE;
219 h = dynamic_cast<TQWidget*>(painter.device())->height() * m_SCALE;
220 }
221 else if (dynamic_cast<TQPixmap*>(painter.device())) {
222 w = dynamic_cast<TQPixmap*>(painter.device())->width() * m_SCALE;
223 h = dynamic_cast<TQPixmap*>(painter.device())->height() * m_SCALE;
224 }
225 else {//KPrinter...
226 w = m_pdm.widthMM();
227 h = m_pdm.heightMM();
228 }
229
230 if (!m_paintInitialized) {
231 m_paintInitialized = true;
232
233 double widthMM = KoPageFormat::width(
234 m_settings->pageLayout.format, m_settings->pageLayout.orientation);
235 double heightMM = KoPageFormat::height(
236 m_settings->pageLayout.format, m_settings->pageLayout.orientation);
237
238 m_dpiY = m_pdm.logicalDpiY();
239 m_dpiX = m_pdm.logicalDpiX();
240#ifdef TQ_WS_WIN //fix for 120dpi
241 if (!printing) {
242 m_dpiY = 96;
243 m_dpiX = 96;
244// m_dpiY = 86;
245// m_dpiX = 86;
246 }
247#endif
248 double pdWidthMM = m_pdm.widthMM();
249 double pdHeightMM = m_pdm.heightMM();
250
251// double screenF;
252// screenF = 1.0;
253
254 m_leftMargin = POINT_TO_INCH(m_settings->pageLayout.ptLeft)*m_dpiX * (double)m_SCALE;//* screenF;
255 m_rightMargin = POINT_TO_INCH(m_settings->pageLayout.ptRight)*m_dpiX * (double)m_SCALE;//* screenF;
256 m_topMargin = POINT_TO_INCH(m_settings->pageLayout.ptTop)*m_dpiY * (double)m_SCALE;//* screenF;
257 m_bottomMargin = POINT_TO_INCH(m_settings->pageLayout.ptBottom)*m_dpiY * (double)m_SCALE;//* screenF;
258
259 m_fx = widthMM / (pdWidthMM);// * screenF);
260 m_fy = heightMM / (pdHeightMM);// * screenF);
261
262 //screen only
263 // painter.fillRect(TQRect(0,0,w,h), TQBrush(white));
264 m_pageWidth = uint( m_fx*double(m_pdm.width()) * m_SCALE - m_leftMargin - m_rightMargin );
265 m_pageHeight = uint( m_fy*double(m_pdm.height()) * m_SCALE - m_topMargin - m_bottomMargin );
266 m_headerFont = m_settings->pageTitleFont;
267 if(!printing) {
268 int pixelSize = int( POINT_TO_INCH((double)TQFontInfo(m_headerFont).pointSize())*m_dpiX ) * m_SCALE;
269 m_headerFont.setPixelSize(pixelSize);
270 }
271
273 m_mainFont = kapp->font();
274 if(!printing) {
275 int pixelSize = int( POINT_TO_INCH(m_mainFont.pointSizeFloat())*m_dpiX )
276 * m_SCALE;
277 m_mainFont.setPixelSize(pixelSize);
278 }
279 painter.setFont(m_mainFont);
280
281 m_dateTimeText = TDEGlobal::locale()->formatDateTime(TQDateTime::currentDateTime(),
282 true, false);
283 m_dateTimeWidth = painter.fontMetrics().width(m_dateTimeText+" ");
284 m_mainLineSpacing = painter.fontMetrics().lineSpacing();
285 m_footerHeight = m_mainLineSpacing * 2; //2 lines
286 painter.setFont(m_headerFont);
287 m_headerTextRect = painter.fontMetrics().boundingRect(
288 (int)m_leftMargin, (int)m_topMargin,
289 m_pageWidth - m_dateTimeWidth,
290 m_pageHeight, TQt::AlignAuto|TQt::WordBreak, m_headerText);
291 m_headerTextRect.setRight(m_headerTextRect.right()+10);
292 m_headerTextRect.setWidth(
293 TQMIN(int(m_pageWidth - m_dateTimeWidth), m_headerTextRect.width()));
294
295 //--compute max width of field names
296 m_maxFieldNameWidth = 0;
297
298 painter.setFont(m_mainFont);
299 for (uint i=0; i < m_visibleFieldsCount; i++) {
300 const int newW =
301 painter.fontMetrics().width(m_fieldsExpanded[i]->captionOrAliasOrName()+":");
302// kdDebug() << "row"<<i<<": "<<m_fieldsExpanded[i]->captionOrAliasOrName()<<" "
303// << newW <<endl;
304 if (m_maxFieldNameWidth < newW)
305 m_maxFieldNameWidth = newW;
306 }
307 m_maxFieldNameWidth += painter.fontMetrics().width("ww"); //more space
308 }
309
310 //screen only
311 if(!printing) {
312 painter.setWindow(0, 0, int(w*m_fx), int(h*m_fy));
313 }
314
315 //paint header
316 painter.setFont(m_headerFont);
317 if (paint) {
318 painter.drawText(m_headerTextRect, TQt::AlignAuto|TQt::WordBreak, m_headerText);
319 }
320 painter.setFont(m_mainFont);
321 if (paint) {
322 painter.drawText((int)m_leftMargin + m_pageWidth - m_dateTimeWidth,
323 (int)m_topMargin, m_dateTimeWidth,
324 m_headerTextRect.height(), TQt::AlignRight, m_dateTimeText);
325 //footer
326 TQString pageNumString;
327 if (m_pagesCount>0)
328 pageNumString = i18n("Page (number) of (total)", "Page %1 of %2")
329 .arg(pageNumber+1).arg(m_pagesCount);
330 else
331 pageNumString = i18n("Page %1").arg(pageNumber+1);
332 painter.drawText((int)m_leftMargin,
333 (int)m_topMargin + m_pageHeight - m_mainLineSpacing,
334 m_pageWidth, m_mainLineSpacing,
335 TQt::AlignRight | TQt::AlignBottom, pageNumString);
336 painter.drawLine((int)m_leftMargin,
337 (int)m_topMargin + m_pageHeight - m_mainLineSpacing*3/2,
338 (int)m_leftMargin + m_pageWidth,
339 (int)m_topMargin + m_pageHeight - m_mainLineSpacing*3/2);
340 }
341 y = (double)m_topMargin + (double)m_headerTextRect.height() + double(m_mainLineSpacing)/2;
342 if (!m_settings->addTableBorders) {
343 //separator line
344 if (paint)
345 painter.drawLine((int)m_leftMargin, (int)y, (int)m_leftMargin + m_pageWidth-1, (int)y);
346 y += (double)m_mainLineSpacing;
347 }
348
349 //--print records
350 KexiDB::RowData row;
351 KexiTableItem *item;
352// const uint count = m_fieldsExpanded.count();
353// const uint count = m_cursor->query()->fieldsExpanded().count(); //real fields count without internals
354 const uint rows = m_data->count();
355 const int cellMargin = m_settings->addTableBorders ?
356 painter.fontMetrics().width("i") : 0;
357 uint paintedRows = 0;
358 for (;offset < rows; ++offset) {
359 item = m_data->at(offset);
360
361 //compute height of this record
362 double newY = y;
363 paintRecord(painter, item, cellMargin, newY, paintedRows, false, printing);
364// if ((int(m_topMargin + m_pageHeight-newY-m_footerHeight)) < 0 /*(1)*/ && paintedRows > 0/*(2)*/) {
365 if (newY > (m_topMargin + m_pageHeight - m_mainLineSpacing*2 + m_mainLineSpacing) /*(1)*/ && paintedRows > 0/*(2)*/) {
366 //(1) do not break records between pages
367 //(2) but paint at least one record
369 break;
370 }
371/* if (int(count * m_mainLineSpacing) > int(m_topMargin + m_pageHeight-(int)y-m_footerHeight))
372 {
373 //do not break records between pages
374 break;
375 }*/
376// kdDebug() << " -------- " << y << " / " << m_pageHeight << endl;
377 if (paint)
378 paintRecord(painter, item, cellMargin, y, paintedRows, paint, printing);
379 else
380 y = newY; //speedup
381 paintedRows++;
382 }
383
384 if (int(m_dataOffsets.count()-1)==pageNumber) {//this was next page
385 m_dataOffsets.append(new uint(offset));
386 }
387 m_eof = offset == rows;
388}
389
390void KexiSimplePrintingEngine::paintRecord(TQPainter& painter, KexiTableItem *item,
391 int cellMargin, double &y, uint paintedRows, bool paint, bool printing)
392{
393 if (paintedRows>0 && !m_settings->addTableBorders) {//separator
394 if (paint) {
395 painter.setPen(TQt::darkGray);
396 painter.drawLine(
397 int(m_leftMargin), int( y-(double)m_mainLineSpacing ),
398 int(m_leftMargin)+m_pageWidth-1, int(y-(double)m_mainLineSpacing));
399 painter.setPen(TQt::black);
400 }
401 }
402
403 for (uint i=0; i<m_visibleFieldsCount; i++) {
404// kdDebug() << "row"<<i<<": "<<row.at(i).toString()<<endl;
405 if (paint) {
406 painter.drawText(
407 (int)m_leftMargin+cellMargin, (int)y, m_maxFieldNameWidth-cellMargin*2, m_mainLineSpacing,
408 TQt::AlignTop, m_fieldsExpanded[i]->captionOrAliasOrName()
409 + (m_settings->addTableBorders ? "" : ":"));
410 }
411 TQString text;
413 //get real column and real index to get the visible value
415 int indexForVisibleLookupValue = m_fieldsExpanded[i]->indexForVisibleLookupValue();
416 if (-1 != indexForVisibleLookupValue && indexForVisibleLookupValue < (int)item->count()/*sanity*/)
417 ci = m_fieldsExpanded[ indexForVisibleLookupValue ];
418 else {
419 ci = m_fieldsExpanded[ i ];
420 indexForVisibleLookupValue = i;
421 }
422
423 TQVariant v(item->at( indexForVisibleLookupValue ));
424 KexiDB::Field::Type ftype = ci->field->type();
425 TQRect rect( (int)m_leftMargin + m_maxFieldNameWidth + cellMargin, (int)y,
426 m_pageWidth - m_maxFieldNameWidth - cellMargin*2, m_pageHeight - (int)y);
427
428 if (v.isNull() || !v.isValid()) {
429 //nothing to do
430 }
432 else if (ftype==KexiDB::Field::DateTime) {
433 TQDateTime dt(v.toDateTime());
434 if (dt.isValid())
435 text = TDEGlobal::locale()->formatDateTime(dt);
436 }
438 else if (ftype==KexiDB::Field::Date) {
439 TQDate date(v.toDate());
440 if (date.isValid())
441 text = TDEGlobal::locale()->formatDate(date, true/*short*/);
442 }
444 else if (ftype==KexiDB::Field::Time) {
445 TQTime time(v.toTime());
446 if (time.isValid())
447 text = TDEGlobal::locale()->formatTime(time);
448 }
450 else if (ci->field->isFPNumericType())
451 text = TDEGlobal::locale()->formatNumber(v.toDouble());
452 else if (ftype==KexiDB::Field::Boolean)
453 text = v.toBool()
454 ? i18n("Boolean Yes (true)","Yes") : i18n("Boolean No (false)", "No");
455 else if (ftype==KexiDB::Field::BLOB) {
456 const TQByteArray ba( v.toByteArray() );
457 if (!ba.isEmpty()) {
458 TQPixmap pixmap(ba);
459#define MAX_PIXMAP_HEIGHT (m_mainLineSpacing * 5)
460 double pixmapHeight = MAX_PIXMAP_HEIGHT;
461 double pixmapWidth = double(MAX_PIXMAP_HEIGHT) * pixmap.width() / (double)pixmap.height();
462 if (pixmapWidth > (double)rect.width()) { //too wide
463 pixmapHeight = pixmapHeight * (double)rect.width() / pixmapWidth;
464 pixmapWidth = rect.width();
465 }
466 rect.setHeight( int( pixmapHeight + m_mainLineSpacing / 2 ) );
467 if (paint && !pixmap.isNull()) {
468 if (printing) {
469 painter.drawPixmap(
470 TQRect(rect.x(), rect.y()+m_mainLineSpacing/4,
471 int(pixmapWidth), int(pixmapHeight)), pixmap );
472 }
473 else {// we're just previewing the pixmap, so let's resize it and cache
474 // so redrawing will be faster
475 painter.save();
476 painter.setWindow( // set 1:1 scale to avoid unnecessary image scaling
477 TQRect(painter.window().topLeft(),
478 painter.window().size() / (int)m_SCALE ) );
479 painter.drawImage(
480 int(rect.x() / m_SCALE),
481 int( (rect.y()+m_mainLineSpacing/4) / m_SCALE),
482 pixmap.convertToImage().smoothScale(
483 int(pixmapWidth / m_SCALE), int(pixmapHeight / m_SCALE),
484 TQImage::ScaleMin ));
485 painter.restore(); // back to m_SCALE:1 scale
486 }
487 }
488 }
489 }
490 else
491 text = v.toString();
492
493 if (ftype!=KexiDB::Field::BLOB || v.isNull() || !v.isValid())
494 rect = TQRect( painter.fontMetrics().boundingRect(
495 rect.x(), rect.y(), rect.width(), rect.height(),
496 TQt::AlignAuto|TQt::WordBreak, text) );
497 if (!text.isEmpty() && paint) {
498// kdDebug() << "print engine: painter.drawText: "
499// << rect.x() <<" "<< rect.y() <<" "<< m_pageWidth - m_maxFieldNameWidth - cellMargin*2
500// <<" "<< m_topMargin + m_pageHeight - (int)y <<" "<<m_pageHeight<<" "<<y<<" "<< text << endl;
501 painter.drawText(
502// rect.x(), rect.y(), rect.width(), rect.height(),
503 rect.x(), rect.y(), m_pageWidth - m_maxFieldNameWidth - cellMargin*2,
504 int(m_topMargin + m_pageHeight - (int)y),
505 TQt::AlignTop|TQt::WordBreak, text);
506 }
507 if (m_settings->addTableBorders) {
508 if (paint) {
509 painter.setPen(TQt::darkGray);
510 painter.drawLine(
511 (int)m_leftMargin, rect.top(), (int)m_leftMargin+m_pageWidth-1, rect.top());
512 painter.drawLine(
513 (int)m_leftMargin, rect.top(), (int)m_leftMargin, rect.bottom());
514 painter.drawLine(
515 (int)m_leftMargin+m_pageWidth-1, rect.top(),
516 (int)m_leftMargin+m_pageWidth-1, rect.bottom());
517 painter.drawLine(
518 (int)m_leftMargin+m_maxFieldNameWidth, rect.top(),
519 (int)m_leftMargin+m_maxFieldNameWidth, rect.bottom());
520 painter.setPen(TQt::black);
521 }
522 }
523 y += (double)rect.height();
524 }
525 if (m_settings->addTableBorders) {
526 if (paint) {
527 painter.setPen(TQt::darkGray);
528 painter.drawLine(
529 (int)m_leftMargin, (int)y, (int)m_leftMargin+m_pageWidth-1, (int)y);
530 painter.setPen(TQt::black);
531 }
532 }
533 //record spacing
534 y += double(m_mainLineSpacing)*3.0/2.0;
535// if (m_settings->addTableBorders)
536// y -= m_mainLineSpacing; //a bit less
537}
538
540{
541 if (m_eof || !m_data) {
542 m_pagesCount = 0;
543 return;
544 }
545
546 uint pageNumber = 0;
547 for(;!m_eof; ++pageNumber) {
548 paintPage(pageNumber, painter, false /* !paint */);
549 }
550 m_pagesCount = pageNumber;
551}
552
553void KexiSimplePrintingEngine::setTitleText(const TQString& titleText)
554{
555 m_headerText = titleText;
556}
557
558#include "kexisimpleprintingengine.moc"
Provides database connection, allowing queries and data modification.
Definition connection.h:62
bool deleteCursor(Cursor *cursor)
Cursor * executeQuery(const TQString &statement, uint cursor_options=0)
Connection * connection() const
Definition cursor.h:81
QuerySchema * query() const
Definition cursor.h:104
Type type() const
Definition field.cpp:134
bool isFPNumericType() const
Definition field.h:266
bool error() const
Definition object.h:38
void debugError()
Definition object.cpp:159
Helper class that assigns additional information for the column in a query.
Definition queryschema.h:49
KexiDB::QuerySchema provides information about database query.
@ WithInternalFields
Like Default but internal fields (for lookup) are appended.
QueryColumnInfo::Vector fieldsExpanded(FieldsExpandedOptions options=Default)
QuerySchema * query() const
TableSchema * table() const
QuerySchema * query()
void paintPage(int pageNumber, TQPainter &painter, bool paint=true)
void paintRecord(TQPainter &painter, KexiTableItem *item, int cellMargin, double &y, uint paintedRows, bool paint, bool printing)
bool m_paintInitialized
used by paintPage()
bool init(KexiDB::Connection &conn, KexiDB::TableOrQuerySchema &tableOrQuery, const TQString &titleText, TQString &errorMessage)
void calculatePagesCount(TQPainter &painter)
Calculates pafe count that can be later obtained using pagesCount().
Settings data for simple printing engine.
static KexiSimplePrintingSettings load()
TQValueVector< TQVariant > RowData
structure for storing single record with type information
Definition connection.h:47