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_dataOffsets.setAutoDelete(true);
00128 clear();
00129 }
00130
00131 KexiSimplePrintingEngine::~KexiSimplePrintingEngine()
00132 {
00133 done();
00134 }
00135
00136 bool KexiSimplePrintingEngine::init(KexiDB::Connection& conn,
00137 KexiDB::TableOrQuerySchema& tableOrQuery, const QString& titleText, QString& errorMessage)
00138 {
00139 errorMessage = QString::null;
00140 done();
00141 m_headerText = titleText;
00142
00143
00144 KexiDB::QuerySchema *query = 0;
00145 if (tableOrQuery.table())
00146 query = tableOrQuery.table()->query();
00147 else
00148 query = tableOrQuery.query();
00149 if (!query) {
00150 errorMessage = i18n("Could not load data from table or query.");
00151 return false;
00152 }
00153
00154 m_cursor = conn.executeQuery(*query);
00155 if (!m_cursor) {
00156 conn.debugError();
00157 return false;
00158 }
00159 bool ok = !m_cursor->error();
00160 if (ok) {
00161 m_data = new KexiTableViewData(m_cursor);
00163 m_data->preloadAllRows();
00164 m_fieldsExpanded = KexiDB::QueryColumnInfo::Vector( query->fieldsExpanded() );
00165 }
00166 else {
00167 conn.debugError();
00168 }
00169 m_eof = !ok || m_data->count() == 0;
00170 conn.deleteCursor(m_cursor);
00171 m_cursor = 0;
00172 return ok;
00173 }
00174
00175 bool KexiSimplePrintingEngine::done()
00176 {
00177 bool result = true;
00178 if (m_cursor && (m_cursor->error() || !m_cursor->connection()->deleteCursor(m_cursor))) {
00179 m_cursor->debugError();
00180 result = false;
00181 }
00182 m_cursor = 0;
00183 delete m_data;
00184 m_data = 0;
00185 m_pagesCount = 0;
00186 m_paintInitialized = false;
00187 m_fieldsExpanded.clear();
00188 return result;
00189 }
00190
00191 void KexiSimplePrintingEngine::clear()
00192 {
00193 m_eof = false;
00194 m_pagesCount = 0;
00195 m_dataOffsets.clear();
00196 m_dataOffsets.append(new uint(0));
00197 m_paintInitialized = false;
00198 }
00199
00200 void KexiSimplePrintingEngine::paintPage(int pageNumber, QPainter& painter, bool paint)
00201 {
00202 uint offset = 0;
00203 if (pageNumber < (int)m_dataOffsets.count()) {
00204 offset = *m_dataOffsets.at(pageNumber);
00205 }
00206
00207 uint y = 0;
00208
00209 const bool printer = painter.device()->devType() == QInternal::Printer;
00210
00211 int w = 0, h = 0;
00212 m_pdm = QPaintDeviceMetrics( painter.device() );
00213
00214 if (dynamic_cast<QWidget*>(painter.device())) {
00215 w = dynamic_cast<QWidget*>(painter.device())->width();
00216 h = dynamic_cast<QWidget*>(painter.device())->height();
00217 }
00218 else if (dynamic_cast<QPixmap*>(painter.device())) {
00219 w = dynamic_cast<QPixmap*>(painter.device())->width();
00220 h = dynamic_cast<QPixmap*>(painter.device())->height();
00221 }
00222 else {
00223 w = m_pdm.widthMM();
00224 h = m_pdm.heightMM();
00225 }
00226
00227 if (!m_paintInitialized) {
00228 m_paintInitialized = true;
00229
00230 double widthMM = KoPageFormat::width(
00231 m_settings->pageLayout.format, m_settings->pageLayout.orientation);
00232 double heightMM = KoPageFormat::height(
00233 m_settings->pageLayout.format, m_settings->pageLayout.orientation);
00234
00235 m_dpiY = m_pdm.logicalDpiY();
00236 m_dpiX = m_pdm.logicalDpiX();
00237 #ifdef Q_WS_WIN //fix for 120dpi
00238 if (!printer) {
00239
00240
00241 m_dpiY = 86;
00242 m_dpiX = 86;
00243 }
00244 #endif
00245 int pdWidthMM = m_pdm.widthMM();
00246 int pdHeightMM = m_pdm.heightMM();
00247
00248 double screenF;
00249
00250 screenF = 1.0;
00251
00252
00253
00254 leftMargin = POINT_TO_INCH(m_settings->pageLayout.ptLeft)*m_dpiX* screenF;
00255 rightMargin = POINT_TO_INCH(m_settings->pageLayout.ptRight)*m_dpiX* screenF;
00256 topMargin = POINT_TO_INCH(m_settings->pageLayout.ptTop)*m_dpiY* screenF;
00257 bottomMargin = POINT_TO_INCH(m_settings->pageLayout.ptBottom)*m_dpiY* screenF;
00258
00259 m_fx = widthMM / (pdWidthMM * screenF);
00260 m_fy = heightMM / (pdHeightMM * screenF);
00261
00262
00263
00264 m_pageWidth = int( m_fx*(double)m_pdm.width() - leftMargin - rightMargin);
00265 m_pageHeight = int( m_fy*(double)m_pdm.height() - topMargin - bottomMargin);
00266 m_headerFont = m_settings->pageTitleFont;
00267 if(!printer) {
00268 int pixelSize = int( POINT_TO_INCH((double)QFontInfo(m_headerFont).pointSize())*m_dpiX );
00269 m_headerFont.setPixelSize(pixelSize);
00270 }
00271
00273 m_mainFont = kapp->font();
00274 if(!printer) {
00275 int pixelSize = int( POINT_TO_INCH(m_mainFont.pointSizeFloat())*m_dpiX );
00276 m_mainFont.setPixelSize(pixelSize);
00277 }
00278 painter.setFont(m_mainFont);
00279
00280 m_dateTimeText = KGlobal::locale()->formatDateTime(QDateTime::currentDateTime(),
00281 true, false);
00282 m_dateTimeWidth = painter.fontMetrics().width(m_dateTimeText+" ");
00283 m_mainLineSpacing = painter.fontMetrics().lineSpacing();
00284 m_footerHeight = m_mainLineSpacing * 2;
00285 painter.setFont(m_headerFont);
00286 m_headerTextRect = painter.fontMetrics().boundingRect(
00287 (int)leftMargin, (int)topMargin,
00288 m_pageWidth - m_dateTimeWidth,
00289 m_pageHeight, Qt::AlignAuto|Qt::WordBreak, m_headerText);
00290 m_headerTextRect.setRight(m_headerTextRect.right()+10);
00291 m_headerTextRect.setWidth(
00292 QMIN(int(m_pageWidth - m_dateTimeWidth), m_headerTextRect.width()));
00293
00294
00295 m_maxFieldNameWidth = 0;
00296
00297 painter.setFont(m_mainFont);
00298 for (uint i=0; i < m_fieldsExpanded.count(); i++) {
00299 const int newW =
00300 painter.fontMetrics().width(m_fieldsExpanded[i]->captionOrAliasOrName()+":");
00301
00302
00303 if (m_maxFieldNameWidth < newW)
00304 m_maxFieldNameWidth = newW;
00305 }
00306 m_maxFieldNameWidth += painter.fontMetrics().width("ww");
00307 }
00308
00309
00310 if(!printer) {
00311 painter.setWindow(0, 0, int((double)w*m_fx), int((double)h*m_fy));
00312 }
00313
00314
00315 painter.setFont(m_headerFont);
00316 if (paint) {
00317 painter.drawText(m_headerTextRect, Qt::AlignAuto|Qt::WordBreak, m_headerText);
00318 }
00319 painter.setFont(m_mainFont);
00320 if (paint) {
00321 painter.drawText((int)leftMargin + m_pageWidth - m_dateTimeWidth,
00322 (int)topMargin, m_dateTimeWidth,
00323 m_headerTextRect.height(), Qt::AlignRight, m_dateTimeText);
00324
00325
00326 QString pageNumString;
00327 if (m_pagesCount>0)
00328 pageNumString = i18n("Page (number) of (total)", "Page %1 of %2")
00329 .arg(pageNumber+1).arg(m_pagesCount);
00330 else
00331 pageNumString = i18n("Page %1").arg(pageNumber+1);
00332 painter.drawText((int)leftMargin,
00333 (int)topMargin + m_pageHeight - m_mainLineSpacing,
00334 m_pageWidth, m_mainLineSpacing,
00335 Qt::AlignRight | Qt::AlignBottom, pageNumString);
00336 painter.drawLine((int)leftMargin,
00337 (int)topMargin + m_pageHeight - m_mainLineSpacing*3/2,
00338 (int)leftMargin + m_pageWidth,
00339 (int)topMargin + m_pageHeight - m_mainLineSpacing*3/2);
00340 }
00341 y = (int)topMargin + m_headerTextRect.height() + m_mainLineSpacing/2;
00342 if (!m_settings->addTableBorders) {
00343
00344 if (paint)
00345 painter.drawLine((int)leftMargin, y, (int)leftMargin + m_pageWidth-1, y);
00346 y += m_mainLineSpacing;
00347 }
00348
00349
00350 KexiDB::RowData row;
00351 KexiTableItem *item;
00352 const uint count = m_fieldsExpanded.count();
00353 const uint rows = m_data->count();
00354 const int cellMargin = m_settings->addTableBorders ?
00355 painter.fontMetrics().width("i") : 0;
00356 uint paintedRows = 0;
00357 for (;offset < rows; ++offset) {
00358 item = m_data->at(offset);
00359
00360
00361 uint newY = y;
00362 paintRecord(painter, item, count, cellMargin, newY, paintedRows, false);
00363 if ((int(topMargin + m_pageHeight-(int)newY-m_footerHeight)) < 0 && paintedRows > 0) {
00364
00365
00367 break;
00368 }
00369
00370
00371
00372
00373
00374
00375 if (paint)
00376 paintRecord(painter, item, count, cellMargin, y, paintedRows, paint);
00377 else
00378 y = newY;
00379 paintedRows++;
00380 }
00381
00382 if (int(m_dataOffsets.count()-1)==pageNumber) {
00383 m_dataOffsets.append(new uint(offset));
00384 }
00385 m_eof = offset == rows;
00386 }
00387
00388 void KexiSimplePrintingEngine::paintRecord(QPainter& painter, KexiTableItem *item,
00389 uint count, int cellMargin, uint &y, uint paintedRows, bool paint)
00390 {
00391 if (paintedRows>0 && !m_settings->addTableBorders) {
00392 if (paint) {
00393 painter.setPen(Qt::darkGray);
00394 painter.drawLine(
00395 (int)leftMargin, y-m_mainLineSpacing,
00396 (int)leftMargin+m_pageWidth-1, y-m_mainLineSpacing);
00397 painter.setPen(Qt::black);
00398 }
00399 }
00400
00401 for (uint i=0; i<count; i++) {
00402
00403 if (paint) {
00404 painter.drawText(
00405 (int)leftMargin+cellMargin, y, m_maxFieldNameWidth-cellMargin*2, m_mainLineSpacing,
00406 Qt::AlignTop, m_fieldsExpanded[i]->captionOrAliasOrName()
00407 + (m_settings->addTableBorders ? "" : ":"));
00408 }
00409 QString text;
00410 QVariant v(item->at(i));
00411 KexiDB::Field::Type ftype = m_fieldsExpanded[i]->field->type();
00412 if (v.isNull() || !v.isValid()) {
00413
00414 }
00416 else if (ftype==KexiDB::Field::DateTime) {
00417 QDateTime dt(v.toDateTime());
00418 if (dt.isValid())
00419 text = KGlobal::locale()->formatDateTime(dt);
00420 }
00422 else if (ftype==KexiDB::Field::Date) {
00423 QDate date(v.toDate());
00424 if (date.isValid())
00425 text = KGlobal::locale()->formatDate(date, true);
00426 }
00428 else if (ftype==KexiDB::Field::Time) {
00429 QTime time(v.toTime());
00430 if (time.isValid())
00431 text = KGlobal::locale()->formatTime(time);
00432 }
00434 else if (m_fieldsExpanded[i]->field->isFPNumericType())
00435 text = KGlobal::locale()->formatNumber(v.toDouble());
00436 else if (ftype==KexiDB::Field::Boolean)
00437 text = v.toBool()
00438 ? i18n("Boolean Yes (true)","Yes") : i18n("Boolean No (false)", "No");
00439 else
00440 text = v.toString();
00441 QRect rect( painter.fontMetrics().boundingRect(
00442 (int)leftMargin + m_maxFieldNameWidth + cellMargin, y,
00443 m_pageWidth - m_maxFieldNameWidth - cellMargin*2, m_pageHeight - y,
00444 Qt::AlignAuto|Qt::WordBreak, text) );
00445 if (paint) {
00446 painter.drawText(
00447 rect.x(), rect.y(), rect.width(), rect.height(),
00448 Qt::AlignTop|Qt::WordBreak, text);
00449 }
00450 if (m_settings->addTableBorders) {
00451 if (paint) {
00452 painter.setPen(Qt::darkGray);
00453 painter.drawLine(
00454 (int)leftMargin, rect.top(), (int)leftMargin+m_pageWidth-1, rect.top());
00455 painter.drawLine(
00456 (int)leftMargin, rect.top(), (int)leftMargin, rect.bottom());
00457 painter.drawLine(
00458 (int)leftMargin+m_pageWidth-1, rect.top(),
00459 (int)leftMargin+m_pageWidth-1, rect.bottom());
00460 painter.drawLine(
00461 (int)leftMargin+m_maxFieldNameWidth, rect.top(),
00462 (int)leftMargin+m_maxFieldNameWidth, rect.bottom());
00463 painter.setPen(Qt::black);
00464 }
00465 }
00466 y += rect.height();
00467 }
00468 if (m_settings->addTableBorders) {
00469 if (paint) {
00470 painter.setPen(Qt::darkGray);
00471 painter.drawLine(
00472 (int)leftMargin, y, (int)leftMargin+m_pageWidth-1, y);
00473 painter.setPen(Qt::black);
00474 }
00475 }
00476
00477 y += m_mainLineSpacing*3/2;
00478
00479
00480 }
00481
00482 void KexiSimplePrintingEngine::calculatePagesCount(QPainter& painter)
00483 {
00484 if (m_eof || !m_data) {
00485 m_pagesCount = 0;
00486 return;
00487 }
00488
00489 uint pageNumber = 0;
00490 for(;!m_eof; ++pageNumber) {
00491 paintPage(pageNumber, painter, false );
00492 }
00493 m_pagesCount = pageNumber;
00494 }
00495
00496 void KexiSimplePrintingEngine::setTitleText(const QString& titleText)
00497 {
00498 m_headerText = titleText;
00499 }
00500
00501 #include "kexisimpleprintingengine.moc"