• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

digikam

albumfolderview.cpp

Go to the documentation of this file.
00001 /* ============================================================
00002  *
00003  * This file is a part of digiKam project
00004  * http://www.digikam.org
00005  *
00006  * Date        : 2005-05-06
00007  * Description : Albums folder view.
00008  *
00009  * Copyright (C) 2005-2006 by Joern Ahrens <joern.ahrens@kdemail.net>
00010  * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
00011  *
00012  * This program is free software; you can redistribute it
00013  * and/or modify it under the terms of the GNU General
00014  * Public License as published by the Free Software Foundation;
00015  * either version 2, or (at your option)
00016  * any later version.
00017  *
00018  * This program is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * ============================================================ */
00024 
00025 // Qt includes.
00026 
00027 #include <QList>
00028 #include <QList>
00029 #include <QPixmap>
00030 #include <QPointer>
00031 #include <QDir>
00032 #include <QDropEvent>
00033 #include <QCursor>
00034 #include <QDataStream>
00035 #include <QDateTime>
00036 
00037 // KDE includes.
00038 
00039 #include <kdebug.h>
00040 #include <kmenu.h>
00041 #include <klocale.h>
00042 #include <kglobal.h>
00043 #include <kcalendarsystem.h>
00044 #include <kiconloader.h>
00045 #include <kapplication.h>
00046 #include <kmessagebox.h>
00047 #include <kaction.h>
00048 #include <kfiledialog.h>
00049 #include <kdeversion.h>
00050 #include <kinputdialog.h>
00051 #include <kio/job.h>
00052 #include <kio/jobuidelegate.h>
00053 
00054 // Local includes.
00055 
00056 #include "albumlister.h"
00057 #include "albumpropsedit.h"
00058 #include "album.h"
00059 #include "albumdb.h"
00060 #include "albummanager.h"
00061 #include "albumsettings.h"
00062 #include "albumthumbnailloader.h"
00063 #include "cameraui.h"
00064 #include "collectionmanager.h"
00065 #include "deletedialog.h"
00066 #include "digikamapp.h"
00067 #include "dio.h"
00068 #include "ddragobjects.h"
00069 #include "folderitem.h"
00070 #include "thumbnailsize.h"
00071 #include "albumfolderview.h"
00072 #include "albumfolderview.moc"
00073 
00074 namespace Digikam
00075 {
00076 
00077 class AlbumFolderViewItem : public FolderItem
00078 {
00079 public:
00080 
00081     AlbumFolderViewItem(Q3ListView *parent, PAlbum *album);
00082     AlbumFolderViewItem(Q3ListViewItem *parent, PAlbum *album);
00083 
00084     // special group item (collection/dates)
00085     AlbumFolderViewItem(Q3ListViewItem* parent, const QString& name,
00086                         int year, int month);
00087 
00088     PAlbum* album() const;
00089     int     id() const;
00090     bool    isGroupItem() const;
00091     int     compare(Q3ListViewItem *i, int col, bool ascending) const;
00092     void    refresh();
00093     void    setOpen(bool o);
00094     void    setCount(int count);
00095     int     count();
00096 
00097 private:
00098 
00099     bool    m_groupItem;
00100 
00101     int     m_year;
00102     int     m_month;
00103     int     m_count;
00104 
00105     PAlbum *m_album;
00106 };
00107 
00108 AlbumFolderViewItem::AlbumFolderViewItem(Q3ListView *parent, PAlbum *album)
00109                    : FolderItem(parent, album->title())
00110 {
00111     setDragEnabled(true);
00112     m_album     = album;
00113     m_groupItem = false;
00114     m_count     = 0;
00115 }
00116 
00117 AlbumFolderViewItem::AlbumFolderViewItem(Q3ListViewItem *parent, PAlbum *album)
00118                    : FolderItem(parent, album->title())
00119 {
00120     setDragEnabled(true);
00121     m_album     = album;
00122     m_groupItem = false;
00123     m_count     = 0;
00124  }
00125 
00126 // special group item (collection/dates)
00127 AlbumFolderViewItem::AlbumFolderViewItem(Q3ListViewItem* parent, const QString& name,
00128                                          int year, int month)
00129                    : FolderItem(parent, name, true)
00130 {
00131     setDragEnabled(false);
00132     m_album     = 0;
00133     m_year      = year;
00134     m_month     = month;
00135     m_groupItem = true;
00136     m_count     = 0;
00137 }
00138 
00139 void AlbumFolderViewItem::refresh()
00140 {
00141     if (!m_album) return;
00142 
00143     if (AlbumSettings::instance()->getShowFolderTreeViewItemsCount() &&
00144         dynamic_cast<AlbumFolderViewItem*>(parent()))
00145     {
00146         if (isOpen())
00147             setText(0, QString("%1 (%2)").arg(m_album->title()).arg(m_count));
00148         else
00149         {
00150             int countRecursive = m_count;
00151             AlbumIterator it(m_album);
00152             while ( it.current() )
00153             {
00154                 AlbumFolderViewItem *item = (AlbumFolderViewItem*)it.current()->extraData(listView());
00155                 if (item)
00156                     countRecursive += item->count();
00157                 ++it;
00158             }
00159             setText(0, QString("%1 (%2)").arg(m_album->title()).arg(countRecursive));
00160         }
00161     }
00162     else
00163     {
00164         setText(0, m_album->title());
00165     }
00166 }
00167 
00168 void AlbumFolderViewItem::setOpen(bool o)
00169 {
00170     Q3ListViewItem::setOpen(o);
00171     refresh();
00172 }
00173 
00174 PAlbum* AlbumFolderViewItem::album() const
00175 {
00176     return m_album;
00177 }
00178 
00179 int AlbumFolderViewItem::id() const
00180 {
00181     if (m_groupItem)
00182     {
00183         if (m_year != 0 && m_month != 0)
00184         {
00185             return (m_year*(-100) + m_month*(-1));
00186         }
00187         else
00188         {
00189             return ( - (AlbumSettings::instance()->getAlbumCollectionNames()
00190                         .indexOf(text(0)) ) );
00191         }
00192     }
00193     else
00194     {
00195         return m_album ? m_album->id() : 0;
00196     }
00197 }
00198 
00199 bool AlbumFolderViewItem::isGroupItem() const
00200 {
00201     return m_groupItem;
00202 }
00203 
00204 int AlbumFolderViewItem::compare(Q3ListViewItem *i, int col, bool ascending) const
00205 {
00206     if (!m_groupItem || m_year == 0 || m_month == 0)
00207         return Q3ListViewItem::compare(i, col, ascending);
00208 
00209     AlbumFolderViewItem* thatItem = dynamic_cast<AlbumFolderViewItem*>(i);
00210     if (!thatItem)
00211         return 0;
00212 
00213     int myWeight  = m_year*100 + m_month;
00214     int hisWeight = thatItem->m_year*100 + thatItem->m_month;
00215 
00216     if (myWeight == hisWeight)
00217         return 0;
00218     else if (myWeight > hisWeight)
00219         return 1;
00220     else
00221         return -1;
00222 }
00223 
00224 void AlbumFolderViewItem::setCount(int count)
00225 {
00226     m_count = count;
00227     refresh();
00228 }
00229 
00230 int AlbumFolderViewItem::count()
00231 {
00232     return m_count;
00233 }
00234 
00235 // -----------------------------------------------------------------------------
00236 
00237 class AlbumFolderViewPriv
00238 {
00239 public:
00240 
00241     AlbumFolderViewPriv()
00242     {
00243         albumMan = 0;
00244     }
00245 
00246     AlbumManager                *albumMan;
00247     QList<AlbumFolderViewItem*>  groupItems;
00248 };
00249 
00250 AlbumFolderView::AlbumFolderView(QWidget *parent)
00251                : FolderView(parent, "AlbumFolderView")
00252 {
00253     d = new AlbumFolderViewPriv();
00254     d->albumMan = AlbumManager::instance();
00255 
00256     addColumn(i18n("My Albums"));
00257     setResizeMode(Q3ListView::LastColumn);
00258     setRootIsDecorated(false);
00259     setAllColumnsShowFocus(true);
00260 
00261     setAcceptDrops(true);
00262     viewport()->setAcceptDrops(true);
00263 
00264     connect(d->albumMan, SIGNAL(signalAlbumAdded(Album*)),
00265             this, SLOT(slotAlbumAdded(Album*)));
00266 
00267     connect(d->albumMan, SIGNAL(signalAlbumDeleted(Album*)),
00268             this, SLOT(slotAlbumDeleted(Album*)));
00269 
00270     connect(d->albumMan, SIGNAL(signalAlbumsCleared()),
00271             this, SLOT(slotAlbumsCleared()));
00272 
00273     connect(d->albumMan, SIGNAL(signalAlbumIconChanged(Album*)),
00274             this, SLOT(slotAlbumIconChanged(Album*)));
00275 
00276     connect(d->albumMan, SIGNAL(signalAlbumRenamed(Album*)),
00277             this, SLOT(slotAlbumRenamed(Album*)));
00278 
00279     connect(d->albumMan, SIGNAL(signalPAlbumsDirty(const QMap<int, int>&)),
00280             this, SLOT(slotRefresh(const QMap<int, int>&)));
00281 
00282     AlbumThumbnailLoader *loader = AlbumThumbnailLoader::instance();
00283 
00284     connect(loader, SIGNAL(signalThumbnail(Album *, const QPixmap&)),
00285             this, SLOT(slotGotThumbnailFromIcon(Album *, const QPixmap&)));
00286 
00287     connect(loader, SIGNAL(signalFailed(Album *)),
00288             this, SLOT(slotThumbnailLost(Album *)));
00289 
00290     connect(loader, SIGNAL(signalReloadThumbnails()),
00291             this, SLOT(slotReloadThumbnails()));
00292 
00293     connect(this, SIGNAL(contextMenuRequested(Q3ListViewItem*, const QPoint&, int)),
00294             this, SLOT(slotContextMenu(Q3ListViewItem*, const QPoint&, int)));
00295 
00296     connect(this, SIGNAL(selectionChanged()),
00297             this, SLOT(slotSelectionChanged()));
00298 }
00299 
00300 AlbumFolderView::~AlbumFolderView()
00301 {
00302     delete d;
00303 }
00304 
00305 void AlbumFolderView::slotTextFolderFilterChanged(const QString& filter)
00306 {
00307     QString search = filter.toLower();
00308 
00309     bool atleastOneMatch = false;
00310 
00311     AlbumList pList = d->albumMan->allPAlbums();
00312     for (AlbumList::iterator it = pList.begin(); it != pList.end(); ++it)
00313     {
00314         PAlbum* palbum  = (PAlbum*)(*it);
00315 
00316         // don't touch the root Album
00317         if (palbum->isRoot())
00318             continue;
00319 
00320         bool match = palbum->title().toLower().contains(search);
00321         if (!match)
00322         {
00323             // check if any of the parents match the search
00324             Album* parent = palbum->parent();
00325             while (parent && !parent->isRoot())
00326             {
00327                 if (parent->title().toLower().contains(search))
00328                 {
00329                     match = true;
00330                     break;
00331                 }
00332 
00333                 parent = parent->parent();
00334             }
00335         }
00336 
00337         if (!match)
00338         {
00339             // check if any of the children match the search
00340             AlbumIterator it(palbum);
00341             while (it.current())
00342             {
00343                 if ((*it)->title().toLower().contains(search))
00344                 {
00345                     match = true;
00346                     break;
00347                 }
00348                 ++it;
00349             }
00350         }
00351 
00352         AlbumFolderViewItem* viewItem = (AlbumFolderViewItem*) palbum->extraData(this);
00353 
00354         if (match)
00355         {
00356             atleastOneMatch = true;
00357 
00358             if (viewItem)
00359                 viewItem->setVisible(true);
00360         }
00361         else
00362         {
00363             if (viewItem)
00364             {
00365                 viewItem->setVisible(false);
00366             }
00367         }
00368     }
00369 
00370     emit signalTextFolderFilterMatch(atleastOneMatch);
00371 }
00372 
00373 void AlbumFolderView::slotAlbumAdded(Album *album)
00374 {
00375     if(!album)
00376         return;
00377 
00378     PAlbum *palbum = dynamic_cast<PAlbum*>(album);
00379     if(!palbum)
00380         return;
00381 
00382     bool failed;
00383     AlbumFolderViewItem* parent = findParent(palbum, failed);
00384     if (failed)
00385     {
00386         kWarning(50003) << " Failed to find Album parent "
00387                         << palbum->albumPath() << endl;
00388         return;
00389     }
00390 
00391     AlbumFolderViewItem *item;
00392     if (!parent)
00393     {
00394         // root album
00395         item = new AlbumFolderViewItem(this, palbum);
00396         palbum->setExtraData(this, item);
00397         item->setOpen(true);
00398     }
00399     else
00400     {
00401         item = new AlbumFolderViewItem(parent, palbum);
00402         palbum->setExtraData(this, item);
00403     }
00404 
00405     setAlbumThumbnail(palbum);
00406 }
00407 
00408 void AlbumFolderView::slotAlbumDeleted(Album *album)
00409 {
00410     if(!album)
00411         return;
00412 
00413     PAlbum* palbum = dynamic_cast<PAlbum*>(album);
00414     if(!palbum)
00415         return;
00416 
00417     AlbumFolderViewItem* item = (AlbumFolderViewItem*) palbum->extraData(this);
00418     if(item)
00419     {
00420         AlbumFolderViewItem *itemParent = dynamic_cast<AlbumFolderViewItem*>(item->parent());
00421 
00422         if(itemParent)
00423             itemParent->takeItem(item);
00424         else
00425             takeItem(item);
00426 
00427         delete item;
00428         clearEmptyGroupItems();
00429     }
00430 }
00431 
00432 void AlbumFolderView::slotAlbumRenamed(Album *album)
00433 {
00434     PAlbum* palbum = dynamic_cast<PAlbum*>(album);
00435     if(!palbum)
00436         return;
00437 
00438     AlbumFolderViewItem* item = (AlbumFolderViewItem*) palbum->extraData(this);
00439     if(item)
00440         item->refresh();
00441 }
00442 
00443 void AlbumFolderView::slotAlbumsCleared()
00444 {
00445     d->groupItems.clear();
00446     clear();
00447 }
00448 
00449 void AlbumFolderView::setAlbumThumbnail(PAlbum *album)
00450 {
00451     if(!album)
00452         return;
00453 
00454     AlbumFolderViewItem* item = (AlbumFolderViewItem*) album->extraData(this);
00455 
00456     if(!item)
00457         return;
00458 
00459     // Either, getThumbnail returns true and loads an icon asynchronously.
00460     // Then, for the time being, we set the standard icon.
00461     // Or, no icon is associated with the album, then we set the standard icon anyway.
00462     AlbumThumbnailLoader *loader = AlbumThumbnailLoader::instance();
00463     item->setPixmap(0, loader->getStandardAlbumIcon(album));
00464     loader->getAlbumThumbnail(album);
00465 }
00466 
00467 void AlbumFolderView::setCurrentAlbum(Album *album)
00468 {
00469     if(!album) return;
00470 
00471     AlbumFolderViewItem* item = (AlbumFolderViewItem*) album->extraData(this);
00472     if(!item) return;
00473 
00474     setCurrentItem(item);
00475     ensureItemVisible(item);
00476 }
00477 
00478 void AlbumFolderView::slotGotThumbnailFromIcon(Album *album,
00479                                                const QPixmap& thumbnail)
00480 {
00481     if(!album || album->type() != Album::PHYSICAL)
00482         return;
00483 
00484     AlbumFolderViewItem* item = (AlbumFolderViewItem*)album->extraData(this);
00485 
00486     if(!item)
00487         return;
00488 
00489     item->setPixmap(0, thumbnail);
00490 }
00491 
00492 void AlbumFolderView::slotThumbnailLost(Album *)
00493 {
00494     // we already set the standard icon before loading
00495 }
00496 
00497 void AlbumFolderView::slotReloadThumbnails()
00498 {
00499     AlbumList tList = d->albumMan->allPAlbums();
00500     for (AlbumList::iterator it = tList.begin(); it != tList.end(); ++it)
00501     {
00502         PAlbum* album  = (PAlbum*)(*it);
00503         setAlbumThumbnail(album);
00504     }
00505 }
00506 
00507 void AlbumFolderView::slotAlbumIconChanged(Album* album)
00508 {
00509     if(!album || album->type() != Album::PHYSICAL)
00510         return;
00511 
00512     setAlbumThumbnail((PAlbum*)album);
00513 }
00514 
00515 void AlbumFolderView::slotSelectionChanged()
00516 {
00517     if(!active())
00518         return;
00519 
00520     Q3ListViewItem* selItem = 0;
00521     Q3ListViewItemIterator it(this);
00522     while(it.current())
00523     {
00524         if(it.current()->isSelected())
00525         {
00526             selItem = it.current();
00527             break;
00528         }
00529         ++it;
00530     }
00531 
00532     if(!selItem)
00533     {
00534         d->albumMan->setCurrentAlbum(0);
00535         return;
00536     }
00537 
00538     AlbumFolderViewItem *albumitem = dynamic_cast<AlbumFolderViewItem*>(selItem);
00539     if(!albumitem)
00540     {
00541         d->albumMan->setCurrentAlbum(0);
00542         return;
00543     }
00544 
00545     d->albumMan->setCurrentAlbum(albumitem->album());
00546 }
00547 
00548 void AlbumFolderView::slotContextMenu(Q3ListViewItem *listitem, const QPoint &, int)
00549 {
00550     QMenu menuImport(i18n("Import"));
00551     QMenu menuExport(i18n("Export"));
00552     QMenu menuKIPIBatch(i18n("Batch Process"));
00553 
00554     KMenu popmenu(this);
00555     popmenu.addTitle(SmallIcon("digikam"), i18n("My Albums"));
00556     QAction *newAction = popmenu.addAction(SmallIcon("albumfolder-new"), i18n("New Album..."));
00557 
00558     AlbumFolderViewItem *item = dynamic_cast<AlbumFolderViewItem*>(listitem);
00559     if (item && !item->album())
00560     {
00561         // if collection/date return
00562         return;
00563     }
00564 
00565     // Root folder only shows "New Album..."
00566     QAction *renameAction = 0, *propertiesAction = 0, *resetIconAction = 0, *deleteAction = 0;
00567     if(item && item->parent())
00568     {
00569         renameAction     = popmenu.addAction(SmallIcon("edit-rename"), i18n("Rename..."));
00570         propertiesAction = popmenu.addAction(SmallIcon("albumfolder-properties"), i18n("Album Properties..."));
00571         resetIconAction  = popmenu.addAction(SmallIcon("view-refresh"), i18n("Reset Album Icon"));
00572         popmenu.addSeparator();
00573 
00574         // Add KIPI Albums plugins Actions
00575         const QList<QAction*>& albumActions = DigikamApp::getinstance()->menuAlbumActions();
00576         if(!albumActions.isEmpty())
00577         {
00578             foreach(QAction *action, albumActions)
00579             {
00580                 popmenu.addAction(action);
00581             }
00582         }
00583 
00584         // Add All Export Actions
00585         const QList<QAction*> exportActions = DigikamApp::getinstance()->menuExportActions();
00586         if(!exportActions.isEmpty())
00587         {
00588             foreach(QAction *action, exportActions)
00589             {
00590                 menuExport.addAction(action);
00591             }
00592             popmenu.addMenu(&menuExport);
00593         }
00594 
00595         // Add KIPI Batch processes plugins Actions
00596         const QList<QAction*>& batchActions = DigikamApp::getinstance()->menuBatchActions();
00597         if(!batchActions.isEmpty())
00598         {
00599             foreach(QAction *action, batchActions)
00600             {
00601                 menuKIPIBatch.addAction(action);
00602             }
00603             popmenu.addMenu(&menuKIPIBatch);
00604         }
00605 
00606         if(!albumActions.isEmpty() || !batchActions.isEmpty())
00607         {
00608             popmenu.addSeparator();
00609         }
00610 
00611         if(AlbumSettings::instance()->getUseTrash())
00612         {
00613             deleteAction = popmenu.addAction(SmallIcon("user-trash"), i18n("Move Album to Trash"));
00614         }
00615         else
00616         {
00617             deleteAction = popmenu.addAction(SmallIcon("editshred"), i18n("Delete Album"));
00618         }
00619     }
00620 
00621     QAction *choice = popmenu.exec(QCursor::pos());
00622     if (choice)
00623     {
00624         if (choice == newAction)
00625         {
00626             albumNew(item);
00627         }
00628         else if (choice == propertiesAction)
00629         {
00630             albumEdit(item);
00631         }
00632         else if (choice == resetIconAction)
00633         {
00634             QString err;
00635             d->albumMan->updatePAlbumIcon(item->album(), 0, err);
00636         }
00637         else if (choice == renameAction)
00638         {
00639             albumRename(item);
00640         }
00641         else if (choice == deleteAction)
00642         {
00643             albumDelete(item);
00644         }
00645     }
00646 }
00647 
00648 void AlbumFolderView::albumNew()
00649 {
00650     AlbumFolderViewItem *item = dynamic_cast<AlbumFolderViewItem*>(selectedItem());
00651     if (!item)
00652     {
00653         item = dynamic_cast<AlbumFolderViewItem*>(firstChild());
00654     }
00655 
00656     if (!item)
00657         return;
00658 
00659     albumNew(item);
00660 }
00661 
00662 void AlbumFolderView::albumNew(AlbumFolderViewItem *item)
00663 {
00664     AlbumSettings* settings = AlbumSettings::instance();
00665     if(!settings)
00666     {
00667         kWarning(50003) << "AlbumFolderView: Could not get Album Settings" << endl;
00668         return;
00669     }
00670 
00671     /*
00672     QDir libraryDir(settings->getAlbumLibraryPath());
00673     if(!libraryDir.exists())
00674     {
00675         KMessageBox::error(0,
00676                            i18n("The album library has not been set correctly.\n"
00677                                 "Select \"Configure Digikam\" from the Settings "
00678                                 "menu and choose a folder to use for the album "
00679                                 "library."));
00680         return;
00681     }
00682     */
00683 
00684     PAlbum *parent;
00685 
00686     if(!item)
00687         parent = d->albumMan->findPAlbum(0);
00688     else
00689         parent = item->album();
00690 
00691     if (!parent)
00692         return;
00693 
00694     // if we create an album under root, need to supply the album root path.
00695     QString albumRootPath;
00696     if (parent->isRoot())
00697     {
00698         //TODO: Let user choose an album root
00699         albumRootPath = CollectionManager::instance()->oneAlbumRootPath();
00700     }
00701 
00702     QString     title;
00703     QString     comments;
00704     QString     collection;
00705     QDate       date;
00706     QStringList albumCollections;
00707 
00708     if(!AlbumPropsEdit::createNew(parent, title, comments, date, collection,
00709                                   albumCollections))
00710         return;
00711 
00712     QStringList oldAlbumCollections(AlbumSettings::instance()->getAlbumCollectionNames());
00713     if(albumCollections != oldAlbumCollections)
00714     {
00715         AlbumSettings::instance()->setAlbumCollectionNames(albumCollections);
00716         resort();
00717     }
00718 
00719     QString errMsg;
00720     PAlbum* album;
00721     if (parent->isRoot())
00722         album = d->albumMan->createPAlbum(albumRootPath, title, comments,
00723                                           date, collection, errMsg);
00724     else
00725         album = d->albumMan->createPAlbum(parent, title, comments,
00726                                           date, collection, errMsg);
00727 
00728     if (!album)
00729     {
00730         KMessageBox::error(0, errMsg);
00731         return;
00732     }
00733 
00734     // by this time the signalAlbumAdded has been fired and the appropriate
00735     // AlbumFolderViewItem has been created. Now make this folderviewitem visible
00736     AlbumFolderViewItem* newItem = (AlbumFolderViewItem*)album->extraData(this);
00737     if (newItem)
00738     {
00739         if(item)
00740             item->setOpen(true);
00741 
00742         ensureItemVisible(newItem);
00743         setSelected(newItem, true);
00744     }
00745 }
00746 
00747 void AlbumFolderView::albumDelete()
00748 {
00749     AlbumFolderViewItem *item = dynamic_cast<AlbumFolderViewItem*>(selectedItem());
00750     if(!item)
00751         return;
00752 
00753     albumDelete(item);
00754 }
00755 
00756 void AlbumFolderView::albumDelete(AlbumFolderViewItem *item)
00757 {
00758     PAlbum *album = item->album();
00759 
00760     if(!album || album->isRoot())
00761         return;
00762 
00763     // find subalbums
00764     KUrl::List childrenList;
00765     addAlbumChildrenToList(childrenList, album);
00766 
00767     DeleteDialog dialog(this);
00768 
00769     // All subalbums will be presented in the list as well
00770     if (!dialog.confirmDeleteList(childrenList,
00771                                   childrenList.size() == 1 ?
00772                                   DeleteDialogMode::Albums : DeleteDialogMode::Subalbums,
00773                                   DeleteDialogMode::UserPreference))
00774         return;
00775 
00776     bool useTrash = !dialog.shouldDelete();
00777 
00778     // Currently trash kioslave can handle only full paths.
00779     // pass full folder path to the trashing job
00780     //TODO: Use digikamalbums:// url?
00781     KUrl u;
00782     u.setProtocol("file");
00783     u.setPath(album->folderPath());
00784     KIO::Job* job = DIO::del(u, useTrash);
00785     connect(job, SIGNAL(result(KJob *)),
00786             this, SLOT(slotDIOResult(KJob *)));
00787 }
00788 
00789 void AlbumFolderView::addAlbumChildrenToList(KUrl::List &list, Album *album)
00790 {
00791     // simple recursive helper function
00792     if (album)
00793     {
00794         list.append(album->databaseUrl());
00795         AlbumIterator it(album);
00796         while(it.current())
00797         {
00798             addAlbumChildrenToList(list, *it);
00799             ++it;
00800         }
00801     }
00802 }
00803 
00804 void AlbumFolderView::slotDIOResult(KJob* kjob)
00805 {
00806     KIO::Job *job = static_cast<KIO::Job*>(kjob);
00807     if (job->error())
00808     {
00809         job->ui()->setWindow(this);
00810         job->ui()->showErrorMessage();
00811     }
00812 }
00813 
00814 void AlbumFolderView::albumRename()
00815 {
00816     AlbumFolderViewItem *item = dynamic_cast<AlbumFolderViewItem*>(selectedItem());
00817     if(!item)
00818         return;
00819 
00820     albumRename(item);
00821 }
00822 
00823 void AlbumFolderView::albumRename(AlbumFolderViewItem* item)
00824 {
00825     PAlbum *album = item->album();
00826 
00827     if (!album)
00828         return;
00829 
00830     QString oldTitle(album->title());
00831     bool    ok;
00832 
00833     QString title = KInputDialog::getText(i18n("Rename Album (%1)",oldTitle),
00834                                           i18n("Enter new album name:"),
00835                                           oldTitle, &ok, this);
00836     if (!ok)
00837         return;
00838 
00839     if(title != oldTitle)
00840     {
00841         QString errMsg;
00842         if (!d->albumMan->renamePAlbum(album, title, errMsg))
00843             KMessageBox::error(0, errMsg);
00844     }
00845 
00846     emit signalAlbumModified();
00847 }
00848 
00849 void AlbumFolderView::albumEdit()
00850 {
00851     AlbumFolderViewItem *item = dynamic_cast<AlbumFolderViewItem*>(selectedItem());
00852     if(!item)
00853         return;
00854 
00855     albumEdit(item);
00856 }
00857 
00858 void AlbumFolderView::albumEdit(AlbumFolderViewItem* item)
00859 {
00860     PAlbum *album = item->album();
00861 
00862     if (!album)
00863         return;
00864 
00865     QString     oldTitle(album->title());
00866     QString     oldComments(album->caption());
00867     QString     oldCollection(album->collection());
00868     QDate       oldDate(album->date());
00869     QStringList oldAlbumCollections(AlbumSettings::instance()->getAlbumCollectionNames());
00870 
00871     QString     title, comments, collection;
00872     QDate       date;
00873     QStringList albumCollections;
00874 
00875     if(AlbumPropsEdit::editProps(album, title, comments, date,
00876                                  collection, albumCollections))
00877     {
00878         if(comments != oldComments)
00879             album->setCaption(comments);
00880 
00881         if(date != oldDate && date.isValid())
00882             album->setDate(date);
00883 
00884         if(collection != oldCollection)
00885             album->setCollection(collection);
00886 
00887         AlbumSettings::instance()->setAlbumCollectionNames(albumCollections);
00888         resort();
00889 
00890         // Do this last : so that if anything else changed we can
00891         // successfuly save to the db with the old name
00892 
00893         if(title != oldTitle)
00894         {
00895             QString errMsg;
00896             if (!d->albumMan->renamePAlbum(album, title, errMsg))
00897                 KMessageBox::error(0, errMsg);
00898         }
00899 
00900         emit signalAlbumModified();
00901     }
00902 }
00903 
00904 QDrag* AlbumFolderView::makeDragObject()
00905 {
00906     AlbumFolderViewItem *item = dynamic_cast<AlbumFolderViewItem*>(dragItem());
00907     if(!item)
00908         return 0;
00909 
00910     PAlbum *album = item->album();
00911     if(album->isRoot())
00912         return 0;
00913 
00914     QDrag *drag = new QDrag(this);
00915     drag->setMimeData(new DAlbumDrag(album->databaseUrl(), album->id()));
00916     drag->setPixmap(*item->pixmap(0));
00917 
00918     return drag;
00919 }
00920 
00921 bool AlbumFolderView::acceptDrop(const QDropEvent *e) const
00922 {
00923     QPoint vp = contentsToViewport(e->pos());
00924     AlbumFolderViewItem *itemDrop = dynamic_cast<AlbumFolderViewItem*>(itemAt(vp));
00925     AlbumFolderViewItem *itemDrag = dynamic_cast<AlbumFolderViewItem*>(dragItem());
00926 
00927     if(DAlbumDrag::canDecode(e->mimeData()))
00928     {
00929         switch(AlbumSettings::instance()->getAlbumSortOrder())
00930         {
00931             case(AlbumSettings::ByFolder):
00932             {
00933                 // Allow dragging at the root, to move the album at the root
00934                 if(!itemDrop)
00935                     return true;
00936 
00937                 // Dragging an item on itself makes no sense
00938                 if(itemDrag == itemDrop)
00939                     return false;
00940 
00941                 // Dragging a parent on its child makes no sense
00942                 if(itemDrag && itemDrag->album()->isAncestorOf(itemDrop->album()))
00943                     return false;
00944 
00945                 return true;
00946             }
00947             case (AlbumSettings::ByCollection):
00948             {
00949                 if (!itemDrop)
00950                     return false;
00951 
00952                 // Only allow dragging onto Collection
00953                 if (itemDrop->isGroupItem())
00954                     return true;
00955 
00956                 return false;
00957             }
00958             default:
00959             {
00960                 return false;
00961             }
00962         }
00963     }
00964 
00965     if(itemDrop  && !itemDrop->parent())
00966     {
00967         // Do not allow drop images on album root
00968         return false;
00969     }
00970 
00971     if(itemDrop && itemDrop->isGroupItem())
00972     {
00973         // do not allow drop on a group item
00974         return false;
00975     }
00976 
00977     if(DItemDrag::canDecode(e->mimeData()))
00978     {
00979         return true;
00980     }
00981 
00982     if(DCameraItemListDrag::canDecode(e->mimeData()))
00983     {
00984         return true;
00985     }
00986 
00987     if(KUrl::List::canDecode(e->mimeData()))
00988     {
00989         return true;
00990     }
00991 
00992     return false;
00993 }
00994 
00995 void AlbumFolderView::contentsDropEvent(QDropEvent *e)
00996 {
00997     FolderView::contentsDropEvent(e);
00998 
00999     if(!acceptDrop(e))
01000         return;
01001 
01002     QPoint vp                     = contentsToViewport(e->pos());
01003     AlbumFolderViewItem *itemDrop = dynamic_cast<AlbumFolderViewItem*>(itemAt(vp));
01004 
01005     if(DAlbumDrag::canDecode(e->mimeData()))
01006     {
01007         AlbumFolderViewItem *itemDrag = dynamic_cast<AlbumFolderViewItem*>(dragItem());
01008         if(!itemDrag)
01009             return;
01010 
01011         if (AlbumSettings::instance()->getAlbumSortOrder() == AlbumSettings::ByFolder)
01012         {
01013             // TODO: Copy?
01014             KMenu popMenu(this);
01015             popMenu.addTitle(SmallIcon("digikam"), i18n("My Albums"));
01016             QAction *moveAction = popMenu.addAction(SmallIcon("go-jump"), i18n("&Move Here"));
01017             popMenu.addSeparator();
01018             popMenu.addAction(SmallIcon("dialog-cancel"), i18n("C&ancel"));
01019             popMenu.setMouseTracking(true);
01020             QAction *choice = popMenu.exec(QCursor::pos());
01021 
01022             if(choice == moveAction)
01023             {
01024                 PAlbum *album = itemDrag->album();
01025                 PAlbum *destAlbum;
01026                 if(!itemDrop)
01027                 {
01028                     // move dragItem to the root
01029                     destAlbum = d->albumMan->findPAlbum(0);
01030                 }
01031                 else
01032                 {
01033                     // move dragItem below dropItem
01034                     destAlbum = itemDrop->album();
01035                 }
01036                 KIO::Job* job = DIO::move(album, destAlbum);
01037                 connect(job, SIGNAL(result(KJob*)),
01038                         this, SLOT(slotDIOResult(KJob*)));
01039             }
01040         }
01041         else if (AlbumSettings::instance()->getAlbumSortOrder() == AlbumSettings::ByCollection)
01042         {
01043             if (!itemDrop)
01044                 return;
01045 
01046             if (itemDrop->isGroupItem())
01047             {
01048                 PAlbum *album = itemDrag->album();
01049                 if (!album)
01050                     return;
01051 
01052                 album->setCollection(itemDrop->text(0));
01053                 resort();
01054             }
01055         }
01056 
01057         return;
01058     }
01059 
01060     if (DItemDrag::canDecode(e->mimeData()))
01061     {
01062         if (!itemDrop)
01063             return;
01064 
01065         PAlbum *destAlbum = itemDrop->album();
01066 
01067         KUrl::List urls;
01068         KUrl::List kioURLs;
01069         QList<int> albumIDs;
01070         QList<int> imageIDs;
01071 
01072         if (!DItemDrag::decode(e->mimeData(), urls, kioURLs, albumIDs, imageIDs))
01073             return;
01074 
01075         if (urls.isEmpty() || kioURLs.isEmpty() || albumIDs.isEmpty() || imageIDs.isEmpty())
01076             return;
01077 
01078         // Check if items dropped come from outside current album.
01079         // This can be the case with reccursive content album mode.
01080         KUrl::List extUrls;
01081         ImageInfoList extImgInfList;
01082         QList<qlonglong> extImageIDs;
01083         for (QList<int>::iterator it = imageIDs.begin(); it != imageIDs.end(); ++it)
01084         {
01085             ImageInfo info(*it);
01086             if (info.albumId() != destAlbum->id())
01087             {
01088                 extUrls.append(info.databaseUrl());
01089                 extImgInfList.append(info);
01090                 extImageIDs << *it;
01091             }
01092         }
01093 
01094         if(extUrls.isEmpty())
01095         {
01096             // Setting the dropped image as the album thumbnail
01097             // If the ctrl key is pressed, when dropping the image, the
01098             // thumbnail is set without a popup menu
01099             bool set = false;
01100             if (e->keyboardModifiers() == Qt::ControlModifier)
01101             {
01102                 set = true;
01103             }
01104             else
01105             {
01106                 KMenu popMenu(this);
01107                 popMenu.addTitle(SmallIcon("digikam"), i18n("My Albums"));
01108                 QAction *setAction = popMenu.addAction(i18n("Set as Album Thumbnail"));
01109                 popMenu.addSeparator();
01110                 popMenu.addAction(SmallIcon("dialog-cancel"), i18n("C&ancel"));
01111                 popMenu.setMouseTracking(true);
01112                 QAction *choice = popMenu.exec(QCursor::pos());
01113                 set = (setAction == choice);
01114             }
01115 
01116             if(set)
01117             {
01118                 QString errMsg;
01119                 d->albumMan->updatePAlbumIcon(destAlbum, imageIDs.first(), errMsg);
01120             }
01121             return;
01122         }
01123 
01124         // If shift key is pressed while dragging, move the drag object without
01125         // displaying popup menu -> move
01126         bool move = false, copy = false, setThumbnail = false;
01127         if (e->keyboardModifiers() == Qt::ShiftModifier)
01128         {
01129             move = true;
01130         }
01131         // If ctrl key is pressed while dragging, copy the drag object without
01132         // displaying popup menu -> copy
01133         else if (e->keyboardModifiers() == Qt::ControlModifier)
01134         {
01135             copy = true;
01136         }
01137         else
01138         {
01139             KMenu popMenu(this);
01140             popMenu.addTitle(SmallIcon("digikam"), i18n("My Albums"));
01141             QAction *moveAction = popMenu.addAction(SmallIcon("go-jump"), i18n("&Move Here"));
01142             QAction *copyAction = popMenu.addAction(SmallIcon("edit-copy"), i18n("&Copy Here"));
01143             QAction *thumbnailAction = 0;
01144             if (imageIDs.count() == 1)
01145                 thumbnailAction = popMenu.addAction(i18n("Set as Album Thumbnail"));
01146             popMenu.addSeparator();
01147             popMenu.addAction(SmallIcon("dialog-cancel"), i18n("C&ancel"));
01148             popMenu.setMouseTracking(true);
01149             QAction *choice = popMenu.exec(QCursor::pos());
01150             if (choice)
01151             {
01152                 if (choice == moveAction)
01153                     move = true;
01154                 else if (choice == copyAction)
01155                     copy = true;
01156                 else if (choice == thumbnailAction)
01157                     setThumbnail = true;
01158             }
01159         }
01160 
01161         if (move)
01162         {
01163             KIO::Job* job = DIO::move(extUrls, extImageIDs, destAlbum);
01164             connect(job, SIGNAL(result(KJob*)),
01165                     this, SLOT(slotDIOResult(KJob*)));
01166 
01167             // In recurssive album contents mode, we need to force AlbumLister to take a care about
01168             // moved items. This will have no incidence in normal mode.
01169             for (ImageInfoListIterator it = extImgInfList.begin(); it != extImgInfList.end(); ++it)
01170             {
01171                 AlbumLister::instance()->invalidateItem(*it);
01172             }
01173         }
01174         else if (copy)
01175         {
01176             KIO::Job* job = DIO::copy(extUrls, extImageIDs, destAlbum);
01177             connect(job, SIGNAL(result(KJob*)),
01178                     this, SLOT(slotDIOResult(KJob*)));
01179         }
01180         else if (setThumbnail)
01181         {
01182             QString errMsg;
01183             d->albumMan->updatePAlbumIcon(destAlbum, imageIDs.first(), errMsg);
01184         }
01185 
01186         return;
01187     }
01188 
01189     // -- DnD from Camera GUI ------------------------------------------------
01190 
01191     if(DCameraItemListDrag::canDecode(e->mimeData()))
01192     {
01193         Album *album = dynamic_cast<Album*>(itemDrop->album());
01194         if (!album) return;
01195 
01196         CameraUI *ui = dynamic_cast<CameraUI*>(e->source());
01197         if (ui)
01198         {
01199             KMenu popMenu(this);
01200             popMenu.addTitle(SmallIcon("digikam"), i18n("My Albums"));
01201             QAction *downAction    = popMenu.addAction(SmallIcon("file-export"),
01202                                                        i18n("Download from camera"));
01203             QAction *downDelAction = popMenu.addAction(SmallIcon("file-export"),
01204                                                        i18n("Download && Delete from camera"));
01205             popMenu.addSeparator();
01206             popMenu.addAction(SmallIcon("dialog-cancel"), i18n("C&ancel"));
01207             popMenu.setMouseTracking(true);
01208             QAction *choice = popMenu.exec(QCursor::pos());
01209             if (choice)
01210             {
01211                 if (choice == downAction)
01212                     ui->slotDownload(true, false, album);
01213                 else if (choice == downDelAction)
01214                     ui->slotDownload(true, true, album);
01215             }
01216         }
01217     }
01218 
01219     // -- DnD from an external source ----------------------------------------
01220 
01221     if(KUrl::List::canDecode(e->mimeData()))