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 <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 <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 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 TQString 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 TQStringList phoneNumbers; 00131 for (unsigned int no=0; no<pnList.count(); ++no) { 00132 TQString 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 TQString 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( TQPixmap( pixmap ) ); 00171 mSplitter->setItemSize( TQSize( 4, 7 ) ); 00172 } 00173 00174 TQSize 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 TQRect rect; 00186 int rest = mPixmap.width() - (numCharsPerLine * chSize.width()); 00187 xborder = TQMAX( xborder, rest / 2 ); // center horizontally 00188 rest = mPixmap.height() - (numLines * chSize.height()); 00189 yborder = TQMAX( 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 TQPixmap *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 TQChar 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, TQPoint(x,y), fontPixmap, rect, TQt::CopyROP ); 00232 00233 x += xOffset; // next character 00234 } 00235 00236 return true; 00237 } 00238 00239 bool VCard_LDIFCreator::createImageBig() 00240 { 00241 TQFont normalFont( KGlobalSettings::generalFont() ); 00242 TQFont titleFont( normalFont ); 00243 titleFont.setBold(true); 00244 // titleFont.setUnderline(true); 00245 titleFont.setItalic(true); 00246 00247 TQPainter painter(&mPixmap); 00248 painter.setFont(titleFont); 00249 TQFontMetrics fm(painter.fontMetrics()); 00250 00251 // draw contact name 00252 painter.setClipRect(2, 2, pixmapSize.width()-4, pixmapSize.height()-4); 00253 TQPoint 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 TQStringList list( TQStringList::split('\n', text) ); 00262 for ( TQStringList::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 TQString &path, int width, int height, TQImage &img) 00272 { 00273 if ( !readContents(path) ) 00274 return false; 00275 00276 // resize the image if necessary 00277 pixmapSize = TQSize( 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( TQColor( 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 }