/* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2005-05-06 * Description : Albums folder view. * * Copyright (C) 2005-2006 by Joern Ahrens * Copyright (C) 2006-2009 by Gilles Caulier * Copyright (C) 2009 by Andi Clemens * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ // TQt includes. #include #include #include #include #include #include #include #include // KDE includes. #include #include #include #include #include #include #include #include #include #if KDE_IS_VERSION(3,2,0) #include #else #include #endif // Local includes. #include "ddebug.h" #include "digikamapp.h" #include "albumlister.h" #include "album.h" #include "albumdb.h" #include "albumpropsedit.h" #include "albummanager.h" #include "albumsettings.h" #include "thumbnailjob.h" #include "thumbnailsize.h" #include "folderitem.h" #include "cameraui.h" #include "dio.h" #include "dragobjects.h" #include "albumthumbnailloader.h" #include "deletedialog.h" #include "albumfolderview.h" #include "albumfolderview.moc" // X11 C Ansi includes. extern "C" { #include } namespace Digikam { class AlbumFolderViewItem : public FolderItem { public: AlbumFolderViewItem(TQListView *parent, PAlbum *album); AlbumFolderViewItem(TQListViewItem *parent, PAlbum *album); // special group item (collection/dates) AlbumFolderViewItem(TQListViewItem* parent, const TQString& name, int year, int month); PAlbum* album() const; int id() const; bool isGroupItem() const; int compare(TQListViewItem *i, int col, bool ascending) const; void refresh(); void setOpen(bool o); void setCount(int count); int count(); private: bool m_groupItem; int m_count; int m_year; int m_month; PAlbum *m_album; }; AlbumFolderViewItem::AlbumFolderViewItem(TQListView *parent, PAlbum *album) : FolderItem(parent, album->title()) { setDragEnabled(true); m_album = album; m_groupItem = false; m_count = 0; } AlbumFolderViewItem::AlbumFolderViewItem(TQListViewItem *parent, PAlbum *album) : FolderItem(parent, album->title()) { setDragEnabled(true); m_album = album; m_groupItem = false; m_count = 0; } // special group item (collection/dates) AlbumFolderViewItem::AlbumFolderViewItem(TQListViewItem* parent, const TQString& name, int year, int month) : FolderItem(parent, name, true) { m_album = 0; m_year = year; m_month = month; m_groupItem = true; m_count = 0; } void AlbumFolderViewItem::refresh() { if (!m_album) return; if (AlbumSettings::instance()->getShowFolderTreeViewItemsCount() && dynamic_cast(parent())) { if (isOpen()) setText(0, TQString("%1 (%2)").arg(m_album->title()).arg(m_count)); else { int countRecursive = m_count; AlbumIterator it(m_album); while ( it.current() ) { AlbumFolderViewItem *item = (AlbumFolderViewItem*)it.current()->extraData(listView()); if (item) countRecursive += item->count(); ++it; } setText(0, TQString("%1 (%2)").arg(m_album->title()).arg(countRecursive)); } } else { setText(0, m_album->title()); } } void AlbumFolderViewItem::setOpen(bool o) { TQListViewItem::setOpen(o); refresh(); } PAlbum* AlbumFolderViewItem::album() const { return m_album; } int AlbumFolderViewItem::id() const { if (m_groupItem) { if (m_year != 0 && m_month != 0) { return (m_year*(-100) + m_month*(-1)); } else { return ( - (AlbumSettings::instance()->getAlbumCollectionNames() .findIndex(text(0)) ) ); } } else { return m_album ? m_album->id() : 0; } } bool AlbumFolderViewItem::isGroupItem() const { return m_groupItem; } int AlbumFolderViewItem::compare(TQListViewItem *i, int col, bool ascending) const { if (!m_groupItem || m_year == 0 || m_month == 0) return TQListViewItem::compare(i, col, ascending); AlbumFolderViewItem* thatItem = dynamic_cast(i); if (!thatItem) return 0; int myWeight = m_year*100 + m_month; int hisWeight = thatItem->m_year*100 + thatItem->m_month; if (myWeight == hisWeight) return 0; else if (myWeight > hisWeight) return 1; else return -1; } void AlbumFolderViewItem::setCount(int count) { m_count = count; refresh(); } int AlbumFolderViewItem::count() { return m_count; } // ----------------------------------------------------------------------------- class AlbumFolderViewPriv { public: AlbumFolderViewPriv() { albumMan = 0; iconThumbJob = 0; } AlbumManager *albumMan; ThumbnailJob *iconThumbJob; TQValueList groupItems; }; AlbumFolderView::AlbumFolderView(TQWidget *parent) : FolderView(parent, "AlbumFolderView") { d = new AlbumFolderViewPriv(); d->albumMan = AlbumManager::instance(); d->iconThumbJob = 0; addColumn(i18n("My Albums")); setResizeMode(TQListView::LastColumn); setRootIsDecorated(false); setAllColumnsShowFocus(true); setAcceptDrops(true); viewport()->setAcceptDrops(true); connect(d->albumMan, TQ_SIGNAL(signalAlbumAdded(Album*)), this, TQ_SLOT(slotAlbumAdded(Album*))); connect(d->albumMan, TQ_SIGNAL(signalAlbumDeleted(Album*)), this, TQ_SLOT(slotAlbumDeleted(Album*))); connect(d->albumMan, TQ_SIGNAL(signalAlbumsCleared()), this, TQ_SLOT(slotAlbumsCleared())); connect(d->albumMan, TQ_SIGNAL(signalAlbumIconChanged(Album*)), this, TQ_SLOT(slotAlbumIconChanged(Album*))); connect(d->albumMan, TQ_SIGNAL(signalAlbumRenamed(Album*)), this, TQ_SLOT(slotAlbumRenamed(Album*))); connect(d->albumMan, TQ_SIGNAL(signalPAlbumsDirty(const TQMap&)), this, TQ_SLOT(slotRefresh(const TQMap&))); AlbumThumbnailLoader *loader = AlbumThumbnailLoader::instance(); connect(loader, TQ_SIGNAL(signalThumbnail(Album *, const TQPixmap&)), this, TQ_SLOT(slotGotThumbnailFromIcon(Album *, const TQPixmap&))); connect(loader, TQ_SIGNAL(signalFailed(Album *)), this, TQ_SLOT(slotThumbnailLost(Album *))); connect(loader, TQ_SIGNAL(signalReloadThumbnails()), this, TQ_SLOT(slotReloadThumbnails())); connect(this, TQ_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint&, int)), this, TQ_SLOT(slotContextMenu(TQListViewItem*, const TQPoint&, int))); connect(this, TQ_SIGNAL(selectionChanged()), this, TQ_SLOT(slotSelectionChanged())); } AlbumFolderView::~AlbumFolderView() { if (d->iconThumbJob) d->iconThumbJob->kill(); saveViewState(); delete d; } void AlbumFolderView::slotTextFolderFilterChanged(const TQString& filter) { if (filter.isEmpty()) { collapseView(); return; } TQString search = filter.lower(); bool atleastOneMatch = false; AlbumList pList = d->albumMan->allPAlbums(); for (AlbumList::iterator it = pList.begin(); it != pList.end(); ++it) { PAlbum* palbum = (PAlbum*)(*it); // don't touch the root Album if (palbum->isRoot()) continue; bool match = palbum->title().lower().contains(search); bool doesExpand = false; if (!match) { // check if any of the parents match the search Album* parent = palbum->parent(); while (parent && !parent->isRoot()) { if (parent->title().lower().contains(search)) { match = true; break; } parent = parent->parent(); } } if (!match) { // check if any of the children match the search AlbumIterator it(palbum); while (it.current()) { if ((*it)->title().lower().contains(search)) { match = true; doesExpand = true; break; } ++it; } } AlbumFolderViewItem* viewItem = (AlbumFolderViewItem*) palbum->extraData(this); if (match) { atleastOneMatch = true; if (viewItem) { viewItem->setVisible(true); viewItem->setOpen(doesExpand); } } else { if (viewItem) { viewItem->setVisible(false); viewItem->setOpen(false); } } } emit signalTextFolderFilterMatch(atleastOneMatch); } void AlbumFolderView::slotAlbumAdded(Album *album) { if(!album) return; PAlbum *palbum = dynamic_cast(album); if(!palbum) return; bool failed; AlbumFolderViewItem* parent = findParent(palbum, failed); if (failed) { DWarning() << k_funcinfo << " Failed to find Album parent " << palbum->url() << endl; return; } AlbumFolderViewItem *item; if (!parent) { // root album item = new AlbumFolderViewItem(this, palbum); palbum->setExtraData(this, item); item->setOpen(true); } else { item = new AlbumFolderViewItem(parent, palbum); palbum->setExtraData(this, item); } setAlbumThumbnail(palbum); } void AlbumFolderView::slotAlbumDeleted(Album *album) { if(!album) return; PAlbum* palbum = dynamic_cast(album); if(!palbum) return; if(!palbum->icon().isEmpty() && d->iconThumbJob) d->iconThumbJob->removeItem(palbum->icon()); AlbumFolderViewItem* item = (AlbumFolderViewItem*) palbum->extraData(this); if(item) { AlbumFolderViewItem *itemParent = dynamic_cast(item->parent()); if(itemParent) itemParent->takeItem(item); else takeItem(item); delete item; clearEmptyGroupItems(); } } void AlbumFolderView::slotAlbumRenamed(Album *album) { PAlbum* palbum = dynamic_cast(album); if(!palbum) return; AlbumFolderViewItem* item = (AlbumFolderViewItem*) palbum->extraData(this); if(item) item->refresh(); if (item->parent()) item->parent()->sort(); } void AlbumFolderView::slotAlbumsCleared() { d->groupItems.clear(); clear(); } void AlbumFolderView::setAlbumThumbnail(PAlbum *album) { if(!album) return; AlbumFolderViewItem* item = (AlbumFolderViewItem*) album->extraData(this); if(!item) return; // Either, getThumbnail returns true and loads an icon asynchronously. // Then, for the time being, we set the standard icon. // Or, no icon is associated with the album, then we set the standard icon anyway. AlbumThumbnailLoader *loader = AlbumThumbnailLoader::instance(); item->setPixmap(0, loader->getStandardAlbumIcon(album)); loader->getAlbumThumbnail(album); } void AlbumFolderView::setCurrentAlbum(Album *album) { if(!album) return; AlbumFolderViewItem* item = (AlbumFolderViewItem*) album->extraData(this); if(!item) return; setCurrentItem(item); ensureItemVisible(item); } void AlbumFolderView::slotGotThumbnailFromIcon(Album *album, const TQPixmap& thumbnail) { if(!album || album->type() != Album::PHYSICAL) return; AlbumFolderViewItem* item = (AlbumFolderViewItem*)album->extraData(this); if(!item) return; item->setPixmap(0, thumbnail); } void AlbumFolderView::slotThumbnailLost(Album *) { // we already set the standard icon before loading } void AlbumFolderView::slotReloadThumbnails() { AlbumList tList = d->albumMan->allPAlbums(); for (AlbumList::iterator it = tList.begin(); it != tList.end(); ++it) { PAlbum* album = (PAlbum*)(*it); setAlbumThumbnail(album); } } void AlbumFolderView::slotAlbumIconChanged(Album* album) { if(!album || album->type() != Album::PHYSICAL) return; setAlbumThumbnail((PAlbum*)album); } void AlbumFolderView::slotSelectionChanged() { if (!active()) return; TQListViewItem* selItem = 0; TQListViewItemIterator it(this); while(it.current()) { if(it.current()->isSelected()) { selItem = it.current(); break; } ++it; } if(!selItem) { d->albumMan->setCurrentAlbum(0); return; } AlbumFolderViewItem *albumitem = dynamic_cast(selItem); if(!albumitem) { d->albumMan->setCurrentAlbum(0); return; } d->albumMan->setCurrentAlbum(albumitem->album()); } void AlbumFolderView::slotContextMenu(TQListViewItem *listitem, const TQPoint &, int) { TDEActionMenu menuImport(i18n("Import")); TDEActionMenu menuExport(i18n("Export")); TDEActionMenu menuKIPIBatch(i18n("Batch Process")); TDEPopupMenu popmenu(this); popmenu.insertTitle(SmallIcon("digikam"), i18n("My Albums")); popmenu.insertItem(SmallIcon("albumfolder-new"), i18n("New Album..."), 10); AlbumFolderViewItem *item = dynamic_cast(listitem); if (item && !item->album()) { // if collection/date return return; } // Root folder only shows "New Album..." if(item && item->parent()) { popmenu.insertItem(SmallIcon("pencil"), i18n("Rename..."), 14); popmenu.insertItem(SmallIcon("albumfolder-properties"), i18n("Album Properties..."), 11); popmenu.insertItem(SmallIcon("reload_page"), i18n("Reset Album Icon"), 13); popmenu.insertSeparator(); // Add KIPI Albums plugins Actions TDEAction *action; const TQPtrList& albumActions = DigikamApp::getinstance()->menuAlbumActions(); if(!albumActions.isEmpty()) { TQPtrListIterator it(albumActions); while((action = it.current())) { action->plug(&popmenu); ++it; } } // Add All Import Actions const TQPtrList importActions = DigikamApp::getinstance()->menuImportActions(); if(!importActions.isEmpty()) { TQPtrListIterator it3(importActions); while((action = it3.current())) { menuImport.insert(action); ++it3; } menuImport.plug(&popmenu); } // Add All Export Actions const TQPtrList exportActions = DigikamApp::getinstance()->menuExportActions(); if(!exportActions.isEmpty()) { TQPtrListIterator it4(exportActions); while((action = it4.current())) { menuExport.insert(action); ++it4; } menuExport.plug(&popmenu); } // Add KIPI Batch processes plugins Actions const TQPtrList& batchActions = DigikamApp::getinstance()->menuBatchActions(); if(!batchActions.isEmpty()) { TQPtrListIterator it2(batchActions); while((action = it2.current())) { menuKIPIBatch.insert(action); ++it2; } menuKIPIBatch.plug(&popmenu); } if(!albumActions.isEmpty() || !batchActions.isEmpty() || !importActions.isEmpty()) { popmenu.insertSeparator(-1); } if(AlbumSettings::instance()->getUseTrash()) { popmenu.insertItem(SmallIcon("edittrash"), i18n("Move Album to Trash"), 12); } else { popmenu.insertItem(SmallIcon("edit-delete"), i18n("Delete Album"), 12); } } switch(popmenu.exec((TQCursor::pos()))) { case 10: { albumNew(item); break; } case 11: { albumEdit(item); break; } case 12: { albumDelete(item); break; } case 13: { TQString err; d->albumMan->updatePAlbumIcon(item->album(), 0, err); break; } case 14: { albumRename(item); break; } default: break; } } void AlbumFolderView::albumNew() { AlbumFolderViewItem *item = dynamic_cast(selectedItem()); if (!item) { item = dynamic_cast(firstChild()); } if (!item) return; albumNew(item); } void AlbumFolderView::albumNew(AlbumFolderViewItem *item) { AlbumSettings* settings = AlbumSettings::instance(); if(!settings) { DWarning() << "AlbumFolderView: Couldn't get Album Settings" << endl; return; } TQDir libraryDir(settings->getAlbumLibraryPath()); if(!libraryDir.exists()) { KMessageBox::error(0, i18n("The album library has not been set correctly.\n" "Select \"Configure Digikam\" from the Settings " "menu and choose a folder to use for the album " "library.")); return; } PAlbum *parent; if(!item) parent = d->albumMan->findPAlbum(0); else parent = item->album(); if (!parent) return; TQString title; TQString comments; TQString collection; TQDate date; TQStringList albumCollections; if(!AlbumPropsEdit::createNew(parent, title, comments, date, collection, albumCollections)) return; TQStringList oldAlbumCollections(AlbumSettings::instance()->getAlbumCollectionNames()); if(albumCollections != oldAlbumCollections) { AlbumSettings::instance()->setAlbumCollectionNames(albumCollections); resort(); } TQString errMsg; PAlbum* album = d->albumMan->createPAlbum(parent, title, comments, date, collection, errMsg); if (!album) { KMessageBox::error(0, errMsg); return; } // by this time the signalAlbumAdded has been fired and the appropriate // AlbumFolderViewItem has been created. Now make this folderviewitem visible AlbumFolderViewItem* newItem = (AlbumFolderViewItem*)album->extraData(this); if (newItem) { if(item) item->setOpen(true); ensureItemVisible(newItem); } } void AlbumFolderView::albumDelete() { AlbumFolderViewItem *item = dynamic_cast(selectedItem()); if(!item) return; albumDelete(item); } void AlbumFolderView::albumDelete(AlbumFolderViewItem *item) { PAlbum *album = item->album(); if(!album || album->isRoot()) return; // find subalbums KURL::List childrenList; addAlbumChildrenToList(childrenList, album); DeleteDialog dialog(this); // All subalbums will be presented in the list as well if (!dialog.confirmDeleteList(childrenList, childrenList.size() == 1 ? DeleteDialogMode::Albums : DeleteDialogMode::Subalbums, DeleteDialogMode::UserPreference)) return; bool useTrash = !dialog.shouldDelete(); // Currently trash tdeioslave can handle only full paths. // pass full folder path to the trashing job KURL u; u.setProtocol("file"); u.setPath(album->folderPath()); TDEIO::Job* job = DIO::del(u, useTrash); connect(job, TQ_SIGNAL(result(TDEIO::Job *)), this, TQ_SLOT(slotDIOResult(TDEIO::Job *))); } void AlbumFolderView::addAlbumChildrenToList(KURL::List &list, Album *album) { // simple recursive helper function if (album) { list.append(album->kurl()); AlbumIterator it(album); while(it.current()) { addAlbumChildrenToList(list, *it); ++it; } } } void AlbumFolderView::slotDIOResult(TDEIO::Job* job) { if (job->error()) job->showErrorDialog(this); } void AlbumFolderView::albumRename() { AlbumFolderViewItem *item = dynamic_cast(selectedItem()); if(!item) return; albumRename(item); } void AlbumFolderView::albumRename(AlbumFolderViewItem* item) { PAlbum *album = item->album(); if (!album) return; TQString oldTitle(album->title()); bool ok; #if KDE_IS_VERSION(3,2,0) TQString title = KInputDialog::getText(i18n("Rename Album (%1)").arg(oldTitle), i18n("Enter new album name:"), oldTitle, &ok, this); #else TQString title = KLineEditDlg::getText(i18n("Rename Item (%1)").arg(oldTitle), i18n("Enter new album name:"), oldTitle, &ok, this); #endif if (!ok) return; if(title != oldTitle) { TQString errMsg; if (!d->albumMan->renamePAlbum(album, title, errMsg)) KMessageBox::error(0, errMsg); } emit signalAlbumModified(); } void AlbumFolderView::albumEdit() { AlbumFolderViewItem *item = dynamic_cast(selectedItem()); if(!item) return; albumEdit(item); } void AlbumFolderView::albumEdit(AlbumFolderViewItem* item) { PAlbum *album = item->album(); if (!album) return; TQString oldTitle(album->title()); TQString oldComments(album->caption()); TQString oldCollection(album->collection()); TQDate oldDate(album->date()); TQStringList oldAlbumCollections(AlbumSettings::instance()->getAlbumCollectionNames()); TQString title, comments, collection; TQDate date; TQStringList albumCollections; if(AlbumPropsEdit::editProps(album, title, comments, date, collection, albumCollections)) { if(comments != oldComments) album->setCaption(comments); if(date != oldDate && date.isValid()) album->setDate(date); if(collection != oldCollection) album->setCollection(collection); AlbumSettings::instance()->setAlbumCollectionNames(albumCollections); resort(); // Do this last : so that if anything else changed we can // successfuly save to the db with the old name if(title != oldTitle) { TQString errMsg; if (!d->albumMan->renamePAlbum(album, title, errMsg)) KMessageBox::error(0, errMsg); } emit signalAlbumModified(); } } TQDragObject* AlbumFolderView::dragObject() { AlbumFolderViewItem *item = dynamic_cast(dragItem()); if(!item) return 0; PAlbum *album = item->album(); if(album->isRoot()) return 0; AlbumDrag *a = new AlbumDrag(album->kurl(), album->id(), this); if(!a) return 0; a->setPixmap(*item->pixmap(0)); return a; } bool AlbumFolderView::acceptDrop(const TQDropEvent *e) const { TQPoint vp = contentsToViewport(e->pos()); AlbumFolderViewItem *itemDrop = dynamic_cast(itemAt(vp)); AlbumFolderViewItem *itemDrag = dynamic_cast(dragItem()); if(AlbumDrag::canDecode(e)) { switch(AlbumSettings::instance()->getAlbumSortOrder()) { case(AlbumSettings::ByFolder): { // Allow dragging at the root, to move the album at the root if(!itemDrop) return true; // Dragging an item on itself makes no sense if(itemDrag == itemDrop) return false; // Dragging a parent on its child makes no sense if(itemDrag && itemDrag->album()->isAncestorOf(itemDrop->album())) return false; return true; } case (AlbumSettings::ByCollection): { if (!itemDrop) return false; // Only allow dragging onto Collection if (itemDrop->isGroupItem()) return true; return false; } default: { return false; } } } if(itemDrop && !itemDrop->parent()) { // Do not allow drop images on album root return false; } if (itemDrop && itemDrop->isGroupItem()) { // do not allow drop on a group item return false; } if(ItemDrag::canDecode(e)) { return true; } if (CameraItemListDrag::canDecode(e)) { return true; } if(TQUriDrag::canDecode(e)) { return true; } return false; } void AlbumFolderView::contentsDropEvent(TQDropEvent *e) { FolderView::contentsDropEvent(e); if(!acceptDrop(e)) return; TQPoint vp = contentsToViewport(e->pos()); AlbumFolderViewItem *itemDrop = dynamic_cast(itemAt(vp)); if(AlbumDrag::canDecode(e)) { AlbumFolderViewItem *itemDrag = dynamic_cast(dragItem()); if(!itemDrag) return; if (AlbumSettings::instance()->getAlbumSortOrder() == AlbumSettings::ByFolder) { // TODO: Copy? TDEPopupMenu popMenu(this); popMenu.insertTitle(SmallIcon("digikam"), i18n("My Albums")); popMenu.insertItem(SmallIcon("goto"), i18n("&Move Here"), 10); popMenu.insertSeparator(-1); popMenu.insertItem(SmallIcon("cancel"), i18n("C&ancel"), 20); popMenu.setMouseTracking(true); int id = popMenu.exec(TQCursor::pos()); if(id == 10) { PAlbum *album = itemDrag->album(); PAlbum *destAlbum; if(!itemDrop) { // move dragItem to the root destAlbum = d->albumMan->findPAlbum(0); } else { // move dragItem below dropItem destAlbum = itemDrop->album(); } TDEIO::Job* job = DIO::move(album->kurl(), destAlbum->kurl()); connect(job, TQ_SIGNAL(result(TDEIO::Job*)), this, TQ_SLOT(slotDIOResult(TDEIO::Job*))); } } else if (AlbumSettings::instance()->getAlbumSortOrder() == AlbumSettings::ByCollection) { if (!itemDrop) return; if (itemDrop->isGroupItem()) { PAlbum *album = itemDrag->album(); if (!album) return; album->setCollection(itemDrop->text(0)); resort(); } } return; } if (ItemDrag::canDecode(e)) { if (!itemDrop) return; PAlbum *destAlbum = itemDrop->album(); KURL::List urls; KURL::List kioURLs; TQValueList albumIDs; TQValueList imageIDs; if (!ItemDrag::decode(e, urls, kioURLs, albumIDs, imageIDs)) return; if (urls.isEmpty() || kioURLs.isEmpty() || albumIDs.isEmpty() || imageIDs.isEmpty()) return; // Check if items dropped come from outside current album. // This can be the case with reccursive content album mode. KURL::List extUrls; ImageInfoList extImgInfList; for (TQValueList::iterator it = imageIDs.begin(); it != imageIDs.end(); ++it) { ImageInfo *info = new ImageInfo(*it); if (info->albumID() != destAlbum->id()) { extUrls.append(info->kurlForKIO()); extImgInfList.append(info); } } int id = 0; char keys_return[32]; XQueryKeymap(x11Display(), keys_return); int key_1 = XKeysymToKeycode(x11Display(), 0xFFE3); int key_2 = XKeysymToKeycode(x11Display(), 0xFFE4); int key_3 = XKeysymToKeycode(x11Display(), 0xFFE1); int key_4 = XKeysymToKeycode(x11Display(), 0xFFE2); if(extUrls.isEmpty()) { // Setting the dropped image as the album thumbnail // If the ctrl key is pressed, when dropping the image, the // thumbnail is set without a popup menu if (((keys_return[key_1 / 8]) && (1 << (key_1 % 8))) || ((keys_return[key_2 / 8]) && (1 << (key_2 % 8)))) { id = 12; } else { TDEPopupMenu popMenu(this); popMenu.insertTitle(SmallIcon("digikam"), i18n("My Albums")); popMenu.insertItem(i18n("Set as Album Thumbnail"), 12); popMenu.insertSeparator(-1); popMenu.insertItem( SmallIcon("cancel"), i18n("C&ancel") ); popMenu.setMouseTracking(true); id = popMenu.exec(TQCursor::pos()); } if(id == 12) { TQString errMsg; d->albumMan->updatePAlbumIcon(destAlbum, imageIDs.first(), errMsg); } return; } // If shift key is pressed while dragging, move the drag object without // displaying popup menu -> move if (((keys_return[key_3 / 8]) && (1 << (key_3 % 8))) || ((keys_return[key_4 / 8]) && (1 << (key_4 % 8)))) { id = 10; } // If ctrl key is pressed while dragging, copy the drag object without // displaying popup menu -> copy else if (((keys_return[key_1 / 8]) && (1 << (key_1 % 8))) || ((keys_return[key_2 / 8]) && (1 << (key_2 % 8)))) { id = 11; } else { TDEPopupMenu popMenu(this); popMenu.insertTitle(SmallIcon("digikam"), i18n("My Albums")); popMenu.insertItem( SmallIcon("goto"), i18n("&Move Here"), 10 ); popMenu.insertItem( SmallIcon("edit-copy"), i18n("&Copy Here"), 11 ); if (imageIDs.count() == 1) popMenu.insertItem(i18n("Set as Album Thumbnail"), 12); popMenu.insertSeparator(-1); popMenu.insertItem( SmallIcon("cancel"), i18n("C&ancel") ); popMenu.setMouseTracking(true); id = popMenu.exec(TQCursor::pos()); } switch(id) { case 10: { TDEIO::Job* job = DIO::move(extUrls, destAlbum->kurl()); connect(job, TQ_SIGNAL(result(TDEIO::Job*)), this, TQ_SLOT(slotDIOResult(TDEIO::Job*))); // In recurssive album contents mode, we need to force AlbumLister to take a care about // moved items. This will have no incidence in normal mode. ImageInfo* item; for (ImageInfoListIterator it(extImgInfList); (item = it.current()) ; ++it) { AlbumLister::instance()->invalidateItem(item); } break; } case 11: { TDEIO::Job* job = DIO::copy(extUrls, destAlbum->kurl()); connect(job, TQ_SIGNAL(result(TDEIO::Job*)), this, TQ_SLOT(slotDIOResult(TDEIO::Job*))); break; } case 12: { TQString errMsg; d->albumMan->updatePAlbumIcon(destAlbum, imageIDs.first(), errMsg); } default: break; } return; } // -- DnD from Camera GUI ------------------------------------------------ if(CameraItemListDrag::canDecode(e)) { Album *album = dynamic_cast(itemDrop->album()); if (!album) return; CameraUI *ui = dynamic_cast(e->source()); if (ui) { TDEPopupMenu popMenu(this); popMenu.insertTitle(SmallIcon("digikam"), i18n("My Albums")); popMenu.insertItem(SmallIcon("go-down"), i18n("Download from camera"), 10); popMenu.insertItem(SmallIcon("go-down"), i18n("Download && Delete from camera"), 11); popMenu.insertSeparator(-1); popMenu.insertItem(SmallIcon("cancel"), i18n("&Cancel")); popMenu.setMouseTracking(true); int id = popMenu.exec(TQCursor::pos()); switch(id) { case 10: // Download from camera { ui->slotDownload(true, false, album); break; } case 11: // Download and Delete from camera { ui->slotDownload(true, true, album); break; } default: break; } } } // -- DnD from an external source ---------------------------------------- if(TQUriDrag::canDecode(e)) { PAlbum* destAlbum = 0; if (itemDrop) destAlbum = itemDrop->album(); else destAlbum = d->albumMan->findPAlbum(0); // B.K.O #119205: do not handle root album. if (destAlbum->isRoot()) return; KURL destURL(destAlbum->kurl()); KURL::List srcURLs; KURLDrag::decode(e, srcURLs); char keys_return[32]; XQueryKeymap(x11Display(), keys_return); int id = 0; int key_1 = XKeysymToKeycode(x11Display(), 0xFFE3); int key_2 = XKeysymToKeycode(x11Display(), 0xFFE4); int key_3 = XKeysymToKeycode(x11Display(), 0xFFE1); int key_4 = XKeysymToKeycode(x11Display(), 0xFFE2); // If shift key is pressed while dropping, move the drag object without // displaying popup menu -> move if(((keys_return[key_3 / 8]) && (1 << (key_3 % 8))) || ((keys_return[key_4 / 8]) && (1 << (key_4 % 8)))) { id = 10; } // If ctrl key is pressed while dropping, copy the drag object without // displaying popup menu -> copy else if(((keys_return[key_1 / 8]) && (1 << (key_1 % 8))) || ((keys_return[key_2 / 8]) && (1 << (key_2 % 8)))) { id = 11; } else { TDEPopupMenu popMenu(this); popMenu.insertTitle(SmallIcon("digikam"), i18n("My Albums")); popMenu.insertItem( SmallIcon("goto"), i18n("&Move Here"), 10 ); popMenu.insertItem( SmallIcon("edit-copy"), i18n("&Copy Here"), 11 ); popMenu.insertSeparator(-1); popMenu.insertItem( SmallIcon("cancel"), i18n("C&ancel") ); popMenu.setMouseTracking(true); id = popMenu.exec(TQCursor::pos()); } switch(id) { case 10: { TDEIO::Job* job = DIO::move(srcURLs, destAlbum->kurl()); connect(job, TQ_SIGNAL(result(TDEIO::Job*)), this, TQ_SLOT(slotDIOResult(TDEIO::Job*))); break; } case 11: { TDEIO::Job* job = DIO::copy(srcURLs, destAlbum->kurl()); connect(job, TQ_SIGNAL(result(TDEIO::Job*)), this, TQ_SLOT(slotDIOResult(TDEIO::Job*))); break; } default: break; } return; } } void AlbumFolderView::albumImportFolder() { AlbumSettings* settings = AlbumSettings::instance(); TQDir libraryDir(settings->getAlbumLibraryPath()); if(!libraryDir.exists()) { KMessageBox::error(0, i18n("The album library has not been set correctly.\n" "Select \"Configure digiKam\" from the Settings " "menu and choose a folder to use for the album " "library.")); return; } PAlbum* parent = 0; if(selectedItem()) { AlbumFolderViewItem *folderItem = dynamic_cast(selectedItem()); Album *album = folderItem->album(); if (album && album->type() == Album::PHYSICAL) { parent = dynamic_cast(album); } } if(!parent) parent = dynamic_cast(d->albumMan->findPAlbum(0)); TQString libraryPath = parent->folderPath(); KFileDialog dlg(TQString(), "inode/directory", this, "importFolder", true); dlg.setCaption(i18n("Select folders to import")); dlg.setMode(KFile::Directory | KFile::Files); if(dlg.exec() != TQDialog::Accepted) return; KURL::List urls = dlg.selectedURLs(); if(urls.empty()) return; TDEIO::Job* job = DIO::copy(urls, parent->kurl()); connect(job, TQ_SIGNAL(result(TDEIO::Job *)), this, TQ_SLOT(slotDIOResult(TDEIO::Job *))); } void AlbumFolderView::selectItem(int id) { PAlbum* album = d->albumMan->findPAlbum(id); if(!album) return; AlbumFolderViewItem *item = (AlbumFolderViewItem*)album->extraData(this); if(item) { setSelected(item, true); ensureItemVisible(item); } } AlbumFolderViewItem* AlbumFolderView::findParent(PAlbum* album, bool& failed) { if (album->isRoot()) { failed = false; return 0; } switch(AlbumSettings::instance()->getAlbumSortOrder()) { case(AlbumSettings::ByFolder): { return findParentByFolder(album, failed); } case(AlbumSettings::ByCollection): { return findParentByCollection(album, failed); } case(AlbumSettings::ByDate): { return findParentByDate(album, failed); } } failed = true; return 0; } AlbumFolderViewItem* AlbumFolderView::findParentByFolder(PAlbum* album, bool& failed) { AlbumFolderViewItem* parent = (AlbumFolderViewItem*) album->parent()->extraData(this); if (!parent) { failed = true; return 0; } failed = false; return parent; } AlbumFolderViewItem* AlbumFolderView::findParentByCollection(PAlbum* album, bool& failed) { TQStringList collectionList = AlbumSettings::instance()->getAlbumCollectionNames(); TQString collection = album->collection(); if (collection.isEmpty() || !collectionList.contains(collection)) collection = i18n("Uncategorized Albums"); AlbumFolderViewItem* parent = 0; for (TQValueList::iterator it=d->groupItems.begin(); it != d->groupItems.end(); ++it) { AlbumFolderViewItem* groupItem = *it; if (groupItem->text(0) == collection) { parent = groupItem; break; } } // Need to create a new parent item if (!parent) { parent = new AlbumFolderViewItem(firstChild(), collection, 0, 0); d->groupItems.append(parent); } failed = false; return parent; } AlbumFolderViewItem* AlbumFolderView::findParentByDate(PAlbum* album, bool& failed) { TQDate date = album->date(); TQString timeString = TQString::number(date.year()) + ", " + TDEGlobal::locale()->calendar()->monthName(date, false); AlbumFolderViewItem* parent = 0; for (TQValueList::iterator it=d->groupItems.begin(); it != d->groupItems.end(); ++it) { AlbumFolderViewItem* groupItem = *it; if (groupItem->text(0) == timeString) { parent = groupItem; break; } } // Need to create a new parent item if (!parent) { parent = new AlbumFolderViewItem(firstChild(), timeString, date.year(), date.month()); d->groupItems.append(parent); } failed = false; return parent; } void AlbumFolderView::resort() { AlbumFolderViewItem* prevSelectedItem = dynamic_cast(selectedItem()); if (prevSelectedItem && prevSelectedItem->isGroupItem()) prevSelectedItem = 0; AlbumList pList(d->albumMan->allPAlbums()); for (AlbumList::iterator it = pList.begin(); it != pList.end(); ++it) { PAlbum *album = (PAlbum*)(*it); if (!album->isRoot() && album->extraData(this)) { reparentItem(static_cast(album->extraData(this))); } } // Clear any groupitems which have been left empty clearEmptyGroupItems(); if (prevSelectedItem) { ensureItemVisible(prevSelectedItem); setSelected(prevSelectedItem, true); } } void AlbumFolderView::reparentItem(AlbumFolderViewItem* folderItem) { if (!folderItem) return; PAlbum* album = folderItem->album(); if (!album || album->isRoot()) return; AlbumFolderViewItem* oldParent = dynamic_cast(folderItem->parent()); bool failed; AlbumFolderViewItem* newParent = findParent(album, failed); if (failed) return; if (oldParent == newParent) return; if (oldParent) oldParent->removeItem(folderItem); else removeItem(folderItem); // insert into new parent if (newParent) newParent->insertItem(folderItem); else insertItem(folderItem); } void AlbumFolderView::clearEmptyGroupItems() { TQValueList deleteItems; for (TQValueList::iterator it=d->groupItems.begin(); it != d->groupItems.end(); ++it) { AlbumFolderViewItem* groupItem = *it; if (!groupItem->firstChild()) { deleteItems.append(groupItem); } } for (TQValueList::iterator it=deleteItems.begin(); it != deleteItems.end(); ++it) { d->groupItems.remove(*it); delete *it; } } void AlbumFolderView::refresh() { TQListViewItemIterator it(this); while (it.current()) { AlbumFolderViewItem* item = dynamic_cast(*it); if (item) item->refresh(); ++it; } } void AlbumFolderView::slotRefresh(const TQMap& albumsStatMap) { TQListViewItemIterator it(this); while (it.current()) { AlbumFolderViewItem* item = dynamic_cast(*it); if (item) { if (item->album()) { int id = item->id(); TQMap::const_iterator it2 = albumsStatMap.find(id); if ( it2 != albumsStatMap.end() ) item->setCount(it2.data()); } } ++it; } refresh(); } } // namespace Digikam