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  *  kioslave 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 <qdatetime.h>
00030 #include <qfile.h>
00031 #include <qpixmap.h>
00032 #include <qimage.h>
00033 #include <qpainter.h>
00034 #include <qtextstream.h>
00035 
00036 #include <kdebug.h>
00037 #include <kglobal.h>
00038 #include <klocale.h>
00039 #include <kabc/ldifconverter.h>
00040 #include <kabc/vcardconverter.h>
00041 #include <kpixmapsplitter.h>
00042 #include <kstandarddirs.h>
00043 #include <kglobalsettings.h>
00044 
00045 #include "ldifvcardcreator.h"
00046 
00047 extern "C"
00048 {
00049   ThumbCreator *new_creator()
00050   {
00051     KGlobal::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 QString &path )
00068 {
00069   // read file contents
00070   QFile file( path );
00071   if ( !file.open( IO_ReadOnly ) )
00072     return false;
00073 
00074   QString info;
00075   text.truncate(0);
00076 
00077   // read the file
00078 #if defined(KABC_VCARD_ENCODING_FIX)
00079   const QByteArray data = file.readAll();
00080   const QString contents( data );
00081   const QCString contentsRaw( data.data(), data.size() );
00082 #else
00083   QString contents = file.readAll();
00084 #endif
00085   file.close();
00086 
00087   // convert the file contents to a KABC::Addressee address
00088   KABC::AddresseeList addrList;
00089   KABC::Addressee addr;
00090   KABC::VCardConverter converter;
00091 
00092 #if defined(KABC_VCARD_ENCODING_FIX)
00093   addrList = converter.parseVCardsRaw( contentsRaw );
00094 #else
00095   addrList = converter.parseVCards( contents );
00096 #endif
00097   if ( addrList.count() == 0 )
00098     if ( !KABC::LDIFConverter::LDIFToAddressee( contents, addrList ) )
00099     return false;
00100   if ( addrList.count()>1 ) {
00101     // create an overview (list of all names)
00102     name = i18n("One contact found:", "%n contacts found:", addrList.count());
00103     unsigned int no, linenr;
00104     for (linenr=no=0; linenr<30 && no<addrList.count(); ++no) {
00105        addr = addrList[no];
00106        info = addr.formattedName().simplifyWhiteSpace();
00107        if (info.isEmpty())
00108           info = addr.givenName() + " " + addr.familyName();
00109        info = info.simplifyWhiteSpace();
00110        if (info.isEmpty())
00111          continue;
00112        text.append(info);
00113        text.append("\n");
00114        ++linenr;
00115     }
00116     return true;
00117   }
00118 
00119   // create card for _one_ contact
00120   addr = addrList[ 0 ];
00121 
00122   // prepare the text
00123   name = addr.formattedName().simplifyWhiteSpace();
00124   if ( name.isEmpty() )
00125     name = addr.givenName() + " " + addr.familyName();
00126   name = name.simplifyWhiteSpace();
00127 
00128 
00129   KABC::PhoneNumber::List pnList = addr.phoneNumbers();
00130   QStringList phoneNumbers;
00131   for (unsigned int no=0; no<pnList.count(); ++no) {
00132     QString pn = pnList[no].number().simplifyWhiteSpace();
00133     if (!pn.isEmpty() && !phoneNumbers.contains(pn))
00134       phoneNumbers.append(pn);
00135   }
00136   if ( !phoneNumbers.isEmpty() )
00137       text += phoneNumbers.join("\n") + "\n";
00138 
00139   info = addr.organization().simplifyWhiteSpace();
00140   if ( !info.isEmpty() )
00141     text += info + "\n";
00142 
00143   // get an address
00144   KABC::Address address = addr.address(KABC::Address::Work);
00145   if (address.isEmpty())
00146     address = addr.address(KABC::Address::Home);
00147   if (address.isEmpty())
00148     address = addr.address(KABC::Address::Pref);
00149   info = address.formattedAddress();
00150   if ( !info.isEmpty() )
00151     text += info + "\n";
00152 
00153   return true;
00154 }
00155 
00156 
00157 bool VCard_LDIFCreator::createImageSmall()
00158 {
00159   text = name + "\n" + text;
00160 
00161   if ( !mSplitter ) {
00162     mSplitter = new KPixmapSplitter;
00163     QString pixmap = locate( "data", "konqueror/pics/thumbnailfont_7x4.png" );
00164     if ( pixmap.isEmpty() ) {
00165       delete mSplitter;
00166       mSplitter=0;
00167       kdWarning() << "VCard_LDIFCreator: Font image \"thumbnailfont_7x4.png\" not found!\n";
00168       return false;
00169     }
00170     mSplitter->setPixmap( QPixmap( pixmap ) );
00171     mSplitter->setItemSize( QSize( 4, 7 ) );
00172   }
00173 
00174   QSize chSize = mSplitter->itemSize(); // the size of one char
00175   int xOffset = chSize.width();
00176   int yOffset = chSize.height();
00177 
00178   // calculate a better border so that the text is centered
00179   int canvasWidth = pixmapSize.width() - 2 * xborder;
00180   int canvasHeight = pixmapSize.height() -  2 * yborder;
00181   int numCharsPerLine = (int) (canvasWidth / chSize.width());
00182   int numLines = (int) (canvasHeight / chSize.height());
00183 
00184   // render the information
00185   QRect rect;
00186   int rest = mPixmap.width() - (numCharsPerLine * chSize.width());
00187   xborder = QMAX( xborder, rest / 2 ); // center horizontally
00188   rest = mPixmap.height() - (numLines * chSize.height());
00189   yborder = QMAX( yborder, rest / 2 ); // center vertically
00190   // end centering
00191 
00192   int x = xborder, y = yborder; // where to paint the characters
00193   int posNewLine  = mPixmap.width() - (chSize.width() + xborder);
00194   int posLastLine = mPixmap.height() - (chSize.height() + yborder);
00195   bool newLine = false;
00196   Q_ASSERT( posNewLine > 0 );
00197   const QPixmap *fontPixmap = &(mSplitter->pixmap());
00198 
00199   for ( uint i = 0; i < text.length(); i++ ) {
00200     if ( x > posNewLine || newLine ) {  // start a new line?
00201       x = xborder;
00202       y += yOffset;
00203 
00204       if ( y > posLastLine ) // more text than space
00205         break;
00206 
00207       // after starting a new line, we also jump to the next
00208       // physical newline in the file if we don't come from one
00209       if ( !newLine ) {
00210         int pos = text.find( '\n', i );
00211         if ( pos > (int) i )
00212           i = pos +1;
00213       }
00214 
00215       newLine = false;
00216     }
00217 
00218     // check for newlines in the text (unix,dos)
00219     QChar ch = text.at( i );
00220     if ( ch == '\n' ) {
00221       newLine = true;
00222       continue;
00223     } else if ( ch == '\r' && text.at(i+1) == '\n' ) {
00224       newLine = true;
00225       i++; // skip the next character (\n) as well
00226       continue;
00227     }
00228 
00229     rect = mSplitter->coordinates( ch );
00230     if ( !rect.isEmpty() )
00231       bitBlt( &mPixmap, QPoint(x,y), fontPixmap, rect, Qt::CopyROP );
00232 
00233     x += xOffset; // next character
00234   }
00235 
00236   return true;
00237 }
00238 
00239 bool VCard_LDIFCreator::createImageBig()
00240 {
00241   QFont normalFont( KGlobalSettings::generalFont() );
00242   QFont titleFont( normalFont );
00243   titleFont.setBold(true);
00244   // titleFont.setUnderline(true);
00245   titleFont.setItalic(true);
00246 
00247   QPainter painter(&mPixmap);
00248   painter.setFont(titleFont);
00249   QFontMetrics fm(painter.fontMetrics());
00250 
00251   // draw contact name
00252   painter.setClipRect(2, 2, pixmapSize.width()-4, pixmapSize.height()-4);
00253   QPoint p(5, fm.height()+2);
00254   painter.drawText(p, name);
00255   p.setY( 3*p.y()/2 );
00256 
00257   // draw contact information
00258   painter.setFont(normalFont);
00259   fm = painter.fontMetrics();
00260 
00261   const QStringList list( QStringList::split('\n', text) );
00262   for ( QStringList::ConstIterator it = list.begin();
00263              p.y()<=pixmapSize.height() && it != list.end(); ++it ) {
00264      p.setY( p.y() + fm.height() );
00265      painter.drawText(p, *it);
00266   }
00267 
00268   return true;
00269 }
00270 
00271 bool VCard_LDIFCreator::create(const QString &path, int width, int height, QImage &img)
00272 {
00273   if ( !readContents(path) )
00274     return false;
00275 
00276   // resize the image if necessary
00277   pixmapSize = QSize( width, height );
00278   if (height * 3 > width * 4)
00279     pixmapSize.setHeight( width * 4 / 3 );
00280   else
00281     pixmapSize.setWidth( height * 3 / 4 );
00282 
00283   if ( pixmapSize != mPixmap.size() )
00284     mPixmap.resize( pixmapSize );
00285 
00286   mPixmap.fill( QColor( 245, 245, 245 ) ); // light-grey background
00287 
00288   // one pixel for the rectangle, the rest. whitespace
00289   xborder = 1 + pixmapSize.width()/16;  // minimum x-border
00290   yborder = 1 + pixmapSize.height()/16; // minimum y-border
00291 
00292   bool ok;
00293   if ( width >= 150 /*pixel*/ )
00294     ok = createImageBig();
00295   else
00296     ok = createImageSmall();
00297   if (!ok)
00298     return false;
00299 
00300   img = mPixmap.convertToImage();
00301   return true;
00302 }
00303 
00304 ThumbCreator::Flags VCard_LDIFCreator::flags() const
00305 {
00306   return (Flags)(DrawFrame | BlendIcon);
00307 }
KDE Home | KDE Accessibility Home | Description of Access Keys