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(0, Qt::Vertical, i18n("Icon Source"), main);
00262     bgroup->layout()->setSpacing(KDialog::spacingHint());
00263     bgroup->layout()->setMargin(KDialog::marginHint());
00264     top->addWidget(bgroup);
00265     connect(bgroup, SIGNAL(clicked(int)), SLOT(slotButtonClicked(int)));
00266     QGridLayout *grid = new QGridLayout(bgroup->layout(), 3, 2);
00267     grid->addRowSpacing(0, 15);
00268     mpRb1 = new QRadioButton(i18n("&System icons:"), bgroup);
00269     grid->addWidget(mpRb1, 1, 0);
00270     mpCombo = new QComboBox(bgroup);
00271     connect(mpCombo, SIGNAL(activated(int)), SLOT(slotContext(int)));
00272     grid->addWidget(mpCombo, 1, 1);
00273     mpRb2 = new QRadioButton(i18n("O&ther icons:"), bgroup);
00274     grid->addWidget(mpRb2, 2, 0);
00275     mpBrowseBut = new QPushButton(i18n("&Browse..."), bgroup);
00276     grid->addWidget(mpBrowseBut, 2, 1);
00277 
00278     mpCanvas = new KIconCanvas(main);
00279     connect(mpCanvas, SIGNAL(executed(QIconViewItem *)), SLOT(slotAcceptIcons()));
00280     mpCanvas->setMinimumSize(400, 125);
00281     top->addWidget(mpCanvas);
00282 
00283     mpProgress = new KProgress(main);
00284     top->addWidget(mpProgress);
00285     connect(mpCanvas, SIGNAL(startLoading(int)), SLOT(slotStartLoading(int)));
00286     connect(mpCanvas, SIGNAL(progress(int)), SLOT(slotProgress(int)));
00287     connect(mpCanvas, SIGNAL(finished()), SLOT(slotFinished()));
00288 
00289     // When pressing Ok or Cancel, stop loading icons
00290     connect(this, SIGNAL(hidden()), mpCanvas, SLOT(stopLoading()));
00291 
00292     // The order must match the context definitions in KIcon.
00293     mpCombo->insertItem(i18n("Actions"));
00294     mpCombo->insertItem(i18n("Applications"));
00295     mpCombo->insertItem(i18n("Devices"));
00296     mpCombo->insertItem(i18n("Filesystems"));
00297     mpCombo->insertItem(i18n("Mimetypes"));
00298     mpCombo->setFixedSize(mpCombo->sizeHint());
00299     mpBrowseBut->setFixedWidth(mpCombo->width());
00300 
00301     // Make the dialog a little taller
00302     incInitialSize(QSize(0,100));
00303 }
00304 
00305 
00306 KIconDialog::~KIconDialog()
00307 {
00308     delete d;
00309 }
00310 
00311 void KIconDialog::slotAcceptIcons()
00312 {
00313   d->custom=QString::null;
00314   slotOk();
00315 }
00316 
00317 void KIconDialog::showIcons()
00318 {
00319     mpCanvas->clear();
00320     QStringList filelist;
00321     if (mType == 0)
00322     if (d->m_bStrictIconSize)
00323             filelist=mpLoader->queryIcons(mGroupOrSize, mContext);
00324         else
00325             filelist=mpLoader->queryIconsByContext(mGroupOrSize, mContext);
00326     else if ( !d->customLocation.isNull() )
00327     filelist=mpLoader->queryIconsByDir( d->customLocation );
00328     else
00329     filelist=mFileList;
00330 
00331     QSortedList <IconPath>iconlist;
00332     iconlist.setAutoDelete(true);
00333     QStringList::Iterator it;
00334     for( it = filelist.begin(); it != filelist.end(); ++it )
00335        iconlist.append(new IconPath(*it));
00336 
00337     iconlist.sort();
00338     filelist.clear();
00339 
00340     for ( IconPath *ip=iconlist.first(); ip != 0; ip=iconlist.next() )
00341        filelist.append(*ip);
00342 
00343     mpCanvas->loadFiles(filelist);
00344 }
00345 
00346 void KIconDialog::setStrictIconSize(bool b)
00347 {
00348     d->m_bStrictIconSize=b;
00349 }
00350 
00351 bool KIconDialog::strictIconSize() const
00352 {
00353     return d->m_bStrictIconSize;
00354 }
00355 
00356 void KIconDialog::setIconSize( int size )
00357 {
00358     // see KIconLoader, if you think this is weird
00359     if ( size == 0 )
00360         mGroupOrSize = KIcon::Desktop; // default Group
00361     else
00362         mGroupOrSize = -size; // yes, KIconLoader::queryIconsByContext is weird
00363 }
00364 
00365 int KIconDialog::iconSize() const
00366 {
00367     // 0 or any other value ==> mGroupOrSize is a group, so we return 0
00368     return (mGroupOrSize < 0) ? -mGroupOrSize : 0;
00369 }
00370 
00371 #ifndef KDE_NO_COMPAT
00372 QString KIconDialog::selectIcon(KIcon::Group group, KIcon::Context context, bool user)
00373 {
00374     setup( group, context, false, 0, user );
00375     return openDialog();
00376 }
00377 #endif
00378 
00379 void KIconDialog::setup(KIcon::Group group, KIcon::Context context,
00380                         bool strictIconSize, int iconSize, bool user )
00381 {
00382     d->m_bStrictIconSize = strictIconSize;
00383     mGroupOrSize = (iconSize == 0) ? group : -iconSize;
00384     mType = user ? 1 : 0;
00385     mpRb1->setChecked(!user);
00386     mpRb2->setChecked(user);
00387     mpCombo->setEnabled(!user);
00388     mpBrowseBut->setEnabled(user);
00389     mContext = context;
00390     mpCombo->setCurrentItem(mContext-1);
00391 }
00392 
00393 void KIconDialog::setup(KIcon::Group group, KIcon::Context context,
00394                         bool strictIconSize, int iconSize, bool user,
00395                         bool lockUser, bool lockCustomDir )
00396 {
00397     d->m_bStrictIconSize = strictIconSize;
00398     d->m_bLockUser = lockUser;
00399     d->m_bLockCustomDir = lockCustomDir;
00400     mGroupOrSize = (iconSize == 0) ? group : -iconSize;
00401     mType = user ? 1 : 0;
00402     mpRb1->setChecked(!user);
00403     mpRb1->setEnabled( !lockUser || !user );
00404     mpRb2->setChecked(user);
00405     mpRb2->setEnabled( !lockUser || user );
00406     mpCombo->setEnabled(!user);
00407     mpBrowseBut->setEnabled( user && !lockCustomDir );
00408     mContext = context;
00409     mpCombo->setCurrentItem(mContext-1);
00410 }
00411 
00412 void KIconDialog::setCustomLocation( const QString& location )
00413 {
00414     d->customLocation = location;
00415 }
00416 
00417 QString KIconDialog::openDialog()
00418 {
00419     showIcons();
00420 
00421     if ( exec() == Accepted )
00422     {
00423         if (!d->custom.isNull())
00424             return d->custom;
00425     QString name = mpCanvas->getCurrent();
00426     if (name.isEmpty() || (mType == 1))
00427         return name;
00428     QFileInfo fi(name);
00429     return fi.baseName();
00430     }
00431     return QString::null;
00432 }
00433 
00434 void KIconDialog::showDialog()
00435 {
00436     setModal(false);
00437     showIcons();
00438     show();
00439 }
00440 
00441 void KIconDialog::slotOk()
00442 {
00443     QString name;
00444     if (!d->custom.isNull())
00445     {
00446         name = d->custom;
00447     }
00448     else
00449     {
00450         name = mpCanvas->getCurrent();
00451         if (!name.isEmpty() && (mType != 1))
00452         {
00453             QFileInfo fi(name);
00454             name = fi.baseName();
00455         }
00456     }
00457 
00458     emit newIconName(name);
00459     KDialogBase::slotOk();
00460 }
00461 
00462 QString KIconDialog::getIcon(KIcon::Group group, KIcon::Context context,
00463                              bool strictIconSize, int iconSize, bool user,
00464                              QWidget *parent, const QString &caption)
00465 {
00466     KIconDialog dlg(parent, "icon dialog");
00467     dlg.setup( group, context, strictIconSize, iconSize, user );
00468     if (!caption.isNull())
00469         dlg.setCaption(caption);
00470 
00471     return dlg.openDialog();
00472 }
00473 
00474 void KIconDialog::slotButtonClicked(int id)
00475 {
00476     QString file;
00477 
00478     switch (id)
00479     {
00480     case 0:
00481         if(mType!=0)
00482         {
00483             mType = 0;
00484             mpBrowseBut->setEnabled(false);
00485             mpCombo->setEnabled(true);
00486             showIcons();
00487         }
00488     break;
00489 
00490     case 1:
00491         if(mType!=1)
00492         {
00493             mType = 1;
00494             mpBrowseBut->setEnabled( !d->m_bLockCustomDir );
00495             mpCombo->setEnabled(false);
00496             showIcons();
00497         }
00498         break;
00499     case 2:
00500         {
00501             // Create a file dialog to select a PNG, XPM or SVG file,
00502             // with the image previewer shown.
00503             // KFileDialog::getImageOpenURL doesn't allow svg.
00504             KFileDialog dlg(QString::null, i18n("*.png *.xpm *.svg *.svgz|Icon Files (*.png *.xpm *.svg *.svgz)"),
00505                             this, "filedialog", true);
00506             dlg.setOperationMode( KFileDialog::Opening );
00507             dlg.setCaption( i18n("Open") );
00508             dlg.setMode( KFile::File );
00509 
00510             KImageFilePreview *ip = new KImageFilePreview( &dlg );
00511             dlg.setPreviewWidget( ip );
00512             dlg.exec();
00513 
00514             file = dlg.selectedFile();
00515             if (!file.isEmpty())
00516             {
00517                 d->custom = file;
00518                 if ( mType == 1 )
00519                   d->customLocation = QFileInfo( file ).dirPath( true );
00520                 slotOk();
00521             }
00522         }
00523         break;
00524     }
00525 }
00526 
00527 void KIconDialog::slotContext(int id)
00528 {
00529     mContext = static_cast<KIcon::Context>(id+1);
00530     showIcons();
00531 }
00532 
00533 void KIconDialog::slotStartLoading(int steps)
00534 {
00535     if (steps < 10)
00536     mpProgress->hide();
00537     else
00538     {
00539         mpProgress->setTotalSteps(steps);
00540         mpProgress->setProgress(0);
00541         mpProgress->show();
00542     }
00543 }
00544 
00545 void KIconDialog::slotProgress(int p)
00546 {
00547     mpProgress->setProgress(p);
00548     // commented out the following since setProgress already paints ther
00549     // progress bar. ->repaint() only makes it flicker
00550     //mpProgress->repaint();
00551 }
00552 
00553 void KIconDialog::slotFinished()
00554 {
00555     mpProgress->hide();
00556 }
00557 
00558 class KIconButton::KIconButtonPrivate
00559 {
00560   public:
00561     KIconButtonPrivate() {
00562         m_bStrictIconSize = false;
00563         iconSize = 0; // let KIconLoader choose the default
00564     }
00565     ~KIconButtonPrivate() {}
00566     bool m_bStrictIconSize;
00567     int iconSize;
00568 };
00569 
00570 
00571 /*
00572  * KIconButton: A "choose icon" pushbutton.
00573  */
00574 
00575 KIconButton::KIconButton(QWidget *parent, const char *name)
00576     : QPushButton(parent, name)
00577 {
00578     init( KGlobal::iconLoader() );
00579 }
00580 
00581 KIconButton::KIconButton(KIconLoader *loader,
00582     QWidget *parent, const char *name)
00583     : QPushButton(parent, name)
00584 {
00585     init( loader );
00586 }
00587 
00588 void KIconButton::init( KIconLoader *loader )
00589 {
00590     d = new KIconButtonPrivate;
00591     mGroup = KIcon::Desktop;
00592     mContext = KIcon::Application;
00593     mbUser = false;
00594 
00595     mpLoader = loader;
00596     mpDialog = 0L;
00597     connect(this, SIGNAL(clicked()), SLOT(slotChangeIcon()));
00598 }
00599 
00600 KIconButton::~KIconButton()
00601 {
00602     delete mpDialog;
00603     delete d;
00604 }
00605 
00606 void KIconButton::setStrictIconSize(bool b)
00607 {
00608     d->m_bStrictIconSize=b;
00609 }
00610 
00611 bool KIconButton::strictIconSize() const
00612 {
00613     return d->m_bStrictIconSize;
00614 }
00615 
00616 void KIconButton::setIconSize( int size )
00617 {
00618     d->iconSize = size;
00619 }
00620 
00621 int KIconButton::iconSize() const
00622 {
00623     return d->iconSize;
00624 }
00625 
00626 void KIconButton::setIconType(KIcon::Group group, KIcon::Context context, bool user)
00627 {
00628     mGroup = group;
00629     mContext = context;
00630     mbUser = user;
00631 }
00632 
00633 void KIconButton::setIcon(const QString& icon)
00634 {
00635     mIcon = icon;
00636     setPixmap(mpLoader->loadIcon(mIcon, mGroup, d->iconSize));
00637 
00638     if (!mpDialog)
00639     {
00640         mpDialog = new KIconDialog(mpLoader, this);
00641         connect(mpDialog, SIGNAL(newIconName(const QString&)), SLOT(newIconName(const QString&)));
00642     }
00643 
00644     if ( mbUser )
00645       mpDialog->setCustomLocation( QFileInfo( mpLoader->iconPath(mIcon, mGroup, true) ).dirPath( true ) );
00646 }
00647 
00648 void KIconButton::resetIcon()
00649 {
00650     mIcon = QString::null;
00651     setPixmap(QPixmap());
00652 }
00653 
00654 void KIconButton::slotChangeIcon()
00655 {
00656     if (!mpDialog)
00657     {
00658         mpDialog = new KIconDialog(mpLoader, this);
00659         connect(mpDialog, SIGNAL(newIconName(const QString&)), SLOT(newIconName(const QString&)));
00660     }
00661 
00662     mpDialog->setup( mGroup, mContext, d->m_bStrictIconSize, d->iconSize, mbUser );
00663     mpDialog->showDialog();
00664 }
00665 
00666 void KIconButton::newIconName(const QString& name)
00667 {
00668     if (name.isEmpty())
00669         return;
00670 
00671     QPixmap pm = mpLoader->loadIcon(name, mGroup, d->iconSize);
00672     setPixmap(pm);
00673     mIcon = name;
00674 
00675     if ( mbUser )
00676       mpDialog->setCustomLocation( QFileInfo( mpLoader->iconPath(mIcon, mGroup, true) ).dirPath( true ) );
00677 
00678     emit iconChanged(name);
00679 }
00680 
00681 void KIconCanvas::virtual_hook( int id, void* data )
00682 { KIconView::virtual_hook( id, data ); }
00683 
00684 void KIconDialog::virtual_hook( int id, void* data )
00685 { KDialogBase::virtual_hook( id, data ); }
00686 
00687 #include "kicondialog.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Jan 15 13:33:25 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003