You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepim/kaddressbook/thumbnailcreator/ldifvcardcreator.cpp

308 lines
8.4 KiB

/*
This file is part of KAddressBook.
Copyright (C) 2003 Helge Deller <deller@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
version 2 License as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
/*
* - ldifvcardthumbnail -
*
* tdeioslave which generates tumbnails for vCard and LDIF files.
* The thumbnails are used e.g. by Konqueror or in the file selection
* dialog.
*
*/
#include <tqdatetime.h>
#include <tqfile.h>
#include <tqpixmap.h>
#include <tqimage.h>
#include <tqpainter.h>
#include <tqtextstream.h>
#include <kdebug.h>
#include <kglobal.h>
#include <klocale.h>
#include <kabc/ldifconverter.h>
#include <kabc/vcardconverter.h>
#include <kpixmapsplitter.h>
#include <kstandarddirs.h>
#include <kglobalsettings.h>
#include "ldifvcardcreator.h"
extern "C"
{
ThumbCreator *new_creator()
{
TDEGlobal::locale()->insertCatalogue( "kaddressbook" );
return new VCard_LDIFCreator;
}
}
VCard_LDIFCreator::VCard_LDIFCreator()
: mSplitter( 0 )
{
}
VCard_LDIFCreator::~VCard_LDIFCreator()
{
delete mSplitter;
}
bool VCard_LDIFCreator::readContents( const TQString &path )
{
// read file contents
TQFile file( path );
if ( !file.open( IO_ReadOnly ) )
return false;
TQString info;
text.truncate(0);
// read the file
#if defined(KABC_VCARD_ENCODING_FIX)
const TQByteArray data = file.readAll();
const TQString contents( data );
const TQCString contentsRaw( data.data(), data.size() );
#else
TQString contents = file.readAll();
#endif
file.close();
// convert the file contents to a KABC::Addressee address
KABC::AddresseeList addrList;
KABC::Addressee addr;
KABC::VCardConverter converter;
#if defined(KABC_VCARD_ENCODING_FIX)
addrList = converter.parseVCardsRaw( contentsRaw );
#else
addrList = converter.parseVCards( contents );
#endif
if ( addrList.count() == 0 )
if ( !KABC::LDIFConverter::LDIFToAddressee( contents, addrList ) )
return false;
if ( addrList.count()>1 ) {
// create an overview (list of all names)
name = i18n("One contact found:", "%n contacts found:", addrList.count());
unsigned int no, linenr;
for (linenr=no=0; linenr<30 && no<addrList.count(); ++no) {
addr = addrList[no];
info = addr.formattedName().simplifyWhiteSpace();
if (info.isEmpty())
info = addr.givenName() + " " + addr.familyName();
info = info.simplifyWhiteSpace();
if (info.isEmpty())
continue;
text.append(info);
text.append("\n");
++linenr;
}
return true;
}
// create card for _one_ contact
addr = addrList[ 0 ];
// prepare the text
name = addr.formattedName().simplifyWhiteSpace();
if ( name.isEmpty() )
name = addr.givenName() + " " + addr.familyName();
name = name.simplifyWhiteSpace();
KABC::PhoneNumber::List pnList = addr.phoneNumbers();
TQStringList phoneNumbers;
for (unsigned int no=0; no<pnList.count(); ++no) {
TQString pn = pnList[no].number().simplifyWhiteSpace();
if (!pn.isEmpty() && !phoneNumbers.contains(pn))
phoneNumbers.append(pn);
}
if ( !phoneNumbers.isEmpty() )
text += phoneNumbers.join("\n") + "\n";
info = addr.organization().simplifyWhiteSpace();
if ( !info.isEmpty() )
text += info + "\n";
// get an address
KABC::Address address = addr.address(KABC::Address::Work);
if (address.isEmpty())
address = addr.address(KABC::Address::Home);
if (address.isEmpty())
address = addr.address(KABC::Address::Pref);
info = address.formattedAddress();
if ( !info.isEmpty() )
text += info + "\n";
return true;
}
bool VCard_LDIFCreator::createImageSmall()
{
text = name + "\n" + text;
if ( !mSplitter ) {
mSplitter = new KPixmapSplitter;
TQString pixmap = locate( "data", "konqueror/pics/thumbnailfont_7x4.png" );
if ( pixmap.isEmpty() ) {
delete mSplitter;
mSplitter=0;
kdWarning() << "VCard_LDIFCreator: Font image \"thumbnailfont_7x4.png\" not found!\n";
return false;
}
mSplitter->setPixmap( TQPixmap( pixmap ) );
mSplitter->setItemSize( TQSize( 4, 7 ) );
}
TQSize chSize = mSplitter->itemSize(); // the size of one char
int xOffset = chSize.width();
int yOffset = chSize.height();
// calculate a better border so that the text is centered
int canvasWidth = pixmapSize.width() - 2 * xborder;
int canvasHeight = pixmapSize.height() - 2 * yborder;
int numCharsPerLine = (int) (canvasWidth / chSize.width());
int numLines = (int) (canvasHeight / chSize.height());
// render the information
TQRect rect;
int rest = mPixmap.width() - (numCharsPerLine * chSize.width());
xborder = TQMAX( xborder, rest / 2 ); // center horizontally
rest = mPixmap.height() - (numLines * chSize.height());
yborder = TQMAX( yborder, rest / 2 ); // center vertically
// end centering
int x = xborder, y = yborder; // where to paint the characters
int posNewLine = mPixmap.width() - (chSize.width() + xborder);
int posLastLine = mPixmap.height() - (chSize.height() + yborder);
bool newLine = false;
Q_ASSERT( posNewLine > 0 );
const TQPixmap *fontPixmap = &(mSplitter->pixmap());
for ( uint i = 0; i < text.length(); i++ ) {
if ( x > posNewLine || newLine ) { // start a new line?
x = xborder;
y += yOffset;
if ( y > posLastLine ) // more text than space
break;
// after starting a new line, we also jump to the next
// physical newline in the file if we don't come from one
if ( !newLine ) {
int pos = text.find( '\n', i );
if ( pos > (int) i )
i = pos +1;
}
newLine = false;
}
// check for newlines in the text (unix,dos)
TQChar ch = text.at( i );
if ( ch == '\n' ) {
newLine = true;
continue;
} else if ( ch == '\r' && text.at(i+1) == '\n' ) {
newLine = true;
i++; // skip the next character (\n) as well
continue;
}
rect = mSplitter->coordinates( ch );
if ( !rect.isEmpty() )
bitBlt( &mPixmap, TQPoint(x,y), fontPixmap, rect, TQt::CopyROP );
x += xOffset; // next character
}
return true;
}
bool VCard_LDIFCreator::createImageBig()
{
TQFont normalFont( TDEGlobalSettings::generalFont() );
TQFont titleFont( normalFont );
titleFont.setBold(true);
// titleFont.setUnderline(true);
titleFont.setItalic(true);
TQPainter painter(&mPixmap);
painter.setFont(titleFont);
TQFontMetrics fm(painter.fontMetrics());
// draw contact name
painter.setClipRect(2, 2, pixmapSize.width()-4, pixmapSize.height()-4);
TQPoint p(5, fm.height()+2);
painter.drawText(p, name);
p.setY( 3*p.y()/2 );
// draw contact information
painter.setFont(normalFont);
fm = painter.fontMetrics();
const TQStringList list( TQStringList::split('\n', text) );
for ( TQStringList::ConstIterator it = list.begin();
p.y()<=pixmapSize.height() && it != list.end(); ++it ) {
p.setY( p.y() + fm.height() );
painter.drawText(p, *it);
}
return true;
}
bool VCard_LDIFCreator::create(const TQString &path, int width, int height, TQImage &img)
{
if ( !readContents(path) )
return false;
// resize the image if necessary
pixmapSize = TQSize( width, height );
if (height * 3 > width * 4)
pixmapSize.setHeight( width * 4 / 3 );
else
pixmapSize.setWidth( height * 3 / 4 );
if ( pixmapSize != mPixmap.size() )
mPixmap.resize( pixmapSize );
mPixmap.fill( TQColor( 245, 245, 245 ) ); // light-grey background
// one pixel for the rectangle, the rest. whitespace
xborder = 1 + pixmapSize.width()/16; // minimum x-border
yborder = 1 + pixmapSize.height()/16; // minimum y-border
bool ok;
if ( width >= 150 /*pixel*/ )
ok = createImageBig();
else
ok = createImageSmall();
if (!ok)
return false;
img = mPixmap.convertToImage();
return true;
}
ThumbCreator::Flags VCard_LDIFCreator::flags() const
{
return (Flags)(DrawFrame | BlendIcon);
}