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 }