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 #include "albumfolderview.moc"
00027
00028
00029
00030 #include <QCursor>
00031 #include <QDataStream>
00032 #include <QDateTime>
00033 #include <QDir>
00034 #include <QDropEvent>
00035 #include <QList>
00036 #include <QPixmap>
00037
00038
00039
00040 #include <kaction.h>
00041 #include <kapplication.h>
00042 #include <kcalendarsystem.h>
00043 #include <kdeversion.h>
00044 #include <kfiledialog.h>
00045 #include <kglobal.h>
00046 #include <kiconloader.h>
00047 #include <kinputdialog.h>
00048 #include <kio/job.h>
00049 #include <kio/jobuidelegate.h>
00050 #include <klocale.h>
00051 #include <kmenu.h>
00052 #include <kmessagebox.h>
00053 #include <kstringhandler.h>
00054 #include <kdebug.h>
00055
00056
00057
00058 #include "album.h"
00059 #include "albumdb.h"
00060 #include "albumlister.h"
00061 #include "albummanager.h"
00062 #include "albumpropsedit.h"
00063 #include "albumsettings.h"
00064 #include "albumthumbnailloader.h"
00065 #include "cameraui.h"
00066 #include "collectionmanager.h"
00067 #include "contextmenuhelper.h"
00068 #include "ddragobjects.h"
00069 #include "deletedialog.h"
00070 #include "digikamapp.h"
00071 #include "dio.h"
00072 #include "thumbnailsize.h"
00073
00074 namespace Digikam
00075 {
00076
00077 AlbumFolderViewItem::AlbumFolderViewItem(Q3ListView *parent, PAlbum *album)
00078 : FolderItem(parent, album->title())
00079 {
00080 setDragEnabled(true);
00081 m_album = album;
00082 m_groupItem = false;
00083 m_count = 0;
00084 m_countRecursive = 0;
00085 }
00086
00087 AlbumFolderViewItem::AlbumFolderViewItem(Q3ListViewItem *parent, PAlbum *album)
00088 : FolderItem(parent, album->title())
00089 {
00090 setDragEnabled(true);
00091 m_album = album;
00092 m_groupItem = false;
00093 m_count = 0;
00094 m_countRecursive = 0;
00095 }
00096
00097
00098 AlbumFolderViewItem::AlbumFolderViewItem(Q3ListViewItem* parent, const QString& name,
00099 int year, int month)
00100 : FolderItem(parent, name, true)
00101 {
00102 setDragEnabled(false);
00103 m_album = 0;
00104 m_year = year;
00105 m_month = month;
00106 m_groupItem = true;
00107 m_count = 0;
00108 m_countRecursive = 0;
00109 }
00110
00111 void AlbumFolderViewItem::refresh()
00112 {
00113 if (!m_album) return;
00114
00115 if (AlbumSettings::instance()->getShowFolderTreeViewItemsCount() &&
00116 dynamic_cast<AlbumFolderViewItem*>(parent()))
00117 {
00118 m_countRecursive = m_count;
00119 AlbumIterator it(m_album);
00120 while ( it.current() )
00121 {
00122 AlbumFolderViewItem *item = (AlbumFolderViewItem*)it.current()->extraData(listView());
00123 if (item)
00124 m_countRecursive += item->count();
00125 ++it;
00126 }
00127
00128 if (isOpen())
00129 setText(0, QString("%1 (%2)").arg(m_album->title()).arg(m_count));
00130 else
00131 setText(0, QString("%1 (%2)").arg(m_album->title()).arg(m_countRecursive));
00132 }
00133 else
00134 {
00135 setText(0, m_album->title());
00136 }
00137 }
00138
00139 void AlbumFolderViewItem::setOpen(bool o)
00140 {
00141 Q3ListViewItem::setOpen(o);
00142 refresh();
00143 }
00144
00145 PAlbum* AlbumFolderViewItem::album() const
00146 {
00147 return m_album;
00148 }
00149
00150 int AlbumFolderViewItem::id() const
00151 {
00152 if (m_groupItem)
00153 {
00154 if (m_year != 0 && m_month != 0)
00155 {
00156 return (m_year*(-100) + m_month*(-1));
00157 }
00158 else
00159 {
00160 return ( - (AlbumSettings::instance()->getAlbumCategoryNames()
00161 .indexOf(text(0)) ) );
00162 }
00163 }
00164 else
00165 {
00166 return m_album ? m_album->id() : 0;
00167 }
00168 }
00169
00170 bool AlbumFolderViewItem::isGroupItem() const
00171 {
00172 return m_groupItem;
00173 }
00174
00175 int AlbumFolderViewItem::compare(Q3ListViewItem *i, int col, bool ascending) const
00176 {
00177 if (!m_groupItem || m_year == 0 || m_month == 0)
00178 {
00179 return KStringHandler::naturalCompare(key(col, ascending), i->key(col, ascending));
00180 }
00181
00182 AlbumFolderViewItem* thatItem = dynamic_cast<AlbumFolderViewItem*>(i);
00183 if (!thatItem)
00184 return 0;
00185
00186 int myWeight = m_year*100 + m_month;
00187 int hisWeight = thatItem->m_year*100 + thatItem->m_month;
00188
00189 if (myWeight == hisWeight)
00190 return 0;
00191 else if (myWeight > hisWeight)
00192 return 1;
00193 else
00194 return -1;
00195 }
00196
00197 void AlbumFolderViewItem::setCount(int count)
00198 {
00199 m_count = count;
00200 refresh();
00201 }
00202
00203 int AlbumFolderViewItem::count()
00204 {
00205 return m_count;
00206 }
00207
00208 int AlbumFolderViewItem::countRecursive()
00209 {
00210 return m_countRecursive;
00211 }
00212
00213
00214
00215 class AlbumFolderViewPriv
00216 {
00217 public:
00218
00219 AlbumFolderViewPriv()
00220 {
00221 albumMan = 0;
00222 }
00223
00224 AlbumManager *albumMan;
00225 QList<AlbumFolderViewItem*> groupItems;
00226 };
00227
00228 AlbumFolderView::AlbumFolderView(QWidget *parent)
00229 : FolderView(parent, "AlbumFolderView"), d(new AlbumFolderViewPriv)
00230 {
00231 d->albumMan = AlbumManager::instance();
00232
00233 addColumn(i18n("Albums"));
00234 setRootIsDecorated(false);
00235 setAcceptDrops(true);
00236 viewport()->setAcceptDrops(true);
00237
00238 connect(d->albumMan, SIGNAL(signalAlbumAdded(Album*)),
00239 this, SLOT(slotAlbumAdded(Album*)));
00240
00241 connect(d->albumMan, SIGNAL(signalAlbumDeleted(Album*)),
00242 this, SLOT(slotAlbumDeleted(Album*)));
00243
00244 connect(d->albumMan, SIGNAL(signalAlbumsCleared()),
00245 this, SLOT(slotAlbumsCleared()));
00246
00247 connect(d->albumMan, SIGNAL(signalAlbumIconChanged(Album*)),
00248 this, SLOT(slotAlbumIconChanged(Album*)));
00249
00250 connect(d->albumMan, SIGNAL(signalAlbumRenamed(Album*)),
00251 this, SLOT(slotAlbumRenamed(Album*)));
00252
00253 connect(d->albumMan, SIGNAL(signalPAlbumsDirty(const QMap<int, int>&)),
00254 this, SLOT(slotRefresh(const QMap<int, int>&)));
00255
00256 AlbumThumbnailLoader *loader = AlbumThumbnailLoader::instance();
00257
00258 connect(loader, SIGNAL(signalThumbnail(Album *, const QPixmap&)),
00259 this, SLOT(slotGotThumbnailFromIcon(Album *, const QPixmap&)));
00260
00261 connect(loader, SIGNAL(signalFailed(Album *)),
00262 this, SLOT(slotThumbnailLost(Album *)));
00263
00264 connect(loader, SIGNAL(signalReloadThumbnails()),
00265 this, SLOT(slotReloadThumbnails()));
00266
00267 connect(this, SIGNAL(contextMenuRequested(Q3ListViewItem*, const QPoint&, int)),
00268 this, SLOT(slotContextMenu(Q3ListViewItem*, const QPoint&, int)));
00269
00270 connect(this, SIGNAL(selectionChanged()),
00271 this, SLOT(slotSelectionChanged()));
00272 }
00273
00274 AlbumFolderView::~AlbumFolderView()
00275 {
00276 saveViewState();
00277 delete d;
00278 }
00279
00280 void AlbumFolderView::slotTextFolderFilterChanged(const SearchTextSettings& settings)
00281 {
00282 if (settings.text.isEmpty())
00283 {
00284 collapseView();
00285 return;
00286 }
00287
00288 QString search = settings.text;
00289 bool atleastOneMatch = false;
00290 bool folderSortMode = AlbumSettings::instance()->getAlbumSortOrder() == AlbumSettings::ByFolder;
00291
00292 Q3ListViewItemIterator it(this);
00293 while (it.current())
00294 {
00295 AlbumFolderViewItem* viewItem = dynamic_cast<AlbumFolderViewItem*>(*it);
00296
00297 if (!viewItem)
00298 {
00299 ++it;
00300 continue;
00301 }
00302
00303
00304
00305 PAlbum* palbum = viewItem->album();
00306
00307
00308 if ((palbum && palbum->isRoot()) ||
00309 ( folderSortMode && (!palbum || palbum->isRoot() || palbum->isAlbumRoot()) ))
00310 {
00311 viewItem->setOpen(true);
00312 ++it;
00313 continue;
00314 }
00315
00316 bool doesExpand = false;
00317 bool match = false;
00318
00319 if (folderSortMode)
00320 {
00321 match = palbum->title().contains(search, settings.caseSensitive);
00322
00323 if (!match)
00324 {
00325
00326 PAlbum* parent = dynamic_cast<PAlbum*>(palbum->parent());
00327
00328 while (parent && !(parent->isRoot() || parent->isAlbumRoot()) )
00329 {
00330 if (parent->title().contains(search, settings.caseSensitive))
00331 {
00332 match = true;
00333 break;
00334 }
00335
00336 parent = dynamic_cast<PAlbum*>(parent->parent());
00337 }
00338 }
00339
00340 if (!match)
00341 {
00342
00343 if (palbum)
00344 {
00345 AlbumIterator it(palbum);
00346 while (it.current())
00347 {
00348 if ((*it)->title().contains(search, settings.caseSensitive))
00349 {
00350 match = true;
00351 doesExpand = true;
00352 break;
00353 }
00354 ++it;
00355 }
00356 }
00357 }
00358 }
00359 else
00360 {
00361 if (viewItem->isGroupItem())
00362 {
00363 Q3ListViewItemIterator it2(viewItem);
00364 while (it2.current())
00365 {
00366 AlbumFolderViewItem* viewItem2 = dynamic_cast<AlbumFolderViewItem*>(*it2);
00367
00368 if (!viewItem2)
00369 {
00370 ++it2;
00371 continue;
00372 }
00373
00374 if (viewItem2->parent() == viewItem)
00375 {
00376 if (viewItem2->text(0).contains(search, settings.caseSensitive))
00377 {
00378 match = true;
00379 doesExpand = true;
00380 break;
00381 }
00382 }
00383 ++it2;
00384 }
00385 }
00386 else
00387 {
00388 if (viewItem->text(0).contains(search, settings.caseSensitive))
00389 {
00390 match = true;
00391 doesExpand = true;
00392 }
00393 }
00394 }
00395
00396 if (match)
00397 {
00398 atleastOneMatch = true;
00399 viewItem->setVisible(true);
00400 viewItem->setOpen(doesExpand);
00401 }
00402 else
00403 {
00404 viewItem->setVisible(false);
00405 viewItem->setOpen(false);
00406 }
00407 ++it;
00408 }
00409 emit signalTextFolderFilterMatch(atleastOneMatch);
00410 }
00411
00412 void AlbumFolderView::slotAlbumAdded(Album *album)
00413 {
00414 if(!album)
00415 return;
00416
00417 PAlbum *palbum = dynamic_cast<PAlbum*>(album);
00418 if(!palbum)
00419 return;
00420
00421 bool failed;
00422 AlbumFolderViewItem* parent = findParent(palbum, failed);
00423 if (failed)
00424 {
00425 kWarning() << " Failed to find Album parent " << palbum->albumPath();
00426 return;
00427 }
00428
00429 AlbumFolderViewItem *item;
00430 if (!parent)
00431 {
00432
00433 item = new AlbumFolderViewItem(this, palbum);
00434 palbum->setExtraData(this, item);
00435 item->setOpen(true);
00436 }
00437 else
00438 {
00439 item = new AlbumFolderViewItem(parent, palbum);
00440 palbum->setExtraData(this, item);
00441 }
00442
00443 setAlbumThumbnail(palbum);
00444 }
00445
00446 void AlbumFolderView::slotAlbumDeleted(Album *album)
00447 {
00448 if(!album)
00449 return;
00450
00451 PAlbum* palbum = dynamic_cast<PAlbum*>(album);
00452 if(!palbum)
00453 return;
00454
00455 AlbumFolderViewItem* item = (AlbumFolderViewItem*) palbum->extraData(this);
00456 if(item)
00457 {
00458 AlbumFolderViewItem *itemParent = dynamic_cast<AlbumFolderViewItem*>(item->parent());
00459
00460 if(itemParent)
00461 itemParent->takeItem(item);
00462 else
00463 takeItem(item);
00464
00465 delete item;
00466 clearEmptyGroupItems();
00467 }
00468 }
00469
00470 void AlbumFolderView::slotAlbumRenamed(Album *album)
00471 {
00472 PAlbum* palbum = dynamic_cast<PAlbum*>(album);
00473 if(!palbum)
00474 return;
00475
00476 AlbumFolderViewItem* item = (AlbumFolderViewItem*) palbum->extraData(this);
00477 if(item)
00478 item->refresh();
00479 if (item->parent())
00480 item->parent()->sort();
00481 }
00482
00483 void AlbumFolderView::slotAlbumsCleared()
00484 {
00485 d->groupItems.clear();
00486 clear();
00487 }
00488
00489 void AlbumFolderView::setAlbumThumbnail(PAlbum *album)
00490 {
00491 if(!album)
00492 return;
00493
00494 AlbumFolderViewItem* item = (AlbumFolderViewItem*) album->extraData(this);
00495
00496 if(!item)
00497 return;
00498
00499
00500
00501
00502 AlbumThumbnailLoader *loader = AlbumThumbnailLoader::instance();
00503 item->setPixmap(0, loader->getStandardAlbumIcon(album));
00504 loader->getAlbumThumbnail(album);
00505 }
00506
00507 void AlbumFolderView::setCurrentAlbum(Album *album)
00508 {
00509 if(!album) return;
00510
00511 AlbumFolderViewItem* item = (AlbumFolderViewItem*) album->extraData(this);
00512 if(!item) return;
00513
00514 setCurrentItem(item);
00515 ensureItemVisible(item);
00516 }
00517
00518 void AlbumFolderView::slotGotThumbnailFromIcon(Album *album,
00519 const QPixmap& thumbnail)
00520 {
00521 if(!album || album->type() != Album::PHYSICAL)
00522 return;
00523
00524 AlbumFolderViewItem* item = (AlbumFolderViewItem*)album->extraData(this);
00525
00526 if(!item)
00527 return;
00528
00529 item->setPixmap(0, thumbnail);
00530 }
00531
00532 void AlbumFolderView::slotThumbnailLost(Album *)
00533 {
00534
00535 }
00536
00537 void AlbumFolderView::slotReloadThumbnails()
00538 {
00539 AlbumList tList = d->albumMan->allPAlbums();
00540 for (AlbumList::const_iterator it = tList.constBegin(); it != tList.constEnd(); ++it)
00541 {
00542 PAlbum* album = (PAlbum*)(*it);
00543 setAlbumThumbnail(album);
00544 }
00545 }
00546
00547 void AlbumFolderView::slotAlbumIconChanged(Album* album)
00548 {
00549 if(!album || album->type() != Album::PHYSICAL)
00550 return;
00551
00552 setAlbumThumbnail((PAlbum*)album);
00553 }
00554
00555 void AlbumFolderView::slotSelectionChanged()
00556 {
00557 if(!active())
00558 return;
00559
00560 Q3ListViewItem* selItem = 0;
00561 Q3ListViewItemIterator it(this);
00562 while(it.current())
00563 {
00564 if(it.current()->isSelected())
00565 {
00566 selItem = it.current();
00567 break;
00568 }
00569 ++it;
00570 }
00571
00572 if(!selItem)
00573 {
00574 d->albumMan->setCurrentAlbum(0);
00575 return;
00576 }
00577
00578 AlbumFolderViewItem *albumitem = dynamic_cast<AlbumFolderViewItem*>(selItem);
00579 if(!albumitem)
00580 {
00581 d->albumMan->setCurrentAlbum(0);
00582 return;
00583 }
00584
00585 d->albumMan->setCurrentAlbum(albumitem->album());
00586 }
00587
00588 void AlbumFolderView::slotContextMenu(Q3ListViewItem *listitem, const QPoint &, int)
00589 {
00590 AlbumFolderViewItem *item = dynamic_cast<AlbumFolderViewItem*>(listitem);
00591 if (!item)
00592 return;
00593
00594 PAlbum *album = item->album();
00595 if (item && (!album || album->isRoot()))
00596 {
00597
00598 return;
00599 }
00600
00601
00602
00603 QAction *renameAction = new QAction(SmallIcon("edit-rename"), i18n("Rename..."), this);
00604 QAction *resetIconAction = new QAction(SmallIcon("view-refresh"), i18n("Reset Album Icon"), this);
00605 QAction *findDuplAction = new QAction(SmallIcon("tools-wizard"), i18n("Find Duplicates..."), this);
00606
00607 if (album->isAlbumRoot())
00608 renameAction->setEnabled(false);
00609
00610
00611
00612 KMenu popmenu(this);
00613 popmenu.addTitle(SmallIcon("digikam"), i18n("My Albums"));
00614 ContextMenuHelper cmhelper(&popmenu);
00615
00616 cmhelper.addAction("album_new");
00617 cmhelper.addAction(renameAction);
00618 cmhelper.addAction(resetIconAction);
00619 cmhelper.addAction("album_openinkonqui");
00620 popmenu.addSeparator();
00621
00622 cmhelper.addAction(findDuplAction);
00623 cmhelper.addImportMenu();
00624 cmhelper.addExportMenu();
00625 cmhelper.addBatchMenu();
00626 cmhelper.addAlbumActions();
00627 popmenu.addSeparator();
00628
00629 cmhelper.addAction("album_delete");
00630 popmenu.addSeparator();
00631
00632 cmhelper.addAction("album_propsEdit");
00633
00634
00635
00636 QAction* choice = cmhelper.exec(QCursor::pos());
00637 if (choice)
00638 {
00639 if (choice == resetIconAction)
00640 {
00641 QString err;
00642 d->albumMan->updatePAlbumIcon(item->album(), 0, err);
00643 }
00644 else if (choice == renameAction)
00645 {
00646 albumRename(item);
00647 }
00648 else if (choice == findDuplAction)
00649 {
00650 emit signalFindDuplicatesInAlbum(album);
00651 }
00652 }
00653 }
00654
00655 void AlbumFolderView::albumNew()
00656 {
00657 AlbumFolderViewItem *item = dynamic_cast<AlbumFolderViewItem*>(selectedItem());
00658 if (!item)
00659 {
00660 item = dynamic_cast<AlbumFolderViewItem*>(firstChild());
00661 }
00662
00663 if (!item)
00664 return;
00665
00666 albumNew(item);
00667 }
00668
00669 void AlbumFolderView::albumNew(AlbumFolderViewItem *item)
00670 {
00671 AlbumSettings* settings = AlbumSettings::instance();
00672 if(!settings)
00673 {
00674 kWarning() << "AlbumFolderView: Could not get Album Settings";
00675 return;
00676 }
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691 PAlbum *parent;
00692
00693 if(!item)
00694 parent = d->albumMan->findPAlbum(0);
00695 else
00696 parent = item->album();
00697
00698 if (!parent)
00699 return;
00700
00701
00702 QString albumRootPath;
00703 if (parent->isRoot())
00704 {
00705
00706 albumRootPath = CollectionManager::instance()->oneAlbumRootPath();
00707 }
00708
00709 QString title;
00710 QString comments;
00711 QString category;
00712 QDate date;
00713 QStringList albumCategories;
00714
00715 if(!AlbumPropsEdit::createNew(parent, title, comments, date, category,
00716 albumCategories))
00717 return;
00718
00719 QStringList oldAlbumCategories(AlbumSettings::instance()->getAlbumCategoryNames());
00720 if(albumCategories != oldAlbumCategories)
00721 {
00722 AlbumSettings::instance()->setAlbumCategoryNames(albumCategories);
00723 resort();
00724 }
00725
00726 QString errMsg;
00727 PAlbum* album;
00728 if (parent->isRoot())
00729 album = d->albumMan->createPAlbum(albumRootPath, title, comments,
00730 date, category, errMsg);
00731 else
00732 album = d->albumMan->createPAlbum(parent, title, comments,
00733 date, category, errMsg);
00734
00735 if (!album)
00736 {
00737 KMessageBox::error(0, errMsg);
00738 return;
00739 }
00740
00741
00742
00743 AlbumFolderViewItem* newItem = (AlbumFolderViewItem*)album->extraData(this);
00744 if (newItem)
00745 {
00746 if(item)
00747 item->setOpen(true);
00748
00749 ensureItemVisible(newItem);
00750 }
00751 }
00752
00753 void AlbumFolderView::albumDelete()
00754 {
00755 AlbumFolderViewItem *item = dynamic_cast<AlbumFolderViewItem*>(selectedItem());
00756 if(!item)
00757 return;
00758
00759 albumDelete(item);
00760 }
00761
00762 void AlbumFolderView::albumDelete(AlbumFolderViewItem *item)
00763 {
00764 PAlbum *album = item->album();
00765
00766 if(!album || album->isRoot() || album->isAlbumRoot())
00767 return;
00768
00769
00770 KUrl::List childrenList;
00771 addAlbumChildrenToList(childrenList, album);
00772
00773 DeleteDialog dialog(this);
00774
00775
00776 if (!dialog.confirmDeleteList(childrenList,
00777 childrenList.size() == 1 ?
00778 DeleteDialogMode::Albums : DeleteDialogMode::Subalbums,
00779 DeleteDialogMode::UserPreference))
00780 return;
00781
00782 bool useTrash = !dialog.shouldDelete();
00783
00784
00785
00786
00787 KUrl u;
00788 u.setProtocol("file");
00789 u.setPath(album->folderPath());
00790 KIO::Job* job = DIO::del(u, useTrash);
00791 connect(job, SIGNAL(result(KJob *)),
00792 this, SLOT(slotDIOResult(KJob *)));
00793 }
00794
00795 void AlbumFolderView::addAlbumChildrenToList(KUrl::List& list, Album *album)
00796 {
00797
00798 if (album)
00799 {
00800 list.append(album->databaseUrl());
00801 AlbumIterator it(album);
00802 while(it.current())
00803 {
00804 addAlbumChildrenToList(list, *it);
00805 ++it;
00806 }
00807 }
00808 }
00809
00810 void AlbumFolderView::slotDIOResult(KJob* kjob)
00811 {
00812 KIO::Job *job = static_cast<KIO::Job*>(kjob);
00813 if (job->error())
00814 {
00815 job->ui()->setWindow(this);
00816 job->ui()->showErrorMessage();
00817 }
00818 }
00819
00820 void AlbumFolderView::albumRename()
00821 {
00822 AlbumFolderViewItem *item = dynamic_cast<AlbumFolderViewItem*>(selectedItem());
00823 if(!item)
00824 return;
00825
00826 albumRename(item);
00827 }
00828
00829 void AlbumFolderView::albumRename(AlbumFolderViewItem* item)
00830 {
00831 PAlbum *album = item->album();
00832
00833 if (!album)
00834 return;
00835
00836 QString oldTitle(album->title());
00837 bool ok;
00838
00839 QString title = KInputDialog::getText(i18n("Rename Album (%1)",oldTitle),
00840 i18n("Enter new album name:"),
00841 oldTitle, &ok, this);
00842 if (!ok)
00843 return;
00844
00845 if(title != oldTitle)
00846 {
00847 QString errMsg;
00848 if (!d->albumMan->renamePAlbum(album, title, errMsg))
00849 KMessageBox::error(0, errMsg);
00850 }
00851
00852 emit signalAlbumModified();
00853 }
00854
00855 void AlbumFolderView::albumEdit()
00856 {
00857 AlbumFolderViewItem *item = dynamic_cast<AlbumFolderViewItem*>(selectedItem());
00858 if(!item)
00859 return;
00860
00861 albumEdit(item);
00862 }
00863
00864 void AlbumFolderView::albumEdit(AlbumFolderViewItem* item)
00865 {
00866 PAlbum *album = item->album();
00867
00868 if (!album || album->isRoot() || album->isAlbumRoot())
00869 return;
00870
00871 QString oldTitle(album->title());
00872 QString oldComments(album->caption());
00873 QString oldCategory(album->category());
00874 QDate oldDate(album->date());
00875 QStringList oldAlbumCategories(AlbumSettings::instance()->getAlbumCategoryNames());
00876
00877 QString title, comments, category;
00878 QDate date;
00879 QStringList albumCategories;
00880
00881 if(AlbumPropsEdit::editProps(album, title, comments, date,
00882 category, albumCategories))
00883 {
00884 if(comments != oldComments)
00885 album->setCaption(comments);
00886
00887 if(date != oldDate && date.isValid())
00888 album->setDate(date);
00889
00890 if(category != oldCategory)
00891 album->setCategory(category);
00892
00893 AlbumSettings::instance()->setAlbumCategoryNames(albumCategories);
00894 resort();
00895
00896
00897
00898
00899 if(title != oldTitle)
00900 {
00901 QString errMsg;
00902 if (!d->albumMan->renamePAlbum(album, title, errMsg))
00903 KMessageBox::error(0, errMsg);
00904 }
00905
00906 emit signalAlbumModified();
00907 }
00908 }
00909
00910 QDrag* AlbumFolderView::makeDragObject()
00911 {
00912 AlbumFolderViewItem *item = dynamic_cast<AlbumFolderViewItem*>(dragItem());
00913 if(!item)
00914 return 0;
00915
00916 PAlbum *album = item->album();
00917 if(album->isRoot())
00918 return 0;
00919
00920 QDrag *drag = new QDrag(this);
00921 drag->setMimeData(new DAlbumDrag(album->databaseUrl(), album->id()));
00922 drag->setPixmap(*item->pixmap(0));
00923
00924 return drag;
00925 }
00926
00927 bool AlbumFolderView::acceptDrop(const QDropEvent *e) const
00928 {
00929 QPoint vp = contentsToViewport(e->pos());
00930 AlbumFolderViewItem *itemDrop = dynamic_cast<AlbumFolderViewItem*>(itemAt(vp));
00931 AlbumFolderViewItem *itemDrag = dynamic_cast<AlbumFolderViewItem*>(dragItem());
00932
00933 if(DAlbumDrag::canDecode(e->mimeData()))
00934 {
00935 switch(AlbumSettings::instance()->getAlbumSortOrder())
00936 {
00937 case(AlbumSettings::ByFolder):
00938 {
00939
00940 if(!itemDrop)
00941 return true;
00942
00943
00944 if(itemDrag == itemDrop)
00945 return false;
00946
00947
00948 if(itemDrag && itemDrag->album()->isAncestorOf(itemDrop->album()))
00949 return false;
00950
00951 return true;
00952 }
00953 case (AlbumSettings::ByCategory):
00954 {
00955 if (!itemDrop)
00956 return false;
00957
00958
00959 if (itemDrop->isGroupItem())
00960 return true;
00961
00962 return false;
00963 }
00964 default:
00965 {
00966 return false;
00967 }
00968 }
00969 }
00970
00971 if(itemDrop && !itemDrop->parent())
00972 {
00973
00974 return false;
00975 }
00976
00977 if(itemDrop && itemDrop->isGroupItem())
00978 {
00979
00980 return false;
00981 }
00982
00983 if(DItemDrag::canDecode(e->mimeData()))
00984 {
00985 return true;
00986 }
00987
00988 if(DCameraItemListDrag::canDecode(e->mimeData()))
00989 {
00990 return true;
00991 }
00992
00993 if(KUrl::List::canDecode(e->mimeData()))
00994 {
00995 return true;
00996 }
00997
00998 return false;
00999 }
01000
01001 void AlbumFolderView::contentsDropEvent(QDropEvent *e)
01002 {
01003 FolderView::contentsDropEvent(e);
01004
01005 if(!acceptDrop(e))
01006 return;
01007
01008 QPoint vp = contentsToViewport(e->pos());
01009 AlbumFolderViewItem *itemDrop = dynamic_cast<AlbumFolderViewItem*>(itemAt(vp));
01010
01011 if(DAlbumDrag::canDecode(e->mimeData()))
01012 {
01013 AlbumFolderViewItem *itemDrag = dynamic_cast<AlbumFolderViewItem*>(dragItem());
01014 if(!itemDrag)
01015 return;
01016
01017 if (AlbumSettings::instance()->getAlbumSortOrder() == AlbumSettings::ByFolder)
01018 {
01019 if (!itemDrop)
01020 return;
01021
01022
01023 KMenu popMenu(this);
01024 popMenu.addTitle(SmallIcon("digikam"), i18n("My Albums"));
01025 QAction *moveAction = popMenu.addAction(SmallIcon("go-jump"), i18n("&Move Here"));
01026 popMenu.addSeparator();
01027 popMenu.addAction(SmallIcon("dialog-cancel"), i18n("C&ancel"));
01028 popMenu.setMouseTracking(true);
01029 QAction *choice = popMenu.exec(QCursor::pos());
01030
01031 if(choice == moveAction)
01032 {
01033 PAlbum *album = itemDrag->album();
01034 PAlbum *destAlbum;
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047 {
01048
01049 destAlbum = itemDrop->album();
01050 }
01051 KIO::Job* job = DIO::move(album, destAlbum);
01052 connect(job, SIGNAL(result(KJob*)),
01053 this, SLOT(slotDIOResult(KJob*)));
01054 }
01055 }
01056 else if (AlbumSettings::instance()->getAlbumSortOrder() == AlbumSettings::ByCategory)
01057 {
01058 if (!itemDrop)
01059 return;
01060
01061 if (itemDrop->isGroupItem())
01062 {
01063 PAlbum *album = itemDrag->album();
01064 if (!album)
01065 return;
01066
01067 album->setCategory(itemDrop->text(0));
01068 resort();
01069 }
01070 }
01071
01072 return;
01073 }
01074
01075 if (DItemDrag::canDecode(e->mimeData()))
01076 {
01077 if (!itemDrop)
01078 return;
01079
01080 PAlbum *destAlbum = itemDrop->album();
01081
01082 KUrl::List urls;
01083 KUrl::List kioURLs;
01084 QList<int> albumIDs;
01085 QList<int> imageIDs;
01086
01087 if (!DItemDrag::decode(e->mimeData(), urls, kioURLs, albumIDs, imageIDs))
01088 return;
01089
01090 if (urls.isEmpty() || kioURLs.isEmpty() || albumIDs.isEmpty() || imageIDs.isEmpty())
01091 return;
01092
01093
01094
01095 KUrl::List extUrls;
01096 ImageInfoList extImgInfList;
01097 QList<qlonglong> extImageIDs;
01098 for (QList<int>::const_iterator it = imageIDs.constBegin(); it != imageIDs.constEnd(); ++it)
01099 {
01100 ImageInfo info(*it);
01101 if (info.albumId() != destAlbum->id())
01102 {
01103 extUrls.append(info.databaseUrl());
01104 extImgInfList.append(info);
01105 extImageIDs << *it;
01106 }
01107 }
01108
01109 if(extUrls.isEmpty())
01110 {
01111
01112
01113
01114 bool set = false;
01115 if (e->keyboardModifiers() == Qt::ControlModifier)
01116 {
01117 set = true;
01118 }
01119 else
01120 {
01121 KMenu popMenu(this);
01122 popMenu.addTitle(SmallIcon("digikam"), i18n("My Albums"));
01123 QAction *setAction = 0;
01124 if (imageIDs.count() == 1)
01125 setAction = popMenu.addAction(i18n("Set as Album Thumbnail"));
01126 popMenu.addSeparator();
01127 popMenu.addAction(SmallIcon("dialog-cancel"), i18n("C&ancel"));
01128 popMenu.setMouseTracking(true);
01129 QAction *choice = popMenu.exec(QCursor::pos());
01130 set = (setAction == choice);
01131 }
01132
01133 if(set)
01134 {
01135 QString errMsg;
01136 d->albumMan->updatePAlbumIcon(destAlbum, imageIDs.first(), errMsg);
01137 }
01138 return;
01139 }
01140
01141
01142
01143 bool move = false, copy = false, setThumbnail = false;
01144 if (e->keyboardModifiers() == Qt::ShiftModifier)
01145 {
01146 move = true;
01147 }
01148
01149
01150 else if (e->keyboardModifiers() == Qt::ControlModifier)
01151 {
01152 copy = true;
01153 }
01154 else
01155 {
01156 KMenu popMenu(this);
01157 popMenu.addTitle(SmallIcon("digikam"), i18n("My Albums"));
01158 QAction *moveAction = popMenu.addAction(SmallIcon("go-jump"), i18n("&Move Here"));
01159 QAction *copyAction = popMenu.addAction(SmallIcon("edit-copy"), i18n("&Copy Here"));
01160 QAction *thumbnailAction = 0;
01161 if (imageIDs.count() == 1)
01162 thumbnailAction = popMenu.addAction(i18n("Set as Album Thumbnail"));
01163 popMenu.addSeparator();
01164 popMenu.addAction(SmallIcon("dialog-cancel"), i18n("C&ancel"));
01165 popMenu.setMouseTracking(true);
01166 QAction *choice = popMenu.exec(QCursor::pos());
01167 if (choice)
01168 {
01169 if (choice == moveAction)
01170 move = true;
01171 else if (choice == copyAction)
01172 copy = true;
01173 else if (choice == thumbnailAction)
01174 setThumbnail = true;
01175 }
01176 }
01177
01178 if (move)
01179 {
01180 KIO::Job* job = DIO::move(extUrls, extImageIDs, destAlbum);
01181 connect(job, SIGNAL(result(KJob*)),
01182 this, SLOT(slotDIOResult(KJob*)));
01183
01184
01185
01186 for (ImageInfoListIterator it = extImgInfList.begin(); it != extImgInfList.end(); ++it)
01187 {
01188 AlbumLister::instance()->invalidateItem(*it);
01189 }
01190 }
01191 else if (copy)
01192 {
01193 KIO::Job* job = DIO::copy(extUrls, extImageIDs, destAlbum);
01194 connect(job, SIGNAL(result(KJob*)),
01195 this, SLOT(slotDIOResult(KJob*)));
01196 }
01197 else if (setThumbnail)
01198 {
01199 QString errMsg;
01200 d->albumMan->updatePAlbumIcon(destAlbum, imageIDs.first(), errMsg);
01201 }
01202
01203 return;
01204 }
01205
01206
01207
01208 if(DCameraItemListDrag::canDecode(e->mimeData()))
01209 {
01210 Album *album = dynamic_cast<Album*>(itemDrop->album());
01211 if (!album) return;
01212
01213 CameraUI *ui = dynamic_cast<CameraUI*>(e->source());
01214 if (ui)
01215 {
01216 KMenu popMenu(this);
01217 popMenu.addTitle(SmallIcon("digikam"), i18n("My Albums"));
01218 QAction *downAction = popMenu.addAction(SmallIcon("file-export"),
01219 i18n("Download From Camera"));
01220 QAction *downDelAction = popMenu.addAction(SmallIcon("file-export"),
01221 i18n("Download && Delete From Camera"));
01222 popMenu.addSeparator();
01223 popMenu.addAction(SmallIcon("dialog-cancel"), i18n("C&ancel"));
01224 popMenu.setMouseTracking(true);
01225 QAction *choice = popMenu.exec(QCursor::pos());
01226 if (choice)
01227 {
01228 if (choice == downAction)
01229 ui->slotDownload(true, false, album);
01230 else if (choice == downDelAction)
01231 ui->slotDownload(true, true, album);
01232 }
01233 }
01234 }
01235
01236
01237
01238 if(KUrl::List::canDecode(e->mimeData()))
01239 {
01240 PAlbum* destAlbum = 0;
01241
01242 if (itemDrop)
01243 destAlbum = itemDrop->album();
01244 else
01245 destAlbum = d->albumMan->findPAlbum(0);
01246
01247
01248 if (destAlbum->isRoot())
01249 return;
01250
01251 KUrl destURL(destAlbum->databaseUrl());
01252
01253 KUrl::List srcURLs = KUrl::List::fromMimeData(e->mimeData());
01254
01255 bool move = false, copy = false;
01256
01257
01258 if (e->keyboardModifiers() == Qt::ShiftModifier)
01259 {
01260 move = true;
01261 }
01262
01263
01264 else if (e->keyboardModifiers() == Qt::ControlModifier)
01265 {
01266 copy = true;
01267 }
01268 else
01269 {
01270 KMenu popMenu(this);
01271 popMenu.addTitle(SmallIcon("digikam"), i18n("My Albums"));
01272 QAction *moveAction = popMenu.addAction( SmallIcon("go-jump"), i18n("&Move Here"));
01273 QAction *copyAction = popMenu.addAction( SmallIcon("edit-copy"), i18n("&Copy Here"));
01274 popMenu.addSeparator();
01275 popMenu.addAction( SmallIcon("dialog-cancel"), i18n("C&ancel") );
01276 popMenu.setMouseTracking(true);
01277 QAction *choice = popMenu.exec(QCursor::pos());
01278 if (choice == copyAction)
01279 copy = true;
01280 else if (choice == moveAction)
01281 move = true;
01282 }
01283
01284 if (move)
01285 {
01286 KIO::Job* job = DIO::move(srcURLs, destAlbum);
01287 connect(job, SIGNAL(result(KJob*)),
01288 this, SLOT(slotDIOResult(KJob*)));
01289 }
01290 else if (copy)
01291 {
01292 KIO::Job* job = DIO::copy(srcURLs, destAlbum);
01293 connect(job, SIGNAL(result(KJob*)),
01294 this, SLOT(slotDIOResult(KJob*)));
01295 }
01296
01297 return;
01298 }
01299 }
01300
01301 void AlbumFolderView::selectItem(int id)
01302 {
01303 PAlbum* album = d->albumMan->findPAlbum(id);
01304 if(!album)
01305 return;
01306
01307 AlbumFolderViewItem *item = (AlbumFolderViewItem*)album->extraData(this);
01308 if(item)
01309 {
01310 setSelected(item, true);
01311 ensureItemVisible(item);
01312 }
01313 }
01314
01315 AlbumFolderViewItem* AlbumFolderView::findParent(PAlbum* album, bool& failed)
01316 {
01317 if (album->isRoot())
01318 {
01319 failed = false;
01320 return 0;
01321 }
01322
01323 switch(AlbumSettings::instance()->getAlbumSortOrder())
01324 {
01325 case(AlbumSettings::ByFolder):
01326 {
01327 return findParentByFolder(album, failed);
01328 }
01329 case(AlbumSettings::ByCategory):
01330 {
01331 return findParentByCategory(album, failed);
01332 }
01333 case(AlbumSettings::ByDate):
01334 {
01335 return findParentByDate(album, failed);
01336 }
01337 }
01338
01339 failed = true;
01340 return 0;
01341 }
01342
01343 AlbumFolderViewItem* AlbumFolderView::findParentByFolder(PAlbum* album, bool& failed)
01344 {
01345 AlbumFolderViewItem* parent = 0;
01346 if (album->parent())
01347 parent = static_cast<AlbumFolderViewItem*>(album->parent()->extraData(this));
01348
01349 if (!parent)
01350 {
01351 failed = true;
01352 return 0;
01353 }
01354
01355 if (album->parent()->isRoot())
01356 {
01357 QStringList albumRoots = CollectionManager::instance()->allAvailableAlbumRootPaths();
01358 if (albumRoots.count() > 1)
01359 {
01360 for (QList<AlbumFolderViewItem*>::const_iterator it = d->groupItems.constBegin();
01361 it != d->groupItems.constEnd(); ++it)
01362 {
01363 AlbumFolderViewItem* groupItem = *it;
01364 if (groupItem->text(0) == album->albumRootPath())
01365 {
01366 parent = groupItem;
01367 break;
01368 }
01369 }
01370
01371
01372 if (!parent)
01373 {
01374 parent = new AlbumFolderViewItem(firstChild(), album->albumRootPath(), 0, 0);
01375 d->groupItems.append(parent);
01376 }
01377 }
01378 }
01379
01380 failed = false;
01381 return parent;
01382 }
01383
01384 AlbumFolderViewItem* AlbumFolderView::findParentByCategory(PAlbum* album, bool& failed)
01385 {
01386 QStringList categoryList = AlbumSettings::instance()->getAlbumCategoryNames();
01387 QString category = album->category();
01388
01389 if (category.isEmpty() || !categoryList.contains(category))
01390 category = i18n("Uncategorized Albums");
01391
01392 AlbumFolderViewItem* parent = 0;
01393
01394 for (QList<AlbumFolderViewItem*>::const_iterator it = d->groupItems.constBegin();
01395 it != d->groupItems.constEnd(); ++it)
01396 {
01397 AlbumFolderViewItem* groupItem = *it;
01398 if (groupItem->text(0) == category)
01399 {
01400 parent = groupItem;
01401 break;
01402 }
01403 }
01404
01405
01406 if (!parent)
01407 {
01408 parent = new AlbumFolderViewItem(firstChild(), category, 0, 0);
01409 d->groupItems.append(parent);
01410 }
01411
01412 failed = false;
01413 return parent;
01414 }
01415
01416 AlbumFolderViewItem* AlbumFolderView::findParentByDate(PAlbum* album, bool& failed)
01417 {
01418 QDate date = album->date();
01419
01420 QString timeString = QString::number(date.year()) + ", " +
01421 KGlobal::locale()->calendar()->monthName(date, KCalendarSystem::LongName);
01422
01423 AlbumFolderViewItem* parent = 0;
01424
01425 for (QList<AlbumFolderViewItem*>::const_iterator it = d->groupItems.constBegin();
01426 it != d->groupItems.constEnd(); ++it)
01427 {
01428 AlbumFolderViewItem* groupItem = *it;
01429 if (groupItem->text(0) == timeString)
01430 {
01431 parent = groupItem;
01432 break;
01433 }
01434 }
01435
01436
01437 if (!parent)
01438 {
01439 parent = new AlbumFolderViewItem(firstChild(), timeString,
01440 date.year(), date.month());
01441 d->groupItems.append(parent);
01442 }
01443
01444 failed = false;
01445 return parent;
01446 }
01447
01448 void AlbumFolderView::resort()
01449 {
01450 AlbumFolderViewItem* prevSelectedItem = dynamic_cast<AlbumFolderViewItem*>(selectedItem());
01451 if (prevSelectedItem && prevSelectedItem->isGroupItem())
01452 prevSelectedItem = 0;
01453
01454 AlbumList pList(d->albumMan->allPAlbums());
01455 for (AlbumList::const_iterator it = pList.constBegin(); it != pList.constEnd(); ++it)
01456 {
01457 PAlbum *album = (PAlbum*)(*it);
01458 if (!album->isRoot() && album->extraData(this))
01459 {
01460 reparentItem(static_cast<AlbumFolderViewItem*>(album->extraData(this)));
01461 }
01462 }
01463
01464
01465 clearEmptyGroupItems();
01466
01467 if (prevSelectedItem)
01468 {
01469 ensureItemVisible(prevSelectedItem);
01470 setSelected(prevSelectedItem, true);
01471 }
01472 }
01473
01474 void AlbumFolderView::reparentItem(AlbumFolderViewItem* folderItem)
01475 {
01476 if (!folderItem)
01477 return;
01478
01479 PAlbum* album = folderItem->album();
01480 if (!album || album->isRoot())
01481 return;
01482
01483 AlbumFolderViewItem* oldParent = dynamic_cast<AlbumFolderViewItem*>(folderItem->parent());
01484
01485 bool failed;
01486 AlbumFolderViewItem* newParent = findParent(album, failed);
01487 if (failed)
01488 return;
01489
01490 if (oldParent == newParent)
01491 return;
01492
01493 if (oldParent)
01494 oldParent->removeItem(folderItem);
01495 else
01496 removeItem(folderItem);
01497
01498
01499 if (newParent)
01500 newParent->insertItem(folderItem);
01501 else
01502 insertItem(folderItem);
01503 }
01504
01505 void AlbumFolderView::clearEmptyGroupItems()
01506 {
01507 QList<AlbumFolderViewItem*> deleteItems;
01508
01509 for (QList<AlbumFolderViewItem*>::iterator it = d->groupItems.begin(); it != d->groupItems.end();)
01510 {
01511 AlbumFolderViewItem* groupItem = *it;
01512
01513 if (!groupItem->firstChild())
01514 {
01515 it = d->groupItems.erase(it);
01516 delete groupItem;
01517 }
01518 else
01519 ++it;
01520 }
01521 }
01522
01523 void AlbumFolderView::refresh()
01524 {
01525 Q3ListViewItemIterator it(this);
01526
01527 while (it.current())
01528 {
01529 AlbumFolderViewItem* item = dynamic_cast<AlbumFolderViewItem*>(*it);
01530 if (item)
01531 item->refresh();
01532 ++it;
01533 }
01534 }
01535
01536 void AlbumFolderView::slotRefresh(const QMap<int, int>& albumsStatMap)
01537 {
01538 Q3ListViewItemIterator it(this);
01539
01540 while (it.current())
01541 {
01542 AlbumFolderViewItem* item = dynamic_cast<AlbumFolderViewItem*>(*it);
01543 if (item)
01544 {
01545 if (item->album())
01546 {
01547 int id = item->id();
01548 QMap<int, int>::const_iterator it2 = albumsStatMap.constFind(id);
01549 if ( it2 != albumsStatMap.constEnd() )
01550 item->setCount(it2.value());
01551 }
01552 }
01553 ++it;
01554 }
01555
01556 refresh();
01557 }
01558
01559 }