kaddressbook

kabentrypainter.cpp

00001 /*
00002     This file is part of KAddressBook.
00003     Copyright (c) 1996-2002 Mirko Boehm <mirko@kde.org>
00004 
00005     This program is free software; you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018 
00019     As a special exception, permission is given to link this program
00020     with any edition of Qt, and distribute the resulting executable,
00021     without including the source code for Qt in the source distribution.
00022 */
00023 
00024 
00025 #include <qpaintdevicemetrics.h>
00026 #include <qpainter.h>
00027 
00028 #include <kdebug.h>
00029 #include <kglobal.h>
00030 #include <klocale.h>
00031 #include <knotifyclient.h>
00032 #include <kprinter.h>
00033 #include <kurl.h>
00034 
00035 #include "kabentrypainter.h"
00036 
00037 KABEntryPainter::KABEntryPainter()
00038   : mShowAddresses( true ), mShowEmails( true ), mShowPhones( true ),
00039     mShowURLs( true )
00040 {
00041 }
00042 
00043 KABEntryPainter::~KABEntryPainter()
00044 {
00045   mEmailRects.clear();
00046   mPhoneRects.clear();
00047   mURLRects.clear();
00048   mTalkRects.clear();
00049 }
00050 
00051 void KABEntryPainter::setForegroundColor( const QColor &color )
00052 {
00053   mForegroundColor = color;
00054 }
00055 
00056 void KABEntryPainter::setBackgroundColor( const QColor &color )
00057 {
00058   mBackgroundColor = color;
00059 }
00060 
00061 void KABEntryPainter::setHeaderColor( const QColor &color )
00062 {
00063   mHeaderColor = color;
00064 }
00065 
00066 void KABEntryPainter::setHeaderFont( const QFont &font )
00067 {
00068   mHeaderFont = font;
00069 }
00070 
00071 void KABEntryPainter::setHeadLineFont( const QFont &font )
00072 {
00073   mHeadLineFont = font;
00074 }
00075 
00076 void KABEntryPainter::setBodyFont( const QFont &font )
00077 {
00078   mBodyFont = font;
00079 }
00080 
00081 void KABEntryPainter::setFixedFont( const QFont &font )
00082 {
00083   mFixedFont = font;
00084 }
00085 
00086 void KABEntryPainter::setCommentFont( const QFont &font )
00087 {
00088   mCommentFont = font;
00089 }
00090 
00091 void KABEntryPainter::setUseHeaderColor( bool value )
00092 {
00093   mUseHeaderColor = value;
00094 }
00095 
00096 void KABEntryPainter::setShowAddresses( bool value )
00097 {
00098   mShowAddresses = value;
00099 }
00100 
00101 void KABEntryPainter::setShowEmails( bool value )
00102 {
00103   mShowEmails = value;
00104 }
00105 
00106 void KABEntryPainter::setShowPhones( bool value )
00107 {
00108   mShowPhones = value;
00109 }
00110 
00111 void KABEntryPainter::setShowURLs( bool value )
00112 {
00113   mShowURLs = value;
00114 }
00115 
00116 int KABEntryPainter::hitsEmail( const QPoint &p )
00117 {
00118   return hits( mEmailRects, p );
00119 }
00120 
00121 int KABEntryPainter::hitsURL( const QPoint &p )
00122 {
00123   return hits( mURLRects, p );
00124 }
00125 
00126 int KABEntryPainter::hitsPhone( const QPoint &p )
00127 {
00128   return hits( mPhoneRects, p );
00129 }
00130 
00131 int KABEntryPainter::hitsTalk( const QPoint &p )
00132 {
00133   return hits( mTalkRects, p );
00134 }
00135 
00136 int KABEntryPainter::hits( const QRectList& list, const QPoint &p )
00137 {
00138   QRectList::const_iterator pos;
00139   int count = 0;
00140 
00141   for ( pos = list.begin(); pos != list.end(); ++pos ) {
00142     if ( (*pos).contains( p ) )
00143       return count;
00144 
00145     ++count;
00146   }
00147 
00148   return -1;
00149 }
00150 
00151 bool KABEntryPainter::printAddressee( const KABC::Addressee &addr,
00152                                       const QRect &window, QPainter *painter,
00153                                       int top, bool fake, QRect *brect )
00154 {
00155   // TODO: custom fields, custom (?) for Entry
00156   const int Width = window.width();
00157   const int Height = window.height();
00158   const int Ruler1 = Width/32;
00159   const int Ruler2 = 2 * Ruler1;
00160   const int Ruler3 = 3 * Ruler1;
00161   QString text, line1, line2, line3, line4;
00162   QRect rect;
00163 
00164   // settings derived from the options:
00165   QFontMetrics fmHeader( mHeaderFont );
00166   QFontMetrics fmHeadLine( mHeadLineFont );
00167   QFontMetrics fmBody( mBodyFont );
00168   QFontMetrics fmFixed( mFixedFont );
00169   QFontMetrics fmComment( mCommentFont );
00170 
00171   int y = top;
00172   KABC::Address address;
00173 
00174   // this is used to prepare some fields for printing and decide about
00175   // the layout later:
00176   QValueList<QStringList> parts;
00177   QValueList<QRectList*> contents;
00178 
00179   mEmailRects.clear();
00180   mPhoneRects.clear();
00181   mURLRects.clear();
00182 
00183   // set window the painter works on:
00184   painter->setWindow( window );
00185 
00186   // first draw a black rectangle on top, containing the entries name, centered:
00187   painter->setFont( mHeaderFont );
00188   painter->setBrush( QBrush( mBackgroundColor ) );
00189   painter->setPen( mBackgroundColor );
00190   text = addr.realName();
00191 
00192   // replacement for: api->addressbook()->literalName(entry, text);
00193   rect = painter->boundingRect( Ruler1, y, Width, Height,
00194                                 Qt::AlignVCenter | Qt::AlignLeft, text );
00195   rect.setHeight( (int)( 1.25 * rect.height() ) );
00196 
00197   if ( !fake && mUseHeaderColor )
00198     painter->drawRect( 0, y, Width, rect.height() );
00199 
00200   painter->setPen( mUseHeaderColor ? mHeaderColor : mForegroundColor );
00201   if ( !fake ) {
00202     // create a little (1/8) space on top of the letters:
00203     float ypos = y + ( (float)rect.height() ) * 0.125;
00204     painter->drawText( Ruler1, (int)ypos, Width, rect.height(),
00205                        Qt::AlignVCenter | Qt::AlignLeft, text );
00206   }
00207 
00208   // paint the birthday to the right:
00209   QDateTime dt = addr.birthday();
00210   if ( dt.isValid() ) {
00211     line1 = KGlobal::locale()->formatDate( dt.date(), true );
00212     if ( !fake ) {
00213       // create a little (1/8) space on top of the letters:
00214       float ypos = y + ( (float)rect.height() ) * 0.125;
00215       painter->drawText( 0, (int)ypos, Width-Ruler1, rect.height(),
00216                          Qt::AlignVCenter | Qt::AlignRight, line1 );
00217     }
00218   }
00219 
00220   y += rect.height();
00221 
00222   // now draw the data according to the person:
00223   painter->setFont( mBodyFont );
00224   y += fmBody.lineSpacing() / 2;
00225 
00226   painter->setPen( mForegroundColor );
00227   if ( !addr.prefix().isEmpty() ) {
00228     line1 = addr.prefix().stripWhiteSpace();
00229 
00230     if ( fake ) {
00231       rect = painter->boundingRect( Ruler1, y, Width-Ruler1, Height,
00232                                     Qt::AlignTop | Qt::AlignLeft, line1 );
00233     } else {
00234       painter->drawText( Ruler1, y, Width-Ruler1, Height, Qt::AlignTop | Qt::AlignLeft,
00235                          line1, -1, &rect );
00236     }
00237 
00238     y += rect.height();
00239   }
00240 
00241   if ( !( addr.prefix().isEmpty() ) )
00242     y += fmBody.lineSpacing() / 2;
00243 
00244   // fill the parts stringlist, it contains "parts" (printable areas)
00245   // that will be combined to fill the page as effectively as possible:
00246   // Email addresses:
00247   if ( !addr.emails().isEmpty() && mShowEmails ) {
00248     contents.push_back( &mEmailRects );
00249     QStringList list;
00250 
00251     list.append( addr.emails().count() == 1 ? i18n( "Email address:" )
00252                  : i18n( "Email addresses:" ) );
00253     list += addr.emails();
00254     parts.push_back( list );
00255   }
00256 
00257   // Telephones:
00258   const KABC::PhoneNumber::List phoneNumbers( addr.phoneNumbers() );
00259   if ( !phoneNumbers.isEmpty() && mShowPhones ) {
00260     contents.push_back( &mPhoneRects );
00261     QStringList list;
00262     QString line;
00263 
00264     list.append( phoneNumbers.count() == 1 ? i18n( "Telephone:" )
00265                  : i18n( "Telephones:" ) );
00266 
00267     KABC::PhoneNumber::List::ConstIterator it;
00268     for ( it = phoneNumbers.begin(); it != phoneNumbers.end(); ++it ) {
00269       line = (*it).typeLabel();
00270       line += ": " + (*it).number();
00271       list.append( line.stripWhiteSpace() );
00272     }
00273 
00274     parts.push_back( list );
00275   }
00276 
00277   // Web pages/URLs:
00278   if ( !addr.url().isEmpty() && addr.url().isValid() && mShowURLs ) {
00279     contents.push_back( &mURLRects );
00280     QStringList list;
00281 
00282     list.append( i18n( "Web page:" ) );
00283     list += addr.url().prettyURL();
00284     parts.push_back( list );
00285   }
00286 
00287   /*
00288   // Talk addresses:
00289   if ( !addr.talk.isEmpty() ) {
00290     contents.push_back( &mTalkRects );
00291     QStringList list;
00292 
00293     list.append( addr.talk.count() == 1 ? i18n( "Talk address:" )
00294                  : i18n( "Talk addresses:" ) );
00295     list += addr.talk;
00296     parts.push_back( list );
00297   }
00298   */
00299 
00300   QRect limits[] = { QRect( 0, y, Width / 2, Height ),
00301                      QRect( Width / 2, y, Width / 2, Height ),
00302                      QRect( 0, y, Width / 2, Height ),
00303                      QRect( Width / 2, y, Width / 2, Height ) };
00304   int heights[ 4 ]= { 0, 0, 0, 0 };
00305 
00306   QValueList<QStringList>::iterator pos = parts.begin();
00307   QValueList<QRectList*>::iterator rpos = contents.begin();
00308 
00309   for ( uint counter = 0; counter < parts.count(); ++counter ) {
00310     const int Offset = counter > 1 ? QMAX( heights[ 0 ], heights[ 1 ] ) : 0;
00311     QStringList list = *pos;
00312 
00313     painter->setFont( mHeadLineFont );
00314     if ( fake ) {
00315       rect = painter->boundingRect( limits[ counter ].left(),
00316                                     limits[ counter ].top() + heights[counter]
00317                                     + Offset, limits[ counter ].width(),
00318                                     limits[ counter ].height(),
00319                                     Qt::AlignTop | Qt::AlignLeft, *list.at( 0 ) );
00320     } else {
00321       painter->drawText( limits[ counter ].left(), limits[ counter ].top() +
00322                          heights[ counter ] + Offset, limits[ counter ].width(),
00323                          limits[ counter ].height(), Qt::AlignTop | Qt::AlignLeft,
00324                          *list.at( 0 ), -1, &rect );
00325     }
00326 
00327     heights[ counter ] += rect.height();
00328 
00329     // paint the other elements at Ruler1:
00330     painter->setFont( mFixedFont );
00331     for ( uint c2 = 1; c2 < list.count(); ++c2 ) {
00332       // TODO: implement proper line breaking!
00333       if ( fake ) {
00334         rect = painter->boundingRect ( limits[ counter ].left() + Ruler1,
00335                                        limits[ counter ].top() + heights[ counter ]
00336                                        + Offset, limits[ counter ].width() - Ruler1,
00337                                        limits[ counter ].height(), Qt::AlignTop | Qt::AlignLeft,
00338                                        *list.at( c2 ) );
00339       } else {
00340         painter->drawText( limits[ counter ].left() + Ruler1, limits[ counter ].top()
00341                            + heights[ counter ] + Offset, limits[ counter ].width()
00342                            - Ruler1, limits[ counter ].height(), Qt::AlignTop | Qt::AlignLeft,
00343                            *list.at( c2 ), -1, &rect );
00344       }
00345       (*rpos)->push_back( rect );
00346       heights[ counter ] += rect.height();
00347     }
00348 
00349     ++pos;
00350     ++rpos;
00351   }
00352 
00353   y = y + QMAX( heights[ 0 ], heights[ 1 ] ) + QMAX( heights[ 2 ], heights[ 3 ] );
00354   // ^^^^^ done with emails, telephone, URLs and talk addresses
00355 
00356   // now print the addresses:
00357   KABC::Address::List addresses = addr.addresses();
00358   if ( addresses.count() > 0 && mShowAddresses ) {
00359     y += fmBody.lineSpacing() / 2;
00360     painter->setFont( mHeadLineFont );
00361     if ( fake ) {
00362       rect = painter->boundingRect( 0, y, Width, Height, Qt::AlignTop | Qt::AlignLeft,
00363                                     addresses.count() == 1 ? i18n( "Address:" )
00364                                     : i18n( "Addresses:" ) );
00365     } else {
00366       painter->drawText( 0, y, Width, Height, Qt::AlignTop | Qt::AlignLeft,
00367                          addresses.count() == 1 ? i18n( "Address:" )
00368                          : i18n( "Addresses:" ), -1, &rect );
00369     }
00370 
00371     y += rect.height();
00372     y += fmBody.lineSpacing() / 4;
00373     painter->setFont( mBodyFont );
00374 
00375     KABC::Address::List::ConstIterator it;
00376     for ( it = addresses.begin(); it != addresses.end(); ++it ) {
00377       address = *it;
00378       switch ( address.type() ) {
00379         case KABC::Address::Dom:
00380           line1 = i18n( "Domestic Address" );
00381           break;
00382         case KABC::Address::Intl:
00383           line1 = i18n( "International Address" );
00384           break;
00385         case KABC::Address::Postal:
00386           line1 = i18n( "Postal Address" );
00387           break;
00388         case KABC::Address::Parcel:
00389           line1 = i18n( "Parcel Address" );
00390           break;
00391         case KABC::Address::Home:
00392           line1 = i18n( "Home Address" );
00393           break;
00394         case KABC::Address::Work:
00395           line1 = i18n( "Work Address" );
00396           break;
00397         case KABC::Address::Pref:
00398         default:
00399           line1 = i18n( "Preferred Address" );
00400       }
00401 
00402       line1 += QString::fromLatin1( ":" );
00403       text = QString::null;
00404 
00405       if ( !address.extended().isEmpty() )
00406         text = address.extended().stripWhiteSpace();
00407 
00408       if ( !text.isEmpty() ) {
00409         line1 = line1 + QString::fromLatin1( " (" ) + text +
00410         QString::fromLatin1( ")" );
00411       }
00412 
00413       line1 = line1.stripWhiteSpace();
00414       line2 = address.street();
00415       if ( !address.postOfficeBox().isEmpty() )
00416         line2 += QString::fromLatin1( " - " ) + address.postOfficeBox();
00417 
00418       // print address in american style, this will need localisation:
00419       line3 = address.locality() + ( address.region().isEmpty() ?
00420               QString::fromLatin1( "" ) : QString::fromLatin1( ", " ) +
00421               address.region() ) + ( address.postalCode().isEmpty()
00422               ? QString::fromLatin1( "" ) : QString::fromLatin1( " " )
00423               + address.postalCode() );
00424       line4 = address.country();
00425 
00426       if ( fake ) {
00427         rect = painter->boundingRect( Ruler1, y, Width - Ruler1, Height,
00428                                       Qt::AlignTop | Qt::AlignLeft, line1 );
00429       } else {
00430         painter->drawText( Ruler1, y, Width - Ruler1, Height,
00431                            Qt::AlignTop | Qt::AlignLeft, line1, -1, &rect );
00432       }
00433 
00434       y += rect.height();
00435       if ( !line2.isEmpty() ) {
00436         if ( fake ) {
00437           rect = painter->boundingRect( Ruler2, y, Width - Ruler2, Height,
00438                                         Qt::AlignTop | Qt::AlignLeft, line2 );
00439         } else {
00440           painter->drawText( Ruler2, y, Width - Ruler2, Height,
00441                              Qt::AlignTop | Qt::AlignLeft, line2, -1, &rect );
00442         }
00443         y += rect.height();
00444       }
00445 
00446       if ( !line3.isEmpty() ) {
00447         if ( fake ) {
00448           rect = painter->boundingRect( Ruler2, y, Width - Ruler2, Height,
00449                                         Qt::AlignTop | Qt::AlignLeft, line3 );
00450         } else {
00451           painter->drawText( Ruler2, y, Width - Ruler2, Height,
00452                              Qt::AlignTop | Qt::AlignLeft, line3, -1, &rect );
00453         }
00454         y += rect.height();
00455       }
00456 
00457       if ( !line4.isEmpty() ) {
00458         if ( fake ) {
00459           rect = painter->boundingRect( Ruler2, y, Width - Ruler2, Height,
00460                                         Qt::AlignTop | Qt::AlignLeft, line4 );
00461         } else {
00462           painter->drawText( Ruler2, y, Width - Ruler2, Height,
00463                              Qt::AlignTop | Qt::AlignLeft, line4, -1, &rect );
00464         }
00465         y += rect.height();
00466       }
00467 
00468       y += fmBody.lineSpacing() / 4;
00469       if ( !address.label().isEmpty() ) {
00470         if ( fake ) {
00471           rect = painter->boundingRect( Ruler2, y, Width - Ruler2, Height,
00472                                         Qt::AlignTop | Qt::AlignLeft,
00473                                         i18n( "(Deliver to:)" ) );
00474         } else {
00475           painter->drawText( Ruler2, y, Width - Ruler2, Height,
00476                              Qt::AlignTop | Qt::AlignLeft,
00477                              i18n( "(Deliver to:)" ), -1, &rect );
00478         }
00479 
00480         y += rect.height();
00481         y += fmBody.lineSpacing() / 4;
00482         if ( fake ) {
00483           rect = painter->boundingRect( Ruler3, y, Width - Ruler3, Height,
00484                                         Qt::AlignTop | Qt::AlignLeft, address.label() );
00485         } else {
00486           painter->drawText( Ruler3, y, Width - Ruler3, Height,
00487                              Qt::AlignTop | Qt::AlignLeft, address.label(), -1, &rect );
00488         }
00489 
00490         y += rect.height();
00491         y += fmBody.lineSpacing() / 2;
00492       }
00493     }
00494   }
00495 
00496   if ( !addr.note().isEmpty() ) {
00497     painter->setFont( mCommentFont );
00498     y += fmBody.lineSpacing() / 2;
00499     if ( fake ) {
00500       rect = painter->boundingRect( 0, y, Width, Height,
00501                                     Qt::AlignTop | Qt::AlignLeft | Qt::WordBreak,
00502                                     addr.note() );
00503     } else {
00504       painter->drawText( 0, y, Width, Height,
00505                          Qt::AlignTop | Qt::AlignLeft | Qt::WordBreak,
00506                          addr.note(), -1, &rect );
00507     }
00508 
00509     y += rect.height();
00510   }
00511 
00512   y += fmBody.lineSpacing() / 2;
00513 
00514   if ( brect != 0 )
00515     *brect = QRect( 0, top, Width, y - top );
00516 
00517   if ( y < Height )
00518     return true;
00519   else
00520     return false;
00521 }
KDE Home | KDE Accessibility Home | Description of Access Keys