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 
37 KABEntryPainter::KABEntryPainter()
38  : mShowAddresses( true ), mShowEmails( true ), mShowPhones( true ),
39  mShowURLs( true )
40 {
41 }
42 
43 KABEntryPainter::~KABEntryPainter()
44 {
45  mEmailRects.clear();
46  mPhoneRects.clear();
47  mURLRects.clear();
48  mTalkRects.clear();
49 }
50 
51 void KABEntryPainter::setForegroundColor( const TQColor &color )
52 {
53  mForegroundColor = color;
54 }
55 
56 void KABEntryPainter::setBackgroundColor( const TQColor &color )
57 {
58  mBackgroundColor = color;
59 }
60 
61 void KABEntryPainter::setHeaderColor( const TQColor &color )
62 {
63  mHeaderColor = color;
64 }
65 
66 void KABEntryPainter::setHeaderFont( const TQFont &font )
67 {
68  mHeaderFont = font;
69 }
70 
71 void KABEntryPainter::setHeadLineFont( const TQFont &font )
72 {
73  mHeadLineFont = font;
74 }
75 
76 void KABEntryPainter::setBodyFont( const TQFont &font )
77 {
78  mBodyFont = font;
79 }
80 
81 void KABEntryPainter::setFixedFont( const TQFont &font )
82 {
83  mFixedFont = font;
84 }
85 
86 void KABEntryPainter::setCommentFont( const TQFont &font )
87 {
88  mCommentFont = font;
89 }
90 
91 void KABEntryPainter::setUseHeaderColor( bool value )
92 {
93  mUseHeaderColor = value;
94 }
95 
96 void KABEntryPainter::setShowAddresses( bool value )
97 {
98  mShowAddresses = value;
99 }
100 
101 void KABEntryPainter::setShowEmails( bool value )
102 {
103  mShowEmails = value;
104 }
105 
106 void KABEntryPainter::setShowPhones( bool value )
107 {
108  mShowPhones = value;
109 }
110 
111 void KABEntryPainter::setShowURLs( bool value )
112 {
113  mShowURLs = value;
114 }
115 
116 int KABEntryPainter::hitsEmail( const TQPoint &p )
117 {
118  return hits( mEmailRects, p );
119 }
120 
121 int KABEntryPainter::hitsURL( const TQPoint &p )
122 {
123  return hits( mURLRects, p );
124 }
125 
126 int KABEntryPainter::hitsPhone( const TQPoint &p )
127 {
128  return hits( mPhoneRects, p );
129 }
130 
131 int KABEntryPainter::hitsTalk( const TQPoint &p )
132 {
133  return hits( mTalkRects, p );
134 }
135 
136 int 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 
151 bool 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 }