kaddressbook

imagewidget.cpp

00001 /*
00002     This file is part of KAddressBook.
00003     Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
00004 
00005     This program is free software; you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018 
00019     As a special exception, permission is given to link this program
00020     with any edition of Qt, and distribute the resulting executable,
00021     without including the source code for Qt in the source distribution.
00022 */
00023 
00024 #include <kabc/picture.h>
00025 #include <kdebug.h>
00026 #include <kdialog.h>
00027 #include <kfiledialog.h>
00028 #include <kglobalsettings.h>
00029 #include <kiconloader.h>
00030 #include <kimageio.h>
00031 #include <kio/netaccess.h>
00032 #include <klocale.h>
00033 #include <kmessagebox.h>
00034 #include <kurldrag.h>
00035 #include <libkdepim/kpixmapregionselectordialog.h>
00036 
00037 #include <librss/loader.h>
00038 #include <librss/document.h>
00039 #include <librss/image.h>
00040 
00041 #include <qapplication.h>
00042 #include <qdragobject.h>
00043 #include <qeventloop.h>
00044 #include <qgroupbox.h>
00045 #include <qlabel.h>
00046 #include <qlayout.h>
00047 #include <qpixmap.h>
00048 #include <qpopupmenu.h>
00049 
00050 #include <unistd.h>
00051 
00052 #include "imagewidget.h"
00053 
00054 ImageLoader::ImageLoader()
00055   : QObject( 0, "ImageLoader" ),
00056     mIsLoadingBlog( false )
00057 {
00058 }
00059 
00060 
00061 KABC::Picture ImageLoader::loadPicture( const KURL &url, bool *ok )
00062 {
00063   KABC::Picture picture;
00064   QString tempFile;
00065 
00066   if ( url.isEmpty() )
00067     return picture;
00068 
00069   (*ok) = false;
00070 
00071   QImage image;
00072   if ( url.isLocalFile() ) {
00073     image.load( url.path() );
00074     picture.setData( image );
00075     (*ok) = true;
00076   } else if ( KIO::NetAccess::download( url, tempFile, 0 ) ) {
00077     image.load( tempFile );
00078     picture.setData( image );
00079     (*ok) = true;
00080     KIO::NetAccess::removeTempFile( tempFile );
00081   }
00082 
00083   if ( !(*ok) ) {
00084     // image does not exist (any more)
00085     KMessageBox::sorry( 0, i18n( "This contact's image cannot be found." ) );
00086     return picture;
00087   }
00088 
00089   QPixmap pixmap = picture.data();
00090 
00091   QPixmap selectedPixmap = KPIM::KPixmapRegionSelectorDialog::getSelectedImage( pixmap, 100, 140, 0 );
00092   if ( selectedPixmap.isNull() ) {
00093     (*ok) = false;
00094     return picture;
00095   }
00096 
00097   image = selectedPixmap;
00098   if ( image.height() != 140 || image.width() != 100 ) {
00099     if ( image.height() > image.width() )
00100       image = image.scaleHeight( 140 );
00101     else
00102       image = image.scaleWidth( 100 );
00103   }
00104 
00105   picture.setData( image );
00106   (*ok) = true;
00107 
00108   return picture;
00109 }
00110 
00111 KABC::Picture ImageLoader::loadBlog( const KURL &url, bool *ok )
00112 {
00113   RSS::Loader *loader = RSS::Loader::create();
00114   connect( loader, SIGNAL( loadingComplete( Loader*, Document, Status ) ),
00115            this, SLOT( loadingComplete( Loader*, Document, Status ) ) );
00116   loader->loadFrom( url, new RSS::FileRetriever );
00117 
00118   mIsLoadingBlog = true;
00119   while ( mIsLoadingBlog ) {
00120     qApp->eventLoop()->processEvents( QEventLoop::ExcludeUserInput );
00121     usleep( 500 );
00122   }
00123 
00124   if ( mPicture.data().isNull() ) {
00125     KMessageBox::sorry( 0,
00126         i18n( "Blog feed at '%1' does not contain an image." ).arg( url.url() ) );
00127     (*ok) = false;
00128   }
00129   (*ok) = true;
00130 
00131   return mPicture;
00132 }
00133 
00134 void ImageLoader::loadingComplete( RSS::Loader*,
00135                                    RSS::Document doc,
00136                                    RSS::Status status )
00137 {
00138   mIsLoadingBlog = false;
00139 
00140   if ( status != RSS::Success ) {
00141     mPicture = KABC::Picture();
00142     return;
00143   }
00144 
00145   if ( !doc.image() ) {
00146     mPicture = KABC::Picture();
00147     return;
00148   }
00149 
00150   bool ok = false;
00151   KABC::Picture pic = loadPicture( doc.image()->url().url(), &ok );
00152   if ( ok )
00153     mPicture = pic;
00154 }
00155 
00156 ImageButton::ImageButton( const QString &title, QWidget *parent )
00157   : QPushButton( title, parent ),
00158     mReadOnly( false ), mImageLoader( 0 )
00159 {
00160   setAcceptDrops( true );
00161 
00162   connect( this, SIGNAL( clicked() ), SLOT( load() ) );
00163 }
00164 
00165 void ImageButton::setReadOnly( bool readOnly )
00166 {
00167   mReadOnly = readOnly;
00168 }
00169 
00170 void ImageButton::setPicture( const KABC::Picture &picture )
00171 {
00172   mPicture = picture;
00173   updateGUI();
00174 }
00175 
00176 KABC::Picture ImageButton::picture() const
00177 {
00178   return mPicture;
00179 }
00180 
00181 void ImageButton::setImageLoader( ImageLoader *loader )
00182 {
00183   mImageLoader = loader;
00184 }
00185 
00186 void ImageButton::setBlogFeed( const KURL &url )
00187 {
00188   mBlogFeed = url;
00189 }
00190 
00191 void ImageButton::startDrag()
00192 {
00193   if ( !mPicture.data().isNull() ) {
00194     QImageDrag *drag = new QImageDrag( mPicture.data(), this );
00195     drag->dragCopy();
00196   }
00197 }
00198 
00199 void ImageButton::updateGUI()
00200 {
00201   if ( mPicture.data().isNull() )
00202     setPixmap( KGlobal::iconLoader()->iconPath( "personal", KIcon::Desktop ) );
00203   else
00204     setPixmap( mPicture.data() );
00205 }
00206 
00207 void ImageButton::dragEnterEvent( QDragEnterEvent *event )
00208 {
00209   bool accepted = false;
00210 
00211   if ( QImageDrag::canDecode( event ) )
00212     accepted = true;
00213 
00214   if ( QUriDrag::canDecode( event ) )
00215     accepted = true;
00216 
00217   event->accept( accepted );
00218 }
00219 
00220 void ImageButton::dropEvent( QDropEvent *event )
00221 {
00222   if ( mReadOnly )
00223     return;
00224 
00225   if ( QImageDrag::canDecode( event ) ) {
00226     QPixmap pm;
00227 
00228     if ( QImageDrag::decode( event, pm ) ) {
00229       mPicture.setData( pm.convertToImage() );
00230       updateGUI();
00231       emit changed();
00232     }
00233   }
00234 
00235   if ( QUriDrag::canDecode( event ) ) {
00236     KURL::List urls;
00237     if ( KURLDrag::decode( event, urls ) ) {
00238       if ( urls.isEmpty() ) { // oops, no data
00239         event->accept( false );
00240         return;
00241       }
00242     }
00243 
00244     if ( mImageLoader ) {
00245       bool ok = false;
00246       KABC::Picture pic = mImageLoader->loadPicture( urls[ 0 ], &ok );
00247       if ( ok ) {
00248         mPicture = pic;
00249         updateGUI();
00250         emit changed();
00251       }
00252     }
00253   }
00254 }
00255 
00256 void ImageButton::mousePressEvent( QMouseEvent *event )
00257 {
00258   mDragStartPos = event->pos();
00259   QPushButton::mousePressEvent( event );
00260 }
00261 
00262 void ImageButton::mouseMoveEvent( QMouseEvent *event )
00263 {
00264   if ( (event->state() & LeftButton) &&
00265        (event->pos() - mDragStartPos).manhattanLength() >
00266        KGlobalSettings::dndEventDelay() ) {
00267     startDrag();
00268   }
00269 }
00270 
00271 void ImageButton::contextMenuEvent( QContextMenuEvent *event )
00272 {
00273   QPopupMenu menu( this );
00274   menu.insertItem( i18n( "Reset" ), this, SLOT( clear() ) );
00275   if ( mBlogFeed.isValid() )
00276     menu.insertItem( i18n("Get From Blog"), this, SLOT( loadBlog() ) );
00277 
00278   menu.exec( event->globalPos() );
00279 }
00280 
00281 void ImageButton::load()
00282 {
00283   KURL url = KFileDialog::getOpenURL( QString(), KImageIO::pattern(), this );
00284   if ( url.isValid() ) {
00285     if ( mImageLoader ) {
00286       bool ok = false;
00287       KABC::Picture pic = mImageLoader->loadPicture( url, &ok );
00288       if ( ok ) {
00289         mPicture = pic;
00290         updateGUI();
00291         emit changed();
00292       }
00293     }
00294   }
00295 }
00296 
00297 void ImageButton::loadBlog()
00298 {
00299   bool ok = false;
00300   KABC::Picture pic = mImageLoader->loadBlog( mBlogFeed, &ok );
00301   if ( ok ) {
00302     mPicture = pic;
00303     updateGUI();
00304     emit changed();
00305   }
00306 }
00307 
00308 void ImageButton::clear()
00309 {
00310   mPicture = KABC::Picture();
00311   updateGUI();
00312 
00313   emit changed();
00314 }
00315 
00316 ImageBaseWidget::ImageBaseWidget( const QString &title,
00317                                   QWidget *parent, const char *name )
00318   : QWidget( parent, name ), mReadOnly( false )
00319 {
00320   mImageLoader = new ImageLoader();
00321 
00322   QVBoxLayout *topLayout = new QVBoxLayout( this, KDialog::marginHint(),
00323                                             KDialog::spacingHint() );
00324   QGroupBox *box = new QGroupBox( 0, Qt::Vertical, title, this );
00325   QVBoxLayout *layout = new QVBoxLayout( box->layout(), KDialog::spacingHint() );
00326 
00327   mImageButton = new ImageButton( i18n( "Picture" ), box );
00328   mImageButton->setFixedSize( 100, 140 );
00329   mImageButton->setImageLoader( mImageLoader );
00330   layout->addWidget( mImageButton );
00331 
00332   topLayout->addWidget( box );
00333 
00334   connect( mImageButton, SIGNAL( changed() ), SIGNAL( changed() ) );
00335 }
00336 
00337 ImageBaseWidget::~ImageBaseWidget()
00338 {
00339   delete mImageLoader;
00340   mImageLoader = 0;
00341 }
00342 
00343 void ImageBaseWidget::setReadOnly( bool readOnly )
00344 {
00345   mReadOnly = readOnly;
00346   mImageButton->setReadOnly( mReadOnly );
00347 }
00348 
00349 void ImageBaseWidget::setBlogFeed( const QString &feed )
00350 {
00351   mImageButton->setBlogFeed( feed );
00352 }
00353 
00354 void ImageBaseWidget::setImage( const KABC::Picture &photo )
00355 {
00356   mImageButton->setPicture( photo );
00357 }
00358 
00359 KABC::Picture ImageBaseWidget::image() const
00360 {
00361   return mImageButton->picture();
00362 }
00363 
00364 
00365 ImageWidget::ImageWidget( KABC::AddressBook *ab, QWidget *parent, const char *name )
00366   : KAB::ContactEditorWidget( ab, parent, name )
00367 {
00368   QHBoxLayout *layout = new QHBoxLayout( this, KDialog::marginHint(),
00369                                          KDialog::spacingHint() );
00370 
00371   mPhotoWidget = new ImageBaseWidget( KABC::Addressee::photoLabel(), this );
00372   layout->addWidget( mPhotoWidget );
00373 
00374   mLogoWidget = new ImageBaseWidget( KABC::Addressee::logoLabel(), this );
00375   layout->addWidget( mLogoWidget );
00376 
00377   connect( mPhotoWidget, SIGNAL( changed() ), SLOT( setModified() ) );
00378   connect( mLogoWidget, SIGNAL( changed() ), SLOT( setModified() ) );
00379 }
00380 
00381 void ImageWidget::loadContact( KABC::Addressee *addr )
00382 {
00383   mPhotoWidget->setImage( addr->photo() );
00384   mPhotoWidget->setBlogFeed( addr->custom( "KADDRESSBOOK", "BlogFeed" ) );
00385   mLogoWidget->setImage( addr->logo() );
00386 }
00387 
00388 void ImageWidget::storeContact( KABC::Addressee *addr )
00389 {
00390   addr->setPhoto( mPhotoWidget->image() );
00391   addr->setLogo( mLogoWidget->image() );
00392 }
00393 
00394 void ImageWidget::setReadOnly( bool readOnly )
00395 {
00396   mPhotoWidget->setReadOnly( readOnly );
00397   mLogoWidget->setReadOnly( readOnly );
00398 }
00399 
00400 #include "imagewidget.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys