You need a space here
[kdepim.git] / kaddressbook / thumbnailcreator / ldifvcardcreator.cpp
blob391064519c86c3bde3227c12a9f0b8296ec29a43
1 /*
2 This file is part of KAddressBook.
3 Copyright (C) 2003 Helge Deller <deller@kde.org>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 version 2 License as published by the Free Software Foundation.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
21 * - ldifvcardthumbnail -
23 * kioslave which generates tumbnails for vCard and LDIF files.
24 * The thumbnails are used e.g. by Konqueror or in the file selection
25 * dialog.
29 #include <QtCore/QFile>
30 #include <QtGui/QImage>
31 #include <QtGui/QPainter>
32 #include <QtGui/QPixmap>
34 #include <kdebug.h>
35 #include <kglobal.h>
36 #include <kglobalsettings.h>
37 #include <klocale.h>
38 #include <kabc/ldifconverter.h>
39 #include <kabc/vcardconverter.h>
40 #include <kstandarddirs.h>
42 #include "ldifvcardcreator.h"
44 extern "C"
46 ThumbCreator *new_creator()
48 KGlobal::locale()->insertCatalog( "kaddressbook" );
49 return new VCard_LDIFCreator;
53 VCard_LDIFCreator::VCard_LDIFCreator()
54 : mFont( 0 )
58 VCard_LDIFCreator::~VCard_LDIFCreator()
60 delete mFont;
64 bool VCard_LDIFCreator::readContents( const QString &path )
66 // read file contents
67 QFile file( path );
68 if ( !file.open( QIODevice::ReadOnly ) )
69 return false;
71 QString info;
72 text.truncate(0);
74 // read the file
75 QByteArray contents = file.readAll();
76 file.close();
78 // convert the file contents to a KABC::Addressee address
79 KABC::Addressee::List addrList;
80 KABC::Addressee addr;
81 KABC::VCardConverter converter;
83 addrList = converter.parseVCards( contents);
84 if ( addrList.count() == 0 ) {
85 KABC::AddresseeList l; // FIXME porting
86 if ( !KABC::LDIFConverter::LDIFToAddressee( contents, l ) )
87 return false;
88 // FIXME porting
89 KABC::AddresseeList::ConstIterator it( l.constBegin() );
90 for ( ; it != l.constEnd(); ++ it ) {
91 addrList.append( *it );
94 if ( addrList.count()>1 ) {
95 // create an overview (list of all names)
96 name = i18np("One contact found:", "%1 contacts found:", addrList.count());
97 int no, linenr;
98 for (linenr=no=0; linenr<30 && no<addrList.count(); ++no) {
99 addr = addrList[no];
100 info = addr.formattedName().simplified();
101 if (info.isEmpty())
102 info = addr.givenName() + ' ' + addr.familyName();
103 info = info.simplified();
104 if (info.isEmpty())
105 continue;
106 text.append(info);
107 text.append("\n");
108 ++linenr;
110 return true;
113 // create card for _one_ contact
114 addr = addrList[ 0 ];
116 // prepare the text
117 name = addr.formattedName().simplified();
118 if ( name.isEmpty() )
119 name = addr.givenName() + ' ' + addr.familyName();
120 name = name.simplified();
123 KABC::PhoneNumber::List pnList = addr.phoneNumbers();
124 QStringList phoneNumbers;
125 for (int no=0; no<pnList.count(); ++no) {
126 QString pn = pnList[no].number().simplified();
127 if (!pn.isEmpty() && !phoneNumbers.contains(pn))
128 phoneNumbers.append(pn);
130 if ( !phoneNumbers.isEmpty() )
131 text += phoneNumbers.join("\n") + '\n';
133 info = addr.organization().simplified();
134 if ( !info.isEmpty() )
135 text += info + '\n';
137 // get an address
138 KABC::Address address = addr.address(KABC::Address::Work);
139 if (address.isEmpty())
140 address = addr.address(KABC::Address::Home);
141 if (address.isEmpty())
142 address = addr.address(KABC::Address::Pref);
143 info = address.formattedAddress();
144 if ( !info.isEmpty() )
145 text += info + '\n';
147 return true;
150 QRect glyphCoords(int index, int fontWidth)
152 int itemsPerRow = fontWidth / 4;
153 return QRect( (index % itemsPerRow) * 4, (index / itemsPerRow) * 7, 4, 7 );
156 bool VCard_LDIFCreator::createImageSmall()
158 text = name + '\n' + text;
160 if ( !mFont ) {
161 QString pixmap = KStandardDirs::locate( "data", "kio_thumbnail/pics/thumbnailfont_7x4.png" );
162 if ( pixmap.isEmpty() ) {
163 kWarning() <<"VCard_LDIFCreator: Font image \"thumbnailfont_7x4.png\" not found!";
164 return false;
166 mFont = new QPixmap( pixmap );
169 QSize chSize(4, 7); // the size of one char
170 int xOffset = chSize.width();
171 int yOffset = chSize.height();
173 // calculate a better border so that the text is centered
174 int canvasWidth = pixmapSize.width() - 2 * xborder;
175 int canvasHeight = pixmapSize.height() - 2 * yborder;
176 int numCharsPerLine = (int) (canvasWidth / chSize.width());
177 int numLines = (int) (canvasHeight / chSize.height());
179 // render the information
180 QRect rect;
181 int rest = mPixmap.width() - (numCharsPerLine * chSize.width());
182 xborder = qMax( xborder, rest / 2 ); // center horizontally
183 rest = mPixmap.height() - (numLines * chSize.height());
184 yborder = qMax( yborder, rest / 2 ); // center vertically
185 // end centering
187 int x = xborder, y = yborder; // where to paint the characters
188 int posNewLine = mPixmap.width() - (chSize.width() + xborder);
189 int posLastLine = mPixmap.height() - (chSize.height() + yborder);
190 bool newLine = false;
191 Q_ASSERT( posNewLine > 0 );
192 //const QPixmap *fontPixmap = &(mSplitter->pixmap());
194 for ( int i = 0; i < text.length(); i++ ) {
195 if ( x > posNewLine || newLine ) { // start a new line?
196 x = xborder;
197 y += yOffset;
199 if ( y > posLastLine ) // more text than space
200 break;
202 // after starting a new line, we also jump to the next
203 // physical newline in the file if we don't come from one
204 if ( !newLine ) {
205 int pos = text.indexOf( '\n', i );
206 if ( pos > (int) i )
207 i = pos +1;
210 newLine = false;
213 // check for newlines in the text (unix,dos)
214 QChar ch = text.at( i );
215 if ( ch == '\n' ) {
216 newLine = true;
217 continue;
218 } else if ( ch == '\r' && text.at(i+1) == '\n' ) {
219 newLine = true;
220 i++; // skip the next character (\n) as well
221 continue;
224 rect = glyphCoords( (unsigned char)ch.toLatin1(), mFont->width() );
225 /* FIXME porting
226 if ( !rect.isEmpty() )
227 bitBlt( &mPixmap, QPoint(x,y), fontPixmap, rect, Qt::CopyROP );
230 x += xOffset; // next character
233 return true;
236 bool VCard_LDIFCreator::createImageBig()
238 QFont normalFont( KGlobalSettings::generalFont() );
239 QFont titleFont( normalFont );
240 titleFont.setBold(true);
241 // titleFont.setUnderline(true);
242 titleFont.setItalic(true);
244 QPainter painter(&mPixmap);
245 painter.setFont(titleFont);
246 QFontMetrics fm(painter.fontMetrics());
248 // draw contact name
249 painter.setClipRect(2, 2, pixmapSize.width()-4, pixmapSize.height()-4);
250 QPoint p(5, fm.height()+2);
251 painter.drawText(p, name);
252 p.setY( 3*p.y()/2 );
254 // draw contact information
255 painter.setFont(normalFont);
256 fm = painter.fontMetrics();
258 const QStringList list( text.split('\n', QString::SkipEmptyParts) );
259 for ( QStringList::ConstIterator it = list.begin();
260 p.y()<=pixmapSize.height() && it != list.end(); ++it ) {
261 p.setY( p.y() + fm.height() );
262 painter.drawText(p, *it);
265 return true;
268 bool VCard_LDIFCreator::create(const QString &path, int width, int height, QImage &img)
270 if ( !readContents(path) )
271 return false;
273 // resize the image if necessary
274 pixmapSize = QSize( width, height );
275 if (height * 3 > width * 4)
276 pixmapSize.setHeight( width * 4 / 3 );
277 else
278 pixmapSize.setWidth( height * 3 / 4 );
280 if ( pixmapSize != mPixmap.size() )
281 mPixmap = QPixmap( pixmapSize );
283 mPixmap.fill( QColor( 245, 245, 245 ) ); // light-grey background
285 // one pixel for the rectangle, the rest. whitespace
286 xborder = 1 + pixmapSize.width()/16; // minimum x-border
287 yborder = 1 + pixmapSize.height()/16; // minimum y-border
289 bool ok;
290 if ( width >= 150 /*pixel*/ )
291 ok = createImageBig();
292 else
293 ok = createImageSmall();
294 if (!ok)
295 return false;
297 img = mPixmap.toImage();
298 return true;
301 ThumbCreator::Flags VCard_LDIFCreator::flags() const
303 return (Flags)(DrawFrame | BlendIcon);