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