00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kexisimpleprintingengine.h"
00021
00022 #include <core/keximainwindow.h>
00023 #include <kexiutils/utils.h>
00024
00025 #include <kapplication.h>
00026 #include <kiconloader.h>
00027 #include <klocale.h>
00028 #include <kfontdialog.h>
00029 #include <kurllabel.h>
00030 #include <kdebug.h>
00031
00032 #include <qlabel.h>
00033 #include <qlayout.h>
00034 #include <qpainter.h>
00035 #include <qcheckbox.h>
00036 #include <qwhatsthis.h>
00037 #include <qpaintdevicemetrics.h>
00038
00039 #include <kprinter.h>
00040
00041 #include <kexiutils/tristate.h>
00042 #include <kexidb/connection.h>
00043 #include <kexidb/tableschema.h>
00044 #include <kexidb/cursor.h>
00045 #include <kexidb/utils.h>
00046 #include <kexidb/queryschema.h>
00047
00048 KexiSimplePrintingSettings::KexiSimplePrintingSettings()
00049 {
00050 pageLayout = KoPageLayout::standardLayout();
00051 addPageNumbers = true;
00052 addDateAndTime = true;
00053 addTableBorders = false;
00054 pageTitleFont = kapp->font();
00055 pageTitleFont.setPointSizeFloat( (double)QFontInfo(pageTitleFont).pointSize()*1.5 );
00056 pageTitleFont.setBold(true);
00057 }
00058
00059 KexiSimplePrintingSettings::~KexiSimplePrintingSettings()
00060 {
00061 }
00062
00063 KexiSimplePrintingSettings KexiSimplePrintingSettings::load()
00064 {
00065 KexiSimplePrintingSettings settings;
00066
00067 KConfig *config = kapp->config();
00068 config->setGroup("Simple Printing");
00069 if (config->hasKey("pageTitleFont"))
00070 settings.pageTitleFont = config->readFontEntry("pageTitleFont");
00072 if (config->hasKey("pageFormat"))
00073 settings.pageLayout.format = KoPageFormat::formatFromString(
00074 config->readEntry("pageFormat" ) );
00075 if (config->readEntry("pageOrientation", "portrait").lower()=="landscape")
00076 settings.pageLayout.orientation = PG_LANDSCAPE;
00077 else
00078 settings.pageLayout.orientation = PG_PORTRAIT;
00079 if (config->hasKey("pageWidth"))
00080 settings.pageLayout.ptWidth = config->readDoubleNumEntry("pageWidth");
00081 if (config->hasKey("pageHeight"))
00082 settings.pageLayout.ptHeight = config->readDoubleNumEntry("pageHeight");
00083 if (config->hasKey("pageLeftMargin"))
00084 settings.pageLayout.ptLeft = config->readDoubleNumEntry("pageLeftMargin");
00085 if (config->hasKey("pageRightMargin"))
00086 settings.pageLayout.ptRight = config->readDoubleNumEntry("pageRightMargin");
00087 if (config->hasKey("pageTopMargin"))
00088 settings.pageLayout.ptTop = config->readDoubleNumEntry("pageTopMargin");
00089 if (config->hasKey("pageBottomMargin"))
00090 settings.pageLayout.ptBottom = config->readDoubleNumEntry("pageBottomMargin");
00091 settings.addPageNumbers = config->readBoolEntry("addPageNumbersToPage", true);
00092 settings.addDateAndTime = config->readBoolEntry("addDateAndTimePage", true);
00093 settings.addTableBorders = config->readBoolEntry("addTableBorders", false);
00094 return settings;
00095 }
00096
00097 void KexiSimplePrintingSettings::save()
00098 {
00099 KConfig *config = kapp->config();
00100 config->setGroup("Simple Printing");
00101 config->writeEntry( "pageTitleFont", pageTitleFont );
00102 config->writeEntry( "pageFormat", KoPageFormat::formatString( pageLayout.format ) );
00103 config->writeEntry("pageOrientation",
00104 pageLayout.orientation == PG_PORTRAIT ? "portrait" : "landscape");
00105 config->writeEntry("pageWidth", pageLayout.ptWidth);
00106 config->writeEntry("pageHeight", pageLayout.ptHeight);
00107 config->writeEntry("pageLeftMargin", pageLayout.ptLeft);
00108 config->writeEntry("pageRightMargin", pageLayout.ptRight);
00109 config->writeEntry("pageTopMargin", pageLayout.ptTop);
00110 config->writeEntry("pageBottomMargin", pageLayout.ptBottom);
00111 config->writeEntry("addPageNumbersToPage", addPageNumbers);
00112 config->writeEntry("addDateAndTimePage", addDateAndTime);
00113 config->writeEntry("addTableBorders", addTableBorders);
00114 config->sync();
00115 }
00116
00117
00118
00119 KexiSimplePrintingEngine::KexiSimplePrintingEngine(
00120 const KexiSimplePrintingSettings& settings, QObject* parent)
00121 : QObject(parent, "KexiSimplePrintingEngine")
00122 , m_settings(&settings)
00123 , m_pdm(0)
00124 {
00125 m_cursor = 0;
00126 m_data = 0;
00127 m_visibleFieldsCount = 0;
00128 m_dataOffsets.setAutoDelete(true);
00129 clear();
00130 }
00131
00132 KexiSimplePrintingEngine::~KexiSimplePrintingEngine()
00133 {
00134 done();
00135 }
00136
00137 bool KexiSimplePrintingEngine::init(KexiDB::Connection& conn,
00138 KexiDB::TableOrQuerySchema& tableOrQuery, const QString& titleText, QString& errorMessage)
00139 {
00140 errorMessage = QString::null;
00141 done();
00142 m_headerText = titleText;
00143
00144
00145 KexiDB::QuerySchema *query = 0;
00146 if (tableOrQuery.table())
00147 query = tableOrQuery.table()->query();
00148 else
00149 query = tableOrQuery.query();
00150 if (!query) {
00151 errorMessage = i18n("Could not load data from table or query.");
00152 return false;
00153 }
00154
00155 m_cursor = conn.executeQuery(*query);
00156 if (!m_cursor) {
00157 conn.debugError();
00158 return false;
00159 }
00160 bool ok = !m_cursor->error();
00161 if (ok) {
00162 m_data = new KexiTableViewData(m_cursor);
00164 m_data->preloadAllRows();
00165 m_fieldsExpanded = query->fieldsExpanded( KexiDB::QuerySchema::WithInternalFields );
00166 m_visibleFieldsCount = m_cursor->query()->fieldsExpanded().count();
00167 }
00168 else {
00169 conn.debugError();
00170 }
00171 m_eof = !ok || m_data->count() == 0;
00172 conn.deleteCursor(m_cursor);
00173 m_cursor = 0;
00174 return ok;
00175 }
00176
00177 bool KexiSimplePrintingEngine::done()
00178 {
00179 bool result = true;
00180 if (m_cursor && (m_cursor->error() || !m_cursor->connection()->deleteCursor(m_cursor))) {
00181 m_cursor->debugError();
00182 result = false;
00183 }
00184 m_cursor = 0;
00185 delete m_data;
00186 m_data = 0;
00187 m_pagesCount = 0;
00188 m_paintInitialized = false;
00189 m_fieldsExpanded.clear();
00190 m_visibleFieldsCount = 0;
00191 return result;
00192 }
00193
00194 void KexiSimplePrintingEngine::clear()
00195 {
00196 m_eof = false;
00197 m_pagesCount = 0;
00198 m_dataOffsets.clear();
00199 m_dataOffsets.append(new uint(0));
00200 m_paintInitialized = false;
00201 }
00202
00203 void KexiSimplePrintingEngine::paintPage(int pageNumber, QPainter& painter, bool paint)
00204 {
00205 uint offset = 0;
00206 if (pageNumber < (int)m_dataOffsets.count()) {
00207 offset = *m_dataOffsets.at(pageNumber);
00208 }
00209
00210 uint y = 0;
00211
00212 const bool printer = painter.device()->devType() == QInternal::Printer;
00213
00214 int w = 0, h = 0;
00215 m_pdm = QPaintDeviceMetrics( painter.device() );
00216
00217 if (dynamic_cast<QWidget*>(painter.device())) {
00218 w = dynamic_cast<QWidget*>(painter.device())->width();
00219 h = dynamic_cast<QWidget*>(painter.device())->height();
00220 }
00221 else if (dynamic_cast<QPixmap*>(painter.device())) {
00222 w = dynamic_cast<QPixmap*>(painter.device())->width();
00223 h = dynamic_cast<QPixmap*>(painter.device())->height();
00224 }
00225 else {
00226 w = m_pdm.widthMM();
00227 h = m_pdm.heightMM();
00228 }
00229
00230 if (!m_paintInitialized) {
00231 m_paintInitialized = true;
00232
00233 double widthMM = KoPageFormat::width(
00234 m_settings->pageLayout.format, m_settings->pageLayout.orientation);
00235 double heightMM = KoPageFormat::height(
00236 m_settings->pageLayout.format, m_settings->pageLayout.orientation);
00237
00238 m_dpiY = m_pdm.logicalDpiY();
00239 m_dpiX = m_pdm.logicalDpiX();
00240 #ifdef Q_WS_WIN //fix for 120dpi
00241 if (!printer) {
00242
00243
00244 m_dpiY = 86;
00245 m_dpiX = 86;
00246 }
00247 #endif
00248 int pdWidthMM = m_pdm.widthMM();
00249 int pdHeightMM = m_pdm.heightMM();
00250
00251 double screenF;
00252
00253 screenF = 1.0;
00254
00255
00256
00257 leftMargin = POINT_TO_INCH(m_settings->pageLayout.ptLeft)*m_dpiX* screenF;
00258 rightMargin = POINT_TO_INCH(m_settings->pageLayout.ptRight)*m_dpiX* screenF;
00259 topMargin = POINT_TO_INCH(m_settings->pageLayout.ptTop)*m_dpiY* screenF;
00260 bottomMargin = POINT_TO_INCH(m_settings->pageLayout.ptBottom)*m_dpiY* screenF;
00261
00262 m_fx = widthMM / (pdWidthMM * screenF);
00263 m_fy = heightMM / (pdHeightMM * screenF);
00264
00265
00266
00267 m_pageWidth = int( m_fx*(double)m_pdm.width() - leftMargin - rightMargin);
00268 m_pageHeight = int( m_fy*(double)m_pdm.height() - topMargin - bottomMargin);
00269 m_headerFont = m_settings->pageTitleFont;
00270 if(!printer) {
00271 int pixelSize = int( POINT_TO_INCH((double)QFontInfo(m_headerFont).pointSize())*m_dpiX );
00272 m_headerFont.setPixelSize(pixelSize);
00273 }
00274
00276 m_mainFont = kapp->font();
00277 if(!printer) {
00278 int pixelSize = int( POINT_TO_INCH(m_mainFont.pointSizeFloat())*m_dpiX );
00279 m_mainFont.setPixelSize(pixelSize);
00280 }
00281 painter.setFont(m_mainFont);
00282
00283 m_dateTimeText = KGlobal::locale()->formatDateTime(QDateTime::currentDateTime(),
00284 true, false);
00285 m_dateTimeWidth = painter.fontMetrics().width(m_dateTimeText+" ");
00286 m_mainLineSpacing = painter.fontMetrics().lineSpacing();
00287 m_footerHeight = m_mainLineSpacing * 2;
00288 painter.setFont(m_headerFont);
00289 m_headerTextRect = painter.fontMetrics().boundingRect(
00290 (int)leftMargin, (int)topMargin,
00291 m_pageWidth - m_dateTimeWidth,
00292 m_pageHeight, Qt::AlignAuto|Qt::WordBreak, m_headerText);
00293 m_headerTextRect.setRight(m_headerTextRect.right()+10);
00294 m_headerTextRect.setWidth(
00295 QMIN(int(m_pageWidth - m_dateTimeWidth), m_headerTextRect.width()));
00296
00297
00298 m_maxFieldNameWidth = 0;
00299
00300 painter.setFont(m_mainFont);
00301 for (uint i=0; i < m_visibleFieldsCount; i++) {
00302 const int newW =
00303 painter.fontMetrics().width(m_fieldsExpanded[i]->captionOrAliasOrName()+":");
00304
00305
00306 if (m_maxFieldNameWidth < newW)
00307 m_maxFieldNameWidth = newW;
00308 }
00309 m_maxFieldNameWidth += painter.fontMetrics().width("ww");
00310 }
00311
00312
00313 if(!printer) {
00314 painter.setWindow(0, 0, int((double)w*m_fx), int((double)h*m_fy));
00315 }
00316
00317
00318 painter.setFont(m_headerFont);
00319 if (paint) {
00320 painter.drawText(m_headerTextRect, Qt::AlignAuto|Qt::WordBreak, m_headerText);
00321 }
00322 painter.setFont(m_mainFont);
00323 if (paint) {
00324 painter.drawText((int)leftMargin + m_pageWidth - m_dateTimeWidth,
00325 (int)topMargin, m_dateTimeWidth,
00326 m_headerTextRect.height(), Qt::AlignRight, m_dateTimeText);
00327
00328
00329 QString pageNumString;
00330 if (m_pagesCount>0)
00331 pageNumString = i18n("Page (number) of (total)", "Page %1 of %2")
00332 .arg(pageNumber+1).arg(m_pagesCount);
00333 else
00334 pageNumString = i18n("Page %1").arg(pageNumber+1);
00335 painter.drawText((int)leftMargin,
00336 (int)topMargin + m_pageHeight - m_mainLineSpacing,
00337 m_pageWidth, m_mainLineSpacing,
00338 Qt::AlignRight | Qt::AlignBottom, pageNumString);
00339 painter.drawLine((int)leftMargin,
00340 (int)topMargin + m_pageHeight - m_mainLineSpacing*3/2,
00341 (int)leftMargin + m_pageWidth,
00342 (int)topMargin + m_pageHeight - m_mainLineSpacing*3/2);
00343 }
00344 y = (int)topMargin + m_headerTextRect.height() + m_mainLineSpacing/2;
00345 if (!m_settings->addTableBorders) {
00346
00347 if (paint)
00348 painter.drawLine((int)leftMargin, y, (int)leftMargin + m_pageWidth-1, y);
00349 y += m_mainLineSpacing;
00350 }
00351
00352
00353 KexiDB::RowData row;
00354 KexiTableItem *item;
00355
00356
00357 const uint rows = m_data->count();
00358 const int cellMargin = m_settings->addTableBorders ?
00359 painter.fontMetrics().width("i") : 0;
00360 uint paintedRows = 0;
00361 for (;offset < rows; ++offset) {
00362 item = m_data->at(offset);
00363
00364
00365 uint newY = y;
00366 paintRecord(painter, item, cellMargin, newY, paintedRows, false);
00367 if ((int(topMargin + m_pageHeight-(int)newY-m_footerHeight)) < 0 && paintedRows > 0) {
00368
00369
00371 break;
00372 }
00373
00374
00375
00376
00377
00378
00379 if (paint)
00380 paintRecord(painter, item, cellMargin, y, paintedRows, paint);
00381 else
00382 y = newY;
00383 paintedRows++;
00384 }
00385
00386 if (int(m_dataOffsets.count()-1)==pageNumber) {
00387 m_dataOffsets.append(new uint(offset));
00388 }
00389 m_eof = offset == rows;
00390 }
00391
00392 void KexiSimplePrintingEngine::paintRecord(QPainter& painter, KexiTableItem *item,
00393 int cellMargin, uint &y, uint paintedRows, bool paint)
00394 {
00395 if (paintedRows>0 && !m_settings->addTableBorders) {
00396 if (paint) {
00397 painter.setPen(Qt::darkGray);
00398 painter.drawLine(
00399 (int)leftMargin, y-m_mainLineSpacing,
00400 (int)leftMargin+m_pageWidth-1, y-m_mainLineSpacing);
00401 painter.setPen(Qt::black);
00402 }
00403 }
00404
00405 for (uint i=0; i<m_visibleFieldsCount; i++) {
00406
00407 if (paint) {
00408 painter.drawText(
00409 (int)leftMargin+cellMargin, y, m_maxFieldNameWidth-cellMargin*2, m_mainLineSpacing,
00410 Qt::AlignTop, m_fieldsExpanded[i]->captionOrAliasOrName()
00411 + (m_settings->addTableBorders ? "" : ":"));
00412 }
00413 QString text;
00415
00416 KexiDB::QueryColumnInfo* ci;
00417 int indexForVisibleLookupValue = m_fieldsExpanded[i]->indexForVisibleLookupValue();
00418 if (-1 != indexForVisibleLookupValue && indexForVisibleLookupValue < (int)item->count())
00419 ci = m_fieldsExpanded[ indexForVisibleLookupValue ];
00420 else {
00421 ci = m_fieldsExpanded[ i ];
00422 indexForVisibleLookupValue = i;
00423 }
00424
00425 QVariant v(item->at( indexForVisibleLookupValue ));
00426 KexiDB::Field::Type ftype = ci->field->type();
00427 if (v.isNull() || !v.isValid()) {
00428
00429 }
00431 else if (ftype==KexiDB::Field::DateTime) {
00432 QDateTime dt(v.toDateTime());
00433 if (dt.isValid())
00434 text = KGlobal::locale()->formatDateTime(dt);
00435 }
00437 else if (ftype==KexiDB::Field::Date) {
00438 QDate date(v.toDate());
00439 if (date.isValid())
00440 text = KGlobal::locale()->formatDate(date, true);
00441 }
00443 else if (ftype==KexiDB::Field::Time) {
00444 QTime time(v.toTime());
00445 if (time.isValid())
00446 text = KGlobal::locale()->formatTime(time);
00447 }
00449 else if (ci->field->isFPNumericType())
00450 text = KGlobal::locale()->formatNumber(v.toDouble());
00451 else if (ftype==KexiDB::Field::Boolean)
00452 text = v.toBool()
00453 ? i18n("Boolean Yes (true)","Yes") : i18n("Boolean No (false)", "No");
00454 else
00455 text = v.toString();
00456 QRect rect( painter.fontMetrics().boundingRect(
00457 (int)leftMargin + m_maxFieldNameWidth + cellMargin, y,
00458 m_pageWidth - m_maxFieldNameWidth - cellMargin*2, m_pageHeight - y,
00459 Qt::AlignAuto|Qt::WordBreak, text) );
00460 if (paint) {
00461 painter.drawText(
00462 rect.x(), rect.y(), rect.width(), rect.height(),
00463 Qt::AlignTop|Qt::WordBreak, text);
00464 }
00465 if (m_settings->addTableBorders) {
00466 if (paint) {
00467 painter.setPen(Qt::darkGray);
00468 painter.drawLine(
00469 (int)leftMargin, rect.top(), (int)leftMargin+m_pageWidth-1, rect.top());
00470 painter.drawLine(
00471 (int)leftMargin, rect.top(), (int)leftMargin, rect.bottom());
00472 painter.drawLine(
00473 (int)leftMargin+m_pageWidth-1, rect.top(),
00474 (int)leftMargin+m_pageWidth-1, rect.bottom());
00475 painter.drawLine(
00476 (int)leftMargin+m_maxFieldNameWidth, rect.top(),
00477 (int)leftMargin+m_maxFieldNameWidth, rect.bottom());
00478 painter.setPen(Qt::black);
00479 }
00480 }
00481 y += rect.height();
00482 }
00483 if (m_settings->addTableBorders) {
00484 if (paint) {
00485 painter.setPen(Qt::darkGray);
00486 painter.drawLine(
00487 (int)leftMargin, y, (int)leftMargin+m_pageWidth-1, y);
00488 painter.setPen(Qt::black);
00489 }
00490 }
00491
00492 y += m_mainLineSpacing*3/2;
00493
00494
00495 }
00496
00497 void KexiSimplePrintingEngine::calculatePagesCount(QPainter& painter)
00498 {
00499 if (m_eof || !m_data) {
00500 m_pagesCount = 0;
00501 return;
00502 }
00503
00504 uint pageNumber = 0;
00505 for(;!m_eof; ++pageNumber) {
00506 paintPage(pageNumber, painter, false );
00507 }
00508 m_pagesCount = pageNumber;
00509 }
00510
00511 void KexiSimplePrintingEngine::setTitleText(const QString& titleText)
00512 {
00513 m_headerText = titleText;
00514 }
00515
00516 #include "kexisimpleprintingengine.moc"