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 TQt, and distribute the resulting executable, 00021 without including the source code for TQt in the source distribution. 00022 */ 00023 00024 00025 #include <tqpaintdevicemetrics.h> 00026 #include <tqpainter.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 TQColor &color ) 00052 { 00053 mForegroundColor = color; 00054 } 00055 00056 void KABEntryPainter::setBackgroundColor( const TQColor &color ) 00057 { 00058 mBackgroundColor = color; 00059 } 00060 00061 void KABEntryPainter::setHeaderColor( const TQColor &color ) 00062 { 00063 mHeaderColor = color; 00064 } 00065 00066 void KABEntryPainter::setHeaderFont( const TQFont &font ) 00067 { 00068 mHeaderFont = font; 00069 } 00070 00071 void KABEntryPainter::setHeadLineFont( const TQFont &font ) 00072 { 00073 mHeadLineFont = font; 00074 } 00075 00076 void KABEntryPainter::setBodyFont( const TQFont &font ) 00077 { 00078 mBodyFont = font; 00079 } 00080 00081 void KABEntryPainter::setFixedFont( const TQFont &font ) 00082 { 00083 mFixedFont = font; 00084 } 00085 00086 void KABEntryPainter::setCommentFont( const TQFont &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 TQPoint &p ) 00117 { 00118 return hits( mEmailRects, p ); 00119 } 00120 00121 int KABEntryPainter::hitsURL( const TQPoint &p ) 00122 { 00123 return hits( mURLRects, p ); 00124 } 00125 00126 int KABEntryPainter::hitsPhone( const TQPoint &p ) 00127 { 00128 return hits( mPhoneRects, p ); 00129 } 00130 00131 int KABEntryPainter::hitsTalk( const TQPoint &p ) 00132 { 00133 return hits( mTalkRects, p ); 00134 } 00135 00136 int KABEntryPainter::hits( const TQRectList& list, const TQPoint &p ) 00137 { 00138 TQRectList::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 TQRect &window, TQPainter *painter, 00153 int top, bool fake, TQRect *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 TQString text, line1, line2, line3, line4; 00162 TQRect rect; 00163 00164 // settings derived from the options: 00165 TQFontMetrics fmHeader( mHeaderFont ); 00166 TQFontMetrics fmHeadLine( mHeadLineFont ); 00167 TQFontMetrics fmBody( mBodyFont ); 00168 TQFontMetrics fmFixed( mFixedFont ); 00169 TQFontMetrics 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 TQValueList<TQStringList> parts; 00177 TQValueList<TQRectList*> 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( TQBrush( 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 TQt::AlignVCenter | TQt::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 TQt::AlignVCenter | TQt::AlignLeft, text ); 00206 } 00207 00208 // paint the birthday to the right: 00209 TQDateTime 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 TQt::AlignVCenter | TQt::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 TQt::AlignTop | TQt::AlignLeft, line1 ); 00233 } else { 00234 painter->drawText( Ruler1, y, Width-Ruler1, Height, TQt::AlignTop | TQt::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 TQStringList 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 TQStringList list; 00262 TQString 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 TQStringList 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 TQStringList 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 TQRect limits[] = { TQRect( 0, y, Width / 2, Height ), 00301 TQRect( Width / 2, y, Width / 2, Height ), 00302 TQRect( 0, y, Width / 2, Height ), 00303 TQRect( Width / 2, y, Width / 2, Height ) }; 00304 int heights[ 4 ]= { 0, 0, 0, 0 }; 00305 00306 TQValueList<TQStringList>::iterator pos = parts.begin(); 00307 TQValueList<TQRectList*>::iterator rpos = contents.begin(); 00308 00309 for ( uint counter = 0; counter < parts.count(); ++counter ) { 00310 const int Offset = counter > 1 ? TQMAX( heights[ 0 ], heights[ 1 ] ) : 0; 00311 TQStringList 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 TQt::AlignTop | TQt::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(), TQt::AlignTop | TQt::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(), TQt::AlignTop | TQt::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(), TQt::AlignTop | TQt::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 + TQMAX( heights[ 0 ], heights[ 1 ] ) + TQMAX( 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, TQt::AlignTop | TQt::AlignLeft, 00363 addresses.count() == 1 ? i18n( "Address:" ) 00364 : i18n( "Addresses:" ) ); 00365 } else { 00366 painter->drawText( 0, y, Width, Height, TQt::AlignTop | TQt::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 += TQString::fromLatin1( ":" ); 00403 text = TQString(); 00404 00405 if ( !address.extended().isEmpty() ) 00406 text = address.extended().stripWhiteSpace(); 00407 00408 if ( !text.isEmpty() ) { 00409 line1 = line1 + TQString::fromLatin1( " (" ) + text + 00410 TQString::fromLatin1( ")" ); 00411 } 00412 00413 line1 = line1.stripWhiteSpace(); 00414 line2 = address.street(); 00415 if ( !address.postOfficeBox().isEmpty() ) 00416 line2 += TQString::fromLatin1( " - " ) + address.postOfficeBox(); 00417 00418 // print address in american style, this will need localisation: 00419 line3 = address.locality() + ( address.region().isEmpty() ? 00420 TQString::fromLatin1( "" ) : TQString::fromLatin1( ", " ) + 00421 address.region() ) + ( address.postalCode().isEmpty() 00422 ? TQString::fromLatin1( "" ) : TQString::fromLatin1( " " ) 00423 + address.postalCode() ); 00424 line4 = address.country(); 00425 00426 if ( fake ) { 00427 rect = painter->boundingRect( Ruler1, y, Width - Ruler1, Height, 00428 TQt::AlignTop | TQt::AlignLeft, line1 ); 00429 } else { 00430 painter->drawText( Ruler1, y, Width - Ruler1, Height, 00431 TQt::AlignTop | TQt::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 TQt::AlignTop | TQt::AlignLeft, line2 ); 00439 } else { 00440 painter->drawText( Ruler2, y, Width - Ruler2, Height, 00441 TQt::AlignTop | TQt::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 TQt::AlignTop | TQt::AlignLeft, line3 ); 00450 } else { 00451 painter->drawText( Ruler2, y, Width - Ruler2, Height, 00452 TQt::AlignTop | TQt::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 TQt::AlignTop | TQt::AlignLeft, line4 ); 00461 } else { 00462 painter->drawText( Ruler2, y, Width - Ruler2, Height, 00463 TQt::AlignTop | TQt::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 TQt::AlignTop | TQt::AlignLeft, 00473 i18n( "(Deliver to:)" ) ); 00474 } else { 00475 painter->drawText( Ruler2, y, Width - Ruler2, Height, 00476 TQt::AlignTop | TQt::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 TQt::AlignTop | TQt::AlignLeft, address.label() ); 00485 } else { 00486 painter->drawText( Ruler3, y, Width - Ruler3, Height, 00487 TQt::AlignTop | TQt::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 TQt::AlignTop | TQt::AlignLeft | TQt::WordBreak, 00502 addr.note() ); 00503 } else { 00504 painter->drawText( 0, y, Width, Height, 00505 TQt::AlignTop | TQt::AlignLeft | TQt::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 = TQRect( 0, top, Width, y - top ); 00516 00517 if ( y < Height ) 00518 return true; 00519 else 00520 return false; 00521 }