00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "kicondialog.h"
00015
00016 #include <config.h>
00017
00018 #include <kiconviewsearchline.h>
00019
00020 #include <kapplication.h>
00021 #include <klocale.h>
00022 #include <kglobal.h>
00023 #include <kstandarddirs.h>
00024 #include <kiconloader.h>
00025 #include <kprogress.h>
00026 #include <kiconview.h>
00027 #include <kfiledialog.h>
00028 #include <kimagefilepreview.h>
00029
00030 #include <qlayout.h>
00031 #include <qstring.h>
00032 #include <qstringlist.h>
00033 #include <qsortedlist.h>
00034 #include <qimage.h>
00035 #include <qpixmap.h>
00036 #include <qlabel.h>
00037 #include <qcombobox.h>
00038 #include <qtimer.h>
00039 #include <qbuttongroup.h>
00040 #include <qradiobutton.h>
00041 #include <qfileinfo.h>
00042 #include <qtoolbutton.h>
00043 #include <qwhatsthis.h>
00044
00045 #ifdef HAVE_LIBART
00046 #include <svgicons/ksvgiconengine.h>
00047 #include <svgicons/ksvgiconpainter.h>
00048 #endif
00049
00050 class KIconCanvas::KIconCanvasPrivate
00051 {
00052 public:
00053 KIconCanvasPrivate() { m_bLoading = false; }
00054 ~KIconCanvasPrivate() {}
00055 bool m_bLoading;
00056 };
00057
00061 class IconPath : public QString
00062 {
00063 protected:
00064 QString m_iconName;
00065
00066 public:
00067 IconPath(const QString &ip) : QString (ip)
00068 {
00069 int n = findRev('/');
00070 m_iconName = (n==-1) ? static_cast<QString>(*this) : mid(n+1);
00071 }
00072
00073
00074 IconPath() : QString ()
00075 { }
00076
00077 bool operator== (const IconPath &ip) const
00078 { return m_iconName == ip.m_iconName; }
00079
00080 bool operator< (const IconPath &ip) const
00081 { return m_iconName < ip.m_iconName; }
00082
00083 };
00084
00085
00086
00087
00088
00089 KIconCanvas::KIconCanvas(QWidget *parent, const char *name)
00090 : KIconView(parent, name)
00091 {
00092 d = new KIconCanvasPrivate;
00093 mpLoader = KGlobal::iconLoader();
00094 mpTimer = new QTimer(this);
00095 connect(mpTimer, SIGNAL(timeout()), SLOT(slotLoadFiles()));
00096 connect(this, SIGNAL(currentChanged(QIconViewItem *)),
00097 SLOT(slotCurrentChanged(QIconViewItem *)));
00098 setGridX(80);
00099 setWordWrapIconText(false);
00100 setShowToolTips(true);
00101 }
00102
00103 KIconCanvas::~KIconCanvas()
00104 {
00105 delete mpTimer;
00106 delete d;
00107 }
00108
00109 void KIconCanvas::loadFiles(const QStringList& files)
00110 {
00111 clear();
00112 mFiles = files;
00113 emit startLoading(mFiles.count());
00114 mpTimer->start(10, true);
00115 d->m_bLoading = false;
00116 }
00117
00118 void KIconCanvas::slotLoadFiles()
00119 {
00120 setResizeMode(Fixed);
00121 QApplication::setOverrideCursor(waitCursor);
00122
00123
00124 setUpdatesEnabled( false );
00125
00126 #ifdef HAVE_LIBART
00127 KSVGIconEngine *svgEngine = new KSVGIconEngine();
00128 #endif
00129
00130 d->m_bLoading = true;
00131 int i;
00132 QStringList::ConstIterator it;
00133 uint emitProgress = 10;
00134 for (it=mFiles.begin(), i=0; it!=mFiles.end(); it++, i++)
00135 {
00136
00137
00138
00139
00140
00141 if ( emitProgress >= 10 ) {
00142 emit progress(i);
00143 emitProgress = 0;
00144 }
00145
00146 emitProgress++;
00147
00148 if ( !d->m_bLoading )
00149 break;
00150 QImage img;
00151
00152
00153 QString path= *it;
00154 QString ext = path.right(3).upper();
00155
00156 if (ext != "SVG" && ext != "VGZ")
00157 img.load(*it);
00158 #ifdef HAVE_LIBART
00159 else
00160 if (svgEngine->load(60, 60, *it))
00161 img = *svgEngine->painter()->image();
00162 #endif
00163
00164 if (img.isNull())
00165 continue;
00166 if (img.width() > 60 || img.height() > 60)
00167 {
00168 if (img.width() > img.height())
00169 {
00170 int height = (int) ((60.0 / img.width()) * img.height());
00171 img = img.smoothScale(60, height);
00172 } else
00173 {
00174 int width = (int) ((60.0 / img.height()) * img.width());
00175 img = img.smoothScale(width, 60);
00176 }
00177 }
00178 QPixmap pm;
00179 pm.convertFromImage(img);
00180 QFileInfo fi(*it);
00181 QIconViewItem *item = new QIconViewItem(this, fi.baseName(), pm);
00182 item->setKey(*it);
00183 item->setDragEnabled(false);
00184 item->setDropEnabled(false);
00185 }
00186
00187 #ifdef HAVE_LIBART
00188 delete svgEngine;
00189 #endif
00190
00191
00192 setUpdatesEnabled( true );
00193
00194 QApplication::restoreOverrideCursor();
00195 d->m_bLoading = false;
00196 emit finished();
00197 setResizeMode(Adjust);
00198 }
00199
00200 QString KIconCanvas::getCurrent() const
00201 {
00202 if (!currentItem())
00203 return QString::null;
00204 return currentItem()->key();
00205 }
00206
00207 void KIconCanvas::stopLoading()
00208 {
00209 d->m_bLoading = false;
00210 }
00211
00212 void KIconCanvas::slotCurrentChanged(QIconViewItem *item)
00213 {
00214 emit nameChanged((item != 0L) ? item->text() : QString::null);
00215 }
00216
00217 class KIconDialog::KIconDialogPrivate
00218 {
00219 public:
00220 KIconDialogPrivate() {
00221 m_bStrictIconSize = true;
00222 m_bLockUser = false;
00223 m_bLockCustomDir = false;
00224 searchLine = 0;
00225 }
00226 ~KIconDialogPrivate() {}
00227 bool m_bStrictIconSize, m_bLockUser, m_bLockCustomDir;
00228 QString custom;
00229 QString customLocation;
00230 KIconViewSearchLine *searchLine;
00231 };
00232
00233
00234
00235
00236
00237
00238 KIconDialog::KIconDialog(QWidget *parent, const char *name)
00239 : KDialogBase(parent, name, true, i18n("Select Icon"), Help|Ok|Cancel, Ok)
00240 {
00241 d = new KIconDialogPrivate;
00242 mpLoader = KGlobal::iconLoader();
00243 init();
00244 }
00245
00246 KIconDialog::KIconDialog(KIconLoader *loader, QWidget *parent,
00247 const char *name)
00248 : KDialogBase(parent, name, true, i18n("Select Icon"), Help|Ok|Cancel, Ok)
00249 {
00250 d = new KIconDialogPrivate;
00251 mpLoader = loader;
00252 init();
00253 }
00254
00255 void KIconDialog::init()
00256 {
00257 mGroupOrSize = KIcon::Desktop;
00258 mContext = KIcon::Any;
00259 mType = 0;
00260 mFileList = KGlobal::dirs()->findAllResources("appicon", QString::fromLatin1("*.png"));
00261
00262 QWidget *main = new QWidget( this );
00263 setMainWidget(main);
00264
00265 QVBoxLayout *top = new QVBoxLayout(main);
00266 top->setSpacing( spacingHint() );
00267
00268 QButtonGroup *bgroup = new QButtonGroup(0, Qt::Vertical, i18n("Icon Source"), main);
00269 bgroup->layout()->setSpacing(KDialog::spacingHint());
00270 bgroup->layout()->setMargin(KDialog::marginHint());
00271 top->addWidget(bgroup);
00272 connect(bgroup, SIGNAL(clicked(int)), SLOT(slotButtonClicked(int)));
00273 QGridLayout *grid = new QGridLayout(bgroup->layout(), 3, 2);
00274 grid->addRowSpacing(0, 15);
00275 mpRb1 = new QRadioButton(i18n("S&ystem icons:"), bgroup);
00276 grid->addWidget(mpRb1, 1, 0);
00277 mpCombo = new QComboBox(bgroup);
00278 connect(mpCombo, SIGNAL(activated(int)), SLOT(slotContext(int)));
00279 grid->addWidget(mpCombo, 1, 1);
00280 mpRb2 = new QRadioButton(i18n("O&ther icons:"), bgroup);
00281 grid->addWidget(mpRb2, 2, 0);
00282 mpBrowseBut = new QPushButton(i18n("&Browse..."), bgroup);
00283 grid->addWidget(mpBrowseBut, 2, 1);
00284
00285
00286
00287
00288 QHBoxLayout *searchLayout = new QHBoxLayout(0, 0, KDialog::spacingHint());
00289 top->addLayout(searchLayout);
00290
00291 QToolButton *clearSearch = new QToolButton(main);
00292 clearSearch->setTextLabel(i18n("Clear Search"), true);
00293 clearSearch->setIconSet(SmallIconSet(QApplication::reverseLayout() ? "clear_left" :"locationbar_erase"));
00294 searchLayout->addWidget(clearSearch);
00295
00296 QLabel *searchLabel = new QLabel(i18n("&Search:"), main);
00297 searchLayout->addWidget(searchLabel);
00298
00299 d->searchLine = new KIconViewSearchLine(main, "searchLine");
00300 searchLayout->addWidget(d->searchLine);
00301 searchLabel->setBuddy(d->searchLine);
00302
00303
00304
00305 connect(clearSearch, SIGNAL(clicked()), d->searchLine, SLOT(clear()));
00306
00307 QString wtstr = i18n("Search interactively for icon names (e.g. folder).");
00308 QWhatsThis::add(searchLabel, wtstr);
00309 QWhatsThis::add(d->searchLine, wtstr);
00310
00311
00312 mpCanvas = new KIconCanvas(main);
00313 connect(mpCanvas, SIGNAL(executed(QIconViewItem *)), SLOT(slotAcceptIcons()));
00314 mpCanvas->setMinimumSize(400, 125);
00315 top->addWidget(mpCanvas);
00316 d->searchLine->setIconView(mpCanvas);
00317
00318 mpProgress = new KProgress(main);
00319 top->addWidget(mpProgress);
00320 connect(mpCanvas, SIGNAL(startLoading(int)), SLOT(slotStartLoading(int)));
00321 connect(mpCanvas, SIGNAL(progress(int)), SLOT(slotProgress(int)));
00322 connect(mpCanvas, SIGNAL(finished()), SLOT(slotFinished()));
00323
00324
00325 connect(this, SIGNAL(hidden()), mpCanvas, SLOT(stopLoading()));
00326
00327
00328 mpCombo->insertItem(i18n("Actions"));
00329 mpCombo->insertItem(i18n("Applications"));
00330 mpCombo->insertItem(i18n("Devices"));
00331 mpCombo->insertItem(i18n("Filesystems"));
00332 mpCombo->insertItem(i18n("Mimetypes"));
00333 mpCombo->setFixedSize(mpCombo->sizeHint());
00334 mpBrowseBut->setFixedWidth(mpCombo->width());
00335
00336
00337 incInitialSize(QSize(0,100));
00338 }
00339
00340
00341 KIconDialog::~KIconDialog()
00342 {
00343 delete d;
00344 }
00345
00346 void KIconDialog::slotAcceptIcons()
00347 {
00348 d->custom=QString::null;
00349 slotOk();
00350 }
00351
00352 void KIconDialog::showIcons()
00353 {
00354 mpCanvas->clear();
00355 QStringList filelist;
00356 if (mType == 0)
00357 if (d->m_bStrictIconSize)
00358 filelist=mpLoader->queryIcons(mGroupOrSize, mContext);
00359 else
00360 filelist=mpLoader->queryIconsByContext(mGroupOrSize, mContext);
00361 else if ( !d->customLocation.isNull() )
00362 filelist=mpLoader->queryIconsByDir( d->customLocation );
00363 else
00364 filelist=mFileList;
00365
00366 QSortedList <IconPath>iconlist;
00367 iconlist.setAutoDelete(true);
00368 QStringList::Iterator it;
00369 for( it = filelist.begin(); it != filelist.end(); ++it )
00370 iconlist.append(new IconPath(*it));
00371
00372 iconlist.sort();
00373 filelist.clear();
00374
00375 for ( IconPath *ip=iconlist.first(); ip != 0; ip=iconlist.next() )
00376 filelist.append(*ip);
00377
00378 d->searchLine->clear();
00379 mpCanvas->loadFiles(filelist);
00380 }
00381
00382 void KIconDialog::setStrictIconSize(bool b)
00383 {
00384 d->m_bStrictIconSize=b;
00385 }
00386
00387 bool KIconDialog::strictIconSize() const
00388 {
00389 return d->m_bStrictIconSize;
00390 }
00391
00392 void KIconDialog::setIconSize( int size )
00393 {
00394
00395 if ( size == 0 )
00396 mGroupOrSize = KIcon::Desktop;
00397 else
00398 mGroupOrSize = -size;
00399 }
00400
00401 int KIconDialog::iconSize() const
00402 {
00403
00404 return (mGroupOrSize < 0) ? -mGroupOrSize : 0;
00405 }
00406
00407 #ifndef KDE_NO_COMPAT
00408 QString KIconDialog::selectIcon(KIcon::Group group, KIcon::Context context, bool user)
00409 {
00410 setup( group, context, false, 0, user );
00411 return openDialog();
00412 }
00413 #endif
00414
00415 void KIconDialog::setup(KIcon::Group group, KIcon::Context context,
00416 bool strictIconSize, int iconSize, bool user )
00417 {
00418 d->m_bStrictIconSize = strictIconSize;
00419 mGroupOrSize = (iconSize == 0) ? group : -iconSize;
00420 mType = user ? 1 : 0;
00421 mpRb1->setChecked(!user);
00422 mpRb2->setChecked(user);
00423 mpCombo->setEnabled(!user);
00424 mpBrowseBut->setEnabled(user);
00425 mContext = context;
00426 mpCombo->setCurrentItem(mContext-1);
00427 }
00428
00429 void KIconDialog::setup(KIcon::Group group, KIcon::Context context,
00430 bool strictIconSize, int iconSize, bool user,
00431 bool lockUser, bool lockCustomDir )
00432 {
00433 d->m_bStrictIconSize = strictIconSize;
00434 d->m_bLockUser = lockUser;
00435 d->m_bLockCustomDir = lockCustomDir;
00436 mGroupOrSize = (iconSize == 0) ? group : -iconSize;
00437 mType = user ? 1 : 0;
00438 mpRb1->setChecked(!user);
00439 mpRb1->setEnabled( !lockUser || !user );
00440 mpRb2->setChecked(user);
00441 mpRb2->setEnabled( !lockUser || user );
00442 mpCombo->setEnabled(!user);
00443 mpBrowseBut->setEnabled( user && !lockCustomDir );
00444 mContext = context;
00445 mpCombo->setCurrentItem(mContext-1);
00446 }
00447
00448 void KIconDialog::setCustomLocation( const QString& location )
00449 {
00450 d->customLocation = location;
00451 }
00452
00453 QString KIconDialog::openDialog()
00454 {
00455 showIcons();
00456
00457 if ( exec() == Accepted )
00458 {
00459 if (!d->custom.isNull())
00460 return d->custom;
00461 QString name = mpCanvas->getCurrent();
00462 if (name.isEmpty() || (mType == 1))
00463 return name;
00464 QFileInfo fi(name);
00465 return fi.baseName();
00466 }
00467 return QString::null;
00468 }
00469
00470 void KIconDialog::showDialog()
00471 {
00472 setModal(false);
00473 showIcons();
00474 show();
00475 }
00476
00477 void KIconDialog::slotOk()
00478 {
00479 QString name;
00480 if (!d->custom.isNull())
00481 {
00482 name = d->custom;
00483 }
00484 else
00485 {
00486 name = mpCanvas->getCurrent();
00487 if (!name.isEmpty() && (mType != 1))
00488 {
00489 QFileInfo fi(name);
00490 name = fi.baseName();
00491 }
00492 }
00493
00494 emit newIconName(name);
00495 KDialogBase::slotOk();
00496 }
00497
00498 QString KIconDialog::getIcon(KIcon::Group group, KIcon::Context context,
00499 bool strictIconSize, int iconSize, bool user,
00500 QWidget *parent, const QString &caption)
00501 {
00502 KIconDialog dlg(parent, "icon dialog");
00503 dlg.setup( group, context, strictIconSize, iconSize, user );
00504 if (!caption.isNull())
00505 dlg.setCaption(caption);
00506
00507 return dlg.openDialog();
00508 }
00509
00510 void KIconDialog::slotButtonClicked(int id)
00511 {
00512 QString file;
00513
00514 switch (id)
00515 {
00516 case 0:
00517 if(mType!=0)
00518 {
00519 mType = 0;
00520 mpBrowseBut->setEnabled(false);
00521 mpCombo->setEnabled(true);
00522 showIcons();
00523 }
00524 break;
00525
00526 case 1:
00527 if(mType!=1)
00528 {
00529 mType = 1;
00530 mpBrowseBut->setEnabled( !d->m_bLockCustomDir );
00531 mpCombo->setEnabled(false);
00532 showIcons();
00533 }
00534 break;
00535 case 2:
00536 {
00537
00538
00539
00540 KFileDialog dlg(QString::null, i18n("*.png *.xpm *.svg *.svgz|Icon Files (*.png *.xpm *.svg *.svgz)"),
00541 this, "filedialog", true);
00542 dlg.setOperationMode( KFileDialog::Opening );
00543 dlg.setCaption( i18n("Open") );
00544 dlg.setMode( KFile::File );
00545
00546 KImageFilePreview *ip = new KImageFilePreview( &dlg );
00547 dlg.setPreviewWidget( ip );
00548 dlg.exec();
00549
00550 file = dlg.selectedFile();
00551 if (!file.isEmpty())
00552 {
00553 d->custom = file;
00554 if ( mType == 1 )
00555 d->customLocation = QFileInfo( file ).dirPath( true );
00556 slotOk();
00557 }
00558 }
00559 break;
00560 }
00561 }
00562
00563 void KIconDialog::slotContext(int id)
00564 {
00565 mContext = static_cast<KIcon::Context>(id+1);
00566 showIcons();
00567 }
00568
00569 void KIconDialog::slotStartLoading(int steps)
00570 {
00571 if (steps < 10)
00572 mpProgress->hide();
00573 else
00574 {
00575 mpProgress->setTotalSteps(steps);
00576 mpProgress->setProgress(0);
00577 mpProgress->show();
00578 }
00579 }
00580
00581 void KIconDialog::slotProgress(int p)
00582 {
00583 mpProgress->setProgress(p);
00584
00585
00586
00587 }
00588
00589 void KIconDialog::slotFinished()
00590 {
00591 mpProgress->hide();
00592 }
00593
00594 class KIconButton::KIconButtonPrivate
00595 {
00596 public:
00597 KIconButtonPrivate() {
00598 m_bStrictIconSize = false;
00599 iconSize = 0;
00600 }
00601 ~KIconButtonPrivate() {}
00602 bool m_bStrictIconSize;
00603 int iconSize;
00604 };
00605
00606
00607
00608
00609
00610
00611 KIconButton::KIconButton(QWidget *parent, const char *name)
00612 : QPushButton(parent, name)
00613 {
00614 init( KGlobal::iconLoader() );
00615 }
00616
00617 KIconButton::KIconButton(KIconLoader *loader,
00618 QWidget *parent, const char *name)
00619 : QPushButton(parent, name)
00620 {
00621 init( loader );
00622 }
00623
00624 void KIconButton::init( KIconLoader *loader )
00625 {
00626 d = new KIconButtonPrivate;
00627 mGroup = KIcon::Desktop;
00628 mContext = KIcon::Application;
00629 mbUser = false;
00630
00631 mpLoader = loader;
00632 mpDialog = 0L;
00633 connect(this, SIGNAL(clicked()), SLOT(slotChangeIcon()));
00634 }
00635
00636 KIconButton::~KIconButton()
00637 {
00638 delete mpDialog;
00639 delete d;
00640 }
00641
00642 void KIconButton::setStrictIconSize(bool b)
00643 {
00644 d->m_bStrictIconSize=b;
00645 }
00646
00647 bool KIconButton::strictIconSize() const
00648 {
00649 return d->m_bStrictIconSize;
00650 }
00651
00652 void KIconButton::setIconSize( int size )
00653 {
00654 d->iconSize = size;
00655 }
00656
00657 int KIconButton::iconSize() const
00658 {
00659 return d->iconSize;
00660 }
00661
00662 void KIconButton::setIconType(KIcon::Group group, KIcon::Context context, bool user)
00663 {
00664 mGroup = group;
00665 mContext = context;
00666 mbUser = user;
00667 }
00668
00669 void KIconButton::setIcon(const QString& icon)
00670 {
00671 mIcon = icon;
00672 setIconSet(mpLoader->loadIconSet(mIcon, mGroup, d->iconSize));
00673
00674 if (!mpDialog)
00675 {
00676 mpDialog = new KIconDialog(mpLoader, this);
00677 connect(mpDialog, SIGNAL(newIconName(const QString&)), SLOT(newIconName(const QString&)));
00678 }
00679
00680 if ( mbUser )
00681 mpDialog->setCustomLocation( QFileInfo( mpLoader->iconPath(mIcon, mGroup, true) ).dirPath( true ) );
00682 }
00683
00684 void KIconButton::resetIcon()
00685 {
00686 mIcon = QString::null;
00687 setIconSet(QIconSet());
00688 }
00689
00690 void KIconButton::slotChangeIcon()
00691 {
00692 if (!mpDialog)
00693 {
00694 mpDialog = new KIconDialog(mpLoader, this);
00695 connect(mpDialog, SIGNAL(newIconName(const QString&)), SLOT(newIconName(const QString&)));
00696 }
00697
00698 mpDialog->setup( mGroup, mContext, d->m_bStrictIconSize, d->iconSize, mbUser );
00699 mpDialog->showDialog();
00700 }
00701
00702 void KIconButton::newIconName(const QString& name)
00703 {
00704 if (name.isEmpty())
00705 return;
00706
00707 QIconSet iconset = mpLoader->loadIconSet(name, mGroup, d->iconSize);
00708 setIconSet(iconset);
00709 mIcon = name;
00710
00711 if ( mbUser )
00712 mpDialog->setCustomLocation( QFileInfo( mpLoader->iconPath(mIcon, mGroup, true) ).dirPath( true ) );
00713
00714 emit iconChanged(name);
00715 }
00716
00717 void KIconCanvas::virtual_hook( int id, void* data )
00718 { KIconView::virtual_hook( id, data ); }
00719
00720 void KIconDialog::virtual_hook( int id, void* data )
00721 { KDialogBase::virtual_hook( id, data ); }
00722
00723 #include "kicondialog.moc"