kaddressbook

ldifvcardcreator.cpp
00001 /*
00002     This file is part of KAddressBook.
00003     Copyright (C) 2003 Helge Deller <deller@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     version 2 License as published by the Free Software Foundation.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to
00016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017     Boston, MA 02110-1301, USA.
00018 */
00019 
00020 /*
00021  *  - ldifvcardthumbnail -
00022  *
00023  *  tdeioslave which generates tumbnails for vCard and LDIF files.
00024  *  The thumbnails are used e.g. by Konqueror or in the file selection
00025  *  dialog.
00026  *
00027  */
00028 
00029 #include <tqdatetime.h>
00030 #include <tqfile.h>
00031 #include <tqpixmap.h>
00032 #include <tqimage.h>
00033 #include <tqpainter.h>
00034 #include <tqtextstream.h>
00035 
00036 #include <kdebug.h>
00037 #include <tdeglobal.h>
00038 #include <tdelocale.h>
00039 #include <tdeabc/ldifconverter.h>
00040 #include <tdeabc/vcardconverter.h>
00041 #include <kpixmapsplitter.h>
00042 #include <kstandarddirs.h>
00043 #include <tdeglobalsettings.h>
00044 
00045 #include "ldifvcardcreator.h"
00046 
00047 extern "C"
00048 {
00049   ThumbCreator *new_creator()
00050   {
00051     TDEGlobal::locale()->insertCatalogue( "kaddressbook" );
00052     return new VCard_LDIFCreator;
00053   }
00054 }
00055 
00056 VCard_LDIFCreator::VCard_LDIFCreator()
00057   : mSplitter( 0 )
00058 {
00059 }
00060 
00061 VCard_LDIFCreator::~VCard_LDIFCreator()
00062 {
00063   delete mSplitter;
00064 }
00065 
00066 
00067 bool VCard_LDIFCreator::readContents( const TQString &path )
00068 {
00069   // read file contents
00070   TQFile file( path );
00071   if ( !file.open( IO_ReadOnly ) )
00072     return false;
00073 
00074   TQString info;
00075   text.truncate(0);
00076 
00077   // read the file
00078 #if defined(KABC_VCARD_ENCODING_FIX)
00079   const TQByteArray data = file.readAll();
00080   const TQString contents( data );
00081   const TQCString contentsRaw( data.data(), data.size() );
00082 #else
00083   TQTextStream s( &file );
00084   s.setEncoding( TQTextStream::UnicodeUTF8 );
00085   TQString contents = s.read();
00086 #endif
00087   file.close();
00088 
00089   // convert the file contents to a TDEABC::Addressee address
00090   TDEABC::AddresseeList addrList;
00091   TDEABC::Addressee addr;
00092   TDEABC::VCardConverter converter;
00093 
00094 #if defined(KABC_VCARD_ENCODING_FIX)
00095   addrList = converter.parseVCardsRaw( contentsRaw );
00096 #else
00097   addrList = converter.parseVCards( contents );
00098 #endif
00099   if ( addrList.count() == 0 )
00100     if ( !TDEABC::LDIFConverter::LDIFToAddressee( contents, addrList ) )
00101     return false;
00102   if ( addrList.count()>1 ) {
00103     // create an overview (list of all names)
00104     name = i18n("One contact found:", "%n contacts found:", addrList.count());
00105     unsigned int no, linenr;
00106     for (linenr=no=0; linenr<30 && no<addrList.count(); ++no) {
00107        addr = addrList[no];
00108        info = addr.formattedName().simplifyWhiteSpace();
00109        if (info.isEmpty())
00110           info = addr.givenName() + " " + addr.familyName();
00111        info = info.simplifyWhiteSpace();
00112        if (info.isEmpty())
00113          continue;
00114        text.append(info);
00115        text.append("\n");
00116        ++linenr;
00117     }
00118     return true;
00119   }
00120 
00121   // create card for _one_ contact
00122   addr = addrList[ 0 ];
00123 
00124   // prepare the text
00125   name = addr.formattedName().simplifyWhiteSpace();
00126   if ( name.isEmpty() )
00127     name = addr.givenName() + " " + addr.familyName();
00128   name = name.simplifyWhiteSpace();
00129 
00130 
00131   TDEABC::PhoneNumber::List pnList = addr.phoneNumbers();
00132   TQStringList phoneNumbers;
00133   for (unsigned int no=0; no<pnList.count(); ++no) {
00134     TQString pn = pnList[no].number().simplifyWhiteSpace();
00135     if (!pn.isEmpty() && !phoneNumbers.contains(pn))
00136       phoneNumbers.append(pn);
00137   }
00138   if ( !phoneNumbers.isEmpty() )
00139       text += phoneNumbers.join("\n") + "\n";
00140 
00141   info = addr.organization().simplifyWhiteSpace();
00142   if ( !info.isEmpty() )
00143     text += info + "\n";
00144 
00145   // get an address
00146   TDEABC::Address address = addr.address(TDEABC::Address::Work);
00147   if (address.isEmpty())
00148     address = addr.address(TDEABC::Address::Home);
00149   if (address.isEmpty())
00150     address = addr.address(TDEABC::Address::Pref);
00151   info = address.formattedAddress();
00152   if ( !info.isEmpty() )
00153     text += info + "\n";
00154 
00155   return true;
00156 }
00157 
00158 
00159 bool VCard_LDIFCreator::createImageSmall()
00160 {
00161   text = name + "\n" + text;
00162 
00163   if ( !mSplitter ) {
00164     mSplitter = new KPixmapSplitter;
00165     TQString pixmap = locate( "data", "konqueror/pics/thumbnailfont_7x4.png" );
00166     if ( pixmap.isEmpty() ) {
00167       delete mSplitter;
00168       mSplitter=0;
00169       kdWarning() << "VCard_LDIFCreator: Font image \"thumbnailfont_7x4.png\" not found!\n";
00170       return false;
00171     }
00172     mSplitter->setPixmap( TQPixmap( pixmap ) );
00173     mSplitter->setItemSize( TQSize( 4, 7 ) );
00174   }
00175 
00176   TQSize chSize = mSplitter->itemSize(); // the size of one char
00177   int xOffset = chSize.width();
00178   int yOffset = chSize.height();
00179 
00180   // calculate a better border so that the text is centered
00181   int canvasWidth = pixmapSize.width() - 2 * xborder;
00182   int canvasHeight = pixmapSize.height() -  2 * yborder;
00183   int numCharsPerLine = (int) (canvasWidth / chSize.width());
00184   int numLines = (int) (canvasHeight / chSize.height());
00185 
00186   // render the information
00187   TQRect rect;
00188   int rest = mPixmap.width() - (numCharsPerLine * chSize.width());
00189   xborder = TQMAX( xborder, rest / 2 ); // center horizontally
00190   rest = mPixmap.height() - (numLines * chSize.height());
00191   yborder = TQMAX( yborder, rest / 2 ); // center vertically
00192   // end centering
00193 
00194   int x = xborder, y = yborder; // where to paint the characters
00195   int posNewLine  = mPixmap.width() - (chSize.width() + xborder);
00196   int posLastLine = mPixmap.height() - (chSize.height() + yborder);
00197   bool newLine = false;
00198   Q_ASSERT( posNewLine > 0 );
00199   const TQPixmap *fontPixmap = &(mSplitter->pixmap());
00200 
00201   for ( uint i = 0; i < text.length(); i++ ) {
00202     if ( x > posNewLine || newLine ) {  // start a new line?
00203       x = xborder;
00204       y += yOffset;
00205 
00206       if ( y > posLastLine ) // more text than space
00207         break;
00208 
00209       // after starting a new line, we also jump to the next
00210       // physical newline in the file if we don't come from one
00211       if ( !newLine ) {
00212         int pos = text.find( '\n', i );
00213         if ( pos > (int) i )
00214           i = pos +1;
00215       }
00216 
00217       newLine = false;
00218     }
00219 
00220     // check for newlines in the text (unix,dos)
00221     TQChar ch = text.at( i );
00222     if ( ch == '\n' ) {
00223       newLine = true;
00224       continue;
00225     } else if ( ch == '\r' && text.at(i+1) == '\n' ) {
00226       newLine = true;
00227       i++; // skip the next character (\n) as well
00228       continue;
00229     }
00230 
00231     rect = mSplitter->coordinates( ch );
00232     if ( !rect.isEmpty() )
00233       bitBlt( &mPixmap, TQPoint(x,y), fontPixmap, rect, TQt::CopyROP );
00234 
00235     x += xOffset; // next character
00236   }
00237 
00238   return true;
00239 }
00240 
00241 bool VCard_LDIFCreator::createImageBig()
00242 {
00243   TQFont normalFont( TDEGlobalSettings::generalFont() );
00244   TQFont titleFont( normalFont );
00245   titleFont.setBold(true);
00246   // titleFont.setUnderline(true);
00247   titleFont.setItalic(true);
00248 
00249   TQPainter painter(&mPixmap);
00250   painter.setFont(titleFont);
00251   TQFontMetrics fm(painter.fontMetrics());
00252 
00253   // draw contact name
00254   painter.setClipRect(2, 2, pixmapSize.width()-4, pixmapSize.height()-4);
00255   TQPoint p(5, fm.height()+2);
00256   painter.drawText(p, name);
00257   p.setY( 3*p.y()/2 );
00258 
00259   // draw contact information
00260   painter.setFont(normalFont);
00261   fm = painter.fontMetrics();
00262 
00263   const TQStringList list( TQStringList::split('\n', text) );
00264   for ( TQStringList::ConstIterator it = list.begin();
00265              p.y()<=pixmapSize.height() && it != list.end(); ++it ) {
00266      p.setY( p.y() + fm.height() );
00267      painter.drawText(p, *it);
00268   }
00269 
00270   return true;
00271 }
00272 
00273 bool VCard_LDIFCreator::create(const TQString &path, int width, int height, TQImage &img)
00274 {
00275   if ( !readContents(path) )
00276     return false;
00277 
00278   // resize the image if necessary
00279   pixmapSize = TQSize( width, height );
00280   if (height * 3 > width * 4)
00281     pixmapSize.setHeight( width * 4 / 3 );
00282   else
00283     pixmapSize.setWidth( height * 3 / 4 );
00284 
00285   if ( pixmapSize != mPixmap.size() )
00286     mPixmap.resize( pixmapSize );
00287 
00288   mPixmap.fill( TQColor( 245, 245, 245 ) ); // light-grey background
00289 
00290   // one pixel for the rectangle, the rest. whitespace
00291   xborder = 1 + pixmapSize.width()/16;  // minimum x-border
00292   yborder = 1 + pixmapSize.height()/16; // minimum y-border
00293 
00294   bool ok;
00295   if ( width >= 150 /*pixel*/ )
00296     ok = createImageBig();
00297   else
00298     ok = createImageSmall();
00299   if (!ok)
00300     return false;
00301 
00302   img = mPixmap.convertToImage();
00303   return true;
00304 }
00305 
00306 ThumbCreator::Flags VCard_LDIFCreator::flags() const
00307 {
00308   return (Flags)(DrawFrame | BlendIcon);
00309 }