You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
digikam/digikam/utilities/lighttable/lighttablebar.cpp

882 lines
25 KiB

/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2007-04-11
* Description : light table thumbs bar
*
* Copyright (C) 2007-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
*
* 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 <tqpixmap.h>
#include <tqpainter.h>
#include <tqimage.h>
#include <tqcursor.h>
// KDE includes.
#include <tdeglobal.h>
#include <kiconloader.h>
#include <tdelocale.h>
#include <tdepopupmenu.h>
#include <kstandarddirs.h>
// Local includes.
#include "ddebug.h"
#include "album.h"
#include "albumdb.h"
#include "albummanager.h"
#include "albumsettings.h"
#include "dragobjects.h"
#include "imageattributeswatch.h"
#include "metadatahub.h"
#include "ratingpopupmenu.h"
#include "themeengine.h"
#include "lighttablebar.h"
#include "lighttablebar.moc"
namespace Digikam
{
class LightTableBarPriv
{
public:
LightTableBarPriv()
{
navigateByPair = false;
toolTip = 0;
}
bool navigateByPair;
TQPixmap ratingPixmap;
LightTableBarToolTip *toolTip;
};
class LightTableBarItemPriv
{
public:
LightTableBarItemPriv()
{
onLeftPanel = false;
onRightPanel = false;
info = 0;
}
bool onLeftPanel;
bool onRightPanel;
ImageInfo *info;
};
LightTableBar::LightTableBar(TQWidget* parent, int orientation, bool exifRotate)
: ThumbBarView(parent, orientation, exifRotate)
{
d = new LightTableBarPriv;
setMouseTracking(true);
readToolTipSettings();
d->toolTip = new LightTableBarToolTip(this);
// -- Load rating Pixmap ------------------------------------------
TDEGlobal::dirs()->addResourceType("digikam_rating", TDEGlobal::dirs()->kde_default("data")
+ "digikam/data");
TQString ratingPixPath = TDEGlobal::dirs()->findResourceDir("digikam_rating", "rating.png");
ratingPixPath += "/rating.png";
d->ratingPixmap = TQPixmap(ratingPixPath);
TQPainter painter(&d->ratingPixmap);
painter.fillRect(0, 0, d->ratingPixmap.width(), d->ratingPixmap.height(),
ThemeEngine::instance()->textSpecialRegColor());
painter.end();
if (orientation ==TQt::Vertical)
setMinimumWidth(d->ratingPixmap.width()*5 + 6 + 2*getMargin());
else
setMinimumHeight(d->ratingPixmap.width()*5 + 6 + 2*getMargin());
// ----------------------------------------------------------------
ImageAttributesWatch *watch = ImageAttributesWatch::instance();
connect(watch, TQT_SIGNAL(signalImageRatingChanged(TQ_LLONG)),
this, TQT_SLOT(slotImageRatingChanged(TQ_LLONG)));
connect(ThemeEngine::instance(), TQT_SIGNAL(signalThemeChanged()),
this, TQT_SLOT(slotThemeChanged()));
connect(this, TQT_SIGNAL(signalItemSelected(ThumbBarItem*)),
this, TQT_SLOT(slotItemSelected(ThumbBarItem*)));
}
LightTableBar::~LightTableBar()
{
delete d->toolTip;
delete d;
}
void LightTableBar::setNavigateByPair(bool b)
{
d->navigateByPair = b;
}
void LightTableBar::slotImageRatingChanged(TQ_LLONG imageId)
{
for (ThumbBarItem *item = firstItem(); item; item = item->next())
{
LightTableBarItem *ltItem = dynamic_cast<LightTableBarItem*>(item);
if (ltItem->info()->id() == imageId)
{
triggerUpdate();
return;
}
}
}
void LightTableBar::contentsMouseReleaseEvent(TQMouseEvent *e)
{
if (!e) return;
ThumbBarView::contentsMouseReleaseEvent(e);
TQPoint pos = TQCursor::pos();
LightTableBarItem *item = findItemByPos(e->pos());
RatingPopupMenu *ratingMenu = 0;
if (e->button() == TQt::RightButton)
{
TDEPopupMenu popmenu(this);
if (item)
{
popmenu.insertItem(SmallIcon("go-previous"), i18n("Show on left panel"), 10);
popmenu.insertItem(SmallIcon("go-next"), i18n("Show on right panel"), 11);
popmenu.insertItem(SmallIcon("editimage"), i18n("Edit"), 12);
if (d->navigateByPair)
{
popmenu.setItemEnabled(10, false);
popmenu.setItemEnabled(11, false);
}
popmenu.insertSeparator();
popmenu.insertItem(SmallIcon("window-close"), i18n("Remove item"), 13);
}
int totalItems = itemsURLs().count();
popmenu.insertItem(SmallIcon("editshred"), i18n("Clear all"), 14);
popmenu.setItemEnabled(14, totalItems ? true : false);
if (item)
{
popmenu.insertSeparator();
// Assign Star Rating -------------------------------------------
ratingMenu = new RatingPopupMenu();
connect(ratingMenu, TQT_SIGNAL(activated(int)),
this, TQT_SLOT(slotAssignRating(int)));
popmenu.insertItem(i18n("Assign Rating"), ratingMenu);
}
switch(popmenu.exec(pos))
{
case 10: // Left panel
{
emit signalSetItemOnLeftPanel(item->info());
break;
}
case 11: // Right panel
{
emit signalSetItemOnRightPanel(item->info());
break;
}
case 12: // Edit
{
emit signalEditItem(item->info());
break;
}
case 13: // Remove
{
emit signalRemoveItem(item->info());
break;
}
case 14: // Clear All
{
emit signalClearAll();
break;
}
default:
break;
}
}
delete ratingMenu;
}
void LightTableBar::slotAssignRating(int rating)
{
rating = TQMIN(5, TQMAX(0, rating));
ImageInfo *info = currentItemImageInfo();
if (info)
{
MetadataHub hub;
hub.load(info);
hub.setRating(rating);
hub.write(info, MetadataHub::PartialWrite);
hub.write(info->filePath(), MetadataHub::FullWriteIfChanged);
}
}
void LightTableBar::slotAssignRatingNoStar()
{
slotAssignRating(0);
}
void LightTableBar::slotAssignRatingOneStar()
{
slotAssignRating(1);
}
void LightTableBar::slotAssignRatingTwoStar()
{
slotAssignRating(2);
}
void LightTableBar::slotAssignRatingThreeStar()
{
slotAssignRating(3);
}
void LightTableBar::slotAssignRatingFourStar()
{
slotAssignRating(4);
}
void LightTableBar::slotAssignRatingFiveStar()
{
slotAssignRating(5);
}
void LightTableBar::setOnLeftPanel(const ImageInfo* info)
{
for (ThumbBarItem *item = firstItem(); item; item = item->next())
{
LightTableBarItem *ltItem = dynamic_cast<LightTableBarItem*>(item);
if (ltItem)
{
if (info)
{
if (ltItem->info()->id() == info->id())
{
ltItem->setOnLeftPanel(true);
repaintItem(item);
}
else if (ltItem->isOnLeftPanel() == true)
{
ltItem->setOnLeftPanel(false);
repaintItem(item);
}
}
else if (ltItem->isOnLeftPanel() == true)
{
ltItem->setOnLeftPanel(false);
repaintItem(item);
}
}
}
}
void LightTableBar::setOnRightPanel(const ImageInfo* info)
{
for (ThumbBarItem *item = firstItem(); item; item = item->next())
{
LightTableBarItem *ltItem = dynamic_cast<LightTableBarItem*>(item);
if (ltItem)
{
if (info)
{
if (ltItem->info()->id() == info->id())
{
ltItem->setOnRightPanel(true);
repaintItem(item);
}
else if (ltItem->isOnRightPanel() == true)
{
ltItem->setOnRightPanel(false);
repaintItem(item);
}
}
else if (ltItem->isOnRightPanel() == true)
{
ltItem->setOnRightPanel(false);
repaintItem(item);
}
}
}
}
void LightTableBar::slotItemSelected(ThumbBarItem* item)
{
if (item)
{
LightTableBarItem *ltItem = dynamic_cast<LightTableBarItem*>(item);
if (ltItem)
{
emit signalLightTableBarItemSelected(ltItem->info());
return;
}
}
emit signalLightTableBarItemSelected(0);
}
ImageInfo* LightTableBar::currentItemImageInfo() const
{
if (currentItem())
{
LightTableBarItem *item = dynamic_cast<LightTableBarItem*>(currentItem());
return item->info();
}
return 0;
}
ImageInfoList LightTableBar::itemsImageInfoList()
{
ImageInfoList list;
for (ThumbBarItem *item = firstItem(); item; item = item->next())
{
LightTableBarItem *ltItem = dynamic_cast<LightTableBarItem*>(item);
if (ltItem)
{
ImageInfo *info = new ImageInfo(*(ltItem->info()));
list.append(info);
}
}
return list;
}
void LightTableBar::setSelectedItem(LightTableBarItem* ltItem)
{
ThumbBarItem *item = static_cast<ThumbBarItem*>(ltItem);
if (item) ThumbBarView::setSelected(item);
}
void LightTableBar::removeItem(const ImageInfo* info)
{
if (!info) return;
LightTableBarItem* ltItem = findItemByInfo(info);
ThumbBarItem *item = static_cast<ThumbBarItem*>(ltItem);
if (item) ThumbBarView::removeItem(item);
}
LightTableBarItem* LightTableBar::findItemByInfo(const ImageInfo* info) const
{
if (info)
{
for (ThumbBarItem *item = firstItem(); item; item = item->next())
{
LightTableBarItem *ltItem = dynamic_cast<LightTableBarItem*>(item);
if (ltItem)
{
if (ltItem->info()->id() == info->id())
return ltItem;
}
}
}
return 0;
}
LightTableBarItem* LightTableBar::findItemByPos(const TQPoint& pos) const
{
ThumbBarItem *item = findItem(pos);
if (item)
{
LightTableBarItem *ltItem = dynamic_cast<LightTableBarItem*>(item);
return ltItem;
}
return 0;
}
void LightTableBar::readToolTipSettings()
{
AlbumSettings* albumSettings = AlbumSettings::instance();
if (!albumSettings) return;
Digikam::ThumbBarToolTipSettings settings;
settings.showToolTips = albumSettings->getShowToolTips();
settings.showFileName = albumSettings->getToolTipsShowFileName();
settings.showFileDate = albumSettings->getToolTipsShowFileDate();
settings.showFileSize = albumSettings->getToolTipsShowFileSize();
settings.showImageType = albumSettings->getToolTipsShowImageType();
settings.showImageDim = albumSettings->getToolTipsShowImageDim();
settings.showPhotoMake = albumSettings->getToolTipsShowPhotoMake();
settings.showPhotoDate = albumSettings->getToolTipsShowPhotoDate();
settings.showPhotoFocal = albumSettings->getToolTipsShowPhotoFocal();
settings.showPhotoExpo = albumSettings->getToolTipsShowPhotoExpo();
settings.showPhotoMode = albumSettings->getToolTipsShowPhotoMode();
settings.showPhotoFlash = albumSettings->getToolTipsShowPhotoFlash();
settings.showPhotoWB = albumSettings->getToolTipsShowPhotoWB();
setToolTipSettings(settings);
}
void LightTableBar::viewportPaintEvent(TQPaintEvent* e)
{
ThemeEngine* te = ThemeEngine::instance();
TQRect er(e->rect());
TQPixmap bgPix;
if (countItems() > 0)
{
int cy, cx, ts, y1, y2, x1, x2;
TQPixmap tile;
if (getOrientation() ==TQt::Vertical)
{
cy = viewportToContents(er.topLeft()).y();
bgPix.resize(contentsRect().width(), er.height());
ts = getTileSize() + 2*getMargin();
tile.resize(visibleWidth(), ts);
y1 = (cy/ts)*ts;
y2 = ((y1 + er.height())/ts +1)*ts;
}
else
{
cx = viewportToContents(er.topLeft()).x();
bgPix.resize(er.width(), contentsRect().height());
ts = getTileSize() + 2*getMargin();
tile.resize(ts, visibleHeight());
x1 = (cx/ts)*ts;
x2 = ((x1 + er.width())/ts +1)*ts;
}
bgPix.fill(te->baseColor());
for (ThumbBarItem *item = firstItem(); item; item = item->next())
{
if (getOrientation() ==TQt::Vertical)
{
if (y1 <= item->position() && item->position() <= y2)
{
if (item == currentItem())
tile = te->thumbSelPixmap(tile.width(), tile.height());
else
tile = te->thumbRegPixmap(tile.width(), tile.height());
TQPainter p(&tile);
if (item == currentItem())
{
p.setPen(TQPen(te->textSelColor(), 3));
p.drawRect(2, 2, tile.width()-2, tile.height()-2);
}
else
{
p.setPen(TQPen(te->textRegColor(), 1));
p.drawRect(0, 0, tile.width(), tile.height());
}
p.end();
if (item->pixmap())
{
TQPixmap pix;
pix.convertFromImage(TQImage(item->pixmap()->convertToImage()).
smoothScale(getTileSize(), getTileSize(), TQImage::ScaleMin));
int x = (tile.width() - pix.width())/2;
int y = (tile.height() - pix.height())/2;
bitBlt(&tile, x, y, &pix);
LightTableBarItem *ltItem = dynamic_cast<LightTableBarItem*>(item);
if (ltItem->isOnLeftPanel())
{
TQPixmap lPix = SmallIcon("go-previous");
bitBlt(&tile, getMargin(), getMargin(), &lPix);
}
if (ltItem->isOnRightPanel())
{
TQPixmap rPix = SmallIcon("go-next");
bitBlt(&tile, tile.width() - getMargin() - rPix.width(), getMargin(), &rPix);
}
TQRect r(0, tile.height()-getMargin()-d->ratingPixmap.height(),
tile.width(), d->ratingPixmap.height());
int rating = ltItem->info()->rating();
int xr = (r.width() - rating * d->ratingPixmap.width())/2;
int wr = rating * d->ratingPixmap.width();
TQPainter p(&tile);
p.drawTiledPixmap(xr, r.y(), wr, r.height(), d->ratingPixmap);
}
bitBlt(&bgPix, 0, item->position() - cy, &tile);
}
}
else
{
if (x1 <= item->position() && item->position() <= x2)
{
if (item == currentItem())
tile = te->thumbSelPixmap(tile.width(), tile.height());
else
tile = te->thumbRegPixmap(tile.width(), tile.height());
TQPainter p(&tile);
if (item == currentItem())
{
p.setPen(TQPen(te->textSelColor(), 2));
p.drawRect(1, 1, tile.width()-1, tile.height()-1);
}
else
{
p.setPen(TQPen(te->textRegColor(), 1));
p.drawRect(0, 0, tile.width(), tile.height());
}
p.end();
if (item->pixmap())
{
TQPixmap pix;
pix.convertFromImage(TQImage(item->pixmap()->convertToImage()).
smoothScale(getTileSize(), getTileSize(), TQImage::ScaleMin));
int x = (tile.width() - pix.width())/2;
int y = (tile.height()- pix.height())/2;
bitBlt(&tile, x, y, &pix);
LightTableBarItem *ltItem = dynamic_cast<LightTableBarItem*>(item);
if (ltItem->isOnLeftPanel())
{
TQPixmap lPix = SmallIcon("go-previous");
bitBlt(&tile, getMargin(), getMargin(), &lPix);
}
if (ltItem->isOnRightPanel())
{
TQPixmap rPix = SmallIcon("go-next");
bitBlt(&tile, tile.width() - getMargin() - rPix.width(), getMargin(), &rPix);
}
TQRect r(0, tile.height()-getMargin()-d->ratingPixmap.height(),
tile.width(), d->ratingPixmap.height());
int rating = ltItem->info()->rating();
int xr = (r.width() - rating * d->ratingPixmap.width())/2;
int wr = rating * d->ratingPixmap.width();
TQPainter p(&tile);
p.drawTiledPixmap(xr, r.y(), wr, r.height(), d->ratingPixmap);
}
bitBlt(&bgPix, item->position() - cx, 0, &tile);
}
}
}
if (getOrientation() ==TQt::Vertical)
bitBlt(viewport(), 0, er.y(), &bgPix);
else
bitBlt(viewport(), er.x(), 0, &bgPix);
}
else
{
bgPix.resize(contentsRect().width(), contentsRect().height());
bgPix.fill(te->baseColor());
TQPainter p(&bgPix);
p.setPen(TQPen(te->textRegColor()));
p.drawText(0, 0, bgPix.width(), bgPix.height(),
TQt::AlignCenter|TQt::WordBreak,
i18n("Drag and drop images here"));
p.end();
bitBlt(viewport(), 0, 0, &bgPix);
}
}
void LightTableBar::startDrag()
{
if (!currentItem()) return;
KURL::List urls;
KURL::List kioURLs;
TQValueList<int> albumIDs;
TQValueList<int> imageIDs;
LightTableBarItem *item = dynamic_cast<LightTableBarItem*>(currentItem());
urls.append(item->info()->kurl());
kioURLs.append(item->info()->kurlForKIO());
imageIDs.append(item->info()->id());
albumIDs.append(item->info()->albumID());
TQPixmap icon(DesktopIcon("image-x-generic", 48));
int w = icon.width();
int h = icon.height();
TQPixmap pix(w+4,h+4);
TQPainter p(&pix);
p.fillRect(0, 0, w+4, h+4, TQColor(TQt::white));
p.setPen(TQPen(TQt::black, 1));
p.drawRect(0, 0, w+4, h+4);
p.drawPixmap(2, 2, icon);
p.end();
TQDragObject* drag = 0;
drag = new ItemDrag(urls, kioURLs, albumIDs, imageIDs, this);
if (drag)
{
drag->setPixmap(pix);
drag->drag();
}
}
void LightTableBar::contentsDragMoveEvent(TQDragMoveEvent *e)
{
int albumID;
TQValueList<int> albumIDs;
TQValueList<int> imageIDs;
KURL::List urls;
KURL::List kioURLs;
if (ItemDrag::decode(e, urls, kioURLs, albumIDs, imageIDs) ||
AlbumDrag::decode(e, urls, albumID) ||
TagDrag::canDecode(e))
{
e->accept();
return;
}
e->ignore();
}
void LightTableBar::contentsDropEvent(TQDropEvent *e)
{
int albumID;
TQValueList<int> albumIDs;
TQValueList<int> imageIDs;
KURL::List urls;
KURL::List kioURLs;
if (ItemDrag::decode(e, urls, kioURLs, albumIDs, imageIDs))
{
ImageInfoList imageInfoList;
for (TQValueList<int>::const_iterator it = imageIDs.begin();
it != imageIDs.end(); ++it)
{
ImageInfo *info = new ImageInfo(*it);
if (!findItemByInfo(info))
{
imageInfoList.append(info);
}
else
{
delete info;
}
}
emit signalDroppedItems(imageInfoList);
e->accept();
}
else if (AlbumDrag::decode(e, urls, albumID))
{
TQValueList<TQ_LLONG> itemIDs = AlbumManager::instance()->albumDB()->getItemIDsInAlbum(albumID);
ImageInfoList imageInfoList;
for (TQValueList<TQ_LLONG>::const_iterator it = itemIDs.begin();
it != itemIDs.end(); ++it)
{
ImageInfo *info = new ImageInfo(*it);
if (!findItemByInfo(info))
{
imageInfoList.append(info);
}
else
{
delete info;
}
}
emit signalDroppedItems(imageInfoList);
e->accept();
}
else if(TagDrag::canDecode(e))
{
TQByteArray ba = e->encodedData("digikam/tag-id");
TQDataStream ds(ba, IO_ReadOnly);
int tagID;
ds >> tagID;
AlbumManager* man = AlbumManager::instance();
TQValueList<TQ_LLONG> itemIDs = man->albumDB()->getItemIDsInTag(tagID, true);
ImageInfoList imageInfoList;
for (TQValueList<TQ_LLONG>::const_iterator it = itemIDs.begin();
it != itemIDs.end(); ++it)
{
ImageInfo *info = new ImageInfo(*it);
if (!findItemByInfo(info))
{
imageInfoList.append(info);
}
else
{
delete info;
}
}
emit signalDroppedItems(imageInfoList);
e->accept();
}
else
{
e->ignore();
}
}
void LightTableBar::slotThemeChanged()
{
TDEGlobal::dirs()->addResourceType("digikam_rating", TDEGlobal::dirs()->kde_default("data")
+ "digikam/data");
TQString ratingPixPath = TDEGlobal::dirs()->findResourceDir("digikam_rating", "rating.png");
ratingPixPath += "/rating.png";
d->ratingPixmap = TQPixmap(ratingPixPath);
TQPainter painter(&d->ratingPixmap);
painter.fillRect(0, 0, d->ratingPixmap.width(), d->ratingPixmap.height(),
ThemeEngine::instance()->textSpecialRegColor());
painter.end();
slotUpdate();
}
// -------------------------------------------------------------------------
LightTableBarItem::LightTableBarItem(LightTableBar *view, ImageInfo *info)
: ThumbBarItem(view, info->kurl())
{
d = new LightTableBarItemPriv;
d->info = info;
}
LightTableBarItem::~LightTableBarItem()
{
delete d;
}
ImageInfo* LightTableBarItem::info() const
{
return d->info;
}
void LightTableBarItem::setOnLeftPanel(bool on)
{
d->onLeftPanel = on;
}
void LightTableBarItem::setOnRightPanel(bool on)
{
d->onRightPanel = on;
}
bool LightTableBarItem::isOnLeftPanel() const
{
return d->onLeftPanel;
}
bool LightTableBarItem::isOnRightPanel() const
{
return d->onRightPanel;
}
// -------------------------------------------------------------------------
LightTableBarToolTip::LightTableBarToolTip(ThumbBarView *parent)
: ThumbBarToolTip(parent)
{
}
TQString LightTableBarToolTip::tipContentExtraData(ThumbBarItem *item)
{
TQString tip, str;
AlbumSettings* settings = AlbumSettings::instance();
ImageInfo* info = static_cast<LightTableBarItem *>(item)->info();
if (settings)
{
if (settings->getToolTipsShowAlbumName() ||
settings->getToolTipsShowComments() ||
settings->getToolTipsShowTags() ||
settings->getToolTipsShowRating())
{
tip += m_headBeg + i18n("digiKam Properties") + m_headEnd;
if (settings->getToolTipsShowAlbumName())
{
PAlbum* album = info->album();
if (album)
tip += m_cellSpecBeg + i18n("Album:") + m_cellSpecMid +
album->url().remove(0, 1) + m_cellSpecEnd;
}
if (settings->getToolTipsShowComments())
{
str = info->caption();
if (str.isEmpty()) str = TQString("---");
tip += m_cellSpecBeg + i18n("Caption:") + m_cellSpecMid + breakString(str) + m_cellSpecEnd;
}
if (settings->getToolTipsShowTags())
{
TQStringList tagPaths = info->tagPaths(false);
str = tagPaths.join(", ");
if (str.isEmpty()) str = TQString("---");
if (str.length() > m_maxStringLen) str = str.left(m_maxStringLen-3) + "...";
tip += m_cellSpecBeg + i18n("Tags:") + m_cellSpecMid + str + m_cellSpecEnd;
}
if (settings->getToolTipsShowRating())
{
str.fill( '*', info->rating() );
if (str.isEmpty()) str = TQString("---");
tip += m_cellSpecBeg + i18n("Rating:") + m_cellSpecMid + str + m_cellSpecEnd;
}
}
}
return tip;
}
} // NameSpace Digikam