kaddressbook

kabentrypainter.cpp
1/*
2 This file is part of KAddressBook.
3 Copyright (c) 1996-2002 Mirko Boehm <mirko@kde.org>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
19 As a special exception, permission is given to link this program
20 with any edition of TQt, and distribute the resulting executable,
21 without including the source code for TQt in the source distribution.
22*/
23
24
25#include <tqpaintdevicemetrics.h>
26#include <tqpainter.h>
27
28#include <kdebug.h>
29#include <tdeglobal.h>
30#include <tdelocale.h>
31#include <knotifyclient.h>
32#include <kprinter.h>
33#include <kurl.h>
34
35#include "kabentrypainter.h"
36
37KABEntryPainter::KABEntryPainter()
38 : mShowAddresses( true ), mShowEmails( true ), mShowPhones( true ),
39 mShowURLs( true )
40{
41}
42
43KABEntryPainter::~KABEntryPainter()
44{
45 mEmailRects.clear();
46 mPhoneRects.clear();
47 mURLRects.clear();
48 mTalkRects.clear();
49}
50
51void KABEntryPainter::setForegroundColor( const TQColor &color )
52{
53 mForegroundColor = color;
54}
55
56void KABEntryPainter::setBackgroundColor( const TQColor &color )
57{
58 mBackgroundColor = color;
59}
60
61void KABEntryPainter::setHeaderColor( const TQColor &color )
62{
63 mHeaderColor = color;
64}
65
66void KABEntryPainter::setHeaderFont( const TQFont &font )
67{
68 mHeaderFont = font;
69}
70
71void KABEntryPainter::setHeadLineFont( const TQFont &font )
72{
73 mHeadLineFont = font;
74}
75
76void KABEntryPainter::setBodyFont( const TQFont &font )
77{
78 mBodyFont = font;
79}
80
81void KABEntryPainter::setFixedFont( const TQFont &font )
82{
83 mFixedFont = font;
84}
85
86void KABEntryPainter::setCommentFont( const TQFont &font )
87{
88 mCommentFont = font;
89}
90
91void KABEntryPainter::setUseHeaderColor( bool value )
92{
93 mUseHeaderColor = value;
94}
95
96void KABEntryPainter::setShowAddresses( bool value )
97{
98 mShowAddresses = value;
99}
100
101void KABEntryPainter::setShowEmails( bool value )
102{
103 mShowEmails = value;
104}
105
106void KABEntryPainter::setShowPhones( bool value )
107{
108 mShowPhones = value;
109}
110
111void KABEntryPainter::setShowURLs( bool value )
112{
113 mShowURLs = value;
114}
115
116int KABEntryPainter::hitsEmail( const TQPoint &p )
117{
118 return hits( mEmailRects, p );
119}
120
121int KABEntryPainter::hitsURL( const TQPoint &p )
122{
123 return hits( mURLRects, p );
124}
125
126int KABEntryPainter::hitsPhone( const TQPoint &p )
127{
128 return hits( mPhoneRects, p );
129}
130
131int KABEntryPainter::hitsTalk( const TQPoint &p )
132{
133 return hits( mTalkRects, p );
134}
135
136int KABEntryPainter::hits( const TQRectList& list, const TQPoint &p )
137{
138 TQRectList::const_iterator pos;
139 int count = 0;
140
141 for ( pos = list.begin(); pos != list.end(); ++pos ) {
142 if ( (*pos).contains( p ) )
143 return count;
144
145 ++count;
146 }
147
148 return -1;
149}
150
151bool KABEntryPainter::printAddressee( const TDEABC::Addressee &addr,
152 const TQRect &window, TQPainter *painter,
153 int top, bool fake, TQRect *brect )
154{
155 // TODO: custom fields, custom (?) for Entry
156 const int Width = window.width();
157 const int Height = window.height();
158 const int Ruler1 = Width/32;
159 const int Ruler2 = 2 * Ruler1;
160 const int Ruler3 = 3 * Ruler1;
161 TQString text, line1, line2, line3, line4;
162 TQRect rect;
163
164 // settings derived from the options:
165 TQFontMetrics fmHeader( mHeaderFont );
166 TQFontMetrics fmHeadLine( mHeadLineFont );
167 TQFontMetrics fmBody( mBodyFont );
168 TQFontMetrics fmFixed( mFixedFont );
169 TQFontMetrics fmComment( mCommentFont );
170
171 int y = top;
172 TDEABC::Address address;
173
174 // this is used to prepare some fields for printing and decide about
175 // the layout later:
176 TQValueList<TQStringList> parts;
177 TQValueList<TQRectList*> contents;
178
179 mEmailRects.clear();
180 mPhoneRects.clear();
181 mURLRects.clear();
182
183 // set window the painter works on:
184 painter->setWindow( window );
185
186 // first draw a black rectangle on top, containing the entries name, centered:
187 painter->setFont( mHeaderFont );
188 painter->setBrush( TQBrush( mBackgroundColor ) );
189 painter->setPen( mBackgroundColor );
190 text = addr.realName();
191
192 // replacement for: api->addressbook()->literalName(entry, text);
193 rect = painter->boundingRect( Ruler1, y, Width, Height,
194 TQt::AlignVCenter | TQt::AlignLeft, text );
195 rect.setHeight( (int)( 1.25 * rect.height() ) );
196
197 if ( !fake && mUseHeaderColor )
198 painter->drawRect( 0, y, Width, rect.height() );
199
200 painter->setPen( mUseHeaderColor ? mHeaderColor : mForegroundColor );
201 if ( !fake ) {
202 // create a little (1/8) space on top of the letters:
203 float ypos = y + ( (float)rect.height() ) * 0.125;
204 painter->drawText( Ruler1, (int)ypos, Width, rect.height(),
205 TQt::AlignVCenter | TQt::AlignLeft, text );
206 }
207
208 // paint the birthday to the right:
209 TQDateTime dt = addr.birthday();
210 if ( dt.isValid() ) {
211 line1 = TDEGlobal::locale()->formatDate( dt.date(), true );
212 if ( !fake ) {
213 // create a little (1/8) space on top of the letters:
214 float ypos = y + ( (float)rect.height() ) * 0.125;
215 painter->drawText( 0, (int)ypos, Width-Ruler1, rect.height(),
216 TQt::AlignVCenter | TQt::AlignRight, line1 );
217 }
218 }
219
220 y += rect.height();
221
222 // now draw the data according to the person:
223 painter->setFont( mBodyFont );
224 y += fmBody.lineSpacing() / 2;
225
226 painter->setPen( mForegroundColor );
227 if ( !addr.prefix().isEmpty() ) {
228 line1 = addr.prefix().stripWhiteSpace();
229
230 if ( fake ) {
231 rect = painter->boundingRect( Ruler1, y, Width-Ruler1, Height,
232 TQt::AlignTop | TQt::AlignLeft, line1 );
233 } else {
234 painter->drawText( Ruler1, y, Width-Ruler1, Height, TQt::AlignTop | TQt::AlignLeft,
235 line1, -1, &rect );
236 }
237
238 y += rect.height();
239 }
240
241 if ( !( addr.prefix().isEmpty() ) )
242 y += fmBody.lineSpacing() / 2;
243
244 // fill the parts stringlist, it contains "parts" (printable areas)
245 // that will be combined to fill the page as effectively as possible:
246 // Email addresses:
247 if ( !addr.emails().isEmpty() && mShowEmails ) {
248 contents.push_back( &mEmailRects );
249 TQStringList list;
250
251 list.append( addr.emails().count() == 1 ? i18n( "Email address:" )
252 : i18n( "Email addresses:" ) );
253 list += addr.emails();
254 parts.push_back( list );
255 }
256
257 // Telephones:
258 const TDEABC::PhoneNumber::List phoneNumbers( addr.phoneNumbers() );
259 if ( !phoneNumbers.isEmpty() && mShowPhones ) {
260 contents.push_back( &mPhoneRects );
261 TQStringList list;
262 TQString line;
263
264 list.append( phoneNumbers.count() == 1 ? i18n( "Telephone:" )
265 : i18n( "Telephones:" ) );
266
267 TDEABC::PhoneNumber::List::ConstIterator it;
268 for ( it = phoneNumbers.begin(); it != phoneNumbers.end(); ++it ) {
269 line = (*it).typeLabel();
270 line += ": " + (*it).number();
271 list.append( line.stripWhiteSpace() );
272 }
273
274 parts.push_back( list );
275 }
276
277 // Web pages/URLs:
278 if ( !addr.url().isEmpty() && addr.url().isValid() && mShowURLs ) {
279 contents.push_back( &mURLRects );
280 TQStringList list;
281
282 list.append( i18n( "Web page:" ) );
283 list += addr.url().prettyURL();
284 parts.push_back( list );
285 }
286
287 /*
288 // Talk addresses:
289 if ( !addr.talk.isEmpty() ) {
290 contents.push_back( &mTalkRects );
291 TQStringList list;
292
293 list.append( addr.talk.count() == 1 ? i18n( "Talk address:" )
294 : i18n( "Talk addresses:" ) );
295 list += addr.talk;
296 parts.push_back( list );
297 }
298 */
299
300 TQRect limits[] = { TQRect( 0, y, Width / 2, Height ),
301 TQRect( Width / 2, y, Width / 2, Height ),
302 TQRect( 0, y, Width / 2, Height ),
303 TQRect( Width / 2, y, Width / 2, Height ) };
304 int heights[ 4 ]= { 0, 0, 0, 0 };
305
306 TQValueList<TQStringList>::iterator pos = parts.begin();
307 TQValueList<TQRectList*>::iterator rpos = contents.begin();
308
309 for ( uint counter = 0; counter < parts.count(); ++counter ) {
310 const int Offset = counter > 1 ? TQMAX( heights[ 0 ], heights[ 1 ] ) : 0;
311 TQStringList list = *pos;
312
313 painter->setFont( mHeadLineFont );
314 if ( fake ) {
315 rect = painter->boundingRect( limits[ counter ].left(),
316 limits[ counter ].top() + heights[counter]
317 + Offset, limits[ counter ].width(),
318 limits[ counter ].height(),
319 TQt::AlignTop | TQt::AlignLeft, *list.at( 0 ) );
320 } else {
321 painter->drawText( limits[ counter ].left(), limits[ counter ].top() +
322 heights[ counter ] + Offset, limits[ counter ].width(),
323 limits[ counter ].height(), TQt::AlignTop | TQt::AlignLeft,
324 *list.at( 0 ), -1, &rect );
325 }
326
327 heights[ counter ] += rect.height();
328
329 // paint the other elements at Ruler1:
330 painter->setFont( mFixedFont );
331 for ( uint c2 = 1; c2 < list.count(); ++c2 ) {
332 // TODO: implement proper line breaking!
333 if ( fake ) {
334 rect = painter->boundingRect ( limits[ counter ].left() + Ruler1,
335 limits[ counter ].top() + heights[ counter ]
336 + Offset, limits[ counter ].width() - Ruler1,
337 limits[ counter ].height(), TQt::AlignTop | TQt::AlignLeft,
338 *list.at( c2 ) );
339 } else {
340 painter->drawText( limits[ counter ].left() + Ruler1, limits[ counter ].top()
341 + heights[ counter ] + Offset, limits[ counter ].width()
342 - Ruler1, limits[ counter ].height(), TQt::AlignTop | TQt::AlignLeft,
343 *list.at( c2 ), -1, &rect );
344 }
345 (*rpos)->push_back( rect );
346 heights[ counter ] += rect.height();
347 }
348
349 ++pos;
350 ++rpos;
351 }
352
353 y = y + TQMAX( heights[ 0 ], heights[ 1 ] ) + TQMAX( heights[ 2 ], heights[ 3 ] );
354 // ^^^^^ done with emails, telephone, URLs and talk addresses
355
356 // now print the addresses:
357 TDEABC::Address::List addresses = addr.addresses();
358 if ( addresses.count() > 0 && mShowAddresses ) {
359 y += fmBody.lineSpacing() / 2;
360 painter->setFont( mHeadLineFont );
361 if ( fake ) {
362 rect = painter->boundingRect( 0, y, Width, Height, TQt::AlignTop | TQt::AlignLeft,
363 addresses.count() == 1 ? i18n( "Address:" )
364 : i18n( "Addresses:" ) );
365 } else {
366 painter->drawText( 0, y, Width, Height, TQt::AlignTop | TQt::AlignLeft,
367 addresses.count() == 1 ? i18n( "Address:" )
368 : i18n( "Addresses:" ), -1, &rect );
369 }
370
371 y += rect.height();
372 y += fmBody.lineSpacing() / 4;
373 painter->setFont( mBodyFont );
374
375 TDEABC::Address::List::ConstIterator it;
376 for ( it = addresses.begin(); it != addresses.end(); ++it ) {
377 address = *it;
378 switch ( address.type() ) {
379 case TDEABC::Address::Dom:
380 line1 = i18n( "Domestic Address" );
381 break;
382 case TDEABC::Address::Intl:
383 line1 = i18n( "International Address" );
384 break;
385 case TDEABC::Address::Postal:
386 line1 = i18n( "Postal Address" );
387 break;
388 case TDEABC::Address::Parcel:
389 line1 = i18n( "Parcel Address" );
390 break;
391 case TDEABC::Address::Home:
392 line1 = i18n( "Home Address" );
393 break;
394 case TDEABC::Address::Work:
395 line1 = i18n( "Work Address" );
396 break;
397 case TDEABC::Address::Pref:
398 default:
399 line1 = i18n( "Preferred Address" );
400 }
401
402 line1 += TQString::fromLatin1( ":" );
403 text = TQString();
404
405 if ( !address.extended().isEmpty() )
406 text = address.extended().stripWhiteSpace();
407
408 if ( !text.isEmpty() ) {
409 line1 = line1 + TQString::fromLatin1( " (" ) + text +
410 TQString::fromLatin1( ")" );
411 }
412
413 line1 = line1.stripWhiteSpace();
414 line2 = address.street();
415 if ( !address.postOfficeBox().isEmpty() )
416 line2 += TQString::fromLatin1( " - " ) + address.postOfficeBox();
417
418 // print address in american style, this will need localisation:
419 line3 = address.locality() + ( address.region().isEmpty() ?
420 TQString::fromLatin1( "" ) : TQString::fromLatin1( ", " ) +
421 address.region() ) + ( address.postalCode().isEmpty()
422 ? TQString::fromLatin1( "" ) : TQString::fromLatin1( " " )
423 + address.postalCode() );
424 line4 = address.country();
425
426 if ( fake ) {
427 rect = painter->boundingRect( Ruler1, y, Width - Ruler1, Height,
428 TQt::AlignTop | TQt::AlignLeft, line1 );
429 } else {
430 painter->drawText( Ruler1, y, Width - Ruler1, Height,
431 TQt::AlignTop | TQt::AlignLeft, line1, -1, &rect );
432 }
433
434 y += rect.height();
435 if ( !line2.isEmpty() ) {
436 if ( fake ) {
437 rect = painter->boundingRect( Ruler2, y, Width - Ruler2, Height,
438 TQt::AlignTop | TQt::AlignLeft, line2 );
439 } else {
440 painter->drawText( Ruler2, y, Width - Ruler2, Height,
441 TQt::AlignTop | TQt::AlignLeft, line2, -1, &rect );
442 }
443 y += rect.height();
444 }
445
446 if ( !line3.isEmpty() ) {
447 if ( fake ) {
448 rect = painter->boundingRect( Ruler2, y, Width - Ruler2, Height,
449 TQt::AlignTop | TQt::AlignLeft, line3 );
450 } else {
451 painter->drawText( Ruler2, y, Width - Ruler2, Height,
452 TQt::AlignTop | TQt::AlignLeft, line3, -1, &rect );
453 }
454 y += rect.height();
455 }
456
457 if ( !line4.isEmpty() ) {
458 if ( fake ) {
459 rect = painter->boundingRect( Ruler2, y, Width - Ruler2, Height,
460 TQt::AlignTop | TQt::AlignLeft, line4 );
461 } else {
462 painter->drawText( Ruler2, y, Width - Ruler2, Height,
463 TQt::AlignTop | TQt::AlignLeft, line4, -1, &rect );
464 }
465 y += rect.height();
466 }
467
468 y += fmBody.lineSpacing() / 4;
469 if ( !address.label().isEmpty() ) {
470 if ( fake ) {
471 rect = painter->boundingRect( Ruler2, y, Width - Ruler2, Height,
472 TQt::AlignTop | TQt::AlignLeft,
473 i18n( "(Deliver to:)" ) );
474 } else {
475 painter->drawText( Ruler2, y, Width - Ruler2, Height,
476 TQt::AlignTop | TQt::AlignLeft,
477 i18n( "(Deliver to:)" ), -1, &rect );
478 }
479
480 y += rect.height();
481 y += fmBody.lineSpacing() / 4;
482 if ( fake ) {
483 rect = painter->boundingRect( Ruler3, y, Width - Ruler3, Height,
484 TQt::AlignTop | TQt::AlignLeft, address.label() );
485 } else {
486 painter->drawText( Ruler3, y, Width - Ruler3, Height,
487 TQt::AlignTop | TQt::AlignLeft, address.label(), -1, &rect );
488 }
489
490 y += rect.height();
491 y += fmBody.lineSpacing() / 2;
492 }
493 }
494 }
495
496 if ( !addr.note().isEmpty() ) {
497 painter->setFont( mCommentFont );
498 y += fmBody.lineSpacing() / 2;
499 if ( fake ) {
500 rect = painter->boundingRect( 0, y, Width, Height,
501 TQt::AlignTop | TQt::AlignLeft | TQt::WordBreak,
502 addr.note() );
503 } else {
504 painter->drawText( 0, y, Width, Height,
505 TQt::AlignTop | TQt::AlignLeft | TQt::WordBreak,
506 addr.note(), -1, &rect );
507 }
508
509 y += rect.height();
510 }
511
512 y += fmBody.lineSpacing() / 2;
513
514 if ( brect != 0 )
515 *brect = TQRect( 0, top, Width, y - top );
516
517 if ( y < Height )
518 return true;
519 else
520 return false;
521}