summaryrefslogtreecommitdiffstats
path: root/src/libs/imageproperties/talbumlistview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/imageproperties/talbumlistview.cpp')
-rw-r--r--src/libs/imageproperties/talbumlistview.cpp528
1 files changed, 528 insertions, 0 deletions
diff --git a/src/libs/imageproperties/talbumlistview.cpp b/src/libs/imageproperties/talbumlistview.cpp
new file mode 100644
index 00000000..1369d228
--- /dev/null
+++ b/src/libs/imageproperties/talbumlistview.cpp
@@ -0,0 +1,528 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-18-12
+ * Description : A list view to display digiKam Tags.
+ *
+ * Copyright (C) 2006-2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2009 by Andi Clemens <andi dot clemens at gmx dot net>
+ *
+ * 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 <tqheader.h>
+
+// KDE includes.
+
+#include <tdepopupmenu.h>
+#include <tdelocale.h>
+#include <kurl.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+#include <kiconloader.h>
+#include <tdemessagebox.h>
+#include <tdeconfig.h>
+#include <tdeglobalsettings.h>
+#include <kdialogbase.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "albumiconitem.h"
+#include "albumlister.h"
+#include "albummanager.h"
+#include "albumdb.h"
+#include "album.h"
+#include "albumsettings.h"
+#include "imageinfo.h"
+#include "navigatebarwidget.h"
+#include "dragobjects.h"
+#include "imageattributeswatch.h"
+#include "albumthumbnailloader.h"
+#include "statusprogressbar.h"
+#include "talbumlistview.h"
+#include "talbumlistview.moc"
+
+// X11 includes.
+
+extern "C"
+{
+#include <X11/Xlib.h>
+}
+
+namespace Digikam
+{
+
+TAlbumCheckListItem::TAlbumCheckListItem(TQListView* parent, TAlbum* album)
+ : FolderCheckListItem(parent, album->title(), TQCheckListItem::RadioButtonController)
+{
+ setDragEnabled(true);
+ m_album = album;
+ m_count = 0;
+
+ if (m_album)
+ m_album->setExtraData(listView(), this);
+}
+
+TAlbumCheckListItem::TAlbumCheckListItem(TQCheckListItem* parent, TAlbum* album)
+ : FolderCheckListItem(parent, album->title(), TQCheckListItem::CheckBox)
+{
+ setDragEnabled(true);
+ m_album = album;
+ m_count = 0;
+
+ if (m_album)
+ m_album->setExtraData(listView(), this);
+}
+
+void TAlbumCheckListItem::refresh()
+{
+ if (!m_album) return;
+
+ if (AlbumSettings::instance()->getShowFolderTreeViewItemsCount() &&
+ dynamic_cast<TAlbumCheckListItem*>(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() )
+ {
+ TAlbumCheckListItem *item = (TAlbumCheckListItem*)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 TAlbumCheckListItem::stateChange(bool val)
+{
+ TQCheckListItem::stateChange(val);
+ ((TAlbumListView*)listView())->stateChanged(this);
+}
+
+void TAlbumCheckListItem::setOpen(bool o)
+{
+ TQListViewItem::setOpen(o);
+ refresh();
+}
+
+TAlbum* TAlbumCheckListItem::album() const
+{
+ return m_album;
+}
+
+int TAlbumCheckListItem::id() const
+{
+ return m_album ? m_album->id() : 0;
+}
+
+void TAlbumCheckListItem::setCount(int count)
+{
+ m_count = count;
+ refresh();
+}
+
+int TAlbumCheckListItem::count()
+{
+ return m_count;
+}
+
+void TAlbumCheckListItem::setStatus(MetadataHub::TagStatus status)
+{
+ if (status == MetadataHub::MetadataDisjoint)
+ {
+ if (type() != TQCheckListItem::RadioButtonController) setTristate(true);
+ setState(TQCheckListItem::NoChange);
+ }
+ else
+ {
+ if (type() != TQCheckListItem::RadioButtonController) setTristate(false);
+ setOn(status.hasTag);
+ }
+}
+
+// ------------------------------------------------------------------------
+
+TAlbumListView::TAlbumListView(TQWidget* parent)
+ : FolderView(parent, "TAlbumListView")
+{
+ addColumn(i18n("Tags"));
+ header()->hide();
+ setResizeMode(TQListView::LastColumn);
+ setRootIsDecorated(true);
+
+ setAcceptDrops(true);
+ viewport()->setAcceptDrops(true);
+
+ connect(AlbumManager::instance(), TQ_SIGNAL(signalTAlbumsDirty(const TQMap<int, int>&)),
+ this, TQ_SLOT(slotRefresh(const TQMap<int, int>&)));
+}
+
+TAlbumListView::~TAlbumListView()
+{
+ saveViewState();
+}
+
+void TAlbumListView::stateChanged(TAlbumCheckListItem *item)
+{
+ emit signalItemStateChanged(item);
+}
+
+TQDragObject* TAlbumListView::dragObject()
+{
+ TAlbumCheckListItem *item = dynamic_cast<TAlbumCheckListItem*>(dragItem());
+ if(!item)
+ return 0;
+
+ if(!item->parent())
+ return 0;
+
+ TagDrag *t = new TagDrag(item->id(), this);
+ t->setPixmap(*item->pixmap(0));
+
+ return t;
+}
+
+bool TAlbumListView::acceptDrop(const TQDropEvent *e) const
+{
+ TQPoint vp = contentsToViewport(e->pos());
+ TAlbumCheckListItem *itemDrop = dynamic_cast<TAlbumCheckListItem*>(itemAt(vp));
+ TAlbumCheckListItem *itemDrag = dynamic_cast<TAlbumCheckListItem*>(dragItem());
+
+ if(TagDrag::canDecode(e) || TagListDrag::canDecode(e))
+ {
+ // Allow dragging at the root, to move the tag to 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;
+ }
+
+ if (ItemDrag::canDecode(e) && itemDrop && itemDrop->album()->parent())
+ {
+ // Only other possibility is image items being dropped
+ // And allow this only if there is a Tag to be dropped
+ // on and also the Tag is not root.
+ return true;
+ }
+
+ return false;
+}
+
+void TAlbumListView::contentsDropEvent(TQDropEvent *e)
+{
+ TQListView::contentsDropEvent(e);
+
+ if(!acceptDrop(e))
+ return;
+
+ TQPoint vp = contentsToViewport(e->pos());
+ TAlbumCheckListItem *itemDrop = dynamic_cast<TAlbumCheckListItem*>(itemAt(vp));
+
+ if(TagDrag::canDecode(e))
+ {
+ TQByteArray ba = e->encodedData("digikam/tag-id");
+ TQDataStream ds(ba, IO_ReadOnly);
+ int tagID;
+ ds >> tagID;
+
+ AlbumManager* man = AlbumManager::instance();
+ TAlbum* talbum = man->findTAlbum(tagID);
+
+ if(!talbum)
+ return;
+
+ if (talbum == itemDrop->album())
+ return;
+
+ TDEPopupMenu popMenu(this);
+ popMenu.insertTitle(SmallIcon("digikam"), i18n("Tags"));
+ 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)
+ {
+ TAlbum *newParentTag = 0;
+
+ if (!itemDrop)
+ {
+ // move dragItem to the root
+ newParentTag = AlbumManager::instance()->findTAlbum(0);
+ }
+ else
+ {
+ // move dragItem as child of dropItem
+ newParentTag = itemDrop->album();
+ }
+
+ TQString errMsg;
+ if (!AlbumManager::instance()->moveTAlbum(talbum, newParentTag, errMsg))
+ {
+ KMessageBox::error(this, errMsg);
+ }
+
+ if(itemDrop && !itemDrop->isOpen())
+ itemDrop->setOpen(true);
+ }
+
+ return;
+ }
+
+ if (ItemDrag::canDecode(e))
+ {
+ TAlbum *destAlbum = itemDrop->album();
+ TAlbum *srcAlbum;
+
+ KURL::List urls;
+ KURL::List kioURLs;
+ TQValueList<int> albumIDs;
+ TQValueList<int> imageIDs;
+
+ if (!ItemDrag::decode(e, urls, kioURLs, albumIDs, imageIDs))
+ return;
+
+ if (urls.isEmpty() || kioURLs.isEmpty() || albumIDs.isEmpty() || imageIDs.isEmpty())
+ return;
+
+ // all the albumids will be the same
+ int albumID = albumIDs.first();
+ srcAlbum = AlbumManager::instance()->findTAlbum(albumID);
+ if (!srcAlbum)
+ {
+ DWarning() << "Could not find source album of drag"
+ << endl;
+ return;
+ }
+
+ int id = 0;
+ char keys_return[32];
+ XQueryKeymap(x11Display(), keys_return);
+ int key_1 = XKeysymToKeycode(x11Display(), 0xFFE3);
+ int key_2 = XKeysymToKeycode(x11Display(), 0xFFE4);
+
+ if(srcAlbum == destAlbum)
+ {
+ // 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("Tags"));
+ popMenu.insertItem(i18n("Set as Tag 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;
+ AlbumManager::instance()->updateTAlbumIcon(destAlbum, TQString(),
+ imageIDs.first(), errMsg);
+ }
+ return;
+ }
+
+ // If a ctrl key is pressed while dropping the drag object,
+ // the tag is assigned to the images without showing a
+ // popup menu.
+ if (((keys_return[key_1 / 8]) && (1 << (key_1 % 8))) ||
+ ((keys_return[key_2 / 8]) && (1 << (key_2 % 8))))
+ {
+ id = 10;
+ }
+ else
+ {
+ TDEPopupMenu popMenu(this);
+ popMenu.insertTitle(SmallIcon("digikam"), i18n("Tags"));
+ popMenu.insertItem( SmallIcon("tag"), i18n("Assign Tag '%1' to Items")
+ .arg(destAlbum->prettyURL()), 10) ;
+ popMenu.insertSeparator(-1);
+ popMenu.insertItem( SmallIcon("cancel"), i18n("C&ancel") );
+
+ popMenu.setMouseTracking(true);
+ id = popMenu.exec(TQCursor::pos());
+ }
+
+ if (id == 10)
+ {
+ emit signalProgressBarMode(StatusProgressBar::ProgressBarMode,
+ i18n("Assign tag to images. Please wait..."));
+
+ AlbumLister::instance()->blockSignals(true);
+ AlbumManager::instance()->albumDB()->beginTransaction();
+ int i=0;
+ for (TQValueList<int>::const_iterator it = imageIDs.begin();
+ it != imageIDs.end(); ++it)
+ {
+ // create temporary ImageInfo object
+ ImageInfo info(*it);
+
+ MetadataHub hub;
+ hub.load(&info);
+ hub.setTag(destAlbum, true);
+ hub.write(&info, MetadataHub::PartialWrite);
+ hub.write(info.filePath(), MetadataHub::FullWriteIfChanged);
+
+ emit signalProgressValue((int)((i++/(float)imageIDs.count())*100.0));
+ kapp->processEvents();
+ }
+ AlbumLister::instance()->blockSignals(false);
+ AlbumManager::instance()->albumDB()->commitTransaction();
+
+ ImageAttributesWatch::instance()->imagesChanged(destAlbum->id());
+
+ emit signalProgressBarMode(StatusProgressBar::TextMode, TQString());
+ }
+ }
+}
+
+void TAlbumListView::refresh()
+{
+ TQListViewItemIterator it(this);
+
+ while (it.current())
+ {
+ TAlbumCheckListItem* item = dynamic_cast<TAlbumCheckListItem*>(*it);
+ if (item)
+ item->refresh();
+ ++it;
+ }
+}
+
+void TAlbumListView::slotRefresh(const TQMap<int, int>& tagsStatMap)
+{
+ TQListViewItemIterator it(this);
+
+ while (it.current())
+ {
+ TAlbumCheckListItem* item = dynamic_cast<TAlbumCheckListItem*>(*it);
+ if (item)
+ {
+ if (item->album())
+ {
+ int id = item->id();
+ TQMap<int, int>::const_iterator it2 = tagsStatMap.find(id);
+ if ( it2 != tagsStatMap.end() )
+ item->setCount(it2.data());
+ }
+ }
+ ++it;
+ }
+
+ refresh();
+}
+
+void TAlbumListView::loadViewState()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup(name());
+
+ int selectedItem = config->readNumEntry("LastSelectedItem", 0);
+
+ TQValueList<int> openFolders;
+ if(config->hasKey("OpenFolders"))
+ {
+ openFolders = config->readIntListEntry("OpenFolders");
+ }
+
+ TAlbumCheckListItem *item = 0;
+ TAlbumCheckListItem *foundItem = 0;
+ TQListViewItemIterator it(this->lastItem());
+
+ for( ; it.current(); --it)
+ {
+ item = dynamic_cast<TAlbumCheckListItem*>(it.current());
+ if(!item)
+ continue;
+
+ // Start the album root always open
+ if(openFolders.contains(item->id()) || item->id() == 0)
+ setOpen(item, true);
+ else
+ setOpen(item, false);
+
+ if(item->id() == selectedItem)
+ {
+ // Save the found selected item so that it can be made visible.
+ foundItem = item;
+ }
+ }
+
+ // Important note: this cannot be done inside the previous loop
+ // because opening folders prevents the visibility.
+ // Fixes bug #144815.
+ // (Looks a bit like a bug in TQt to me ...)
+ if (foundItem)
+ {
+ setSelected(foundItem, true);
+ ensureItemVisible(foundItem);
+ }
+}
+
+void TAlbumListView::saveViewState()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup(name());
+
+ TAlbumCheckListItem *item = dynamic_cast<TAlbumCheckListItem*>(selectedItem());
+ if(item)
+ config->writeEntry("LastSelectedItem", item->id());
+ else
+ config->writeEntry("LastSelectedItem", 0);
+
+ TQValueList<int> openFolders;
+ TQListViewItemIterator it(this);
+ for( ; it.current(); ++it)
+ {
+ item = dynamic_cast<TAlbumCheckListItem*>(it.current());
+ if(item && isOpen(item))
+ openFolders.push_back(item->id());
+ }
+ config->writeEntry("OpenFolders", openFolders);
+}
+
+} // NameSpace Digikam