summaryrefslogtreecommitdiffstats
path: root/src/utilities/lighttable
diff options
context:
space:
mode:
Diffstat (limited to 'src/utilities/lighttable')
-rw-r--r--src/utilities/lighttable/Makefile.am28
-rw-r--r--src/utilities/lighttable/lighttablebar.cpp881
-rw-r--r--src/utilities/lighttable/lighttablebar.h153
-rw-r--r--src/utilities/lighttable/lighttablepreview.cpp777
-rw-r--r--src/utilities/lighttable/lighttablepreview.h125
-rw-r--r--src/utilities/lighttable/lighttableview.cpp446
-rw-r--r--src/utilities/lighttable/lighttableview.h137
-rw-r--r--src/utilities/lighttable/lighttablewindow.cpp1676
-rw-r--r--src/utilities/lighttable/lighttablewindow.h162
-rw-r--r--src/utilities/lighttable/lighttablewindowprivate.h158
-rw-r--r--src/utilities/lighttable/lighttablewindowui.rc83
11 files changed, 4626 insertions, 0 deletions
diff --git a/src/utilities/lighttable/Makefile.am b/src/utilities/lighttable/Makefile.am
new file mode 100644
index 00000000..df38b5f9
--- /dev/null
+++ b/src/utilities/lighttable/Makefile.am
@@ -0,0 +1,28 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/digikam \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/thumbbar \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/themeengine \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/libs/imageproperties \
+ -I$(top_srcdir)/src/libs/threadimageio \
+ -I$(top_srcdir)/src/utilities/setup \
+ -I$(top_srcdir)/src/utilities/slideshow \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_builddir)/src/libs/dialogs \
+ $(LIBKEXIV2_CFLAGS) $(LIBKDCRAW_CFLAGS) $(all_includes)
+
+noinst_LTLIBRARIES = liblighttable.la
+
+liblighttable_la_SOURCES = lighttablebar.cpp lighttablewindow.cpp lighttablepreview.cpp \
+ lighttableview.cpp
+
+liblighttable_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = lighttablewindowui.rc
diff --git a/src/utilities/lighttable/lighttablebar.cpp b/src/utilities/lighttable/lighttablebar.cpp
new file mode 100644
index 00000000..cfb935ab
--- /dev/null
+++ b/src/utilities/lighttable/lighttablebar.cpp
@@ -0,0 +1,881 @@
+/* ============================================================
+ *
+ * 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, TQ_SIGNAL(signalImageRatingChanged(TQ_LLONG)),
+ this, TQ_SLOT(slotImageRatingChanged(TQ_LLONG)));
+
+ connect(ThemeEngine::instance(), TQ_SIGNAL(signalThemeChanged()),
+ this, TQ_SLOT(slotThemeChanged()));
+
+ connect(this, TQ_SIGNAL(signalItemSelected(ThumbBarItem*)),
+ this, TQ_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, TQ_SIGNAL(activated(int)),
+ this, TQ_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
diff --git a/src/utilities/lighttable/lighttablebar.h b/src/utilities/lighttable/lighttablebar.h
new file mode 100644
index 00000000..b64e93a6
--- /dev/null
+++ b/src/utilities/lighttable/lighttablebar.h
@@ -0,0 +1,153 @@
+/* ============================================================
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef LIGHTTABLEBAR_H
+#define LIGHTTABLEBAR_H
+
+// Local includes.
+
+#include "thumbbar.h"
+#include "imageinfo.h"
+#include "digikam_export.h"
+
+class TQDragMoveEvent;
+class TQDropEvent;
+class TQMouseEvent;
+class TQPaintEvent;
+
+class KURL;
+
+namespace Digikam
+{
+
+class LightTableBarItem;
+class LightTableBarItemPriv;
+class LightTableBarPriv;
+
+class DIGIKAM_EXPORT LightTableBar : public ThumbBarView
+{
+ TQ_OBJECT
+
+
+public:
+
+ LightTableBar(TQWidget* parent, int orientation=Vertical, bool exifRotate=true);
+ ~LightTableBar();
+
+ ImageInfo* currentItemImageInfo() const;
+ ImageInfoList itemsImageInfoList();
+
+ void setSelectedItem(LightTableBarItem* ltItem);
+
+ LightTableBarItem* findItemByInfo(const ImageInfo* info) const;
+ LightTableBarItem* findItemByPos(const TQPoint& pos) const;
+
+ /** Read tool tip settings from Album Settings instance */
+ void readToolTipSettings();
+
+ void setOnLeftPanel(const ImageInfo* info);
+ void setOnRightPanel(const ImageInfo* info);
+
+ void removeItem(const ImageInfo* info);
+
+ void setNavigateByPair(bool b);
+
+signals:
+
+ void signalLightTableBarItemSelected(ImageInfo*);
+ void signalSetItemOnLeftPanel(ImageInfo*);
+ void signalSetItemOnRightPanel(ImageInfo*);
+ void signalEditItem(ImageInfo*);
+ void signalRemoveItem(ImageInfo*);
+ void signalClearAll();
+ void signalDroppedItems(const ImageInfoList&);
+
+private:
+
+ void viewportPaintEvent(TQPaintEvent*);
+ void contentsMouseReleaseEvent(TQMouseEvent*);
+ void startDrag();
+ void contentsDragMoveEvent(TQDragMoveEvent*);
+ void contentsDropEvent(TQDropEvent*);
+
+private slots:
+
+ void slotImageRatingChanged(TQ_LLONG);
+ void slotItemSelected(ThumbBarItem*);
+
+ void slotAssignRatingNoStar();
+ void slotAssignRatingOneStar();
+ void slotAssignRatingTwoStar();
+ void slotAssignRatingThreeStar();
+ void slotAssignRatingFourStar();
+ void slotAssignRatingFiveStar();
+ void slotAssignRating(int);
+
+ void slotThemeChanged();
+
+private:
+
+ LightTableBarPriv *d;
+
+ friend class LightTableBarItem;
+};
+
+// -------------------------------------------------------------------------
+
+class DIGIKAM_EXPORT LightTableBarItem : public ThumbBarItem
+{
+public:
+
+ LightTableBarItem(LightTableBar *view, ImageInfo *info);
+ ~LightTableBarItem();
+
+ ImageInfo* info() const;
+
+ void setOnLeftPanel(bool on);
+ void setOnRightPanel(bool on);
+ bool isOnLeftPanel() const;
+ bool isOnRightPanel() const;
+
+private:
+
+ LightTableBarItemPriv *d;
+
+ friend class LightTableBar;
+};
+
+// -------------------------------------------------------------------------
+
+class DIGIKAM_EXPORT LightTableBarToolTip : public ThumbBarToolTip
+{
+public:
+
+ LightTableBarToolTip(ThumbBarView *parent);
+
+private:
+
+ TQString tipContentExtraData(ThumbBarItem *item);
+};
+
+} // NameSpace Digikam
+
+#endif /* LIGHTTABLEBAR_H */
diff --git a/src/utilities/lighttable/lighttablepreview.cpp b/src/utilities/lighttable/lighttablepreview.cpp
new file mode 100644
index 00000000..100427ec
--- /dev/null
+++ b/src/utilities/lighttable/lighttablepreview.cpp
@@ -0,0 +1,777 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-21-12
+ * Description : digiKam light table preview item.
+ *
+ * Copyright (C) 2006-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 <tqpainter.h>
+#include <tqcursor.h>
+#include <tqstring.h>
+#include <tqvaluevector.h>
+#include <tqfileinfo.h>
+#include <tqtoolbutton.h>
+#include <tqtooltip.h>
+#include <tqpixmap.h>
+#include <tqdrawutil.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+#include <tdelocale.h>
+#include <kservice.h>
+#include <krun.h>
+#include <ktrader.h>
+#include <kmimetype.h>
+#include <kcursor.h>
+#include <kdatetbl.h>
+#include <kiconloader.h>
+#include <kprocess.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "ddebug.h"
+#include "albumdb.h"
+#include "constants.h"
+#include "albummanager.h"
+#include "albumsettings.h"
+#include "dragobjects.h"
+#include "dmetadata.h"
+#include "dpopupmenu.h"
+#include "metadatahub.h"
+#include "paniconwidget.h"
+#include "previewloadthread.h"
+#include "loadingdescription.h"
+#include "tagspopupmenu.h"
+#include "ratingpopupmenu.h"
+#include "themeengine.h"
+#include "lighttablepreview.h"
+#include "lighttablepreview.moc"
+
+namespace Digikam
+{
+
+class LightTablePreviewPriv
+{
+public:
+
+ LightTablePreviewPriv()
+ {
+ panIconPopup = 0;
+ panIconWidget = 0;
+ cornerButton = 0;
+ previewThread = 0;
+ previewPreloadThread = 0;
+ imageInfo = 0;
+ hasPrev = false;
+ hasNext = false;
+ selected = false;
+ dragAndDropEnabled = true;
+ loadFullImageSize = false;
+ currentFitWindowZoom = 0;
+ previewSize = 1024;
+ }
+
+ bool hasPrev;
+ bool hasNext;
+ bool selected;
+ bool dragAndDropEnabled;
+ bool loadFullImageSize;
+
+ int previewSize;
+
+ double currentFitWindowZoom;
+
+ TQString path;
+ TQString nextPath;
+ TQString previousPath;
+
+ TQToolButton *cornerButton;
+
+ TDEPopupFrame *panIconPopup;
+
+ PanIconWidget *panIconWidget;
+
+ DImg preview;
+
+ ImageInfo *imageInfo;
+
+ PreviewLoadThread *previewThread;
+ PreviewLoadThread *previewPreloadThread;
+};
+
+LightTablePreview::LightTablePreview(TQWidget *parent)
+ : PreviewWidget(parent)
+{
+ d = new LightTablePreviewPriv;
+
+ // get preview size from screen size, but limit from VGA to WTQXGA
+ d->previewSize = TQMAX(TDEApplication::desktop()->height(),
+ TDEApplication::desktop()->width());
+ if (d->previewSize < 640)
+ d->previewSize = 640;
+ if (d->previewSize > 2560)
+ d->previewSize = 2560;
+
+ viewport()->setAcceptDrops(true);
+ setAcceptDrops(true);
+
+ slotThemeChanged();
+ setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding);
+
+ d->cornerButton = new TQToolButton(this);
+ d->cornerButton->setIconSet(SmallIcon("move"));
+ d->cornerButton->hide();
+ TQToolTip::add(d->cornerButton, i18n("Pan the image"));
+ setCornerWidget(d->cornerButton);
+
+ setLineWidth(5);
+ setSelected(false);
+
+ // ------------------------------------------------------------
+
+ connect(d->cornerButton, TQ_SIGNAL(pressed()),
+ this, TQ_SLOT(slotCornerButtonPressed()));
+
+ connect(this, TQ_SIGNAL(signalRightButtonClicked()),
+ this, TQ_SLOT(slotContextMenu()));
+
+ connect(ThemeEngine::instance(), TQ_SIGNAL(signalThemeChanged()),
+ this, TQ_SLOT(slotThemeChanged()));
+
+ // ------------------------------------------------------------
+
+ slotReset();
+}
+
+LightTablePreview::~LightTablePreview()
+{
+ delete d->previewThread;
+ delete d->previewPreloadThread;
+ delete d;
+}
+
+void LightTablePreview::setLoadFullImageSize(bool b)
+{
+ d->loadFullImageSize = b;
+ reload();
+}
+
+void LightTablePreview::setDragAndDropEnabled(bool b)
+{
+ d->dragAndDropEnabled = b;
+}
+
+void LightTablePreview::setDragAndDropMessage()
+{
+ if (d->dragAndDropEnabled)
+ {
+ TQPixmap pix(visibleWidth(), visibleHeight());
+ pix.fill(ThemeEngine::instance()->baseColor());
+ TQPainter p(&pix);
+ p.setPen(TQPen(ThemeEngine::instance()->textRegColor()));
+ p.drawText(0, 0, pix.width(), pix.height(),
+ TQt::AlignCenter|TQt::WordBreak,
+ i18n("Drag and drop an image here"));
+ p.end();
+ setImage(pix.convertToImage());
+ }
+}
+
+void LightTablePreview::setImage(const DImg& image)
+{
+ d->preview = image;
+
+ updateZoomAndSize(true);
+
+ viewport()->setUpdatesEnabled(true);
+ viewport()->update();
+}
+
+DImg& LightTablePreview::getImage() const
+{
+ return d->preview;
+}
+
+TQSize LightTablePreview::getImageSize()
+{
+ return d->preview.size();
+}
+
+void LightTablePreview::reload()
+{
+ // cache is cleaned from AlbumIconView::refreshItems
+ setImagePath(d->path);
+}
+
+void LightTablePreview::setPreviousNextPaths(const TQString& previous, const TQString &next)
+{
+ d->nextPath = next;
+ d->previousPath = previous;
+}
+
+void LightTablePreview::setImagePath(const TQString& path)
+{
+ setCursor( KCursor::waitCursor() );
+
+ d->path = path;
+ d->nextPath = TQString();
+ d->previousPath = TQString();
+
+ if (d->path.isEmpty())
+ {
+ slotReset();
+ unsetCursor();
+ return;
+ }
+
+ if (!d->previewThread)
+ {
+ d->previewThread = new PreviewLoadThread();
+ connect(d->previewThread, TQ_SIGNAL(signalImageLoaded(const LoadingDescription &, const DImg &)),
+ this, TQ_SLOT(slotGotImagePreview(const LoadingDescription &, const DImg&)));
+ }
+ if (!d->previewPreloadThread)
+ {
+ d->previewPreloadThread = new PreviewLoadThread();
+ connect(d->previewPreloadThread, TQ_SIGNAL(signalImageLoaded(const LoadingDescription &, const DImg &)),
+ this, TQ_SLOT(slotNextPreload()));
+ }
+
+ if (d->loadFullImageSize)
+ d->previewThread->loadHighQuality(LoadingDescription(path, 0, AlbumSettings::instance()->getExifRotate()));
+ else
+ d->previewThread->load(LoadingDescription(path, d->previewSize, AlbumSettings::instance()->getExifRotate()));
+}
+
+void LightTablePreview::slotGotImagePreview(const LoadingDescription &description, const DImg& preview)
+{
+ if (description.filePath != d->path)
+ return;
+
+ if (preview.isNull())
+ {
+ TQPixmap pix(visibleWidth(), visibleHeight());
+ pix.fill(ThemeEngine::instance()->baseColor());
+ TQPainter p(&pix);
+ TQFileInfo info(d->path);
+ p.setPen(TQPen(ThemeEngine::instance()->textRegColor()));
+ p.drawText(0, 0, pix.width(), pix.height(),
+ TQt::AlignCenter|TQt::WordBreak,
+ i18n("Unable to display preview for\n\"%1\"")
+ .arg(info.fileName()));
+ p.end();
+ setImage(DImg(pix.convertToImage()));
+
+ emit signalPreviewLoaded(false);
+ }
+ else
+ {
+ DImg img(preview);
+ if (AlbumSettings::instance()->getExifRotate())
+ d->previewThread->exifRotate(img, description.filePath);
+ setImage(img);
+ emit signalPreviewLoaded(true);
+ }
+
+ unsetCursor();
+ slotNextPreload();
+}
+
+void LightTablePreview::slotNextPreload()
+{
+ TQString loadPath;
+ if (!d->nextPath.isNull())
+ {
+ loadPath = d->nextPath;
+ d->nextPath = TQString();
+ }
+ else if (!d->previousPath.isNull())
+ {
+ loadPath = d->previousPath;
+ d->previousPath = TQString();
+ }
+ else
+ return;
+
+ d->previewPreloadThread->load(LoadingDescription(loadPath, d->previewSize,
+ AlbumSettings::instance()->getExifRotate()));
+}
+
+void LightTablePreview::setImageInfo(ImageInfo* info, ImageInfo *previous, ImageInfo *next)
+{
+ d->imageInfo = info;
+ d->hasPrev = previous;
+ d->hasNext = next;
+
+ if (d->imageInfo)
+ setImagePath(info->filePath());
+ else
+ {
+ setImagePath();
+ setSelected(false);
+ }
+
+ setPreviousNextPaths(previous ? previous->filePath() : TQString(),
+ next ? next->filePath() : TQString());
+}
+
+ImageInfo* LightTablePreview::getImageInfo() const
+{
+ return d->imageInfo;
+}
+
+void LightTablePreview::slotContextMenu()
+{
+ RatingPopupMenu *ratingMenu = 0;
+ TagsPopupMenu *assignTagsMenu = 0;
+ TagsPopupMenu *removeTagsMenu = 0;
+
+ if (!d->imageInfo)
+ return;
+
+ //-- Open With Actions ------------------------------------
+
+ KURL url(d->imageInfo->kurl().path());
+ KMimeType::Ptr mimePtr = KMimeType::findByURL(url, 0, true, true);
+
+ TQValueVector<KService::Ptr> serviceVector;
+ TDETrader::OfferList offers = TDETrader::self()->query(mimePtr->name(), "Type == 'Application'");
+
+ TQPopupMenu openWithMenu;
+
+ TDETrader::OfferList::Iterator iter;
+ KService::Ptr ptr;
+ int index = 100;
+
+ for( iter = offers.begin(); iter != offers.end(); ++iter )
+ {
+ ptr = *iter;
+ openWithMenu.insertItem( ptr->pixmap(TDEIcon::Small), ptr->name(), index++);
+ serviceVector.push_back(ptr);
+ }
+
+ DPopupMenu popmenu(this);
+
+ //-- Zoom actions -----------------------------------------------
+
+ popmenu.insertItem(SmallIcon("viewmag"), i18n("Zoom in"), 17);
+ popmenu.insertItem(SmallIcon("zoom-out"), i18n("Zoom out"), 18);
+ popmenu.insertItem(SmallIcon("view_fit_window"), i18n("Fit to &Window"), 19);
+
+ //-- Edit actions -----------------------------------------------
+
+ popmenu.insertSeparator();
+ popmenu.insertItem(SmallIcon("slideshow"), i18n("SlideShow"), 16);
+ popmenu.insertItem(SmallIcon("editimage"), i18n("Edit..."), 12);
+ popmenu.insertItem(i18n("Open With"), &openWithMenu, 13);
+
+ //-- Trash action -------------------------------------------
+
+ popmenu.insertSeparator();
+ popmenu.insertItem(SmallIcon("edittrash"), i18n("Move to Trash"), 14);
+
+ // Bulk assignment/removal of tags --------------------------
+
+ TQ_LLONG id = d->imageInfo->id();
+ TQValueList<TQ_LLONG> idList;
+ idList.append(id);
+
+ assignTagsMenu = new TagsPopupMenu(idList, 1000, TagsPopupMenu::ASSIGN);
+ removeTagsMenu = new TagsPopupMenu(idList, 2000, TagsPopupMenu::REMOVE);
+
+ popmenu.insertSeparator();
+
+ popmenu.insertItem(i18n("Assign Tag"), assignTagsMenu);
+ int i = popmenu.insertItem(i18n("Remove Tag"), removeTagsMenu);
+
+ connect(assignTagsMenu, TQ_SIGNAL(signalTagActivated(int)),
+ this, TQ_SLOT(slotAssignTag(int)));
+
+ connect(removeTagsMenu, TQ_SIGNAL(signalTagActivated(int)),
+ this, TQ_SLOT(slotRemoveTag(int)));
+
+ AlbumDB* db = AlbumManager::instance()->albumDB();
+ if (!db->hasTags( idList ))
+ popmenu.setItemEnabled(i, false);
+
+ popmenu.insertSeparator();
+
+ // Assign Star Rating -------------------------------------------
+
+ ratingMenu = new RatingPopupMenu();
+
+ connect(ratingMenu, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotAssignRating(int)));
+
+ popmenu.insertItem(i18n("Assign Rating"), ratingMenu);
+
+ // --------------------------------------------------------
+
+ int idm = popmenu.exec(TQCursor::pos());
+
+ switch(idm)
+ {
+ case 12: // Edit...
+ {
+ emit signalEditItem(d->imageInfo);
+ break;
+ }
+
+ case 14: // Move to trash
+ {
+ emit signalDeleteItem(d->imageInfo);
+ break;
+ }
+
+ case 16: // SlideShow
+ {
+ emit signalSlideShow();
+ break;
+ }
+
+ case 17: // Zoom in
+ {
+ slotIncreaseZoom();
+ break;
+ }
+
+ case 18: // Zoom out
+ {
+ slotDecreaseZoom();
+ break;
+ }
+
+ case 19: // Fit to window
+ {
+ fitToWindow();
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ // Open With...
+ if (idm >= 100 && idm < 1000)
+ {
+ KService::Ptr imageServicePtr = serviceVector[idm-100];
+ KRun::run(*imageServicePtr, url);
+ }
+
+ serviceVector.clear();
+ delete assignTagsMenu;
+ delete removeTagsMenu;
+ delete ratingMenu;
+}
+
+void LightTablePreview::slotAssignTag(int tagID)
+{
+ if (d->imageInfo)
+ {
+ MetadataHub hub;
+ hub.load(d->imageInfo);
+ hub.setTag(tagID, true);
+ hub.write(d->imageInfo, MetadataHub::PartialWrite);
+ hub.write(d->imageInfo->filePath(), MetadataHub::FullWriteIfChanged);
+ }
+}
+
+void LightTablePreview::slotRemoveTag(int tagID)
+{
+ if (d->imageInfo)
+ {
+ MetadataHub hub;
+ hub.load(d->imageInfo);
+ hub.setTag(tagID, false);
+ hub.write(d->imageInfo, MetadataHub::PartialWrite);
+ hub.write(d->imageInfo->filePath(), MetadataHub::FullWriteIfChanged);
+ }
+}
+
+void LightTablePreview::slotAssignRating(int rating)
+{
+ rating = TQMIN(RatingMax, TQMAX(RatingMin, rating));
+ if (d->imageInfo)
+ {
+ MetadataHub hub;
+ hub.load(d->imageInfo);
+ hub.setRating(rating);
+ hub.write(d->imageInfo, MetadataHub::PartialWrite);
+ hub.write(d->imageInfo->filePath(), MetadataHub::FullWriteIfChanged);
+ }
+}
+
+void LightTablePreview::slotThemeChanged()
+{
+ setBackgroundColor(ThemeEngine::instance()->baseColor());
+ frameChanged();
+}
+
+void LightTablePreview::slotCornerButtonPressed()
+{
+ if (d->panIconPopup)
+ {
+ d->panIconPopup->hide();
+ delete d->panIconPopup;
+ d->panIconPopup = 0;
+ }
+
+ d->panIconPopup = new TDEPopupFrame(this);
+ PanIconWidget *pan = new PanIconWidget(d->panIconPopup);
+ pan->setImage(180, 120, getImage());
+ d->panIconPopup->setMainWidget(pan);
+
+ TQRect r((int)(contentsX() / zoomFactor()), (int)(contentsY() / zoomFactor()),
+ (int)(visibleWidth() / zoomFactor()), (int)(visibleHeight() / zoomFactor()));
+ pan->setRegionSelection(r);
+ pan->setMouseFocus();
+
+ connect(pan, TQ_SIGNAL(signalSelectionMoved(const TQRect&, bool)),
+ this, TQ_SLOT(slotPanIconSelectionMoved(const TQRect&, bool)));
+
+ connect(pan, TQ_SIGNAL(signalHiden()),
+ this, TQ_SLOT(slotPanIconHiden()));
+
+ TQPoint g = mapToGlobal(viewport()->pos());
+ g.setX(g.x()+ viewport()->size().width());
+ g.setY(g.y()+ viewport()->size().height());
+ d->panIconPopup->popup(TQPoint(g.x() - d->panIconPopup->width(),
+ g.y() - d->panIconPopup->height()));
+
+ pan->setCursorToLocalRegionSelectionCenter();
+}
+
+void LightTablePreview::slotPanIconHiden()
+{
+ d->cornerButton->blockSignals(true);
+ d->cornerButton->animateClick();
+ d->cornerButton->blockSignals(false);
+}
+
+void LightTablePreview::slotPanIconSelectionMoved(const TQRect& r, bool b)
+{
+ setContentsPos((int)(r.x()*zoomFactor()), (int)(r.y()*zoomFactor()));
+
+ if (b)
+ {
+ d->panIconPopup->hide();
+ delete d->panIconPopup;
+ d->panIconPopup = 0;
+ slotPanIconHiden();
+ }
+}
+
+void LightTablePreview::zoomFactorChanged(double zoom)
+{
+ updateScrollBars();
+
+ if (horizontalScrollBar()->isVisible() || verticalScrollBar()->isVisible())
+ d->cornerButton->show();
+ else
+ d->cornerButton->hide();
+
+ PreviewWidget::zoomFactorChanged(zoom);
+}
+
+void LightTablePreview::resizeEvent(TQResizeEvent* e)
+{
+ if (!e) return;
+
+ TQScrollView::resizeEvent(e);
+
+ if (!d->imageInfo)
+ {
+ d->cornerButton->hide();
+ setDragAndDropMessage();
+ }
+
+ updateZoomAndSize(false);
+}
+
+void LightTablePreview::updateZoomAndSize(bool alwaysFitToWindow)
+{
+ // Set zoom for fit-in-window as minimum, but dont scale up images
+ // that are smaller than the available space, only scale down.
+ double zoom = calcAutoZoomFactor(ZoomInOnly);
+ setZoomMin(zoom);
+ setZoomMax(zoom*12.0);
+
+ // Is currently the zoom factor set to fit to window? Then set it again to fit the new size.
+ if (zoomFactor() < zoom || alwaysFitToWindow || zoomFactor() == d->currentFitWindowZoom)
+ {
+ setZoomFactor(zoom);
+ }
+
+ // store which zoom factor means it is fit to window
+ d->currentFitWindowZoom = zoom;
+
+ updateContentsSize();
+}
+
+int LightTablePreview::previewWidth()
+{
+ return d->preview.width();
+}
+
+int LightTablePreview::previewHeight()
+{
+ return d->preview.height();
+}
+
+bool LightTablePreview::previewIsNull()
+{
+ return d->preview.isNull();
+}
+
+void LightTablePreview::resetPreview()
+{
+ d->preview = DImg();
+ d->path = TQString();
+ d->imageInfo = 0;
+
+ setDragAndDropMessage();
+ updateZoomAndSize(true);
+ viewport()->setUpdatesEnabled(true);
+ viewport()->update();
+ emit signalPreviewLoaded(false);
+}
+
+void LightTablePreview::paintPreview(TQPixmap *pix, int sx, int sy, int sw, int sh)
+{
+ DImg img = d->preview.smoothScaleSection(sx, sy, sw, sh, tileSize(), tileSize());
+ TQPixmap pix2 = img.convertToPixmap();
+ bitBlt(pix, 0, 0, &pix2, 0, 0);
+}
+
+void LightTablePreview::contentsDragMoveEvent(TQDragMoveEvent *e)
+{
+ if (d->dragAndDropEnabled)
+ {
+ 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 LightTablePreview::contentsDropEvent(TQDropEvent *e)
+{
+ if (d->dragAndDropEnabled)
+ {
+ int albumID;
+ TQValueList<int> albumIDs;
+ TQValueList<int> imageIDs;
+ KURL::List urls;
+ KURL::List kioURLs;
+ ImageInfoList list;
+
+ if (ItemDrag::decode(e, urls, kioURLs, albumIDs, imageIDs))
+ {
+ for (TQValueList<int>::const_iterator it = imageIDs.begin();
+ it != imageIDs.end(); ++it)
+ {
+ list.append(new ImageInfo(*it));
+ }
+
+ emit signalDroppedItems(list);
+ e->accept();
+ return;
+ }
+ else if (AlbumDrag::decode(e, urls, albumID))
+ {
+ TQValueList<TQ_LLONG> itemIDs = AlbumManager::instance()->albumDB()->getItemIDsInAlbum(albumID);
+
+ for (TQValueList<TQ_LLONG>::const_iterator it = itemIDs.begin();
+ it != itemIDs.end(); ++it)
+ {
+ list.append(new ImageInfo(*it));
+ }
+
+ emit signalDroppedItems(list);
+ e->accept();
+ return;
+ }
+ 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)
+ {
+ list.append(new ImageInfo(*it));
+ }
+
+ emit signalDroppedItems(list);
+ e->accept();
+ return;
+ }
+ }
+
+ e->ignore();
+}
+
+void LightTablePreview::setSelected(bool sel)
+{
+ if (d->selected != sel)
+ {
+ d->selected = sel;
+ frameChanged();
+ }
+}
+
+bool LightTablePreview::isSelected()
+{
+ return d->selected;
+}
+
+void LightTablePreview::drawFrame(TQPainter *p)
+{
+ if (d->selected)
+ {
+ qDrawPlainRect(p, frameRect(), ThemeEngine::instance()->thumbSelColor(), lineWidth());
+ qDrawPlainRect(p, frameRect(), ThemeEngine::instance()->textSelColor(), 2);
+ }
+ else
+ qDrawPlainRect(p, frameRect(), ThemeEngine::instance()->baseColor(), lineWidth());
+}
+
+} // NameSpace Digikam
diff --git a/src/utilities/lighttable/lighttablepreview.h b/src/utilities/lighttable/lighttablepreview.h
new file mode 100644
index 00000000..3549fa1c
--- /dev/null
+++ b/src/utilities/lighttable/lighttablepreview.h
@@ -0,0 +1,125 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-21-12
+ * Description : digiKam light table preview item.
+ *
+ * Copyright (C) 2006-2008 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.
+ *
+ * ============================================================ */
+
+#ifndef LIGHTTABLEPREVIEW_H
+#define LIGHTTABLEPREVIEW_H
+
+// TQt includes.
+
+#include <tqstring.h>
+#include <tqimage.h>
+#include <tqsize.h>
+
+// Local includes.
+
+#include "imageinfo.h"
+#include "previewwidget.h"
+#include "digikam_export.h"
+
+class TQPixmap;
+
+namespace Digikam
+{
+
+class DImg;
+class LoadingDescription;
+class LightTablePreviewPriv;
+
+class DIGIKAM_EXPORT LightTablePreview : public PreviewWidget
+{
+
+TQ_OBJECT
+
+
+public:
+
+ LightTablePreview(TQWidget *parent=0);
+ ~LightTablePreview();
+
+ void setLoadFullImageSize(bool b);
+
+ void setImage(const DImg& image);
+ DImg& getImage() const;
+
+ TQSize getImageSize();
+
+ void setImageInfo(ImageInfo* info=0, ImageInfo *previous=0, ImageInfo *next=0);
+ ImageInfo* getImageInfo() const;
+
+ void reload();
+ void setImagePath(const TQString& path=TQString());
+ void setPreviousNextPaths(const TQString& previous, const TQString &next);
+
+ void setSelected(bool sel);
+ bool isSelected();
+
+ void setDragAndDropEnabled(bool b);
+ void setDragAndDropMessage();
+
+signals:
+
+ void signalDroppedItems(const ImageInfoList&);
+ void signalDeleteItem(ImageInfo*);
+ void signalEditItem(ImageInfo*);
+ void signalPreviewLoaded(bool success);
+ void signalSlideShow();
+
+protected:
+
+ void resizeEvent(TQResizeEvent* e);
+ void drawFrame(TQPainter *p);
+
+private slots:
+
+ void slotGotImagePreview(const LoadingDescription &loadingDescription, const DImg &image);
+ void slotNextPreload();
+ void slotContextMenu();
+ void slotAssignTag(int tagID);
+ void slotRemoveTag(int tagID);
+ void slotAssignRating(int rating);
+ void slotThemeChanged();
+ void slotCornerButtonPressed();
+ void slotPanIconSelectionMoved(const TQRect&, bool);
+ void slotPanIconHiden();
+
+private:
+
+ int previewWidth();
+ int previewHeight();
+ bool previewIsNull();
+ void resetPreview();
+ void zoomFactorChanged(double zoom);
+ void updateZoomAndSize(bool alwaysFitToWindow);
+ inline void paintPreview(TQPixmap *pix, int sx, int sy, int sw, int sh);
+
+ void contentsDragMoveEvent(TQDragMoveEvent*);
+ void contentsDropEvent(TQDropEvent*);
+
+private:
+
+ LightTablePreviewPriv* d;
+};
+
+} // NameSpace Digikam
+
+#endif /* LIGHTTABLEPREVIEW_H */
diff --git a/src/utilities/lighttable/lighttableview.cpp b/src/utilities/lighttable/lighttableview.cpp
new file mode 100644
index 00000000..51f45ab5
--- /dev/null
+++ b/src/utilities/lighttable/lighttableview.cpp
@@ -0,0 +1,446 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-03-05
+ * Description : a widget to display 2 preview image on
+ * lightable to compare pictures.
+ *
+ * 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 <tqlayout.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "thumbnailsize.h"
+#include "lighttablepreview.h"
+#include "lighttableview.h"
+#include "lighttableview.moc"
+
+namespace Digikam
+{
+
+class LightTableViewPriv
+{
+public:
+
+ LightTableViewPriv()
+ {
+ syncPreview = false;
+ leftLoading = false;
+ rightLoading = false;
+ leftPreview = 0;
+ rightPreview = 0;
+ grid = 0;
+ }
+
+ bool syncPreview;
+ bool leftLoading; // To not sync right panel during left loading.
+ bool rightLoading; // To not sync left panel during right loading.
+
+ TQGridLayout *grid;
+
+ LightTablePreview *leftPreview;
+ LightTablePreview *rightPreview;
+};
+
+LightTableView::LightTableView(TQWidget *parent)
+ : TQFrame(parent, 0, TQt::WDestructiveClose)
+{
+ d = new LightTableViewPriv;
+
+ setFrameStyle(TQFrame::NoFrame);
+ setMargin(0);
+ setLineWidth(0);
+
+ d->grid = new TQGridLayout(this, 1, 1, 0, 1);
+ d->leftPreview = new LightTablePreview(this);
+ d->rightPreview = new LightTablePreview(this);
+
+ d->grid->addMultiCellWidget(d->leftPreview, 0, 0, 0, 0);
+ d->grid->addMultiCellWidget(d->rightPreview, 0, 0, 1, 1);
+
+ d->grid->setColStretch(0, 10),
+ d->grid->setColStretch(1, 10),
+ d->grid->setRowStretch(0, 10),
+
+ // Left panel connections ------------------------------------------------
+
+ connect(d->leftPreview, TQ_SIGNAL(signalZoomFactorChanged(double)),
+ this, TQ_SIGNAL(signalLeftZoomFactorChanged(double)));
+
+ connect(d->leftPreview, TQ_SIGNAL(contentsMoving(int, int)),
+ this, TQ_SLOT(slotLeftContentsMoved(int, int)));
+
+ connect(d->leftPreview, TQ_SIGNAL(signalSlideShow()),
+ this, TQ_SIGNAL(signalSlideShow()));
+
+ connect(d->leftPreview, TQ_SIGNAL(signalDeleteItem(ImageInfo*)),
+ this, TQ_SIGNAL(signalDeleteItem(ImageInfo*)));
+
+ connect(d->leftPreview, TQ_SIGNAL(signalEditItem(ImageInfo*)),
+ this, TQ_SIGNAL(signalEditItem(ImageInfo*)));
+
+ connect(d->leftPreview, TQ_SIGNAL(signalDroppedItems(const ImageInfoList&)),
+ this, TQ_SIGNAL(signalLeftDroppedItems(const ImageInfoList&)));
+
+ connect(d->leftPreview, TQ_SIGNAL(signalPreviewLoaded(bool)),
+ this, TQ_SLOT(slotLeftPreviewLoaded(bool)));
+
+ connect(d->leftPreview, TQ_SIGNAL(signalLeftButtonClicked()),
+ this, TQ_SIGNAL(signalLeftPanelLeftButtonClicked()));
+
+ // Right panel connections ------------------------------------------------
+
+ connect(d->rightPreview, TQ_SIGNAL(signalZoomFactorChanged(double)),
+ this, TQ_SIGNAL(signalRightZoomFactorChanged(double)));
+
+ connect(d->rightPreview, TQ_SIGNAL(contentsMoving(int, int)),
+ this, TQ_SLOT(slotRightContentsMoved(int, int)));
+
+ connect(d->rightPreview, TQ_SIGNAL(signalDeleteItem(ImageInfo*)),
+ this, TQ_SIGNAL(signalDeleteItem(ImageInfo*)));
+
+ connect(d->rightPreview, TQ_SIGNAL(signalEditItem(ImageInfo*)),
+ this, TQ_SIGNAL(signalEditItem(ImageInfo*)));
+
+ connect(d->rightPreview, TQ_SIGNAL(signalDroppedItems(const ImageInfoList&)),
+ this, TQ_SIGNAL(signalRightDroppedItems(const ImageInfoList&)));
+
+ connect(d->rightPreview, TQ_SIGNAL(signalSlideShow()),
+ this, TQ_SIGNAL(signalSlideShow()));
+
+ connect(d->rightPreview, TQ_SIGNAL(signalPreviewLoaded(bool)),
+ this, TQ_SLOT(slotRightPreviewLoaded(bool)));
+
+ connect(d->rightPreview, TQ_SIGNAL(signalLeftButtonClicked()),
+ this, TQ_SIGNAL(signalRightPanelLeftButtonClicked()));
+}
+
+LightTableView::~LightTableView()
+{
+ delete d;
+}
+
+void LightTableView::setLoadFullImageSize(bool b)
+{
+ d->leftPreview->setLoadFullImageSize(b);
+ d->rightPreview->setLoadFullImageSize(b);
+}
+
+void LightTableView::setSyncPreview(bool sync)
+{
+ d->syncPreview = sync;
+
+ // Left panel like a reference to resync preview.
+ if (d->syncPreview)
+ slotLeftContentsMoved(d->leftPreview->contentsX(), d->leftPreview->contentsY());
+}
+
+void LightTableView::setNavigateByPair(bool b)
+{
+ d->leftPreview->setDragAndDropEnabled(!b);
+ d->rightPreview->setDragAndDropEnabled(!b);
+}
+
+void LightTableView::slotDecreaseZoom()
+{
+ if (d->syncPreview)
+ {
+ slotDecreaseLeftZoom();
+ return;
+ }
+
+ if (d->leftPreview->isSelected())
+ slotDecreaseLeftZoom();
+ else if (d->rightPreview->isSelected())
+ slotDecreaseRightZoom();
+}
+
+void LightTableView::slotIncreaseZoom()
+{
+ if (d->syncPreview)
+ {
+ slotIncreaseLeftZoom();
+ return;
+ }
+
+ if (d->leftPreview->isSelected())
+ slotIncreaseLeftZoom();
+ else if (d->rightPreview->isSelected())
+ slotIncreaseRightZoom();
+}
+
+void LightTableView::slotDecreaseLeftZoom()
+{
+ d->leftPreview->slotDecreaseZoom();
+}
+
+void LightTableView::slotIncreaseLeftZoom()
+{
+ d->leftPreview->slotIncreaseZoom();
+}
+
+void LightTableView::slotDecreaseRightZoom()
+{
+ d->rightPreview->slotDecreaseZoom();
+}
+
+void LightTableView::slotIncreaseRightZoom()
+{
+ d->rightPreview->slotIncreaseZoom();
+}
+
+void LightTableView::setLeftZoomFactor(double z)
+{
+ d->leftPreview->setZoomFactor(z);
+}
+
+void LightTableView::setRightZoomFactor(double z)
+{
+ d->rightPreview->setZoomFactor(z);
+}
+
+void LightTableView::fitToWindow()
+{
+ d->leftPreview->fitToWindow();
+ d->rightPreview->fitToWindow();
+}
+
+void LightTableView::toggleFitToWindowOr100()
+{
+ // If we are currently precisely at 100%, then fit to window,
+ // otherwise zoom to a centered 100% view.
+ if ((d->leftPreview->zoomFactor()==1.0) &&
+ (d->rightPreview->zoomFactor()==1.0))
+ {
+ fitToWindow();
+ }
+ else
+ {
+ d->leftPreview->setZoomFactor(1.0, true);
+ d->rightPreview->setZoomFactor(1.0, true);
+ }
+}
+
+double LightTableView::leftZoomMax()
+{
+ return d->leftPreview->zoomMax();
+}
+
+double LightTableView::leftZoomMin()
+{
+ return d->leftPreview->zoomMin();
+}
+
+bool LightTableView::leftMaxZoom()
+{
+ return d->leftPreview->maxZoom();
+}
+
+bool LightTableView::leftMinZoom()
+{
+ return d->leftPreview->minZoom();
+}
+
+double LightTableView::rightZoomMax()
+{
+ return d->rightPreview->zoomMax();
+}
+
+double LightTableView::rightZoomMin()
+{
+ return d->rightPreview->zoomMin();
+}
+
+bool LightTableView::rightMaxZoom()
+{
+ return d->rightPreview->maxZoom();
+}
+
+bool LightTableView::rightMinZoom()
+{
+ return d->rightPreview->minZoom();
+}
+
+void LightTableView::slotLeftZoomSliderChanged(int size)
+{
+ double h = (double)ThumbnailSize::Huge;
+ double s = (double)ThumbnailSize::Small;
+ double zmin = d->leftPreview->zoomMin();
+ double zmax = d->leftPreview->zoomMax();
+ double b = (zmin-(zmax*s/h))/(1-s/h);
+ double a = (zmax-b)/h;
+ double z = a*size+b;
+
+ d->leftPreview->setZoomFactorSnapped(z);
+}
+
+void LightTableView::slotRightZoomSliderChanged(int size)
+{
+ double h = (double)ThumbnailSize::Huge;
+ double s = (double)ThumbnailSize::Small;
+ double zmin = d->rightPreview->zoomMin();
+ double zmax = d->rightPreview->zoomMax();
+ double b = (zmin-(zmax*s/h))/(1-s/h);
+ double a = (zmax-b)/h;
+ double z = a*size+b;
+
+ d->rightPreview->setZoomFactorSnapped(z);
+}
+
+void LightTableView::leftReload()
+{
+ d->leftPreview->reload();
+}
+
+void LightTableView::rightReload()
+{
+ d->rightPreview->reload();
+}
+
+void LightTableView::slotLeftContentsMoved(int x, int y)
+{
+ if (d->syncPreview && !d->leftLoading)
+ {
+ disconnect(d->rightPreview, TQ_SIGNAL(signalZoomFactorChanged(double)),
+ this, TQ_SIGNAL(signalRightZoomFactorChanged(double)));
+
+ disconnect(d->rightPreview, TQ_SIGNAL(contentsMoving(int, int)),
+ this, TQ_SLOT(slotRightContentsMoved(int, int)));
+
+ setRightZoomFactor(d->leftPreview->zoomFactor());
+ emit signalRightZoomFactorChanged(d->leftPreview->zoomFactor());
+ d->rightPreview->setContentsPos(x, y);
+
+ connect(d->rightPreview, TQ_SIGNAL(signalZoomFactorChanged(double)),
+ this, TQ_SIGNAL(signalRightZoomFactorChanged(double)));
+
+ connect(d->rightPreview, TQ_SIGNAL(contentsMoving(int, int)),
+ this, TQ_SLOT(slotRightContentsMoved(int, int)));
+ }
+}
+
+void LightTableView::slotRightContentsMoved(int x, int y)
+{
+ if (d->syncPreview && !d->rightLoading)
+ {
+ disconnect(d->leftPreview, TQ_SIGNAL(signalZoomFactorChanged(double)),
+ this, TQ_SIGNAL(signalLeftZoomFactorChanged(double)));
+
+ disconnect(d->leftPreview, TQ_SIGNAL(contentsMoving(int, int)),
+ this, TQ_SLOT(slotLeftContentsMoved(int, int)));
+
+
+ setLeftZoomFactor(d->rightPreview->zoomFactor());
+ emit signalLeftZoomFactorChanged(d->rightPreview->zoomFactor());
+ d->leftPreview->setContentsPos(x, y);
+
+ connect(d->leftPreview, TQ_SIGNAL(signalZoomFactorChanged(double)),
+ this, TQ_SIGNAL(signalLeftZoomFactorChanged(double)));
+
+ connect(d->leftPreview, TQ_SIGNAL(contentsMoving(int, int)),
+ this, TQ_SLOT(slotLeftContentsMoved(int, int)));
+ }
+}
+
+ImageInfo* LightTableView::leftImageInfo() const
+{
+ return d->leftPreview->getImageInfo();
+}
+
+ImageInfo* LightTableView::rightImageInfo() const
+{
+ return d->rightPreview->getImageInfo();
+}
+
+void LightTableView::setLeftImageInfo(ImageInfo* info)
+{
+ d->leftLoading = true;
+ d->leftPreview->setImageInfo(info);
+}
+
+void LightTableView::setRightImageInfo(ImageInfo* info)
+{
+ d->rightLoading = true;
+ d->rightPreview->setImageInfo(info);
+}
+
+void LightTableView::slotLeftPreviewLoaded(bool success)
+{
+ checkForSyncPreview();
+ d->leftLoading = false;
+ slotRightContentsMoved(d->rightPreview->contentsX(),
+ d->rightPreview->contentsY());
+
+ emit signalLeftPreviewLoaded(success);
+}
+
+void LightTableView::slotRightPreviewLoaded(bool success)
+{
+ checkForSyncPreview();
+ d->rightLoading = false;
+ slotLeftContentsMoved(d->leftPreview->contentsX(),
+ d->leftPreview->contentsY());
+
+ emit signalRightPreviewLoaded(success);
+}
+
+void LightTableView::checkForSyncPreview()
+{
+ if (d->leftPreview->getImageInfo() && d->rightPreview->getImageInfo() &&
+ d->leftPreview->getImageSize() == d->rightPreview->getImageSize())
+ {
+ d->syncPreview = true;
+ }
+ else
+ {
+ d->syncPreview = false;
+ }
+
+ emit signalToggleOnSyncPreview(d->syncPreview);
+}
+
+void LightTableView::checkForSelection(ImageInfo* info)
+{
+ if (!info)
+ {
+ d->leftPreview->setSelected(false);
+ d->rightPreview->setSelected(false);
+ return;
+ }
+
+ if (d->leftPreview->getImageInfo())
+ {
+ d->leftPreview->setSelected(d->leftPreview->getImageInfo()->id() == info->id());
+ }
+
+ if (d->rightPreview->getImageInfo())
+ {
+ d->rightPreview->setSelected(d->rightPreview->getImageInfo()->id() == info->id());
+ }
+}
+
+} // namespace Digikam
+
diff --git a/src/utilities/lighttable/lighttableview.h b/src/utilities/lighttable/lighttableview.h
new file mode 100644
index 00000000..273b7072
--- /dev/null
+++ b/src/utilities/lighttable/lighttableview.h
@@ -0,0 +1,137 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-03-05
+ * Description : a widget to display 2 preview image on
+ * lightable to compare pictures.
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef LIGHTTABLEVIEW_H
+#define LIGHTTABLEVIEW_H
+
+// TQt includes.
+
+#include <tqframe.h>
+#include <tqstring.h>
+
+// Local includes.
+
+#include "imageinfo.h"
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class LightTableViewPriv;
+
+class DIGIKAM_EXPORT LightTableView : public TQFrame
+{
+
+TQ_OBJECT
+
+
+public:
+
+ LightTableView(TQWidget *parent=0);
+ ~LightTableView();
+
+ void setSyncPreview(bool sync);
+ void setNavigateByPair(bool b);
+
+ void setLeftImageInfo(ImageInfo* info=0);
+ void setRightImageInfo(ImageInfo* info=0);
+
+ ImageInfo* leftImageInfo() const;
+ ImageInfo* rightImageInfo() const;
+
+ void setLoadFullImageSize(bool b);
+
+ void setLeftZoomFactor(double z);
+ void setRightZoomFactor(double z);
+
+ void checkForSelection(ImageInfo* info);
+
+ double leftZoomMax();
+ double leftZoomMin();
+
+ double rightZoomMax();
+ double rightZoomMin();
+
+ bool leftMaxZoom();
+ bool leftMinZoom();
+
+ bool rightMaxZoom();
+ bool rightMinZoom();
+
+ void leftReload();
+ void rightReload();
+
+ void fitToWindow();
+ void toggleFitToWindowOr100();
+
+signals:
+
+ void signalLeftPreviewLoaded(bool);
+ void signalRightPreviewLoaded(bool);
+
+ void signalLeftZoomFactorChanged(double);
+ void signalRightZoomFactorChanged(double);
+
+ void signalLeftDroppedItems(const ImageInfoList&);
+ void signalRightDroppedItems(const ImageInfoList&);
+
+ void signalLeftPanelLeftButtonClicked();
+ void signalRightPanelLeftButtonClicked();
+
+ void signalSlideShow();
+ void signalDeleteItem(ImageInfo*);
+ void signalEditItem(ImageInfo*);
+ void signalToggleOnSyncPreview(bool);
+
+public slots:
+
+ void slotDecreaseZoom();
+ void slotIncreaseZoom();
+ void slotDecreaseLeftZoom();
+ void slotIncreaseLeftZoom();
+ void slotLeftZoomSliderChanged(int);
+
+ void slotDecreaseRightZoom();
+ void slotIncreaseRightZoom();
+ void slotRightZoomSliderChanged(int);
+
+private slots:
+
+ void slotLeftContentsMoved(int, int);
+ void slotRightContentsMoved(int, int);
+ void slotLeftPreviewLoaded(bool);
+ void slotRightPreviewLoaded(bool);
+
+private :
+
+ void checkForSyncPreview();
+
+private :
+
+ LightTableViewPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* LIGHTTABLEVIEW_H */
diff --git a/src/utilities/lighttable/lighttablewindow.cpp b/src/utilities/lighttable/lighttablewindow.cpp
new file mode 100644
index 00000000..58409aef
--- /dev/null
+++ b/src/utilities/lighttable/lighttablewindow.cpp
@@ -0,0 +1,1676 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-03-05
+ * Description : digiKam light table GUI
+ *
+ * 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 <tqdockarea.h>
+
+// KDE includes.
+
+#include <kkeydialog.h>
+#include <kedittoolbar.h>
+#include <tdeversion.h>
+#include <tdelocale.h>
+#include <twin.h>
+#include <tdemessagebox.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kstatusbar.h>
+#include <tdemenubar.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/version.h>
+#include <libkdcraw/kdcraw.h>
+
+#if KDCRAW_VERSION < 0x000106
+#include <libkdcraw/dcrawbinary.h>
+#endif
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dlogoaction.h"
+#include "themeengine.h"
+#include "dimg.h"
+#include "dmetadata.h"
+#include "albumsettings.h"
+#include "albummanager.h"
+#include "deletedialog.h"
+#include "imagewindow.h"
+#include "slideshow.h"
+#include "setup.h"
+#include "syncjob.h"
+#include "thumbnailsize.h"
+#include "rawcameradlg.h"
+#include "lighttablepreview.h"
+#include "lighttablewindowprivate.h"
+#include "lighttablewindow.h"
+#include "lighttablewindow.moc"
+
+namespace Digikam
+{
+
+LightTableWindow* LightTableWindow::m_instance = 0;
+
+LightTableWindow* LightTableWindow::lightTableWindow()
+{
+ if (!m_instance)
+ new LightTableWindow();
+
+ return m_instance;
+}
+
+bool LightTableWindow::lightTableWindowCreated()
+{
+ return m_instance;
+}
+
+LightTableWindow::LightTableWindow()
+ : TDEMainWindow(0, "lighttable", WType_TopLevel)
+{
+ d = new LightTableWindowPriv;
+ m_instance = this;
+
+ setCaption(i18n("Light Table"));
+
+ // -- Build the GUI -------------------------------
+
+ setupUserArea();
+ setupStatusBar();
+ setupActions();
+ setupAccelerators();
+
+ // Make signals/slots connections
+
+ setupConnections();
+
+ //-------------------------------------------------------------
+
+ d->leftSidebar->loadViewState();
+ d->rightSidebar->loadViewState();
+ d->leftSidebar->populateTags();
+ d->rightSidebar->populateTags();
+
+ readSettings();
+ applySettings();
+ setAutoSaveSettings("LightTable Settings");
+}
+
+LightTableWindow::~LightTableWindow()
+{
+ m_instance = 0;
+
+ delete d->barView;
+ delete d->rightSidebar;
+ delete d->leftSidebar;
+ delete d;
+}
+
+void LightTableWindow::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("LightTable Settings");
+
+ if(config->hasKey("Vertical Splitter Sizes"))
+ d->vSplitter->setSizes(config->readIntListEntry("Vertical Splitter Sizes"));
+
+ if(config->hasKey("Horizontal Splitter Sizes"))
+ d->hSplitter->setSizes(config->readIntListEntry("Horizontal Splitter Sizes"));
+
+ d->navigateByPairAction->setChecked(config->readBoolEntry("Navigate By Pair", false));
+ slotToggleNavigateByPair();
+}
+
+void LightTableWindow::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("LightTable Settings");
+ config->writeEntry("Vertical Splitter Sizes", d->vSplitter->sizes());
+ config->writeEntry("Horizontal Splitter Sizes", d->hSplitter->sizes());
+ config->writeEntry("Navigate By Pair", d->navigateByPairAction->isChecked());
+ config->sync();
+}
+
+void LightTableWindow::applySettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("LightTable Settings");
+
+ d->autoLoadOnRightPanel = config->readBoolEntry("Auto Load Right Panel", true);
+ d->autoSyncPreview = config->readBoolEntry("Auto Sync Preview", true);
+ d->fullScreenHideToolBar = config->readBoolEntry("FullScreen Hide ToolBar", false);
+ d->previewView->setLoadFullImageSize(config->readBoolEntry("Load Full Image size", false));
+ refreshView();
+}
+
+void LightTableWindow::refreshView()
+{
+ d->leftSidebar->refreshTagsView();
+ d->rightSidebar->refreshTagsView();
+}
+
+void LightTableWindow::closeEvent(TQCloseEvent* e)
+{
+ if (!e) return;
+
+ writeSettings();
+
+ e->accept();
+}
+
+void LightTableWindow::setupUserArea()
+{
+ TQWidget* mainW = new TQWidget(this);
+ d->hSplitter = new TQSplitter(TQt::Horizontal, mainW);
+ TQHBoxLayout *hlay = new TQHBoxLayout(mainW);
+ d->leftSidebar = new ImagePropertiesSideBarDB(mainW,
+ "LightTable Left Sidebar", d->hSplitter,
+ Sidebar::Left, true);
+
+ TQWidget* centralW = new TQWidget(d->hSplitter);
+ TQVBoxLayout *vlay = new TQVBoxLayout(centralW);
+ d->vSplitter = new TQSplitter(TQt::Vertical, centralW);
+ d->barView = new LightTableBar(d->vSplitter, ThumbBarView::Horizontal,
+ AlbumSettings::instance()->getExifRotate());
+ d->previewView = new LightTableView(d->vSplitter);
+ vlay->addWidget(d->vSplitter);
+
+ d->rightSidebar = new ImagePropertiesSideBarDB(mainW,
+ "LightTable Right Sidebar", d->hSplitter,
+ Sidebar::Right, true);
+
+ hlay->addWidget(d->leftSidebar);
+ hlay->addWidget(d->hSplitter);
+ hlay->addWidget(d->rightSidebar);
+
+ d->hSplitter->setFrameStyle( TQFrame::NoFrame );
+ d->hSplitter->setFrameShadow( TQFrame::Plain );
+ d->hSplitter->setFrameShape( TQFrame::NoFrame );
+ d->hSplitter->setOpaqueResize(false);
+ d->vSplitter->setFrameStyle( TQFrame::NoFrame );
+ d->vSplitter->setFrameShadow( TQFrame::Plain );
+ d->vSplitter->setFrameShape( TQFrame::NoFrame );
+ d->vSplitter->setOpaqueResize(false);
+
+ setCentralWidget(mainW);
+}
+
+void LightTableWindow::setupStatusBar()
+{
+ d->leftZoomBar = new StatusZoomBar(statusBar());
+ d->leftZoomBar->setMaximumHeight(fontMetrics().height()+2);
+ statusBar()->addWidget(d->leftZoomBar, 1);
+ d->leftZoomBar->setEnabled(false);
+
+ d->statusProgressBar = new StatusProgressBar(statusBar());
+ d->statusProgressBar->setAlignment(TQt::AlignCenter);
+ d->statusProgressBar->setMaximumHeight(fontMetrics().height()+2);
+ statusBar()->addWidget(d->statusProgressBar, 100);
+
+ d->rightZoomBar = new StatusZoomBar(statusBar());
+ d->rightZoomBar->setMaximumHeight(fontMetrics().height()+2);
+ statusBar()->addWidget(d->rightZoomBar, 1);
+ d->rightZoomBar->setEnabled(false);
+}
+
+void LightTableWindow::setupConnections()
+{
+ connect(d->statusProgressBar, TQ_SIGNAL(signalCancelButtonPressed()),
+ this, TQ_SLOT(slotProgressBarCancelButtonPressed()));
+
+ connect(ThemeEngine::instance(), TQ_SIGNAL(signalThemeChanged()),
+ this, TQ_SLOT(slotThemeChanged()));
+
+ // Thumbs bar connections ---------------------------------------
+
+ connect(d->barView, TQ_SIGNAL(signalSetItemOnLeftPanel(ImageInfo*)),
+ this, TQ_SLOT(slotSetItemOnLeftPanel(ImageInfo*)));
+
+ connect(d->barView, TQ_SIGNAL(signalSetItemOnRightPanel(ImageInfo*)),
+ this, TQ_SLOT(slotSetItemOnRightPanel(ImageInfo*)));
+
+ connect(d->barView, TQ_SIGNAL(signalRemoveItem(ImageInfo*)),
+ this, TQ_SLOT(slotRemoveItem(ImageInfo*)));
+
+ connect(d->barView, TQ_SIGNAL(signalEditItem(ImageInfo*)),
+ this, TQ_SLOT(slotEditItem(ImageInfo*)));
+
+ connect(d->barView, TQ_SIGNAL(signalClearAll()),
+ this, TQ_SLOT(slotClearItemsList()));
+
+ connect(d->barView, TQ_SIGNAL(signalLightTableBarItemSelected(ImageInfo*)),
+ this, TQ_SLOT(slotItemSelected(ImageInfo*)));
+
+ connect(d->barView, TQ_SIGNAL(signalDroppedItems(const ImageInfoList&)),
+ this, TQ_SLOT(slotThumbbarDroppedItems(const ImageInfoList&)));
+
+ // Zoom bars connections -----------------------------------------
+
+ connect(d->leftZoomBar, TQ_SIGNAL(signalZoomMinusClicked()),
+ d->previewView, TQ_SLOT(slotDecreaseLeftZoom()));
+
+ connect(d->leftZoomBar, TQ_SIGNAL(signalZoomPlusClicked()),
+ d->previewView, TQ_SLOT(slotIncreaseLeftZoom()));
+
+ connect(d->leftZoomBar, TQ_SIGNAL(signalZoomSliderChanged(int)),
+ d->previewView, TQ_SLOT(slotLeftZoomSliderChanged(int)));
+
+ connect(d->rightZoomBar, TQ_SIGNAL(signalZoomMinusClicked()),
+ d->previewView, TQ_SLOT(slotDecreaseRightZoom()));
+
+ connect(d->rightZoomBar, TQ_SIGNAL(signalZoomPlusClicked()),
+ d->previewView, TQ_SLOT(slotIncreaseRightZoom()));
+
+ connect(d->rightZoomBar, TQ_SIGNAL(signalZoomSliderChanged(int)),
+ d->previewView, TQ_SLOT(slotRightZoomSliderChanged(int)));
+
+ // View connections ---------------------------------------------
+
+ connect(d->previewView, TQ_SIGNAL(signalLeftZoomFactorChanged(double)),
+ this, TQ_SLOT(slotLeftZoomFactorChanged(double)));
+
+ connect(d->previewView, TQ_SIGNAL(signalRightZoomFactorChanged(double)),
+ this, TQ_SLOT(slotRightZoomFactorChanged(double)));
+
+ connect(d->previewView, TQ_SIGNAL(signalEditItem(ImageInfo*)),
+ this, TQ_SLOT(slotEditItem(ImageInfo*)));
+
+ connect(d->previewView, TQ_SIGNAL(signalDeleteItem(ImageInfo*)),
+ this, TQ_SLOT(slotDeleteItem(ImageInfo*)));
+
+ connect(d->previewView, TQ_SIGNAL(signalSlideShow()),
+ this, TQ_SLOT(slotToggleSlideShow()));
+
+ connect(d->previewView, TQ_SIGNAL(signalLeftDroppedItems(const ImageInfoList&)),
+ this, TQ_SLOT(slotLeftDroppedItems(const ImageInfoList&)));
+
+ connect(d->previewView, TQ_SIGNAL(signalRightDroppedItems(const ImageInfoList&)),
+ this, TQ_SLOT(slotRightDroppedItems(const ImageInfoList&)));
+
+ connect(d->previewView, TQ_SIGNAL(signalToggleOnSyncPreview(bool)),
+ this, TQ_SLOT(slotToggleOnSyncPreview(bool)));
+
+ connect(d->previewView, TQ_SIGNAL(signalLeftPreviewLoaded(bool)),
+ this, TQ_SLOT(slotLeftPreviewLoaded(bool)));
+
+ connect(d->previewView, TQ_SIGNAL(signalRightPreviewLoaded(bool)),
+ this, TQ_SLOT(slotRightPreviewLoaded(bool)));
+
+ connect(d->previewView, TQ_SIGNAL(signalLeftPanelLeftButtonClicked()),
+ this, TQ_SLOT(slotLeftPanelLeftButtonClicked()));
+
+ connect(d->previewView, TQ_SIGNAL(signalRightPanelLeftButtonClicked()),
+ this, TQ_SLOT(slotRightPanelLeftButtonClicked()));
+}
+
+void LightTableWindow::setupActions()
+{
+ // -- Standard 'File' menu actions ---------------------------------------------
+
+ d->backwardAction = KStdAction::back(this, TQ_SLOT(slotBackward()),
+ actionCollection(), "lighttable_backward");
+ d->backwardAction->setEnabled(false);
+
+ d->forwardAction = KStdAction::forward(this, TQ_SLOT(slotForward()),
+ actionCollection(), "lighttable_forward");
+ d->forwardAction->setEnabled(false);
+
+ d->firstAction = new TDEAction(i18n("&First"), "go-first",
+ TDEStdAccel::shortcut( TDEStdAccel::Home),
+ this, TQ_SLOT(slotFirst()),
+ actionCollection(), "lighttable_first");
+ d->firstAction->setEnabled(false);
+
+ d->lastAction = new TDEAction(i18n("&Last"), "go-last",
+ TDEStdAccel::shortcut( TDEStdAccel::End),
+ this, TQ_SLOT(slotLast()),
+ actionCollection(), "lighttable_last");
+ d->lastAction->setEnabled(false);
+
+ d->setItemLeftAction = new TDEAction(i18n("On Left"), "go-previous",
+ CTRL+Key_L, this, TQ_SLOT(slotSetItemLeft()),
+ actionCollection(), "lighttable_setitemleft");
+ d->setItemLeftAction->setEnabled(false);
+ d->setItemLeftAction->setWhatsThis(i18n("Show item on left panel"));
+
+ d->setItemRightAction = new TDEAction(i18n("On Right"), "go-next",
+ CTRL+Key_R, this, TQ_SLOT(slotSetItemRight()),
+ actionCollection(), "lighttable_setitemright");
+ d->setItemRightAction->setEnabled(false);
+ d->setItemRightAction->setWhatsThis(i18n("Show item on right panel"));
+
+ d->editItemAction = new TDEAction(i18n("Edit"), "editimage",
+ Key_F4, this, TQ_SLOT(slotEditItem()),
+ actionCollection(), "lighttable_edititem");
+ d->editItemAction->setEnabled(false);
+
+ d->removeItemAction = new TDEAction(i18n("Remove item from LightTable"), "window-close",
+ CTRL+Key_K, this, TQ_SLOT(slotRemoveItem()),
+ actionCollection(), "lighttable_removeitem");
+ d->removeItemAction->setEnabled(false);
+
+ d->clearListAction = new TDEAction(i18n("Remove all items from LightTable"), "editshred",
+ CTRL+SHIFT+Key_K, this, TQ_SLOT(slotClearItemsList()),
+ actionCollection(), "lighttable_clearlist");
+ d->clearListAction->setEnabled(false);
+
+ d->fileDeleteAction = new TDEAction(i18n("Move to Trash"), "edittrash",
+ Key_Delete,
+ this, TQ_SLOT(slotDeleteItem()),
+ actionCollection(), "lighttable_filedelete");
+ d->fileDeleteAction->setEnabled(false);
+
+ KStdAction::close(this, TQ_SLOT(close()), actionCollection(), "lighttable_close");
+
+ // -- Standard 'View' menu actions ---------------------------------------------
+
+ d->syncPreviewAction = new TDEToggleAction(i18n("Synchronize"), "goto",
+ CTRL+SHIFT+Key_Y, this,
+ TQ_SLOT(slotToggleSyncPreview()),
+ actionCollection(), "lighttable_syncpreview");
+ d->syncPreviewAction->setEnabled(false);
+ d->syncPreviewAction->setWhatsThis(i18n("Synchronize preview from left and right panels"));
+
+ d->navigateByPairAction = new TDEToggleAction(i18n("By Pair"), "preferences-system",
+ CTRL+SHIFT+Key_P, this,
+ TQ_SLOT(slotToggleNavigateByPair()),
+ actionCollection(), "lighttable_navigatebypair");
+ d->navigateByPairAction->setEnabled(false);
+ d->navigateByPairAction->setWhatsThis(i18n("Navigate by pair with all items"));
+
+ d->zoomPlusAction = KStdAction::zoomIn(d->previewView, TQ_SLOT(slotIncreaseZoom()),
+ actionCollection(), "lighttable_zoomplus");
+ d->zoomPlusAction->setEnabled(false);
+
+ d->zoomMinusAction = KStdAction::zoomOut(d->previewView, TQ_SLOT(slotDecreaseZoom()),
+ actionCollection(), "lighttable_zoomminus");
+ d->zoomMinusAction->setEnabled(false);
+
+ d->zoomTo100percents = new TDEAction(i18n("Zoom to 100%"), "zoom-original",
+ ALT+CTRL+Key_0, // NOTE: Photoshop 7 use ALT+CTRL+0.
+ this, TQ_SLOT(slotZoomTo100Percents()),
+ actionCollection(), "lighttable_zoomto100percents");
+
+ d->zoomFitToWindowAction = new TDEAction(i18n("Fit to &Window"), "view_fit_window",
+ CTRL+SHIFT+Key_E, this, TQ_SLOT(slotFitToWindow()),
+ actionCollection(), "lighttable_zoomfit2window");
+
+ // Do not use std KDE action for full screen because action text is too large for app. toolbar.
+ d->fullScreenAction = new TDEToggleAction(i18n("Full Screen"), "view-fullscreen",
+ CTRL+SHIFT+Key_F, this,
+ TQ_SLOT(slotToggleFullScreen()),
+ actionCollection(), "lighttable_fullscreen");
+ d->fullScreenAction->setWhatsThis(i18n("Toggle the window to full screen mode"));
+
+ d->slideShowAction = new TDEAction(i18n("Slideshow"), "slideshow", Key_F9,
+ this, TQ_SLOT(slotToggleSlideShow()),
+ actionCollection(),"lighttable_slideshow");
+
+ // -- Standard 'Configure' menu actions ----------------------------------------
+
+ d->showMenuBarAction = KStdAction::showMenubar(this, TQ_SLOT(slotShowMenuBar()), actionCollection());
+
+ KStdAction::keyBindings(this, TQ_SLOT(slotEditKeys()), actionCollection());
+ KStdAction::configureToolbars(this, TQ_SLOT(slotConfToolbars()), actionCollection());
+ KStdAction::preferences(this, TQ_SLOT(slotSetup()), actionCollection());
+
+ // -----------------------------------------------------------------------------------------
+
+ d->themeMenuAction = new TDESelectAction(i18n("&Themes"), 0, actionCollection(), "theme_menu");
+ connect(d->themeMenuAction, TQ_SIGNAL(activated(const TQString&)),
+ this, TQ_SLOT(slotChangeTheme(const TQString&)));
+
+ d->themeMenuAction->setItems(ThemeEngine::instance()->themeNames());
+ slotThemeChanged();
+
+ // -- Standard 'Help' menu actions ---------------------------------------------
+
+
+ d->donateMoneyAction = new TDEAction(i18n("Donate..."),
+ 0, 0,
+ this, TQ_SLOT(slotDonateMoney()),
+ actionCollection(),
+ "lighttable_donatemoney");
+
+ d->contributeAction = new TDEAction(i18n("Contribute..."),
+ 0, 0,
+ this, TQ_SLOT(slotContribute()),
+ actionCollection(),
+ "lighttable_contribute");
+
+ d->rawCameraListAction = new TDEAction(i18n("Supported RAW Cameras"),
+ "kdcraw",
+ 0,
+ this,
+ TQ_SLOT(slotRawCameraList()),
+ actionCollection(),
+ "lighttable_rawcameralist");
+
+
+ // Provides a menu entry that allows showing/hiding the toolbar(s)
+ setStandardToolBarMenuEnabled(true);
+
+ // Provides a menu entry that allows showing/hiding the statusbar
+ createStandardStatusBarAction();
+
+ // -- Rating actions ---------------------------------------------------------------
+
+ d->star0 = new TDEAction(i18n("Assign Rating \"No Stars\""), CTRL+Key_0,
+ d->barView, TQ_SLOT(slotAssignRatingNoStar()),
+ actionCollection(), "lighttable_ratenostar");
+ d->star1 = new TDEAction(i18n("Assign Rating \"One Star\""), CTRL+Key_1,
+ d->barView, TQ_SLOT(slotAssignRatingOneStar()),
+ actionCollection(), "lighttable_rateonestar");
+ d->star2 = new TDEAction(i18n("Assign Rating \"Two Stars\""), CTRL+Key_2,
+ d->barView, TQ_SLOT(slotAssignRatingTwoStar()),
+ actionCollection(), "lighttable_ratetwostar");
+ d->star3 = new TDEAction(i18n("Assign Rating \"Three Stars\""), CTRL+Key_3,
+ d->barView, TQ_SLOT(slotAssignRatingThreeStar()),
+ actionCollection(), "lighttable_ratethreestar");
+ d->star4 = new TDEAction(i18n("Assign Rating \"Four Stars\""), CTRL+Key_4,
+ d->barView, TQ_SLOT(slotAssignRatingFourStar()),
+ actionCollection(), "lighttable_ratefourstar");
+ d->star5 = new TDEAction(i18n("Assign Rating \"Five Stars\""), CTRL+Key_5,
+ d->barView, TQ_SLOT(slotAssignRatingFiveStar()),
+ actionCollection(), "lighttable_ratefivestar");
+
+ // ---------------------------------------------------------------------------------
+
+ new DLogoAction(actionCollection(), "logo_action");
+
+ createGUI("lighttablewindowui.rc", false);
+}
+
+void LightTableWindow::setupAccelerators()
+{
+ d->accelerators = new TDEAccel(this);
+
+ d->accelerators->insert("Exit fullscreen", i18n("Exit Fullscreen mode"),
+ i18n("Exit fullscreen viewing mode"),
+ Key_Escape, this, TQ_SLOT(slotEscapePressed()),
+ false, true);
+
+ d->accelerators->insert("Next Image Key_Space", i18n("Next Image"),
+ i18n("Load Next Image"),
+ Key_Space, this, TQ_SLOT(slotForward()),
+ false, true);
+
+ d->accelerators->insert("Previous Image SHIFT+Key_Space", i18n("Previous Image"),
+ i18n("Load Previous Image"),
+ SHIFT+Key_Space, this, TQ_SLOT(slotBackward()),
+ false, true);
+
+ d->accelerators->insert("Previous Image Key_Backspace", i18n("Previous Image"),
+ i18n("Load Previous Image"),
+ Key_Backspace, this, TQ_SLOT(slotBackward()),
+ false, true);
+
+ d->accelerators->insert("Next Image Key_Next", i18n("Next Image"),
+ i18n("Load Next Image"),
+ Key_Next, this, TQ_SLOT(slotForward()),
+ false, true);
+
+ d->accelerators->insert("Previous Image Key_Prior", i18n("Previous Image"),
+ i18n("Load Previous Image"),
+ Key_Prior, this, TQ_SLOT(slotBackward()),
+ false, true);
+
+ d->accelerators->insert("Zoom Plus Key_Plus", i18n("Zoom in"),
+ i18n("Zoom in on image"),
+ Key_Plus, d->previewView, TQ_SLOT(slotIncreaseZoom()),
+ false, true);
+
+ d->accelerators->insert("Zoom Plus Key_Minus", i18n("Zoom out"),
+ i18n("Zoom out from image"),
+ Key_Minus, d->previewView, TQ_SLOT(slotDecreaseZoom()),
+ false, true);
+}
+
+// Deal with items dropped onto the thumbbar (e.g. from the Album view)
+void LightTableWindow::slotThumbbarDroppedItems(const ImageInfoList& list)
+{
+ // Setting the third parameter of loadImageInfos to true
+ // means that the images are added to the presently available images.
+ loadImageInfos(list, 0, true);
+}
+
+// We get here either
+// - via CTRL+L (from the albumview)
+// a) digikamapp.cpp: CTRL+key_L leads to slotImageLightTable())
+// b) digikamview.cpp: void DigikamView::slotImageLightTable()
+// calls d->iconView->insertToLightTable(list, info);
+// c) albumiconview.cpp: AlbumIconView::insertToLightTable
+// calls ltview->loadImageInfos(list, current);
+// - via drag&drop, i.e. calls issued by the ...Dropped... routines
+void LightTableWindow::loadImageInfos(const ImageInfoList &list,
+ ImageInfo *imageInfoCurrent,
+ bool addTo)
+{
+ // Clear all items before adding new images to the light table.
+ if (!addTo)
+ slotClearItemsList();
+
+ ImageInfoList l = list;
+
+ if (!imageInfoCurrent)
+ imageInfoCurrent = l.first();
+
+ AlbumSettings *settings = AlbumSettings::instance();
+ if (!settings) return;
+
+ TQString imagefilter = settings->getImageFileFilter().lower() +
+ settings->getImageFileFilter().upper();
+
+#if KDCRAW_VERSION < 0x000106
+ if (KDcrawIface::DcrawBinary::instance()->versionIsRight())
+ {
+ // add raw files only if dcraw is available
+ imagefilter += settings->getRawFileFilter().lower() +
+ settings->getRawFileFilter().upper();
+ }
+#else
+ imagefilter += settings->getRawFileFilter().lower() +
+ settings->getRawFileFilter().upper();
+#endif
+
+ d->barView->blockSignals(true);
+ for (TQPtrList<ImageInfo>::const_iterator it = l.begin(); it != l.end(); ++it)
+ {
+ TQString fileExtension = (*it)->kurl().fileName().section( '.', -1 );
+
+ if ( imagefilter.find(fileExtension) != -1 &&
+ !d->barView->findItemByInfo(*it) )
+ {
+ new LightTableBarItem(d->barView, *it);
+ }
+ }
+ d->barView->blockSignals(false);
+
+ // if window is iconified, show it
+ if (isMinimized())
+ {
+ KWin::deIconifyWindow(winId());
+ }
+
+ refreshStatusBar();
+}
+
+void LightTableWindow::refreshStatusBar()
+{
+ switch (d->barView->countItems())
+ {
+ case 0:
+ d->statusProgressBar->progressBarMode(StatusProgressBar::TextMode,
+ i18n("No item on Light Table"));
+ break;
+ case 1:
+ d->statusProgressBar->progressBarMode(StatusProgressBar::TextMode,
+ i18n("1 item on Light Table"));
+ break;
+ default:
+ d->statusProgressBar->progressBarMode(StatusProgressBar::TextMode,
+ i18n("%1 items on Light Table")
+ .arg(d->barView->countItems()));
+ break;
+ }
+}
+
+void LightTableWindow::slotItemsUpdated(const KURL::List& urls)
+{
+ d->barView->refreshThumbs(urls);
+
+ for (KURL::List::const_iterator it = urls.begin() ; it != urls.end() ; ++it)
+ {
+ if (d->previewView->leftImageInfo())
+ {
+ if (d->previewView->leftImageInfo()->kurl() == *it)
+ {
+ d->previewView->leftReload();
+ d->leftSidebar->itemChanged(d->previewView->leftImageInfo());
+ }
+ }
+
+ if (d->previewView->rightImageInfo())
+ {
+ if (d->previewView->rightImageInfo()->kurl() == *it)
+ {
+ d->previewView->rightReload();
+ d->rightSidebar->itemChanged(d->previewView->rightImageInfo());
+ }
+ }
+ }
+}
+
+void LightTableWindow::slotLeftPanelLeftButtonClicked()
+{
+ if (d->navigateByPairAction->isChecked()) return;
+
+ d->barView->setSelectedItem(d->barView->findItemByInfo(d->previewView->leftImageInfo()));
+}
+
+void LightTableWindow::slotRightPanelLeftButtonClicked()
+{
+ // With navigate by pair option, only the left panel can be selected.
+ if (d->navigateByPairAction->isChecked()) return;
+
+ d->barView->setSelectedItem(d->barView->findItemByInfo(d->previewView->rightImageInfo()));
+}
+
+void LightTableWindow::slotLeftPreviewLoaded(bool b)
+{
+ d->leftZoomBar->setEnabled(b);
+
+ if (b)
+ {
+ d->previewView->checkForSelection(d->barView->currentItemImageInfo());
+ d->barView->setOnLeftPanel(d->previewView->leftImageInfo());
+
+ LightTableBarItem *item = d->barView->findItemByInfo(d->previewView->leftImageInfo());
+ if (item) item->setOnLeftPanel(true);
+
+ if (d->navigateByPairAction->isChecked() && item)
+ {
+ LightTableBarItem* next = dynamic_cast<LightTableBarItem*>(item->next());
+ if (next)
+ {
+ d->barView->setOnRightPanel(next->info());
+ slotSetItemOnRightPanel(next->info());
+ }
+ else
+ {
+ LightTableBarItem* first = dynamic_cast<LightTableBarItem*>(d->barView->firstItem());
+ slotSetItemOnRightPanel(first ? first->info() : 0);
+ }
+ }
+ }
+}
+
+void LightTableWindow::slotRightPreviewLoaded(bool b)
+{
+ d->rightZoomBar->setEnabled(b);
+ if (b)
+ {
+ d->previewView->checkForSelection(d->barView->currentItemImageInfo());
+ d->barView->setOnRightPanel(d->previewView->rightImageInfo());
+
+ LightTableBarItem *item = d->barView->findItemByInfo(d->previewView->rightImageInfo());
+ if (item) item->setOnRightPanel(true);
+ }
+}
+
+void LightTableWindow::slotItemSelected(ImageInfo* info)
+{
+ if (info)
+ {
+ d->setItemLeftAction->setEnabled(true);
+ d->setItemRightAction->setEnabled(true);
+ d->editItemAction->setEnabled(true);
+ d->removeItemAction->setEnabled(true);
+ d->clearListAction->setEnabled(true);
+ d->fileDeleteAction->setEnabled(true);
+ d->backwardAction->setEnabled(true);
+ d->forwardAction->setEnabled(true);
+ d->firstAction->setEnabled(true);
+ d->lastAction->setEnabled(true);
+ d->syncPreviewAction->setEnabled(true);
+ d->zoomPlusAction->setEnabled(true);
+ d->zoomMinusAction->setEnabled(true);
+ d->navigateByPairAction->setEnabled(true);
+ d->slideShowAction->setEnabled(true);
+
+ LightTableBarItem* curr = d->barView->findItemByInfo(info);
+ if (curr)
+ {
+ if (!curr->prev())
+ {
+// d->backwardAction->setEnabled(false);
+ d->firstAction->setEnabled(false);
+ }
+
+ if (!curr->next())
+ {
+// d->forwardAction->setEnabled(false);
+ d->lastAction->setEnabled(false);
+ }
+
+ if (d->navigateByPairAction->isChecked())
+ {
+ d->setItemLeftAction->setEnabled(false);
+ d->setItemRightAction->setEnabled(false);
+
+ d->barView->setOnLeftPanel(info);
+ slotSetItemOnLeftPanel(info);
+ }
+ else if (d->autoLoadOnRightPanel && !curr->isOnLeftPanel())
+ {
+ d->barView->setOnRightPanel(info);
+ slotSetItemOnRightPanel(info);
+ }
+ }
+ }
+ else
+ {
+ d->setItemLeftAction->setEnabled(false);
+ d->setItemRightAction->setEnabled(false);
+ d->editItemAction->setEnabled(false);
+ d->removeItemAction->setEnabled(false);
+ d->clearListAction->setEnabled(false);
+ d->fileDeleteAction->setEnabled(false);
+ d->backwardAction->setEnabled(false);
+ d->forwardAction->setEnabled(false);
+ d->firstAction->setEnabled(false);
+ d->lastAction->setEnabled(false);
+ d->zoomPlusAction->setEnabled(false);
+ d->zoomMinusAction->setEnabled(false);
+ d->syncPreviewAction->setEnabled(false);
+ d->navigateByPairAction->setEnabled(false);
+ d->slideShowAction->setEnabled(false);
+ }
+
+ d->previewView->checkForSelection(info);
+}
+
+// Deal with one (or more) items dropped onto the left panel
+void LightTableWindow::slotLeftDroppedItems(const ImageInfoList& list)
+{
+ ImageInfo *info = *(list.begin());
+ // add the image to the existing images
+ loadImageInfos(list, info, true);
+
+ // We will check if first item from list is already stored in thumbbar
+ // Note that the thumbbar stores all ImageInfo reference
+ // in memory for preview object.
+ LightTableBarItem *item = d->barView->findItemByInfo(info);
+ if (item)
+ {
+ slotSetItemOnLeftPanel(item->info());
+ // One approach is to make this item the current one, via
+ // d->barView->setSelectedItem(item);
+ // However, this is not good, because this also sets
+ // the right thumb to the same image.
+ // Therefore we use setLeftRightItems if there is more than
+ // one item in the list of dropped images.
+ }
+}
+
+// Deal with one (or more) items dropped onto the right panel
+void LightTableWindow::slotRightDroppedItems(const ImageInfoList& list)
+{
+ ImageInfo *info = *(list.begin());
+ // add the image to the existing images
+ loadImageInfos(list, info, true);
+
+ // We will check if first item from list is already stored in thumbbar
+ // Note that the thumbbar stores all ImageInfo reference
+ // in memory for preview object.
+ LightTableBarItem *item = d->barView->findItemByInfo(info);
+ if (item)
+ {
+ slotSetItemOnRightPanel(item->info());
+ // Make this item the current one.
+ d->barView->setSelectedItem(item);
+ }
+}
+
+// Set the images for the left and right panel.
+void LightTableWindow::setLeftRightItems(const ImageInfoList &list, bool addTo)
+{
+ ImageInfoList l = list;
+
+ if (l.count() == 0)
+ return;
+
+ ImageInfo *info = l.first();
+ LightTableBarItem *ltItem = d->barView->findItemByInfo(info);
+
+ if (l.count() == 1 && !addTo)
+ {
+ // Just one item; this is used for the left panel.
+ d->barView->setOnLeftPanel(info);
+ slotSetItemOnLeftPanel(info);
+ d->barView->setSelectedItem(ltItem);
+ d->barView->ensureItemVisible(ltItem);
+ return;
+ }
+
+ if (ltItem)
+ {
+ // The first item is used for the left panel.
+ if (!addTo)
+ {
+ d->barView->setOnLeftPanel(info);
+ slotSetItemOnLeftPanel(info);
+ }
+
+ // The subsequent item is used for the right panel.
+ LightTableBarItem* next = dynamic_cast<LightTableBarItem*>(ltItem->next());
+ if (next && !addTo)
+ {
+ d->barView->setOnRightPanel(next->info());
+ slotSetItemOnRightPanel(next->info());
+ if (!d->navigateByPairAction->isChecked())
+ {
+ d->barView->setSelectedItem(next);
+ // ensure that the selected item is visible
+ // FIXME: this does not work:
+ d->barView->ensureItemVisible(next);
+ }
+ }
+
+ // If navigate by pairs is active, the left panel item is selected.
+ // (Fixes parts of bug #150296)
+ if (d->navigateByPairAction->isChecked())
+ {
+ d->barView->setSelectedItem(ltItem);
+ d->barView->ensureItemVisible(ltItem);
+ }
+ }
+}
+
+void LightTableWindow::slotSetItemLeft()
+{
+ if (d->barView->currentItemImageInfo())
+ {
+ slotSetItemOnLeftPanel(d->barView->currentItemImageInfo());
+ }
+}
+
+void LightTableWindow::slotSetItemRight()
+{
+ if (d->barView->currentItemImageInfo())
+ {
+ slotSetItemOnRightPanel(d->barView->currentItemImageInfo());
+ }
+}
+
+void LightTableWindow::slotSetItemOnLeftPanel(ImageInfo* info)
+{
+ d->previewView->setLeftImageInfo(info);
+ if (info)
+ d->leftSidebar->itemChanged(info);
+ else
+ d->leftSidebar->slotNoCurrentItem();
+}
+
+void LightTableWindow::slotSetItemOnRightPanel(ImageInfo* info)
+{
+ d->previewView->setRightImageInfo(info);
+ if (info)
+ d->rightSidebar->itemChanged(info);
+ else
+ d->rightSidebar->slotNoCurrentItem();
+}
+
+void LightTableWindow::slotClearItemsList()
+{
+ if (d->previewView->leftImageInfo())
+ {
+ d->previewView->setLeftImageInfo();
+ d->leftSidebar->slotNoCurrentItem();
+ }
+
+ if (d->previewView->rightImageInfo())
+ {
+ d->previewView->setRightImageInfo();
+ d->rightSidebar->slotNoCurrentItem();
+ }
+
+ d->barView->clear();
+ refreshStatusBar();
+}
+
+void LightTableWindow::slotDeleteItem()
+{
+ if (d->barView->currentItemImageInfo())
+ slotDeleteItem(d->barView->currentItemImageInfo());
+}
+
+void LightTableWindow::slotDeleteItem(ImageInfo* info)
+{
+ bool ask = true;
+ bool permanently = false;
+
+ KURL u = info->kurl();
+ PAlbum *palbum = AlbumManager::instance()->findPAlbum(u.directory());
+ if (!palbum)
+ return;
+
+ // Provide a digikamalbums:// URL to TDEIO
+ KURL kioURL = info->kurlForKIO();
+ KURL fileURL = u;
+
+ bool useTrash;
+
+ if (ask)
+ {
+ bool preselectDeletePermanently = permanently;
+
+ DeleteDialog dialog(this);
+
+ KURL::List urlList;
+ urlList.append(u);
+ if (!dialog.confirmDeleteList(urlList,
+ DeleteDialogMode::Files,
+ preselectDeletePermanently ?
+ DeleteDialogMode::NoChoiceDeletePermanently : DeleteDialogMode::NoChoiceTrash))
+ return;
+
+ useTrash = !dialog.shouldDelete();
+ }
+ else
+ {
+ useTrash = !permanently;
+ }
+
+ // trash does not like non-local URLs, put is not implemented
+ if (useTrash)
+ kioURL = fileURL;
+
+ if (!SyncJob::del(kioURL, useTrash))
+ {
+ TQString errMsg(SyncJob::lastErrorMsg());
+ KMessageBox::error(this, errMsg, errMsg);
+ return;
+ }
+
+ emit signalFileDeleted(u);
+
+ slotRemoveItem(info);
+}
+
+void LightTableWindow::slotRemoveItem()
+{
+ if (d->barView->currentItemImageInfo())
+ slotRemoveItem(d->barView->currentItemImageInfo());
+}
+
+void LightTableWindow::slotRemoveItem(ImageInfo* info)
+{
+ // When either the image from the left or right panel is removed,
+ // there are various situations to account for.
+ // To describe them, 4 images A B C D are used
+ // and the subscript _L and _ R mark the currently
+ // active item on the left and right panel
+
+ bool leftPanelActive = false;
+ ImageInfo *curr_linfo = d->previewView->leftImageInfo();
+ ImageInfo *curr_rinfo = d->previewView->rightImageInfo();
+ ImageInfo *new_linfo = 0;
+ ImageInfo *new_rinfo = 0;
+
+ TQ_LLONG infoId = info->id();
+
+ // First determine the next images to the current left and right image:
+ ImageInfo *next_linfo = 0;
+ ImageInfo *next_rinfo = 0;
+
+ if (curr_linfo)
+ {
+ LightTableBarItem *ltItem = d->barView->findItemByInfo(curr_linfo);
+ if (ltItem)
+ {
+ LightTableBarItem* next = dynamic_cast<LightTableBarItem*>(ltItem->next());
+ if (next)
+ {
+ next_linfo = next->info();
+ }
+ }
+ }
+
+ if (curr_rinfo)
+ {
+ LightTableBarItem *ltItem = d->barView->findItemByInfo(curr_rinfo);
+ if (ltItem)
+ {
+ LightTableBarItem* next = dynamic_cast<LightTableBarItem*>(ltItem->next());
+ if (next)
+ {
+ next_rinfo = next->info();
+ }
+ }
+ }
+
+ d->barView->removeItem(info);
+
+ // Make sure that next_linfo and next_rinfo are still available:
+ if (!d->barView->findItemByInfo(next_linfo))
+ {
+ next_linfo = 0;
+ }
+ if (!d->barView->findItemByInfo(next_rinfo))
+ {
+ next_rinfo = 0;
+ }
+
+ // removal of the left panel item?
+ if (curr_linfo)
+ {
+ if ( curr_linfo->id() == infoId )
+ {
+ leftPanelActive = true;
+ // Delete the item A_L of the left panel:
+ // 1) A_L B_R C D -> B_L C_R D
+ // 2) A_L B C_R D -> B C_L D_R
+ // 3) A_L B C D_R -> B_R C D_L
+ // 4) A_L B_R -> A_L
+ // some more corner cases:
+ // 5) A B_L C_R D -> A C_L D_R
+ // 6) A B_L C_R -> A_R C_L
+ // 7) A_LR B C D -> B_L C_R D (does not yet work)
+ // I.e. in 3) we wrap around circularly.
+
+ // When removing the left panel image,
+ // put the right panel image into the left panel.
+ // Check if this one is not the same (i.e. also removed).
+ if (curr_rinfo)
+ {
+ if (curr_rinfo->id() != infoId)
+ {
+ new_linfo = curr_rinfo;
+ // Set the right panel to the next image:
+ new_rinfo = next_rinfo;
+ // set the right panel active
+ leftPanelActive = false;
+ }
+ }
+ }
+ }
+
+ // removal of the right panel item?
+ if (curr_rinfo)
+ {
+ if (curr_rinfo->id() == infoId)
+ {
+ // Leave the left panel as the current one
+ new_linfo = curr_linfo;
+ // Set the right panel to the next image
+ new_rinfo = next_rinfo;
+ }
+ }
+
+ // Now we deal with the corner cases, where no left or right item exists.
+ // If the right panel would be set, but not the left-one, then swap
+ if (!new_linfo && new_rinfo)
+ {
+ new_linfo = new_rinfo;
+ new_rinfo = 0;
+ leftPanelActive = true;
+ }
+
+ if (!new_linfo)
+ {
+ if (d->barView->countItems() > 0)
+ {
+ LightTableBarItem* first = dynamic_cast<LightTableBarItem*>(d->barView->firstItem());
+ new_linfo = first->info();
+ }
+ }
+
+
+ // Make sure that new_linfo and new_rinfo exist.
+ // This addresses a crash occuring if the last image is removed
+ // in the navigate by pairs mode.
+ if (!d->barView->findItemByInfo(new_linfo))
+ {
+ new_linfo = 0;
+ }
+ if (!d->barView->findItemByInfo(new_rinfo))
+ {
+ new_rinfo = 0;
+ }
+
+ // no right item defined?
+ if (!new_rinfo)
+ {
+ // If there are at least two items, we can find reasonable right image.
+ if (d->barView->countItems() > 1)
+ {
+ // See if there is an item next to the left one:
+ LightTableBarItem *ltItem = d->barView->findItemByInfo(new_linfo);
+ LightTableBarItem* next = 0;
+ // re-check if ltItem is really set
+ if (ltItem)
+ {
+ next = dynamic_cast<LightTableBarItem*>(ltItem->next());
+ }
+ if (next)
+ {
+ new_rinfo = next->info();
+ }
+ else
+ {
+ // If there is no item to the right of new_linfo
+ // then we can choose the first item for new_rinfo
+ // (as we made sure that there are at least two items)
+ LightTableBarItem* first = dynamic_cast<LightTableBarItem*>(d->barView->firstItem());
+ new_rinfo = first->info();
+ }
+ }
+ }
+
+ // Check if left and right are set to the same
+ if (new_linfo && new_rinfo)
+ {
+ if (new_linfo->id() == new_rinfo->id())
+ {
+ // Only keep the left one
+ new_rinfo = 0;
+ }
+ }
+
+ // If the right panel would be set, but not the left-one, then swap
+ // (note that this has to be done here again!)
+ if (!new_linfo && new_rinfo)
+ {
+ new_linfo = new_rinfo;
+ new_rinfo = 0;
+ leftPanelActive = true;
+ }
+
+ // set the image for the left panel
+ if (new_linfo)
+ {
+ d->barView->setOnLeftPanel(new_linfo);
+ slotSetItemOnLeftPanel(new_linfo);
+
+ // make this the selected item if the left was active before
+ if ( leftPanelActive)
+ {
+ LightTableBarItem *ltItem = d->barView->findItemByInfo(new_linfo);
+ d->barView->setSelectedItem(ltItem);
+ }
+ }
+ else
+ {
+ d->previewView->setLeftImageInfo();
+ d->leftSidebar->slotNoCurrentItem();
+ }
+
+ // set the image for the right panel
+ if (new_rinfo)
+ {
+ d->barView->setOnRightPanel(new_rinfo);
+ slotSetItemOnRightPanel(new_rinfo);
+ // make this the selected item if the left was active before
+ if (!leftPanelActive)
+ {
+ LightTableBarItem *ltItem = d->barView->findItemByInfo(new_rinfo);
+ d->barView->setSelectedItem(ltItem);
+ }
+ }
+ else
+ {
+ d->previewView->setRightImageInfo();
+ d->rightSidebar->slotNoCurrentItem();
+ }
+
+ refreshStatusBar();
+}
+
+void LightTableWindow::slotEditItem()
+{
+ if (d->barView->currentItemImageInfo())
+ slotEditItem(d->barView->currentItemImageInfo());
+}
+
+void LightTableWindow::slotEditItem(ImageInfo* info)
+{
+ ImageWindow *im = ImageWindow::imagewindow();
+ ImageInfoList list = d->barView->itemsImageInfoList();
+
+ im->loadImageInfos(list, info, i18n("Light Table"), true);
+
+ if (im->isHidden())
+ im->show();
+ else
+ im->raise();
+
+ im->setFocus();
+}
+
+void LightTableWindow::slotZoomTo100Percents()
+{
+ d->previewView->toggleFitToWindowOr100();
+}
+
+void LightTableWindow::slotFitToWindow()
+{
+ d->previewView->fitToWindow();
+}
+
+void LightTableWindow::slotToggleSlideShow()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("ImageViewer Settings");
+ bool startWithCurrent = config->readBoolEntry("SlideShowStartCurrent", false);
+
+ SlideShowSettings settings;
+ settings.exifRotate = AlbumSettings::instance()->getExifRotate();
+ settings.delay = config->readNumEntry("SlideShowDelay", 5) * 1000;
+ settings.printName = config->readBoolEntry("SlideShowPrintName", true);
+ settings.printDate = config->readBoolEntry("SlideShowPrintDate", false);
+ settings.printApertureFocal = config->readBoolEntry("SlideShowPrintApertureFocal", false);
+ settings.printExpoSensitivity = config->readBoolEntry("SlideShowPrintExpoSensitivity", false);
+ settings.printMakeModel = config->readBoolEntry("SlideShowPrintMakeModel", false);
+ settings.printComment = config->readBoolEntry("SlideShowPrintComment", false);
+ settings.loop = config->readBoolEntry("SlideShowLoop", false);
+ slideShow(startWithCurrent, settings);
+}
+
+void LightTableWindow::slideShow(bool startWithCurrent, SlideShowSettings& settings)
+{
+ if (!d->barView->countItems()) return;
+
+ DMetadata meta;
+ int i = 0;
+ d->cancelSlideShow = false;
+
+ d->statusProgressBar->progressBarMode(StatusProgressBar::CancelProgressBarMode,
+ i18n("Preparing slideshow. Please wait..."));
+
+ ImageInfoList list = d->barView->itemsImageInfoList();
+
+ for (ImageInfo *info = list.first() ; !d->cancelSlideShow && info ; info = list.next())
+ {
+ SlidePictureInfo pictInfo;
+ pictInfo.comment = info->caption();
+
+ // Perform optimizations: only read pictures metadata if necessary.
+ if (settings.printApertureFocal || settings.printExpoSensitivity || settings.printMakeModel)
+ {
+ meta.load(info->kurl().path());
+ pictInfo.photoInfo = meta.getPhotographInformations();
+ }
+
+ // In case of dateTime extraction from metadata failed
+ pictInfo.photoInfo.dateTime = info->dateTime();
+ settings.pictInfoMap.insert(info->kurl(), pictInfo);
+ settings.fileList.append(info->kurl());
+
+ d->statusProgressBar->setProgressValue((int)((i++/(float)list.count())*100.0));
+ kapp->processEvents();
+ }
+
+ d->statusProgressBar->progressBarMode(StatusProgressBar::TextMode, TQString());
+ refreshStatusBar();
+
+ if (!d->cancelSlideShow)
+ {
+ settings.exifRotate = AlbumSettings::instance()->getExifRotate();
+
+ SlideShow *slide = new SlideShow(settings);
+ if (startWithCurrent)
+ slide->setCurrent(d->barView->currentItemImageInfo()->kurl());
+
+ slide->show();
+ }
+}
+
+void LightTableWindow::slotProgressBarCancelButtonPressed()
+{
+ d->cancelSlideShow = true;
+}
+
+void LightTableWindow::slotToggleFullScreen()
+{
+ if (d->fullScreen) // out of fullscreen
+ {
+
+ setWindowState( windowState() & ~WindowFullScreen );
+ menuBar()->show();
+ statusBar()->show();
+ leftDock()->show();
+ rightDock()->show();
+ topDock()->show();
+ bottomDock()->show();
+
+ TQObject* obj = child("ToolBar","TDEToolBar");
+
+ if (obj)
+ {
+ TDEToolBar* toolBar = static_cast<TDEToolBar*>(obj);
+
+ if (d->fullScreenAction->isPlugged(toolBar) && d->removeFullScreenButton)
+ d->fullScreenAction->unplug(toolBar);
+
+ if (toolBar->isHidden())
+ showToolBars();
+ }
+
+ // -- remove the gui action accels ----
+
+ unplugActionAccel(d->zoomFitToWindowAction);
+
+ if (d->fullScreen)
+ {
+ d->leftSidebar->restore();
+ d->rightSidebar->restore();
+ }
+ else
+ {
+ d->leftSidebar->backup();
+ d->rightSidebar->backup();
+ }
+
+ d->fullScreen = false;
+ }
+ else // go to fullscreen
+ {
+ // hide the menubar and the statusbar
+ menuBar()->hide();
+ statusBar()->hide();
+ topDock()->hide();
+ leftDock()->hide();
+ rightDock()->hide();
+ bottomDock()->hide();
+
+ TQObject* obj = child("ToolBar","TDEToolBar");
+
+ if (obj)
+ {
+ TDEToolBar* toolBar = static_cast<TDEToolBar*>(obj);
+
+ if (d->fullScreenHideToolBar)
+ {
+ hideToolBars();
+ }
+ else
+ {
+ showToolBars();
+
+ if ( !d->fullScreenAction->isPlugged(toolBar) )
+ {
+ d->fullScreenAction->plug(toolBar);
+ d->removeFullScreenButton=true;
+ }
+ else
+ {
+ // If FullScreen button is enable in toolbar settings
+ // We don't remove it when we out of fullscreen mode.
+ d->removeFullScreenButton=false;
+ }
+ }
+ }
+
+ // -- Insert all the gui actions into the accel --
+
+ plugActionAccel(d->zoomFitToWindowAction);
+
+ if (d->fullScreen)
+ {
+ d->leftSidebar->restore();
+ d->rightSidebar->restore();
+ }
+ else
+ {
+ d->leftSidebar->backup();
+ d->rightSidebar->backup();
+ }
+
+ showFullScreen();
+ d->fullScreen = true;
+ }
+}
+
+void LightTableWindow::slotEscapePressed()
+{
+ if (d->fullScreen)
+ d->fullScreenAction->activate();
+}
+
+void LightTableWindow::showToolBars()
+{
+ TQPtrListIterator<TDEToolBar> it = toolBarIterator();
+ TDEToolBar* bar;
+
+ for( ; it.current()!=0L ; ++it)
+ {
+ bar=it.current();
+
+ if (bar->area())
+ bar->area()->show();
+ else
+ bar->show();
+ }
+}
+
+void LightTableWindow::hideToolBars()
+{
+ TQPtrListIterator<TDEToolBar> it = toolBarIterator();
+ TDEToolBar* bar;
+
+ for( ; it.current()!=0L ; ++it)
+ {
+ bar=it.current();
+
+ if (bar->area())
+ bar->area()->hide();
+ else
+ bar->hide();
+ }
+}
+
+void LightTableWindow::plugActionAccel(TDEAction* action)
+{
+ if (!action)
+ return;
+
+ d->accelerators->insert(action->text(),
+ action->text(),
+ action->whatsThis(),
+ action->shortcut(),
+ action,
+ TQ_SLOT(activate()));
+}
+
+void LightTableWindow::unplugActionAccel(TDEAction* action)
+{
+ d->accelerators->remove(action->text());
+}
+
+void LightTableWindow::slotDonateMoney()
+{
+ TDEApplication::kApplication()->invokeBrowser("http://www.digikam.org/?q=donation");
+}
+
+void LightTableWindow::slotContribute()
+{
+ TDEApplication::kApplication()->invokeBrowser("http://www.digikam.org/?q=contrib");
+}
+
+void LightTableWindow::slotEditKeys()
+{
+ KKeyDialog dialog(true, this);
+ dialog.insert( actionCollection(), i18n( "General" ) );
+ dialog.configure();
+}
+
+void LightTableWindow::slotConfToolbars()
+{
+ saveMainWindowSettings(TDEGlobal::config(), "LightTable Settings");
+ KEditToolbar dlg(factory(), this);
+
+ connect(&dlg, TQ_SIGNAL(newToolbarConfig()),
+ this, TQ_SLOT(slotNewToolbarConfig()));
+
+ dlg.exec();
+}
+
+void LightTableWindow::slotNewToolbarConfig()
+{
+ applyMainWindowSettings(TDEGlobal::config(), "LightTable Settings");
+}
+
+void LightTableWindow::slotSetup()
+{
+ Setup setup(this, 0);
+
+ if (setup.exec() != TQDialog::Accepted)
+ return;
+
+ kapp->config()->sync();
+
+ applySettings();
+}
+
+void LightTableWindow::slotLeftZoomFactorChanged(double zoom)
+{
+ double h = (double)ThumbnailSize::Huge;
+ double s = (double)ThumbnailSize::Small;
+ double zmin = d->previewView->leftZoomMin();
+ double zmax = d->previewView->leftZoomMax();
+ double b = (zmin-(zmax*s/h))/(1-s/h);
+ double a = (zmax-b)/h;
+ int size = (int)((zoom - b) /a);
+
+ d->leftZoomBar->setZoomSliderValue(size);
+ d->leftZoomBar->setZoomTrackerText(i18n("zoom: %1%").arg((int)(zoom*100.0)));
+
+ d->leftZoomBar->setEnableZoomPlus(true);
+ d->leftZoomBar->setEnableZoomMinus(true);
+
+ if (d->previewView->leftMaxZoom())
+ d->leftZoomBar->setEnableZoomPlus(false);
+
+ if (d->previewView->leftMinZoom())
+ d->leftZoomBar->setEnableZoomMinus(false);
+}
+
+void LightTableWindow::slotRightZoomFactorChanged(double zoom)
+{
+ double h = (double)ThumbnailSize::Huge;
+ double s = (double)ThumbnailSize::Small;
+ double zmin = d->previewView->rightZoomMin();
+ double zmax = d->previewView->rightZoomMax();
+ double b = (zmin-(zmax*s/h))/(1-s/h);
+ double a = (zmax-b)/h;
+ int size = (int)((zoom - b) /a);
+
+ d->rightZoomBar->setZoomSliderValue(size);
+ d->rightZoomBar->setZoomTrackerText(i18n("zoom: %1%").arg((int)(zoom*100.0)));
+
+ d->rightZoomBar->setEnableZoomPlus(true);
+ d->rightZoomBar->setEnableZoomMinus(true);
+
+ if (d->previewView->rightMaxZoom())
+ d->rightZoomBar->setEnableZoomPlus(false);
+
+ if (d->previewView->rightMinZoom())
+ d->rightZoomBar->setEnableZoomMinus(false);
+}
+
+void LightTableWindow::slotToggleSyncPreview()
+{
+ d->previewView->setSyncPreview(d->syncPreviewAction->isChecked());
+}
+
+void LightTableWindow::slotToggleOnSyncPreview(bool t)
+{
+ d->syncPreviewAction->setEnabled(t);
+
+ if (!t)
+ {
+ d->syncPreviewAction->setChecked(false);
+ }
+ else
+ {
+ if (d->autoSyncPreview)
+ d->syncPreviewAction->setChecked(true);
+ }
+}
+
+void LightTableWindow::slotBackward()
+{
+ ThumbBarItem* curr = d->barView->currentItem();
+ ThumbBarItem* last = d->barView->lastItem();
+ if (curr)
+ {
+ if (curr->prev())
+ d->barView->setSelected(curr->prev());
+ else
+ d->barView->setSelected(last);
+ }
+}
+
+void LightTableWindow::slotForward()
+{
+ ThumbBarItem* curr = d->barView->currentItem();
+ ThumbBarItem* first = d->barView->firstItem();
+ if (curr)
+ {
+ if (curr->next())
+ d->barView->setSelected(curr->next());
+ else
+ d->barView->setSelected(first);
+ }
+}
+
+void LightTableWindow::slotFirst()
+{
+ d->barView->setSelected( d->barView->firstItem() );
+}
+
+void LightTableWindow::slotLast()
+{
+ d->barView->setSelected( d->barView->lastItem() );
+}
+
+void LightTableWindow::slotToggleNavigateByPair()
+{
+ d->barView->setNavigateByPair(d->navigateByPairAction->isChecked());
+ d->previewView->setNavigateByPair(d->navigateByPairAction->isChecked());
+ slotItemSelected(d->barView->currentItemImageInfo());
+}
+
+void LightTableWindow::slotRawCameraList()
+{
+ RawCameraDlg dlg(this);
+ dlg.exec();
+}
+
+void LightTableWindow::slotThemeChanged()
+{
+ TQStringList themes(ThemeEngine::instance()->themeNames());
+ int index = themes.findIndex(AlbumSettings::instance()->getCurrentTheme());
+ if (index == -1)
+ index = themes.findIndex(i18n("Default"));
+
+ d->themeMenuAction->setCurrentItem(index);
+}
+
+void LightTableWindow::slotChangeTheme(const TQString& theme)
+{
+ AlbumSettings::instance()->setCurrentTheme(theme);
+ ThemeEngine::instance()->slotChangeTheme(theme);
+}
+
+void LightTableWindow::slotShowMenuBar()
+{
+ if (menuBar()->isVisible())
+ menuBar()->hide();
+ else
+ menuBar()->show();
+}
+
+} // namespace Digikam
diff --git a/src/utilities/lighttable/lighttablewindow.h b/src/utilities/lighttable/lighttablewindow.h
new file mode 100644
index 00000000..f080e2d1
--- /dev/null
+++ b/src/utilities/lighttable/lighttablewindow.h
@@ -0,0 +1,162 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-03-05
+ * Description : digiKam light table GUI
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef LIGHTTABLEWINDOW_H
+#define LIGHTTABLEWINDOW_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <kurl.h>
+#include <tdemainwindow.h>
+
+// Local includes.
+
+#include "imageinfo.h"
+
+class TDEAction;
+
+namespace Digikam
+{
+
+class SlideShowSettings;
+class ThumbBarItem;
+class LightTableWindowPriv;
+
+class LightTableWindow : public TDEMainWindow
+{
+ TQ_OBJECT
+
+
+public:
+
+ ~LightTableWindow();
+
+ static LightTableWindow *lightTableWindow();
+ static bool lightTableWindowCreated();
+
+ void loadImageInfos(const ImageInfoList &list, ImageInfo *imageInfoCurrent, bool addTo);
+ void setLeftRightItems(const ImageInfoList &list, bool addTo);
+ void applySettings();
+ void refreshView();
+
+signals:
+
+ void signalFileDeleted(const KURL&);
+
+public slots:
+
+ void slotItemsUpdated(const KURL::List&);
+
+private:
+
+ void closeEvent(TQCloseEvent* e);
+ void setupActions();
+ void setupConnections();
+ void setupUserArea();
+ void setupStatusBar();
+ void setupAccelerators();
+ void slideShow(bool startWithCurrent, SlideShowSettings& settings);
+ void showToolBars();
+ void hideToolBars();
+ void plugActionAccel(TDEAction* action);
+ void unplugActionAccel(TDEAction* action);
+ void readSettings();
+ void writeSettings();
+ void refreshStatusBar();
+
+ LightTableWindow();
+
+private slots:
+
+ void slotBackward();
+ void slotForward();
+ void slotFirst();
+ void slotLast();
+
+ void slotSetItemLeft();
+ void slotSetItemRight();
+ void slotSetItemOnLeftPanel(ImageInfo*);
+ void slotSetItemOnRightPanel(ImageInfo*);
+ void slotLeftDroppedItems(const ImageInfoList&);
+ void slotRightDroppedItems(const ImageInfoList&);
+
+ void slotLeftPanelLeftButtonClicked();
+ void slotRightPanelLeftButtonClicked();
+
+ void slotLeftPreviewLoaded(bool);
+ void slotRightPreviewLoaded(bool);
+
+ void slotLeftZoomFactorChanged(double);
+ void slotRightZoomFactorChanged(double);
+
+ void slotToggleOnSyncPreview(bool);
+ void slotToggleSyncPreview();
+ void slotToggleNavigateByPair();
+
+ void slotEditItem();
+ void slotEditItem(ImageInfo*);
+
+ void slotDeleteItem();
+ void slotDeleteItem(ImageInfo*);
+
+ void slotRemoveItem();
+ void slotRemoveItem(ImageInfo*);
+
+ void slotItemSelected(ImageInfo*);
+ void slotClearItemsList();
+
+ void slotThumbbarDroppedItems(const ImageInfoList&);
+
+ void slotZoomTo100Percents();
+ void slotFitToWindow();
+
+ void slotProgressBarCancelButtonPressed();
+ void slotToggleSlideShow();
+ void slotToggleFullScreen();
+ void slotEscapePressed();
+ void slotDonateMoney();
+ void slotContribute();
+ void slotRawCameraList();
+ void slotEditKeys();
+ void slotConfToolbars();
+ void slotShowMenuBar();
+ void slotNewToolbarConfig();
+ void slotSetup();
+
+ void slotThemeChanged();
+ void slotChangeTheme(const TQString& theme);
+
+private:
+
+ LightTableWindowPriv *d;
+
+ static LightTableWindow *m_instance;
+};
+
+} // namespace Digikam
+
+#endif /* LIGHTTABLEWINDOW_H */
diff --git a/src/utilities/lighttable/lighttablewindowprivate.h b/src/utilities/lighttable/lighttablewindowprivate.h
new file mode 100644
index 00000000..a96e0b08
--- /dev/null
+++ b/src/utilities/lighttable/lighttablewindowprivate.h
@@ -0,0 +1,158 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-03-05
+ * Description : digiKam light table GUI
+ *
+ * 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 <tqsplitter.h>
+
+// KDE includes.
+
+#include <tdeaction.h>
+#include <tdeaccel.h>
+
+// Local includes.
+
+#include "imagepropertiessidebardb.h"
+#include "statusprogressbar.h"
+#include "statuszoombar.h"
+#include "lighttableview.h"
+#include "lighttablebar.h"
+
+namespace Digikam
+{
+
+class LightTableWindowPriv
+{
+
+public:
+
+ LightTableWindowPriv()
+ {
+ autoLoadOnRightPanel = true;
+ autoSyncPreview = true;
+ fullScreenHideToolBar = false;
+ fullScreen = false;
+ removeFullScreenButton = false;
+ cancelSlideShow = false;
+ star0 = 0;
+ star1 = 0;
+ star2 = 0;
+ star3 = 0;
+ star4 = 0;
+ star5 = 0;
+ accelerators = 0;
+ leftSidebar = 0;
+ rightSidebar = 0;
+ previewView = 0;
+ barView = 0;
+ hSplitter = 0;
+ vSplitter = 0;
+ syncPreviewAction = 0;
+ clearListAction = 0;
+ setItemLeftAction = 0;
+ setItemRightAction = 0;
+ editItemAction = 0;
+ removeItemAction = 0;
+ fileDeleteAction = 0;
+ slideShowAction = 0;
+ fullScreenAction = 0;
+ donateMoneyAction = 0;
+ zoomFitToWindowAction = 0;
+ zoomTo100percents = 0;
+ zoomPlusAction = 0;
+ zoomMinusAction = 0;
+ statusProgressBar = 0;
+ leftZoomBar = 0;
+ rightZoomBar = 0;
+ forwardAction = 0;
+ backwardAction = 0;
+ firstAction = 0;
+ lastAction = 0;
+ navigateByPairAction = 0;
+ rawCameraListAction = 0;
+ themeMenuAction = 0;
+ contributeAction = 0;
+ showMenuBarAction = 0;
+ }
+
+ bool autoLoadOnRightPanel;
+ bool autoSyncPreview;
+ bool fullScreenHideToolBar;
+ bool fullScreen;
+ bool removeFullScreenButton;
+ bool cancelSlideShow;
+
+ TQSplitter *hSplitter;
+ TQSplitter *vSplitter;
+
+ // Rating actions.
+ TDEAction *star0;
+ TDEAction *star1;
+ TDEAction *star2;
+ TDEAction *star3;
+ TDEAction *star4;
+ TDEAction *star5;
+
+ TDEAction *forwardAction;
+ TDEAction *backwardAction;
+ TDEAction *firstAction;
+ TDEAction *lastAction;
+
+ TDEAction *setItemLeftAction;
+ TDEAction *setItemRightAction;
+ TDEAction *clearListAction;
+ TDEAction *editItemAction;
+ TDEAction *removeItemAction;
+ TDEAction *fileDeleteAction;
+ TDEAction *slideShowAction;
+ TDEAction *donateMoneyAction;
+ TDEAction *contributeAction;
+ TDEAction *zoomPlusAction;
+ TDEAction *zoomMinusAction;
+ TDEAction *zoomTo100percents;
+ TDEAction *zoomFitToWindowAction;
+ TDEAction *rawCameraListAction;
+
+ TDESelectAction *themeMenuAction;
+
+ TDEToggleAction *fullScreenAction;
+ TDEToggleAction *syncPreviewAction;
+ TDEToggleAction *navigateByPairAction;
+ TDEToggleAction *showMenuBarAction;
+
+ TDEAccel *accelerators;
+
+ LightTableBar *barView;
+
+ LightTableView *previewView;
+
+ StatusZoomBar *leftZoomBar;
+ StatusZoomBar *rightZoomBar;
+
+ StatusProgressBar *statusProgressBar;
+
+ ImagePropertiesSideBarDB *leftSidebar;
+ ImagePropertiesSideBarDB *rightSidebar;
+};
+
+} // namespace Digikam
diff --git a/src/utilities/lighttable/lighttablewindowui.rc b/src/utilities/lighttable/lighttablewindowui.rc
new file mode 100644
index 00000000..ae7ce721
--- /dev/null
+++ b/src/utilities/lighttable/lighttablewindowui.rc
@@ -0,0 +1,83 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<gui version="24" name="lighttablewindow" >
+
+<MenuBar>
+
+ <Menu name="File" ><text>&amp;File</text>
+ <Action name="lighttable_first" />
+ <Action name="lighttable_backward" />
+ <Action name="lighttable_forward" />
+ <Action name="lighttable_last" />
+ <Separator/>
+ <Action name="lighttable_setitemleft" />
+ <Action name="lighttable_setitemright" />
+ <Action name="lighttable_edititem" />
+ <Separator/>
+ <Action name="lighttable_removeitem" />
+ <Action name="lighttable_clearlist" />
+ <Separator/>
+ <Action name="lighttable_filedelete" />
+ <Separator/>
+ <Action name="lighttable_close" />
+ </Menu>
+
+ <Menu name="View" ><text>&amp;View</text>
+ <Action name="lighttable_fullscreen" />
+ <Action name="lighttable_slideshow" />
+ <Separator/>
+ <Action name="lighttable_syncpreview" />
+ <Action name="lighttable_navigatebypair" />
+ <Separator/>
+ <Action name="lighttable_zoomplus" />
+ <Action name="lighttable_zoomminus" />
+ <Action name="lighttable_zoomto100percents" />
+ <Action name="lighttable_zoomfit2window" />
+ </Menu>
+
+ <Menu name="help" ><text>&amp;Help</text>
+ <Action name="lighttable_rawcameralist"/>
+ <Action name="lighttable_donatemoney" />
+ <Action name="lighttable_contribute" />
+ </Menu>
+
+ <Merge/>
+
+ <Menu name="settings" noMerge="1"><Text>&amp;Settings</Text>
+ <Merge name="StandardToolBarMenuHandler" />
+ <Action name="options_show_menubar"/>
+ <Action name="options_show_statusbar"/>
+ <Action name="options_show_toolbar"/>
+ <Separator/>
+ <Action name="theme_menu" />
+ <Action name="options_configure_keybinding"/>
+ <Action name="options_configure_toolbars"/>
+ <Action name="options_configure" />
+ </Menu>
+
+</MenuBar>
+
+<ToolBar name="ToolBar" ><text>Main Toolbar</text>
+ <Action name="lighttable_first" />
+ <Action name="lighttable_backward" />
+ <Action name="lighttable_forward" />
+ <Action name="lighttable_last" />
+ <Separator/>
+ <Action name="lighttable_zoomplus" />
+ <Action name="lighttable_zoomminus" />
+ <Action name="lighttable_zoomfit2window" />
+ <Separator/>
+ <Action name="lighttable_setitemleft" />
+ <Action name="lighttable_setitemright" />
+ <Action name="lighttable_syncpreview" />
+ <Action name="lighttable_navigatebypair" />
+ <Separator/>
+ <Action name="lighttable_fullscreen" />
+ <Action name="lighttable_slideshow" />
+ <Merge />
+ <WeakSeparator/>
+ <Action name="logo_action" />
+</ToolBar>
+
+<ActionProperties/>
+
+</gui>