kio Library API Documentation

kicondialog.cpp

00001 /* vi: ts=8 sts=4 sw=4
00002  *
00003  * This file is part of the KDE project, module kfile.
00004  * Copyright (C) 2000 Geert Jansen <jansen@kde.org>
00005  *           (C) 2000 Kurt Granroth <granroth@kde.org>
00006  *           (C) 1997 Christoph Neerfeld <chris@kde.org>
00007  *           (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
00008  *
00009  * This is free software; it comes under the GNU Library General
00010  * Public License, version 2. See the file "COPYING.LIB" for the
00011  * exact licensing terms.
00012  */
00013 
00014 #include <qlayout.h>
00015 #include <qstring.h>
00016 #include <qstringlist.h>
00017 #include <qsortedlist.h>
00018 #include <qimage.h>
00019 #include <qpixmap.h>
00020 #include <qlabel.h>
00021 #include <qcombobox.h>
00022 #include <qtimer.h>
00023 #include <qbuttongroup.h>
00024 #include <qradiobutton.h>
00025 #include <qfileinfo.h>
00026 
00027 #include <kapplication.h>
00028 #include <klocale.h>
00029 #include <kglobal.h>
00030 #include <kstandarddirs.h>
00031 #include <kiconloader.h>
00032 #include <kprogress.h>
00033 #include <kiconview.h>
00034 #include <kfiledialog.h>
00035 #include <kimagefilepreview.h>
00036 
00037 #include <config.h>
00038 #ifdef HAVE_LIBART
00039 #include <svgicons/ksvgiconengine.h>
00040 #include <svgicons/ksvgiconpainter.h>
00041 #endif
00042 
00043 #include "kicondialog.h"
00044 
00045 class KIconCanvas::KIconCanvasPrivate
00046 {
00047   public:
00048     KIconCanvasPrivate() { m_bLoading = false; }
00049     ~KIconCanvasPrivate() {}
00050     bool m_bLoading;
00051 };
00052 
00056 class IconPath : public QString
00057 {
00058 protected:
00059  QString m_iconName;
00060 
00061 public:
00062  IconPath(const QString &ip) : QString (ip)
00063  {
00064    int n = findRev('/');
00065    m_iconName = (n==-1) ? static_cast<QString>(*this) : mid(n+1);
00066  }
00067 
00068 
00069  IconPath() : QString ()
00070  { }
00071 
00072  bool operator== (const IconPath &ip) const
00073  { return m_iconName == ip.m_iconName; }
00074 
00075  bool operator< (const IconPath &ip) const
00076  { return m_iconName < ip.m_iconName; }
00077 
00078 };
00079 
00080 /*
00081  * KIconCanvas: Iconview for the iconloader dialog.
00082  */
00083 
00084 KIconCanvas::KIconCanvas(QWidget *parent, const char *name)
00085     : KIconView(parent, name)
00086 {
00087     d = new KIconCanvasPrivate;
00088     mpLoader = KGlobal::iconLoader();
00089     mpTimer = new QTimer(this);
00090     connect(mpTimer, SIGNAL(timeout()), SLOT(slotLoadFiles()));
00091     connect(this, SIGNAL(currentChanged(QIconViewItem *)),
00092         SLOT(slotCurrentChanged(QIconViewItem *)));
00093     setGridX(80);
00094     setWordWrapIconText(false);
00095     setShowToolTips(true);
00096 }
00097 
00098 KIconCanvas::~KIconCanvas()
00099 {
00100     delete mpTimer;
00101     delete d;
00102 }
00103 
00104 void KIconCanvas::loadFiles(const QStringList& files)
00105 {
00106     clear();
00107     mFiles = files;
00108     emit startLoading(mFiles.count());
00109     mpTimer->start(0, true);
00110     d->m_bLoading = false;
00111 }
00112 
00113 void KIconCanvas::slotLoadFiles()
00114 {
00115     setResizeMode(Fixed);
00116     QApplication::setOverrideCursor(waitCursor);
00117 
00118     // disable updates to not trigger paint events when adding child items
00119     setUpdatesEnabled( false );
00120 
00121 #ifdef HAVE_LIBART
00122     KSVGIconEngine *svgEngine = new KSVGIconEngine();
00123 #endif
00124     
00125     d->m_bLoading = true;
00126     int i;
00127     QStringList::ConstIterator it;
00128     uint emitProgress = 10; // so we will emit it once in the beginning
00129     for (it=mFiles.begin(), i=0; it!=mFiles.end(); it++, i++)
00130     {
00131     // Calling kapp->processEvents() makes the iconview flicker like hell
00132     // (it's being repainted once for every new item), so we don't do this.
00133     // Instead, we directly repaint the progress bar without going through
00134     // the event-loop. We do that just once for every 10th item so that
00135     // the progress bar doesn't flicker in turn. (pfeiffer)
00136     if ( emitProgress >= 10 ) {
00137         emit progress(i);
00138             emitProgress = 0;
00139         }
00140 
00141         emitProgress++;
00142 //  kapp->processEvents();
00143         if ( !d->m_bLoading ) // user clicked on a button that will load another set of icons
00144             break;
00145     QImage img;
00146     
00147     // Use the extension as the format. Works for XPM and PNG, but not for SVG
00148     QString path= *it;
00149     QString ext = path.right(3).upper();
00150 
00151     if (ext != "SVG" && ext != "VGZ")
00152         img.load(*it);
00153 #ifdef HAVE_LIBART
00154     else
00155         if (svgEngine->load(60, 60, *it))
00156         img = *svgEngine->painter()->image();
00157 #endif
00158     
00159     if (img.isNull()) 
00160         continue;
00161     if (img.width() > 60 || img.height() > 60)
00162     {
00163         if (img.width() > img.height())
00164         {
00165         int height = (int) ((60.0 / img.width()) * img.height());
00166         img = img.smoothScale(60, height);
00167         } else
00168         {
00169         int width = (int) ((60.0 / img.height()) * img.width());
00170         img = img.smoothScale(width, 60);
00171         }
00172     }
00173     QPixmap pm;
00174     pm.convertFromImage(img);
00175     QFileInfo fi(*it);
00176     QIconViewItem *item = new QIconViewItem(this, fi.baseName(), pm);
00177     item->setKey(*it);
00178     item->setDragEnabled(false);
00179     item->setDropEnabled(false);
00180     }
00181 
00182 #ifdef HAVE_LIBART
00183     delete svgEngine;
00184 #endif
00185 
00186     // enable updates since we have to draw the whole view now
00187     setUpdatesEnabled( true );
00188 
00189     QApplication::restoreOverrideCursor();
00190     d->m_bLoading = false;
00191     emit finished();
00192     setResizeMode(Adjust);
00193 }
00194 
00195 QString KIconCanvas::getCurrent() const
00196 {
00197     if (!currentItem())
00198     return QString::null;
00199     return currentItem()->key();
00200 }
00201 
00202 void KIconCanvas::stopLoading()
00203 {
00204     d->m_bLoading = false;
00205 }
00206 
00207 void KIconCanvas::slotCurrentChanged(QIconViewItem *item)
00208 {
00209     emit nameChanged((item != 0L) ? item->text() : QString::null);
00210 }
00211 
00212 class KIconDialog::KIconDialogPrivate
00213 {
00214   public:
00215     KIconDialogPrivate() {
00216         m_bStrictIconSize = true;
00217     m_bLockUser = false;
00218     m_bLockCustomDir = false;
00219     }
00220     ~KIconDialogPrivate() {}
00221     bool m_bStrictIconSize, m_bLockUser, m_bLockCustomDir;
00222     QString custom;
00223     QString customLocation;
00224 };
00225 
00226 /*
00227  * KIconDialog: Dialog for selecting icons. Both system and user
00228  * specified icons can be chosen.
00229  */
00230 
00231 KIconDialog::KIconDialog(QWidget *parent, const char *name)
00232     : KDialogBase(parent, name, true, i18n("Select Icon"), Help|Ok|Cancel, Ok)
00233 {
00234     d = new KIconDialogPrivate;
00235     mpLoader = KGlobal::iconLoader();
00236     init();
00237 }
00238 
00239 KIconDialog::KIconDialog(KIconLoader *loader, QWidget *parent,
00240     const char *name)
00241     : KDialogBase(parent, name, true, i18n("Select Icon"), Help|Ok|Cancel, Ok)
00242 {
00243     d = new KIconDialogPrivate;
00244     mpLoader = loader;
00245     init();
00246 }
00247 
00248 void KIconDialog::init()
00249 {
00250     mGroupOrSize = KIcon::Desktop;
00251     mContext = KIcon::Any;
00252     mType = 0;
00253     mFileList = KGlobal::dirs()->findAllResources("appicon", QString::fromLatin1("*.png"));
00254 
00255     QWidget *main = new QWidget( this );
00256     setMainWidget(main);
00257 
00258     QVBoxLayout *top = new QVBoxLayout(main);
00259     top->setSpacing( spacingHint() );
00260 
00261     QButtonGroup *bgroup = new QButtonGroup(i18n("Icon Source"), main);
00262     top->addWidget(bgroup);
00263     connect(bgroup, SIGNAL(clicked(int)), SLOT(slotButtonClicked(int)));
00264     QGridLayout *grid = new QGridLayout(bgroup, 3, 2, marginHint(), spacingHint());
00265     grid->addRowSpacing(0, 15);
00266     mpRb1 = new QRadioButton(i18n("&System icons:"), bgroup);
00267     grid->addWidget(mpRb1, 1, 0);
00268     mpCombo = new QComboBox(bgroup);
00269     connect(mpCombo, SIGNAL(activated(int)), SLOT(slotContext(int)));
00270     grid->addWidget(mpCombo, 1, 1);
00271     mpRb2 = new QRadioButton(i18n("O&ther icons:"), bgroup);
00272     grid->addWidget(mpRb2, 2, 0);
00273     mpBrowseBut = new QPushButton(i18n("&Browse..."), bgroup);
00274     grid->addWidget(mpBrowseBut, 2, 1);
00275 
00276     mpCanvas = new KIconCanvas(main);
00277     connect(mpCanvas, SIGNAL(executed(QIconViewItem *)), SLOT(slotAcceptIcons()));
00278     mpCanvas->setMinimumSize(400, 125);
00279     top->addWidget(mpCanvas);
00280 
00281     mpProgress = new KProgress(main);
00282     top->addWidget(mpProgress);
00283     connect(mpCanvas, SIGNAL(startLoading(int)), SLOT(slotStartLoading(int)));
00284     connect(mpCanvas, SIGNAL(progress(int)), SLOT(slotProgress(int)));
00285     connect(mpCanvas, SIGNAL(finished()), SLOT(slotFinished()));
00286 
00287     // When pressing Ok or Cancel, stop loading icons
00288     connect(this, SIGNAL(hidden()), mpCanvas, SLOT(stopLoading()));
00289 
00290     // The order must match the context definitions in KIcon.
00291     mpCombo->insertItem(i18n("Actions"));
00292     mpCombo->insertItem(i18n("Applications"));
00293     mpCombo->insertItem(i18n("Devices"));
00294     mpCombo->insertItem(i18n("Filesystems"));
00295     mpCombo->insertItem(i18n("Mimetypes"));
00296     mpCombo->setFixedSize(mpCombo->sizeHint());
00297     mpBrowseBut->setFixedWidth(mpCombo->width());
00298 
00299     // Make the dialog a little taller
00300     incInitialSize(QSize(0,100));
00301 }
00302 
00303 
00304 KIconDialog::~KIconDialog()
00305 {
00306     delete d;
00307 }
00308 
00309 void KIconDialog::slotAcceptIcons()
00310 {
00311   d->custom=QString::null;
00312   slotOk();
00313 }
00314 
00315 void KIconDialog::showIcons()
00316 {
00317     mpCanvas->clear();
00318     QStringList filelist;
00319     if (mType == 0)
00320     if (d->m_bStrictIconSize)
00321             filelist=mpLoader->queryIcons(mGroupOrSize, mContext);
00322         else
00323             filelist=mpLoader->queryIconsByContext(mGroupOrSize, mContext);
00324     else if ( !d->customLocation.isNull() )
00325     filelist=mpLoader->queryIconsByDir( d->customLocation );
00326     else
00327     filelist=mFileList;
00328 
00329     QSortedList <IconPath>iconlist;
00330     iconlist.setAutoDelete(true);
00331     QStringList::Iterator it;
00332     for( it = filelist.begin(); it != filelist.end(); ++it )
00333        iconlist.append(new IconPath(*it));
00334        
00335     iconlist.sort();
00336     filelist.clear();
00337 
00338     for ( IconPath *ip=iconlist.first(); ip != 0; ip=iconlist.next() )
00339        filelist.append(*ip);
00340 
00341     mpCanvas->loadFiles(filelist);
00342 }
00343 
00344 void KIconDialog::setStrictIconSize(bool b)
00345 {
00346     d->m_bStrictIconSize=b;
00347 }
00348 
00349 bool KIconDialog::strictIconSize() const
00350 {
00351     return d->m_bStrictIconSize;
00352 }
00353 
00354 void KIconDialog::setIconSize( int size )
00355 {
00356     // see KIconLoader, if you think this is weird
00357     if ( size == 0 )
00358         mGroupOrSize = KIcon::Desktop; // default Group
00359     else
00360         mGroupOrSize = -size; // yes, KIconLoader::queryIconsByContext is weird
00361 }
00362 
00363 int KIconDialog::iconSize() const
00364 {
00365     // 0 or any other value ==> mGroupOrSize is a group, so we return 0
00366     return (mGroupOrSize < 0) ? -mGroupOrSize : 0;
00367 }
00368 
00369 #ifndef KDE_NO_COMPAT
00370 QString KIconDialog::selectIcon(KIcon::Group group, KIcon::Context context, bool user)
00371 {
00372     setup( group, context, false, 0, user );
00373     return openDialog();
00374 }
00375 #endif
00376 
00377 void KIconDialog::setup(KIcon::Group group, KIcon::Context context,
00378                         bool strictIconSize, int iconSize, bool user )
00379 {
00380     d->m_bStrictIconSize = strictIconSize;
00381     mGroupOrSize = (iconSize == 0) ? group : -iconSize;
00382     mType = user ? 1 : 0;
00383     mpRb1->setChecked(!user);
00384     mpRb2->setChecked(user);
00385     mpCombo->setEnabled(!user);
00386     mpBrowseBut->setEnabled(user);
00387     mContext = context;
00388     mpCombo->setCurrentItem(mContext-1);
00389 }
00390 
00391 void KIconDialog::setup(KIcon::Group group, KIcon::Context context,
00392                         bool strictIconSize, int iconSize, bool user,
00393                         bool lockUser, bool lockCustomDir )
00394 {
00395     d->m_bStrictIconSize = strictIconSize;
00396     d->m_bLockUser = lockUser;
00397     d->m_bLockCustomDir = lockCustomDir;
00398     mGroupOrSize = (iconSize == 0) ? group : -iconSize;
00399     mType = user ? 1 : 0;
00400     mpRb1->setChecked(!user);
00401     mpRb1->setEnabled( !lockUser || !user );
00402     mpRb2->setChecked(user);
00403     mpRb2->setEnabled( !lockUser || user );
00404     mpCombo->setEnabled(!user);
00405     mpBrowseBut->setEnabled( user && !lockCustomDir );
00406     mContext = context;
00407     mpCombo->setCurrentItem(mContext-1);
00408 }
00409 
00410 void KIconDialog::setCustomLocation( const QString& location )
00411 {
00412     d->customLocation = location;
00413 }
00414 
00415 QString KIconDialog::openDialog()
00416 {
00417     showIcons();
00418 
00419     if ( exec() == Accepted )
00420     {
00421         if (!d->custom.isNull())
00422             return d->custom;
00423     QString name = mpCanvas->getCurrent();
00424     if (name.isEmpty() || (mType == 1))
00425         return name;
00426     QFileInfo fi(name);
00427     return fi.baseName();
00428     }
00429     return QString::null;
00430 }
00431 
00432 void KIconDialog::showDialog()
00433 {
00434     setModal(false);
00435     showIcons();
00436     show();
00437 }
00438 
00439 void KIconDialog::slotOk()
00440 {
00441     QString name;
00442     if (!d->custom.isNull())
00443     {
00444         name = d->custom;
00445     }
00446     else
00447     {
00448         name = mpCanvas->getCurrent();
00449         if (!name.isEmpty() && (mType != 1))
00450         {
00451             QFileInfo fi(name);
00452             name = fi.baseName();
00453         }
00454     }
00455 
00456     emit newIconName(name);
00457     KDialogBase::slotOk();
00458 }
00459 
00460 QString KIconDialog::getIcon(KIcon::Group group, KIcon::Context context,
00461                              bool strictIconSize, int iconSize, bool user,
00462                              QWidget *parent, const QString &caption)
00463 {
00464     KIconDialog dlg(parent, "icon dialog");
00465     dlg.setup( group, context, strictIconSize, iconSize, user );
00466     if (!caption.isNull())
00467         dlg.setCaption(caption);
00468 
00469     return dlg.openDialog();
00470 }
00471 
00472 void KIconDialog::slotButtonClicked(int id)
00473 {
00474     QString file;
00475 
00476     switch (id)
00477     {
00478     case 0:
00479         if(mType!=0)
00480         {
00481             mType = 0;
00482             mpBrowseBut->setEnabled(false);
00483             mpCombo->setEnabled(true);
00484             showIcons();
00485         }
00486     break;
00487 
00488     case 1:
00489         if(mType!=1)
00490         {
00491             mType = 1;
00492             mpBrowseBut->setEnabled( !d->m_bLockCustomDir );
00493             mpCombo->setEnabled(false);
00494             showIcons();
00495         }
00496         break;
00497     case 2:
00498         {
00499             // Create a file dialog to select a PNG, XPM or SVG file,
00500             // with the image previewer shown.
00501             // KFileDialog::getImageOpenURL doesn't allow svg.
00502             KFileDialog dlg(QString::null, i18n("*.png *.xpm *.svg *.svgz|Icon Files (*.png *.xpm *.svg *.svgz)"),
00503                             this, "filedialog", true);
00504             dlg.setOperationMode( KFileDialog::Opening );
00505             dlg.setCaption( i18n("Open") );
00506             dlg.setMode( KFile::File );
00507 
00508             KImageFilePreview *ip = new KImageFilePreview( &dlg );
00509             dlg.setPreviewWidget( ip );
00510             dlg.exec();
00511 
00512             file = dlg.selectedFile();
00513             if (!file.isEmpty())
00514             {
00515                 d->custom = file;
00516                 if ( mType == 1 )
00517                   d->customLocation = QFileInfo( file ).dirPath( true );
00518                 slotOk();
00519             }
00520         }
00521         break;
00522     }
00523 }
00524 
00525 void KIconDialog::slotContext(int id)
00526 {
00527     mContext = static_cast<KIcon::Context>(id+1);
00528     showIcons();
00529 }
00530 
00531 void KIconDialog::slotStartLoading(int steps)
00532 {
00533     if (steps < 10)
00534     mpProgress->hide();
00535     else
00536     {
00537         mpProgress->setTotalSteps(steps);
00538         mpProgress->setProgress(0);
00539         mpProgress->show();
00540     }
00541 }
00542 
00543 void KIconDialog::slotProgress(int p)
00544 {
00545     mpProgress->setProgress(p);
00546     // commented out the following since setProgress already paints ther
00547     // progress bar. ->repaint() only makes it flicker
00548     //mpProgress->repaint();
00549 }
00550 
00551 void KIconDialog::slotFinished()
00552 {
00553     mpProgress->hide();
00554 }
00555 
00556 class KIconButton::KIconButtonPrivate
00557 {
00558   public:
00559     KIconButtonPrivate() {
00560         m_bStrictIconSize = false;
00561         iconSize = 0; // let KIconLoader choose the default
00562     }
00563     ~KIconButtonPrivate() {}
00564     bool m_bStrictIconSize;
00565     int iconSize;
00566 };
00567 
00568 
00569 /*
00570  * KIconButton: A "choose icon" pushbutton.
00571  */
00572 
00573 KIconButton::KIconButton(QWidget *parent, const char *name)
00574     : QPushButton(parent, name)
00575 {
00576     init( KGlobal::iconLoader() );
00577 }
00578 
00579 KIconButton::KIconButton(KIconLoader *loader,
00580     QWidget *parent, const char *name)
00581     : QPushButton(parent, name)
00582 {
00583     init( loader );
00584 }
00585 
00586 void KIconButton::init( KIconLoader *loader )
00587 {
00588     d = new KIconButtonPrivate;
00589     mGroup = KIcon::Desktop;
00590     mContext = KIcon::Application;
00591     mbUser = false;
00592 
00593     mpLoader = loader;
00594     mpDialog = 0L;
00595     connect(this, SIGNAL(clicked()), SLOT(slotChangeIcon()));
00596 }
00597 
00598 KIconButton::~KIconButton()
00599 {
00600     delete mpDialog;
00601     delete d;
00602 }
00603 
00604 void KIconButton::setStrictIconSize(bool b)
00605 {
00606     d->m_bStrictIconSize=b;
00607 }
00608 
00609 bool KIconButton::strictIconSize() const
00610 {
00611     return d->m_bStrictIconSize;
00612 }
00613 
00614 void KIconButton::setIconSize( int size )
00615 {
00616     d->iconSize = size;
00617 }
00618 
00619 int KIconButton::iconSize() const
00620 {
00621     return d->iconSize;
00622 }
00623 
00624 void KIconButton::setIconType(KIcon::Group group, KIcon::Context context, bool user)
00625 {
00626     mGroup = group;
00627     mContext = context;
00628     mbUser = user;
00629 }
00630 
00631 void KIconButton::setIcon(const QString& icon)
00632 {
00633     mIcon = icon;
00634     setPixmap(mpLoader->loadIcon(mIcon, mGroup, d->iconSize));
00635 
00636     if (!mpDialog)
00637     {
00638         mpDialog = new KIconDialog(mpLoader, this);
00639         connect(mpDialog, SIGNAL(newIconName(const QString&)), SLOT(newIconName(const QString&)));
00640     }
00641 
00642     if ( mbUser )
00643       mpDialog->setCustomLocation( QFileInfo( mpLoader->iconPath(mIcon, mGroup, true) ).dirPath( true ) );
00644 }
00645 
00646 void KIconButton::resetIcon()
00647 {
00648     mIcon = QString::null;
00649     setPixmap(QPixmap());
00650 }
00651 
00652 void KIconButton::slotChangeIcon()
00653 {
00654     if (!mpDialog)
00655     {
00656         mpDialog = new KIconDialog(mpLoader, this);
00657         connect(mpDialog, SIGNAL(newIconName(const QString&)), SLOT(newIconName(const QString&)));
00658     }
00659 
00660     mpDialog->setup( mGroup, mContext, d->m_bStrictIconSize, d->iconSize, mbUser );
00661     mpDialog->showDialog();
00662 }
00663 
00664 void KIconButton::newIconName(const QString& name)
00665 {
00666     if (name.isEmpty())
00667         return;
00668 
00669     QPixmap pm = mpLoader->loadIcon(name, mGroup, d->iconSize);
00670     setPixmap(pm);
00671     mIcon = name;
00672 
00673     if ( mbUser )
00674       mpDialog->setCustomLocation( QFileInfo( mpLoader->iconPath(mIcon, mGroup, true) ).dirPath( true ) );
00675 
00676     emit iconChanged(name);
00677 }
00678 
00679 void KIconCanvas::virtual_hook( int id, void* data )
00680 { KIconView::virtual_hook( id, data ); }
00681 
00682 void KIconDialog::virtual_hook( int id, void* data )
00683 { KDialogBase::virtual_hook( id, data ); }
00684 
00685 #include "kicondialog.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Sep 23 17:12:22 2004 by doxygen 1.3.8-20040913 written by Dimitri van Heesch, © 1997-2003