00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "ringbinderstyle.h"
00025
00026 #include <qcheckbox.h>
00027 #include <qlayout.h>
00028 #include <qpaintdevicemetrics.h>
00029 #include <qpainter.h>
00030 #include <qspinbox.h>
00031 #include <qstringlist.h>
00032
00033 #include <kapplication.h>
00034 #include <kcombobox.h>
00035 #include <kconfig.h>
00036 #include <kdebug.h>
00037 #include <klistbox.h>
00038 #include <klocale.h>
00039 #include <kprinter.h>
00040 #include <kstandarddirs.h>
00041 #include <kabc/addresseelist.h>
00042
00043 #include "printingwizard.h"
00044 #include "printprogress.h"
00045 #include "printstyle.h"
00046
00047 #include "rbs_appearance.h"
00048
00049 namespace KABPrinting
00050 {
00051
00052 const char* RingBinderConfigSectionName = "RingBinderPrintStyle";
00053 const char* ShowPhoneNumbers = "ShowPhoneNumbers";
00054 const char* ShowEmailAddresses = "ShowEmailAddresses";
00055 const char* ShowStreetAddresses = "ShowStreetAddresses";
00056 const char* ShowOrganization = "ShowOrganization";
00057 const char* ShowBirthday = "ShowBirthday";
00058 const char* FillWithEmptyFields = "FillWithEmptyFields";
00059 const char* MinNumberOfEmptyFields = "MinNumberOfEmptyFields";
00060 const char* LetterGroups = "LetterGroups";
00061
00062 RingBinderPrintStyle::RingBinderPrintStyle( PrintingWizard* parent,
00063 const char* name )
00064 : PrintStyle( parent, name ),
00065 mPageAppearance( new RingBinderStyleAppearanceForm( parent,
00066 "AppearancePage" ) ),
00067 mPrintProgress( 0 )
00068 {
00069 KConfig * config;
00070 setPreview( "ringbinder-style.png" );
00071
00072
00073 addPage( mPageAppearance, i18n( "Ring Binder Printing Style - Appearance" ) );
00074
00075
00076 config = kapp->config();
00077 config->setGroup( RingBinderConfigSectionName );
00078 mPageAppearance->cbPhoneNumbers->setChecked( config->readBoolEntry( ShowPhoneNumbers, true ) );
00079 mPageAppearance->cbEmails->setChecked( config->readBoolEntry( ShowEmailAddresses, true ) );
00080 mPageAppearance->cbStreetAddresses->setChecked( config->readBoolEntry( ShowStreetAddresses, true ) );
00081 mPageAppearance->cbOrganization->setChecked( config->readBoolEntry( ShowOrganization, true ) );
00082 mPageAppearance->cbBirthday->setChecked( config->readBoolEntry( ShowBirthday, false ) );
00083 mPageAppearance->cbFillEmpty->setChecked( config->readBoolEntry( FillWithEmptyFields, true ) );
00084 mPageAppearance->sbMinNumFill->setValue( config->readUnsignedNumEntry( MinNumberOfEmptyFields, 0 ) );
00085 QStringList tabNames = config->readListEntry( LetterGroups, ',' );
00086 if ( tabNames.isEmpty() ) {
00087 tabNames = QStringList::split( ',', QString( "AB,CD,EF,GH,IJK,LM,NO,PQR,S,TU,VW,XYZ" ) );
00088 }
00089 mPageAppearance->letterListBox->insertStringList( tabNames );
00090 }
00091
00092 RingBinderPrintStyle::~RingBinderPrintStyle()
00093 {}
00094
00095 void RingBinderPrintStyle::print( KABC::Addressee::List &contacts, PrintProgress *progress )
00096 {
00097 mPrintProgress = progress;
00098 progress->addMessage( i18n( "Setting up fonts and colors" ) );
00099 progress->setProgress( 0 );
00100
00101
00102 KConfig *config = kapp->config();
00103 config->setGroup( RingBinderConfigSectionName );
00104 config->writeEntry( ShowPhoneNumbers, mPageAppearance->cbPhoneNumbers->isChecked() );
00105 config->writeEntry( ShowEmailAddresses, mPageAppearance->cbEmails->isChecked() );
00106 config->writeEntry( ShowStreetAddresses, mPageAppearance->cbStreetAddresses->isChecked() );
00107 config->writeEntry( ShowOrganization, mPageAppearance->cbOrganization->isChecked() );
00108 config->writeEntry( ShowBirthday, mPageAppearance->cbBirthday->isChecked() );
00109 config->writeEntry( FillWithEmptyFields, mPageAppearance->cbFillEmpty->isChecked() );
00110 config->writeEntry( MinNumberOfEmptyFields, mPageAppearance->sbMinNumFill->value() );
00111 QStringList tmpstrl;
00112 for ( uint i = 0; i < mPageAppearance->letterListBox->count(); i++ ) {
00113 if ( !mPageAppearance->letterListBox->text( i ).isEmpty() ) {
00114 tmpstrl.append( mPageAppearance->letterListBox->text( i ) );
00115 }
00116 }
00117 config->writeEntry( LetterGroups, tmpstrl );
00118
00119 KPrinter *printer = wizard() ->printer();
00120 QPainter painter;
00121
00122
00123 progress->addMessage( i18n( "Setting up margins and spacing" ) );
00124 int marginTop = 0,
00125 marginLeft = 64,
00126 marginRight = 0,
00127 marginBottom = 0;
00128 register int left, top, width, height;
00129
00130
00131 painter.begin( printer );
00132 painter.setPen( Qt::black );
00133 printer->setFullPage( true );
00134 QPaintDeviceMetrics metrics( printer );
00135 kdDebug(5720) << "RingBinderPrintStyle::print: printing on a "
00136 << metrics.width() << "x" << metrics.height()
00137 << " size area," << endl << " "
00138 << "margins are "
00139 << printer->margins().width() << " (left/right) and "
00140 << printer->margins().height() << " (top/bottom)." << endl;
00141 left = QMAX( printer->margins().width(), marginLeft );
00142 top = QMAX( printer->margins().height(), marginTop );
00143 width = metrics.width() - left
00144 - QMAX( printer->margins().width(), marginRight );
00145 height = metrics.height() - top
00146 - QMAX( printer->margins().height(), marginBottom );
00147
00148
00149
00150 painter.setViewport( left, top, width, height );
00151 progress->addMessage( i18n( "Printing" ) );
00152 printEntries( contacts, printer, &painter,
00153 QRect( 0, 0, metrics.width(), metrics.height() ) );
00154 progress->addMessage( i18n( "Done" ) );
00155 painter.end();
00156 config->sync();
00157 }
00158
00159 bool RingBinderPrintStyle::printEntries( KABC::Addressee::List &contacts,
00160 KPrinter *printer,
00161 QPainter *painter,
00162 const QRect& window )
00163 {
00164
00165
00166
00167
00168
00169 KABC::AddresseeList * tmpl = ( KABC::AddresseeList* ) & contacts;
00170 #if KDE_VERSION >= 319
00171 KABC::Field* sfield = tmpl->sortingField();
00172 #else
00173 KABC::Field* sfield = *(KABC::Field::defaultFields().begin());
00174 #endif
00175
00176
00177
00178 QStringList ltgroups;
00179 if ( !tmpl->reverseSorting() ) {
00180 for ( unsigned int i = 0; i < mPageAppearance->letterListBox->count(); i++ ) {
00181 ltgroups.append( mPageAppearance->letterListBox->text( i ) );
00182 }
00183 } else {
00184 for ( unsigned int i = mPageAppearance->letterListBox->count() - 1; i > 0; i-- ) {
00185 ltgroups.append( mPageAppearance->letterListBox->text( i ) );
00186 }
00187 }
00188
00189
00190 int ypos = 0;
00191
00192 int count = 0;
00193
00194
00195 uint grpnum = 0;
00196
00197
00198 printPageHeader( ltgroups[ grpnum ], window, painter );
00199 ypos = pageHeaderMetrics( window, painter ).height();
00200 for ( KABC::AddresseeList::iterator it = contacts.begin();
00201 it != contacts.end(); ++it ) {
00202 KABC::Addressee addressee = ( *it );
00203 if ( !addressee.isEmpty() ) {
00204
00205 while ( ltgroups.count() > grpnum + 1 ) {
00206 QChar nextchar;
00207 QChar nowchar;
00208 if ( !tmpl->reverseSorting() ) {
00209 nextchar = ltgroups[ grpnum + 1 ].at( 0 ).upper();
00210 } else {
00211 QString tmpstr = ltgroups[ grpnum + 1 ];
00212 nextchar = tmpstr.at( tmpstr.length() - 1 ).upper();
00213 kdDebug(5720) << "################### " << tmpstr << " last is: " <<
00214 QString(nextchar) << endl;
00215 }
00216
00217
00218 {
00219 QString tmpstr = sfield->value( addressee );
00220 if ( !tmpstr.isEmpty() ) {
00221 nowchar = tmpstr.at( 0 ).upper();
00222 kdDebug(5720) << "------------------ " << tmpstr << " has nowchar: "
00223 << QString(nowchar) << endl;
00224 }
00225 }
00226 if ( ( !tmpl->reverseSorting() && nowchar >= nextchar )
00227 || ( tmpl->reverseSorting() && nowchar <= nextchar ) ) {
00228
00229
00230
00231
00232 fillEmpty( window, printer, painter, ypos, grpnum );
00233
00234
00235 grpnum++;
00236 printer->newPage();
00237 printPageHeader( ltgroups[ grpnum ], window, painter );
00238 ypos = pageHeaderMetrics( window, painter ).height();
00239
00240 } else {
00241 break;
00242 }
00243 }
00244
00245 kdDebug(5720) << "RingBinderPrintStyle::printEntries: printing addressee "
00246 << addressee.realName() << endl;
00247
00248
00249 int entryheight = entryMetrics( addressee, window, painter, ypos ).height();
00250
00251
00252
00253 if ( entryheight > ( window.height() - ypos )
00254 && !( entryheight > window.height() ) ) {
00255
00256 printer->newPage();
00257 printPageHeader( mPageAppearance->letterListBox->text( grpnum )
00258 , window, painter );
00259 ypos = pageHeaderMetrics( window, painter ).height();
00260 }
00261 printEntry( addressee, window, painter, ypos );
00262 ypos += entryheight;
00263 } else {
00264 kdDebug(5720) << "RingBinderPrintStyle::printEntries: strange, addressee "
00265 << "with UID " << addressee.uid() << " not available." << endl;
00266 }
00267 mPrintProgress->setProgress( ( count++*100 ) / contacts.count() );
00268 }
00269
00270
00271
00272 fillEmpty( window, printer, painter, ypos, grpnum );
00273
00274 mPrintProgress->setProgress( 100 );
00275 kdDebug(5720) << "PLANNER STYLE: PRINT FINISHED" << endl;
00276 return true;
00277 }
00278
00279 void RingBinderPrintStyle::fillEmpty( const QRect& window
00280 , KPrinter *printer
00281 , QPainter* painter
00282 , int top
00283 , int grpnum
00284 )
00285 {
00286 if ( mPageAppearance->cbFillEmpty->isChecked() ) {
00287
00288 int ypos = top;
00289 int fieldscounter = 0;
00290 int entryheight = emptyEntryMetrics( window, painter, ypos ).height();
00291 do {
00292 while ( ( window.height() - ypos ) > entryheight ) {
00293 printEmptyEntry( window, painter, ypos );
00294 ypos += entryheight;
00295 fieldscounter++;
00296 }
00297 qDebug( "fieldscounter %i", fieldscounter );
00298 qDebug( "minNumFill %i", mPageAppearance->sbMinNumFill->value() );
00299 if ( fieldscounter < mPageAppearance->sbMinNumFill->value() ) {
00300 printer->newPage();
00301 printPageHeader( mPageAppearance->letterListBox->text( grpnum )
00302 , window, painter );
00303 ypos = pageHeaderMetrics( window, painter ).height();
00304 }
00305 } while ( fieldscounter < mPageAppearance->sbMinNumFill->value() );
00306 }
00307 }
00308
00309 bool RingBinderPrintStyle::printEntry( const KABC::Addressee& contact
00310 , const QRect& window
00311 , QPainter* painter
00312 , int top
00313 , bool fake
00314 , QRect* brect
00315 )
00316 {
00317 QFont normfont( "Helvetica", 10, QFont::Normal );
00318 QFontMetrics fmnorm( normfont );
00319 QPen thickpen( Qt::black, 0 );
00320 QPen thinpen ( Qt::black, 0 );
00321
00322 int linenum = 0;
00323 int maxlines = 0;
00324 painter->setFont( normfont );
00325 linenum++;
00326
00327
00328
00329 if ( !fake ) {
00330 QString namestr = contact.formattedName();
00331 if ( namestr.isEmpty() ) {
00332 namestr = contact.familyName() + ", " + contact.givenName();
00333 }
00334 if ( mPageAppearance->cbOrganization->isChecked()
00335 && !contact.organization().isEmpty() ) {
00336 namestr += QString( " (" ) + contact.organization() + QString( ")" );
00337 }
00338 if ( mPageAppearance->cbBirthday->isChecked() && !contact.birthday().isNull() ) {
00339 namestr += QString( " *" ) + KGlobal::locale()->formatDate(
00340 contact.birthday().date(), true );
00341 }
00342 painter->drawText( 5, top + ( linenum * fmnorm.lineSpacing() )
00343 - fmnorm.leading(), namestr );
00344 }
00345 painter->setFont( normfont );
00346
00347
00348 if ( mPageAppearance->cbStreetAddresses->isChecked() ) {
00349 KABC::Address::List addrl = contact.addresses();
00350 KABC::Address::List::iterator it;
00351 for ( it = addrl.begin(); it != addrl.end(); ++it ) {
00352 if ( !( *it ).isEmpty() ) {
00353
00354
00355
00356
00357
00358 painter->setFont( normfont );
00359 QString formattedAddress;
00360 #if KDE_VERSION >= 319
00361 formattedAddress = (*it).formattedAddress();
00362 #else
00363 formattedAddress = (*it).label();
00364 #endif
00365 QStringList laddr = QStringList::split( QChar( '\n' ),
00366 formattedAddress );
00367 for ( QStringList::iterator it = laddr.begin(); it != laddr.end(); ++it ) {
00368 linenum++;
00369 if ( !fake ) {
00370 painter->drawText( 20, top + ( linenum * fmnorm.lineSpacing() )
00371 - fmnorm.leading(), *it );
00372 }
00373 }
00374 }
00375 }
00376 }
00377 maxlines = linenum;
00378 linenum = 0;
00379
00380
00381 if ( mPageAppearance->cbPhoneNumbers->isChecked() ) {
00382 KABC::PhoneNumber::List phonel = contact.phoneNumbers();
00383 KABC::PhoneNumber::List::iterator nit;
00384 for ( nit = phonel.begin(); nit != phonel.end(); ++nit ) {
00385
00386
00387 if ( ( *nit ).number().isEmpty() ) {
00388 continue;
00389 }
00390 linenum++;
00391
00392
00393 QString numstr = ( *nit ).typeLabel();
00394 if ( !numstr.isEmpty() ) {
00395 numstr.append( ": " );
00396 }
00397 numstr.append( ( *nit ).number() );
00398 painter->drawText( ( int ) ( window.width() * 0.5 ) + 5,
00399 top + ( linenum * fmnorm.lineSpacing() )
00400 - fmnorm.leading(), numstr );
00401 }
00402 }
00403
00404
00405 if ( mPageAppearance->cbEmails->isChecked() ) {
00406 QStringList emails = contact.emails();
00407 for ( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) {
00408
00409 if ( ( *it ).isEmpty() ) {
00410 continue;
00411 }
00412 linenum++;
00413 painter->drawText( ( int ) ( window.width() * 0.5 ) + 5,
00414 top + ( linenum * fmnorm.lineSpacing() )
00415 - fmnorm.leading(), *it );
00416 }
00417 }
00418
00419
00420 if ( linenum > maxlines ) {
00421 maxlines = linenum;
00422 }
00423 if ( brect ) {
00424 brect->setRect( 0, top, window.width(),
00425 ( maxlines * fmnorm.lineSpacing() ) + fmnorm.leading() );
00426 }
00427 if ( fake ) {
00428 return true;
00429 }
00430 painter->setPen( thickpen );
00431 if ( !fake )
00432 painter->drawRect( 0, top, window.width(),
00433 ( maxlines * fmnorm.lineSpacing() ) + fmnorm.leading() );
00434 if ( !fake )
00435 painter->drawLine( ( int ) ( window.width() * 0.5 ), top,
00436 (int)( window.width() * 0.5 ),
00437 top + ( maxlines * fmnorm.lineSpacing() ) + fmnorm.leading() );
00438 painter->setPen( thinpen );
00439 return true;
00440 }
00441
00442 QRect RingBinderPrintStyle::entryMetrics( const KABC::Addressee& contact
00443 , const QRect& window
00444 , QPainter* painter
00445 , int top
00446 )
00447 {
00448 QRect ret;
00449 printEntry( contact, window, painter, top, true, &ret );
00450 return ret;
00451 }
00452
00453 bool RingBinderPrintStyle::printEmptyEntry(
00454 const QRect& window
00455 , QPainter* painter
00456 , int top
00457 )
00458 {
00459 QFont normfont( "Helvetica", 10, QFont::Normal );
00460 QFontMetrics fmnorm( normfont );
00461
00462 QPen thickpen( Qt::black, 0 );
00463 QPen thinpen ( Qt::black, 0 );
00464 painter->setFont( normfont );
00465 painter->setPen( thickpen );
00466 painter->drawRect( 0, top, window.width(), ( 3 * fmnorm.lineSpacing() ) );
00467 painter->setPen( thinpen );
00468 for ( int i = 1; i < 3; i++ ) {
00469 painter->drawLine( 0, top + i * fmnorm.lineSpacing(), window.width(),
00470 top + i * fmnorm.lineSpacing() );
00471 }
00472 painter->drawLine( (int)( window.width() * 0.5 ), top,
00473 (int)( window.width() * 0.5 ), top + ( 3 * fmnorm.lineSpacing() ) );
00474
00475 painter->drawLine( (int)( window.width() * 0.75 ), top,
00476 (int)( window.width() * 0.75 ), top + ( 2 * fmnorm.lineSpacing() ) );
00477
00478
00479 return true;
00480 }
00481
00482 QRect RingBinderPrintStyle::emptyEntryMetrics(
00483 const QRect& window
00484 , QPainter*
00485 , int top
00486 )
00487 {
00488 QFont normfont( "Helvetica", 10, QFont::Normal );
00489 QFontMetrics fmnorm( normfont );
00490 return QRect( 0, top, window.width(), ( 3 * fmnorm.lineSpacing() ) );
00491 }
00492
00493
00494 bool RingBinderPrintStyle::printPageHeader(
00495 const QString section
00496 , const QRect& window
00497 , QPainter* painter
00498 )
00499 {
00500 QFont sectfont( "Helvetica", 16, QFont::Normal );
00501 QFontMetrics fmsect( sectfont );
00502 painter->setFont( sectfont );
00503 painter->drawText( QRect( 0, 0, window.width(), fmsect.height() ),
00504 Qt::AlignRight, section );
00505 return true;
00506 }
00507
00508 QRect RingBinderPrintStyle::pageHeaderMetrics(
00509 const QRect& window
00510 , QPainter*
00511 )
00512 {
00513 QFont sectfont( "Helvetica", 16, QFont::Normal );
00514 QFont normfont( "Helvetica", 12, QFont::Normal );
00515 QFontMetrics fmsect( sectfont );
00516 QFontMetrics fmnorm( normfont );
00517 return QRect( 0, 0, window.width(), fmsect.height() + 10 );
00518 }
00519
00520
00521 RingBinderPrintStyleFactory::RingBinderPrintStyleFactory(
00522 PrintingWizard* parent,
00523 const char* name )
00524 : PrintStyleFactory( parent, name )
00525 {}
00526
00527
00528 PrintStyle *RingBinderPrintStyleFactory::create()
00529 {
00530 return new RingBinderPrintStyle( mParent, mName );
00531 }
00532
00533 QString RingBinderPrintStyleFactory::description()
00534 {
00535 return i18n( "Printout for Ring Binders" );
00536 }
00537
00538 }
00539
00540 #include "ringbinderstyle.moc"
00541