00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 extern "C"
00029 {
00030 #include <sys/types.h>
00031 #include <sys/stat.h>
00032 #include <unistd.h>
00033 }
00034
00035
00036
00037 #include <cstdio>
00038
00039
00040
00041 #include <Q3IntDict>
00042 #include <Q3Dict>
00043 #include <QImage>
00044 #include <QString>
00045 #include <QStringList>
00046 #include <QEvent>
00047 #include <QPainter>
00048 #include <QPoint>
00049 #include <QPolygon>
00050 #include <QDateTime>
00051 #include <QFileInfo>
00052 #include <QFile>
00053 #include <QCursor>
00054 #include <QDataStream>
00055 #include <QTimer>
00056 #include <QClipboard>
00057 #include <QPixmap>
00058 #include <QDragMoveEvent>
00059 #include <QDropEvent>
00060 #include <QResizeEvent>
00061
00062
00063
00064 #include <kdebug.h>
00065 #include <kurl.h>
00066 #include <kapplication.h>
00067 #include <klocale.h>
00068 #include <kglobal.h>
00069 #include <kmessagebox.h>
00070 #include <kiconloader.h>
00071 #include <kpropsdlg.h>
00072 #include <ktrader.h>
00073 #include <kservice.h>
00074 #include <krun.h>
00075 #include <kaction.h>
00076 #include <kmenu.h>
00077 #include <kstandarddirs.h>
00078 #include <kiconeffect.h>
00079 #include <kdeversion.h>
00080 #include <kcalendarsystem.h>
00081 #include <kinputdialog.h>
00082 #include <kio/jobuidelegate.h>
00083 #include <kmimetypetrader.h>
00084 #include <kstandardaction.h>
00085
00086
00087
00088 #include <libkipi/pluginloader.h>
00089 #include <libkipi/plugin.h>
00090
00091
00092
00093 #include <libkdcraw/version.h>
00094 #include <libkdcraw/kdcraw.h>
00095
00096 #if KDCRAW_VERSION < 0x000400
00097 #include <libkdcraw/dcrawbinary.h>
00098 #endif
00099
00100
00101
00102 #include "constants.h"
00103 #include "album.h"
00104 #include "albumdb.h"
00105 #include "albummanager.h"
00106 #include "dio.h"
00107 #include "albumlister.h"
00108 #include "albumfiletip.h"
00109 #include "albumsettings.h"
00110 #include "databasetransaction.h"
00111 #include "databaseaccess.h"
00112 #include "imagewindow.h"
00113 #include "thumbnailsize.h"
00114 #include "themeengine.h"
00115 #include "dpopupmenu.h"
00116 #include "tagspopupmenu.h"
00117 #include "ratingpopupmenu.h"
00118 #include "scancontroller.h"
00119 #include "thumbnailloadthread.h"
00120 #include "cameraui.h"
00121 #include "ddragobjects.h"
00122 #include "dmetadata.h"
00123 #include "albumdb.h"
00124 #include "imageattributeswatch.h"
00125 #include "deletedialog.h"
00126 #include "albumiconitem.h"
00127 #include "albumicongroupitem.h"
00128 #include "loadingcacheinterface.h"
00129 #include "lighttablewindow.h"
00130 #include "statusprogressbar.h"
00131 #include "metadatahub.h"
00132 #include "albumiconview.h"
00133 #include "albumiconview.moc"
00134
00135 namespace Digikam
00136 {
00137
00138 class AlbumIconViewPrivate
00139 {
00140 public:
00141
00142 void init()
00143 {
00144 imageLister = 0;
00145 currentAlbum = 0;
00146 albumSettings = 0;
00147 toolTip = 0;
00148
00149
00150 starPolygon << QPoint(0, 6);
00151 starPolygon << QPoint(5, 5);
00152 starPolygon << QPoint(7, 0);
00153 starPolygon << QPoint(9, 5);
00154 starPolygon << QPoint(14, 6);
00155 starPolygon << QPoint(10, 9);
00156 starPolygon << QPoint(11, 14);
00157 starPolygon << QPoint(7, 11);
00158 starPolygon << QPoint(3, 14);
00159 starPolygon << QPoint(4, 9);
00160
00161 starPolygonSize = QSize(15, 15);
00162
00163 ratingPixmaps = QVector<QPixmap>(10);
00164 }
00165
00166 QString albumTitle;
00167 QString albumDate;
00168 QString albumComments;
00169
00170 QRect itemRect;
00171 QRect itemRatingRect;
00172 QRect itemDateRect;
00173 QRect itemModDateRect;
00174 QRect itemPixmapRect;
00175 QRect itemNameRect;
00176 QRect itemCommentsRect;
00177 QRect itemResolutionRect;
00178 QRect itemSizeRect;
00179 QRect itemTagRect;
00180 QRect bannerRect;
00181
00182 QPixmap itemRegPixmap;
00183 QPixmap itemSelPixmap;
00184 QPixmap bannerPixmap;
00185 QVector<QPixmap> ratingPixmaps;
00186
00187 QFont fnReg;
00188 QFont fnCom;
00189 QFont fnXtra;
00190
00191 QPolygon starPolygon;
00192 QSize starPolygonSize;
00193
00194 Q3Dict<AlbumIconItem> itemDict;
00195 QHash<ImageInfo, AlbumIconItem*> itemInfoMap;
00196
00197 KUrl itemUrlToFind;
00198
00199 AlbumLister *imageLister;
00200 Album *currentAlbum;
00201 const AlbumSettings *albumSettings;
00202 Q3IntDict<AlbumIconGroupItem> albumDict;
00203
00204 ThumbnailSize thumbSize;
00205
00206 AlbumFileTip *toolTip;
00207 };
00208
00209 AlbumIconView::AlbumIconView(QWidget* parent)
00210 : IconView(parent)
00211 {
00212 d = new AlbumIconViewPrivate;
00213 d->init();
00214 d->imageLister = AlbumLister::instance();
00215 d->toolTip = new AlbumFileTip(this);
00216
00217 setAcceptDrops(true);
00218 viewport()->setAcceptDrops(true);
00219
00220
00221
00222 connect(d->imageLister, SIGNAL(signalNewFilteredItems(const ImageInfoList&)),
00223 this, SLOT(slotImageListerNewItems(const ImageInfoList&)));
00224
00225 connect(d->imageLister, SIGNAL(signalDeleteFilteredItem(const ImageInfo &)),
00226 this, SLOT(slotImageListerDeleteItem(const ImageInfo &)) );
00227
00228 connect(d->imageLister, SIGNAL(signalClear()),
00229 this, SLOT(slotImageListerClear()));
00230
00231
00232
00233 connect(this, SIGNAL(signalDoubleClicked(IconItem*)),
00234 this, SLOT(slotDoubleClicked(IconItem*)));
00235
00236 connect(this, SIGNAL(signalReturnPressed(IconItem*)),
00237 this, SLOT(slotDoubleClicked(IconItem*)));
00238
00239 connect(this, SIGNAL(signalRightButtonClicked(IconItem*, const QPoint &)),
00240 this, SLOT(slotRightButtonClicked(IconItem*, const QPoint &)));
00241
00242 connect(this, SIGNAL(signalRightButtonClicked(const QPoint &)),
00243 this, SLOT(slotRightButtonClicked(const QPoint &)));
00244
00245 connect(this, SIGNAL(signalSelectionChanged()),
00246 this, SLOT(slotSelectionChanged()));
00247
00248 connect(this, SIGNAL(signalShowToolTip(IconItem*)),
00249 this, SLOT(slotShowToolTip(IconItem*)));
00250
00251
00252
00253 connect(ThemeEngine::instance(), SIGNAL(signalThemeChanged()),
00254 this, SLOT(slotThemeChanged()));
00255
00256
00257
00258 connect(ThumbnailLoadThread::defaultIconViewThread(), SIGNAL(signalThumbnailLoaded(const LoadingDescription &, const QPixmap&)),
00259 this, SLOT(slotThumbnailLoaded(const LoadingDescription &, const QPixmap&)));
00260
00261
00262
00263 ImageAttributesWatch *watch = ImageAttributesWatch::instance();
00264
00265 connect(watch, SIGNAL(signalImageTagsChanged(qlonglong)),
00266 this, SLOT(slotImageAttributesChanged(qlonglong)));
00267
00268 connect(watch, SIGNAL(signalImagesChanged(int)),
00269 this, SLOT(slotAlbumImagesChanged(int)));
00270
00271 connect(watch, SIGNAL(signalImageRatingChanged(qlonglong)),
00272 this, SLOT(slotImageAttributesChanged(qlonglong)));
00273
00274 connect(watch, SIGNAL(signalImageDateChanged(qlonglong)),
00275 this, SLOT(slotImageAttributesChanged(qlonglong)));
00276
00277 connect(watch, SIGNAL(signalImageCaptionChanged(qlonglong)),
00278 this, SLOT(slotImageAttributesChanged(qlonglong)));
00279 }
00280
00281 AlbumIconView::~AlbumIconView()
00282 {
00283 delete d->toolTip;
00284 delete d;
00285 }
00286
00287 void AlbumIconView::applySettings(const AlbumSettings* settings)
00288 {
00289 if (!settings)
00290 return;
00291
00292 d->albumSettings = settings;
00293
00294 d->thumbSize = (ThumbnailSize::Size)d->albumSettings->getDefaultIconSize();
00295
00296 setEnableToolTips(d->albumSettings->getShowToolTips());
00297
00298 updateRectsAndPixmaps();
00299
00300 d->imageLister->stop();
00301 clear();
00302
00303 ThumbnailLoadThread::defaultIconViewThread()->setThumbnailSize(d->thumbSize.size());
00304
00305 if (d->currentAlbum)
00306 {
00307 d->imageLister->openAlbum(d->currentAlbum);
00308 }
00309 }
00310
00311 void AlbumIconView::setThumbnailSize(const ThumbnailSize& thumbSize)
00312 {
00313 if ( d->thumbSize != thumbSize)
00314 {
00315 d->imageLister->stop();
00316 clear();
00317
00318 d->thumbSize = thumbSize;
00319 ThumbnailLoadThread::defaultIconViewThread()->setThumbnailSize(d->thumbSize.size());
00320
00321 updateRectsAndPixmaps();
00322
00323 d->imageLister->openAlbum(d->currentAlbum);
00324 }
00325 }
00326
00327 void AlbumIconView::setAlbum(Album* album)
00328 {
00329 if (!album)
00330 {
00331 d->currentAlbum = 0;
00332 d->imageLister->stop();
00333 clear();
00334
00335 return;
00336 }
00337
00338 if (d->currentAlbum == album)
00339 return;
00340
00341 d->imageLister->stop();
00342 clear();
00343
00344 d->currentAlbum = album;
00345 d->imageLister->openAlbum(d->currentAlbum);
00346
00347 updateRectsAndPixmaps();
00348 }
00349
00350 void AlbumIconView::setAlbumItemToFind(const KUrl& url)
00351 {
00352 d->itemUrlToFind = url;
00353 }
00354
00355 void AlbumIconView::refreshIcon(AlbumIconItem* item)
00356 {
00357 if (!item)
00358 return;
00359
00360 emit signalSelectionChanged();
00361 }
00362
00363 void AlbumIconView::clear(bool update)
00364 {
00365 emit signalCleared();
00366
00367 d->itemDict.clear();
00368 d->albumDict.clear();
00369 d->itemInfoMap.clear();
00370
00371 IconView::clear(update);
00372
00373 emit signalSelectionChanged();
00374 }
00375
00376 void AlbumIconView::slotImageListerNewItems(const ImageInfoList& itemList)
00377 {
00378 if (!d->currentAlbum || d->currentAlbum->isRoot())
00379 return;
00380
00381 for (ImageInfoList::const_iterator it = itemList.begin(); it != itemList.end(); ++it)
00382 {
00383 KUrl url( it->fileUrl() );
00384 url.cleanPath();
00385
00386 if (d->itemInfoMap.contains(*it))
00387 {
00388
00389
00390 continue;
00391 }
00392
00393 AlbumIconGroupItem* group = d->albumDict.find(it->albumId());
00394 if (!group)
00395 {
00396 group = new AlbumIconGroupItem(this, it->albumId());
00397 d->albumDict.insert(it->albumId(), group);
00398 }
00399
00400 PAlbum *album = AlbumManager::instance()->findPAlbum(it->albumId());
00401 if (!album)
00402 {
00403 kWarning(50003) << "No album for item: " << it->name()
00404 << ", albumID: " << it->albumId() << endl;
00405 continue;
00406 }
00407
00408 AlbumIconItem* iconItem = new AlbumIconItem(group, (*it));
00409
00410 d->itemDict.insert(url.url(), iconItem);
00411 d->itemInfoMap.insert((*it), iconItem);
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426 if (!d->itemUrlToFind.isEmpty())
00427 {
00428 AlbumIconItem* icon = findItem(d->itemUrlToFind.url());
00429 if (icon)
00430 {
00431 clearSelection();
00432 updateContents();
00433 setCurrentItem(icon);
00434 ensureItemVisible(icon);
00435
00436
00437
00438 setStoredVisibleItem(icon);
00439 triggerRearrangement();
00440 }
00441 }
00442
00443 emit signalItemsAdded();
00444 }
00445
00446 void AlbumIconView::slotImageListerDeleteItem(const ImageInfo &item)
00447 {
00448 QHash<ImageInfo, AlbumIconItem*>::iterator itMap = d->itemInfoMap.find(item);
00449 if (itMap == d->itemInfoMap.end())
00450 return;
00451
00452 AlbumIconItem* iconItem = (*itMap);
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 emit signalItemDeleted(iconItem);
00471
00472 delete iconItem;
00473
00474 d->itemInfoMap.remove(item);
00475 d->itemDict.remove(item.fileUrl().url());
00476
00477 IconGroupItem* group = firstGroup();
00478 IconGroupItem* tmp;
00479
00480 while (group)
00481 {
00482 tmp = group->nextGroup();
00483
00484 if (group->count() == 0)
00485 {
00486 d->albumDict.remove(((AlbumIconGroupItem*)group)->albumID());
00487 delete group;
00488 }
00489
00490 group = tmp;
00491 }
00492 }
00493
00494 void AlbumIconView::slotImageListerClear()
00495 {
00496 clear();
00497 }
00498
00499 void AlbumIconView::slotDoubleClicked(IconItem *item)
00500 {
00501 if (!item) return;
00502
00503 if (d->albumSettings->getItemRightClickAction() == AlbumSettings::ShowPreview)
00504 {
00505
00506
00507 signalPreviewItem(static_cast<AlbumIconItem *>(item));
00508 }
00509 else
00510 {
00511
00512
00513 slotDisplayItem(static_cast<AlbumIconItem *>(item));
00514 }
00515 }
00516
00517 void AlbumIconView::slotRightButtonClicked(const QPoint& pos)
00518 {
00519 if (!d->currentAlbum)
00520 return;
00521
00522 if (d->currentAlbum->isRoot() ||
00523 ( d->currentAlbum->type() != Album::PHYSICAL
00524 && d->currentAlbum->type() != Album::TAG))
00525 {
00526 return;
00527 }
00528
00529 QMenu popmenu(this);
00530 KAction *paste = KStandardAction::paste(this, SLOT(slotPaste()), 0);
00531 const QMimeData *data = kapp->clipboard()->mimeData(QClipboard::Clipboard);
00532
00533 if(!data || !KUrl::List::canDecode(data))
00534 paste->setEnabled(false);
00535
00536 popmenu.addAction(paste);
00537 popmenu.exec(pos);
00538 delete paste;
00539 }
00540
00541 void AlbumIconView::slotRightButtonClicked(IconItem *item, const QPoint& pos)
00542 {
00543 if (!item)
00544 return;
00545
00546 AlbumIconItem* iconItem = static_cast<AlbumIconItem *>(item);
00547
00548
00549
00550 KMimeType::Ptr mimePtr = KMimeType::findByUrl(iconItem->imageInfo().fileUrl(), 0, true, true);
00551
00552 QMap<QAction*, KService::Ptr> serviceMap;
00553
00554 const KService::List offers = KMimeTypeTrader::self()->query(mimePtr->name());
00555 KService::List::ConstIterator iter;
00556 KService::Ptr ptr;
00557
00558 KMenu openWithMenu;
00559
00560 for( iter = offers.begin(); iter != offers.end(); ++iter )
00561 {
00562 ptr = *iter;
00563 QAction *serviceAction = openWithMenu.addAction(SmallIcon(ptr->icon()), ptr->name());
00564 serviceMap[serviceAction] = ptr;
00565 }
00566
00567 if (openWithMenu.isEmpty())
00568 openWithMenu.menuAction()->setEnabled(false);
00569
00570
00571
00572
00573
00574
00575 QList<qlonglong> selectedImageIDs;
00576
00577 for (IconItem *it = firstItem(); it; it=it->nextItem())
00578 {
00579 if (it->isSelected())
00580 {
00581 AlbumIconItem *selItem = static_cast<AlbumIconItem *>(it);
00582 selectedImageIDs.append(selItem->imageInfo().id());
00583 }
00584 }
00585
00586
00587
00588 QMenu gotoMenu;
00589
00590 QAction *gotoAlbum = gotoMenu.addAction(SmallIcon("folder-image"), i18n("Album"));
00591 QAction *gotoDate = gotoMenu.addAction(SmallIcon("view-calendar-month"), i18n("Date"));
00592
00593 TagsPopupMenu* gotoTagsPopup = new TagsPopupMenu(selectedImageIDs, TagsPopupMenu::DISPLAY);
00594 QAction *gotoTag = gotoMenu.addMenu(gotoTagsPopup);
00595 gotoTag->setIcon(SmallIcon("tag"));
00596 gotoTag->setText(i18n("Tag"));
00597
00598
00599 if (!DatabaseAccess().db()->hasTags(selectedImageIDs))
00600 gotoTag->setEnabled(false);
00601
00602 connect(gotoTagsPopup, SIGNAL(signalTagActivated(int)),
00603 this, SLOT(slotGotoTag(int)));
00604
00605 if (d->currentAlbum->type() == Album::PHYSICAL )
00606 {
00607
00608
00609
00610 if (iconItem->imageInfo().albumId() == d->currentAlbum->id())
00611 gotoAlbum->setEnabled(false);
00612 }
00613 else if (d->currentAlbum->type() == Album::DATE )
00614 {
00615 gotoDate->setEnabled(false);
00616 }
00617
00618
00619
00620 DPopupMenu popmenu(this);
00621 QAction *viewAction = popmenu.addAction(SmallIcon("viewimage"), i18n("View..."));
00622 QAction *editAction = popmenu.addAction(SmallIcon("editimage"), i18n("Edit..."));
00623 QAction *lighttableAction = popmenu.addAction(SmallIcon("lighttableadd"), i18n("Add to Light Table"));
00624 QAction *gotoAction = popmenu.addMenu(&gotoMenu);
00625 gotoAction->setIcon(SmallIcon("go-jump"));
00626 gotoAction->setText(i18n("Go To"));
00627
00628
00629 if (selectedImageIDs.count() > 1)
00630 {
00631 gotoAction->setEnabled(false);
00632 }
00633
00634 popmenu.addMenu(&openWithMenu);
00635 openWithMenu.menuAction()->setText(i18n("Open With"));
00636
00637
00638
00639 KIPI::PluginLoader* kipiPluginLoader = KIPI::PluginLoader::instance();
00640 KIPI::PluginLoader::PluginList pluginList = kipiPluginLoader->pluginList();
00641
00642 for (KIPI::PluginLoader::PluginList::const_iterator it = pluginList.begin();
00643 it != pluginList.end(); ++it)
00644 {
00645 KIPI::Plugin* plugin = (*it)->plugin();
00646
00647 if (plugin && (*it)->name() == "JPEGLossless")
00648 {
00649 kDebug(50003) << "Found JPEGLossless plugin" << endl;
00650
00651 QList<KAction*> actionList = plugin->actions();
00652
00653 for (QList<KAction*>::const_iterator iter = actionList.begin();
00654 iter != actionList.end(); ++iter)
00655 {
00656 KAction* action = *iter;
00657
00658 if (action->objectName().toLatin1() == QString::fromLatin1("jpeglossless_rotate"))
00659 {
00660 popmenu.addAction(action);
00661 }
00662 }
00663 }
00664 }
00665
00666
00667
00668 QAction *renameAction = popmenu.addAction(SmallIcon("edit-rename"), i18n("Rename..."));
00669 popmenu.addSeparator();
00670
00671
00672
00673 QAction *thumbnailAction = 0;
00674 if (d->currentAlbum)
00675 {
00676 if (d->currentAlbum->type() == Album::PHYSICAL )
00677 {
00678 thumbnailAction = popmenu.addAction(i18n("Set as Album Thumbnail"));
00679 popmenu.addSeparator();
00680 }
00681 else if (d->currentAlbum->type() == Album::TAG )
00682 {
00683 thumbnailAction = popmenu.addAction(i18n("Set as Tag Thumbnail"));
00684 popmenu.addSeparator();
00685 }
00686 }
00687
00688
00689
00690 KAction *copy = KStandardAction::copy(this, SLOT(slotCopy()), 0);
00691 KAction *paste = KStandardAction::paste(this, SLOT(slotPaste()), 0);
00692 const QMimeData *data = kapp->clipboard()->mimeData(QClipboard::Clipboard);
00693
00694 if(!data || !KUrl::List::canDecode(data))
00695 paste->setEnabled(false);
00696
00697 popmenu.addAction(copy);
00698 popmenu.addAction(paste);
00699 popmenu.addSeparator();
00700
00701
00702
00703 QAction *trashAction = popmenu.addAction(SmallIcon("user-trash"),
00704 i18np("Move to Trash", "Move %1 Files to Trash", selectedImageIDs.count()));
00705
00706 popmenu.addSeparator();
00707
00708
00709
00710 TagsPopupMenu* assignTagsPopup = new TagsPopupMenu(selectedImageIDs, TagsPopupMenu::ASSIGN);
00711 TagsPopupMenu* removeTagsPopup = new TagsPopupMenu(selectedImageIDs, TagsPopupMenu::REMOVE);
00712
00713 connect(assignTagsPopup, SIGNAL(signalTagActivated(int)),
00714 this, SLOT(slotAssignTag(int)));
00715
00716 connect(removeTagsPopup, SIGNAL(signalTagActivated(int)),
00717 this, SLOT(slotRemoveTag(int)));
00718
00719 popmenu.addMenu(assignTagsPopup);
00720 assignTagsPopup->menuAction()->setText(i18n("Assign Tag"));
00721
00722 popmenu.addMenu(removeTagsPopup);
00723 removeTagsPopup->menuAction()->setText(i18n("Remove Tag"));
00724
00725
00726
00727 if (selectedImageIDs.count() > 250 ||
00728 !DatabaseAccess().db()->hasTags(selectedImageIDs))
00729 removeTagsPopup->menuAction()->setEnabled(false);
00730
00731 popmenu.addSeparator();
00732
00733
00734
00735 RatingPopupMenu ratingMenu;
00736
00737 connect(&ratingMenu, SIGNAL(signalRatingChanged(int)),
00738 this, SLOT(slotAssignRating(int)));
00739
00740 popmenu.addMenu(&ratingMenu);
00741 ratingMenu.menuAction()->setText(i18n("Assign Rating"));
00742
00743
00744
00745 QAction *choice = popmenu.exec(pos);
00746
00747 if (choice)
00748 {
00749 if (choice == editAction)
00750 {
00751 slotDisplayItem(iconItem);
00752 }
00753 else if (choice == renameAction)
00754 {
00755 slotRename(iconItem);
00756 }
00757 else if (choice == trashAction)
00758 {
00759 slotDeleteSelectedItems();
00760 }
00761 else if (choice == thumbnailAction)
00762 {
00763 slotSetAlbumThumbnail(iconItem);
00764 }
00765 else if (choice == viewAction)
00766 {
00767 signalPreviewItem(iconItem);
00768 }
00769 else if (choice == lighttableAction)
00770 {
00771
00772 insertSelectionToLightTable(true);
00773 }
00774 else if (choice == gotoAlbum)
00775 {
00776
00777 emit signalGotoAlbumAndItem(iconItem);
00778 }
00779 else if (choice == gotoDate)
00780 {
00781
00782 emit signalGotoDateAndItem(iconItem);
00783 }
00784 else
00785 {
00786 if (serviceMap.contains(choice))
00787 {
00788 KService::Ptr imageServicePtr = serviceMap[choice];
00789 KUrl::List urlList;
00790 for (IconItem *it = firstItem(); it; it=it->nextItem())
00791 {
00792 if (it->isSelected())
00793 {
00794 AlbumIconItem *selItem = static_cast<AlbumIconItem *>(it);
00795 urlList.append(selItem->imageInfo().fileUrl());
00796 }
00797 }
00798 if (urlList.count())
00799 KRun::run(*imageServicePtr, urlList, this);
00800 }
00801 }
00802 }
00803
00804
00805
00806 popmenu.deleteLater();
00807 }
00808
00809 void AlbumIconView::slotCopy()
00810 {
00811 if (!d->currentAlbum)
00812 return;
00813
00814 KUrl::List urls;
00815 KUrl::List kioURLs;
00816 QList<int> albumIDs;
00817 QList<int> imageIDs;
00818
00819 for (IconItem *it = firstItem(); it; it=it->nextItem())
00820 {
00821 if (it->isSelected())
00822 {
00823 AlbumIconItem *albumItem = static_cast<AlbumIconItem *>(it);
00824 ImageInfo info = albumItem->imageInfo();
00825 urls.append(info.fileUrl());
00826 kioURLs.append(info.databaseUrl());
00827 imageIDs.append(info.id());
00828 }
00829 }
00830 albumIDs.append(d->currentAlbum->id());
00831
00832 if (urls.isEmpty())
00833 return;
00834
00835 kapp->clipboard()->setMimeData(new DItemDrag(urls, kioURLs, albumIDs, imageIDs));
00836 }
00837
00838 void AlbumIconView::slotPaste()
00839 {
00840 const QMimeData *data = kapp->clipboard()->mimeData(QClipboard::Clipboard);
00841 if(!data)
00842 return;
00843
00844 Album *album = 0;
00845
00846
00847 if (groupCount() > 1)
00848 {
00849 AlbumIconGroupItem *grp = dynamic_cast<AlbumIconGroupItem*>(findGroup(QCursor::pos()));
00850 if (grp)
00851 {
00852 if(d->currentAlbum->type() == Album::PHYSICAL)
00853 album = dynamic_cast<Album*>(AlbumManager::instance()->findPAlbum(grp->albumID()));
00854 else if(d->currentAlbum->type() == Album::TAG)
00855 album = dynamic_cast<Album*>(AlbumManager::instance()->findTAlbum(grp->albumID()));
00856 }
00857 }
00858 if (!album)
00859 album = d->currentAlbum;
00860
00861 if (d->currentAlbum->type() == Album::PHYSICAL)
00862 {
00863 if (DItemDrag::canDecode(data))
00864 {
00865
00866
00867 PAlbum* palbum = (PAlbum*)album;
00868
00869
00870 if (palbum->isRoot())
00871 return;
00872
00873 KUrl::List urls;
00874 KUrl::List kioURLs;
00875 QList<int> albumIDs;
00876 QList<int> imageIDs;
00877
00878 if (!DItemDrag::decode(data, urls, kioURLs, albumIDs, imageIDs))
00879 return;
00880
00881 if (urls.isEmpty() || kioURLs.isEmpty() || albumIDs.isEmpty() || imageIDs.isEmpty())
00882 return;
00883
00884
00885 KUrl::List extUrls;
00886 QList<qlonglong> extImageIDs;
00887 for (QList<int>::iterator it = imageIDs.begin(); it != imageIDs.end(); ++it)
00888 {
00889 ImageInfo info(*it);
00890 if (info.albumId() != album->id())
00891 {
00892 extUrls << info.databaseUrl();
00893 extImageIDs << *it;
00894 }
00895 }
00896
00897 if(extUrls.isEmpty())
00898 return;
00899
00900 KIO::Job* job = DIO::copy(kioURLs, extImageIDs, palbum);
00901 connect(job, SIGNAL(result(KJob*)),
00902 this, SLOT(slotDIOResult(KJob*)));
00903 }
00904 else if (KUrl::List::canDecode(data))
00905 {
00906 PAlbum* palbum = (PAlbum*)album;
00907
00908
00909 if (palbum->isRoot())
00910 return;
00911
00912 KUrl::List srcURLs;
00913 srcURLs.fromMimeData(data);
00914
00915 KIO::Job* job = DIO::copy(srcURLs, palbum);
00916 connect(job, SIGNAL(result(KJob*)),
00917 this, SLOT(slotDIOResult(KJob*)));
00918 }
00919 }
00920 else if(d->currentAlbum->type() == Album::TAG && DItemDrag::canDecode(data))
00921 {
00922 TAlbum* talbum = (TAlbum*)album;
00923
00924
00925 if (talbum->isRoot())
00926 return;
00927
00928 KUrl::List urls;
00929 KUrl::List kioURLs;
00930 QList<int> albumIDs;
00931 QList<int> imageIDs;
00932
00933 if (!DItemDrag::decode(data, urls, kioURLs, albumIDs, imageIDs))
00934 return;
00935
00936 if (urls.isEmpty() || kioURLs.isEmpty() || albumIDs.isEmpty() || imageIDs.isEmpty())
00937 return;
00938
00939 ImageInfoList list;
00940 for (QList<int>::const_iterator it = imageIDs.begin();
00941 it != imageIDs.end(); ++it)
00942 {
00943 ImageInfo info(*it);
00944 list.append(info);
00945 }
00946
00947 changeTagOnImageInfos(list, QList<int>() << talbum->id(), true, true);
00948 }
00949 }
00950
00951 void AlbumIconView::slotSetAlbumThumbnail(AlbumIconItem *iconItem)
00952 {
00953 if(!d->currentAlbum)
00954 return;
00955
00956 if(d->currentAlbum->type() == Album::PHYSICAL)
00957 {
00958 PAlbum *album = static_cast<PAlbum*>(d->currentAlbum);
00959
00960 QString err;
00961 AlbumManager::instance()->updatePAlbumIcon( album,
00962 iconItem->imageInfo().id(),
00963 err );
00964 }
00965 else if (d->currentAlbum->type() == Album::TAG)
00966 {
00967 TAlbum *album = static_cast<TAlbum*>(d->currentAlbum);
00968
00969 QString err;
00970 AlbumManager::instance()->updateTAlbumIcon( album,
00971 QString(),
00972 iconItem->imageInfo().id(),
00973 err );
00974 }
00975 }
00976
00977 void AlbumIconView::slotRename(AlbumIconItem* item)
00978 {
00979 if (!item)
00980 return;
00981
00982
00983
00984 ImageInfo renameInfo = item->imageInfo();
00985
00986 QFileInfo fi(renameInfo.name());
00987 QString ext = QString(".") + fi.suffix();
00988 QString name = fi.fileName();
00989 name.truncate(fi.fileName().length() - ext.length());
00990
00991 bool ok;
00992
00993 QString newName = KInputDialog::getText(i18n("Rename Item (%1)",fi.fileName()),
00994 i18n("Enter new name (without extension):"),
00995 name, &ok, this);
00996 if (!ok)
00997 return;
00998
00999 KIO::CopyJob* job = DIO::rename(renameInfo, newName + ext);
01000
01001 connect(job, SIGNAL(result(KJob*)),
01002 this, SLOT(slotDIOResult(KJob*)));
01003
01004 connect(job, SIGNAL(copyingDone(KIO::Job *, const KUrl &, const KUrl &, bool, bool)),
01005 this, SLOT(slotRenamed(KIO::Job*, const KUrl &, const KUrl&)));
01006
01007
01008
01009
01010
01011
01012 d->imageLister->invalidateItem(renameInfo);
01013 }
01014
01015 void AlbumIconView::slotRenamed(KIO::Job*, const KUrl &, const KUrl&newURL)
01016 {
01017
01018 KUrl fileURL;
01019 fileURL.setPath(newURL.user());
01020 fileURL.addPath(newURL.path());
01021
01022
01023 ThumbnailLoadThread::deleteThumbnail(fileURL.path());
01024
01025 LoadingCacheInterface::cleanFromCache(fileURL.path());
01026 }
01027
01028 void AlbumIconView::slotDeleteSelectedItems(bool deletePermanently)
01029 {
01030 KUrl::List urlList;
01031 KUrl::List kioUrlList;
01032
01033 for (IconItem *it = firstItem(); it; it=it->nextItem())
01034 {
01035 if (it->isSelected())
01036 {
01037 AlbumIconItem *iconItem = static_cast<AlbumIconItem *>(it);
01038 ImageInfo info = iconItem->imageInfo();
01039 urlList.append(info.fileUrl());
01040 kioUrlList.append(info.databaseUrl());
01041 }
01042 }
01043
01044 if (urlList.count() <= 0)
01045 return;
01046
01047 DeleteDialog dialog(this);
01048
01049 if (!dialog.confirmDeleteList(urlList,
01050 DeleteDialogMode::Files,
01051 deletePermanently ?
01052 DeleteDialogMode::NoChoiceDeletePermanently :
01053 DeleteDialogMode::NoChoiceTrash))
01054 return;
01055
01056 bool useTrash = !dialog.shouldDelete();
01057
01058
01059 KIO::Job* job = DIO::del(useTrash ? urlList : kioUrlList, useTrash);
01060
01061 connect(job, SIGNAL(result(KJob*)),
01062 this, SLOT(slotDIOResult(KJob*)));
01063 }
01064
01065 void AlbumIconView::slotDeleteSelectedItemsDirectly(bool useTrash)
01066 {
01067
01068
01069
01070 KUrl::List kioUrlList;
01071 KUrl::List urlList;
01072
01073 for (IconItem *it = firstItem(); it; it=it->nextItem())
01074 {
01075 if (it->isSelected())
01076 {
01077 AlbumIconItem *iconItem = static_cast<AlbumIconItem *>(it);
01078 ImageInfo info = iconItem->imageInfo();
01079 kioUrlList.append(info.databaseUrl());
01080 urlList.append(info.fileUrl());
01081 }
01082 }
01083
01084 if (kioUrlList.count() <= 0)
01085 return;
01086
01087
01088 KIO::Job* job = DIO::del(useTrash ? urlList : kioUrlList , useTrash);
01089
01090 connect(job, SIGNAL(result(KJob*)),
01091 this, SLOT(slotDIOResult(KJob*)));
01092 }
01093
01094 void AlbumIconView::slotFilesModified()
01095 {
01096 d->imageLister->refresh();
01097 }
01098
01099 void AlbumIconView::slotFilesModified(const KUrl& url)
01100 {
01101 refreshItems(url);
01102 }
01103
01104 void AlbumIconView::slotImageWindowURLChanged(const KUrl &url)
01105 {
01106 IconItem* item = findItem(url.url());
01107 if (item)
01108 setCurrentItem(item);
01109 }
01110
01111 void AlbumIconView::slotDisplayItem(AlbumIconItem *item)
01112 {
01113 if (!item) return;
01114
01115 AlbumSettings *settings = AlbumSettings::instance();
01116
01117 if (!settings) return;
01118
01119 QString currentFileExtension = item->imageInfo().name().section( '.', -1 );
01120 QString imagefilter = settings->getImageFileFilter().toLower() +
01121 settings->getImageFileFilter().toUpper();
01122
01123 #if KDCRAW_VERSION < 0x000400
01124 if (KDcrawIface::DcrawBinary::instance()->versionIsRight())
01125 {
01126
01127 imagefilter += settings->getRawFileFilter().toLower() +
01128 settings->getRawFileFilter().toUpper();
01129 }
01130 #else
01131
01132 imagefilter += settings->getRawFileFilter().toLower() +
01133 settings->getRawFileFilter().toUpper();
01134 #endif
01135
01136
01137 if ( !imagefilter.contains(currentFileExtension) )
01138 {
01139 KMimeType::Ptr mimePtr = KMimeType::findByUrl(item->imageInfo().fileUrl(), 0, true, true);
01140 const KService::List offers = KServiceTypeTrader::self()->query(mimePtr->name(), "Type == 'Application'");
01141
01142 if (offers.isEmpty())
01143 return;
01144
01145 KService::Ptr ptr = offers.first();
01146
01147 KRun::run(*ptr, item->imageInfo().fileUrl(), this);
01148 return;
01149 }
01150
01151
01152
01153 ImageInfoList list;
01154 ImageInfo current;
01155
01156 for (IconItem *it = firstItem() ; it ; it = it->nextItem())
01157 {
01158 AlbumIconItem *iconItem = static_cast<