summaryrefslogtreecommitdiffstats
path: root/src/utilities/imageeditor
diff options
context:
space:
mode:
Diffstat (limited to 'src/utilities/imageeditor')
-rw-r--r--src/utilities/imageeditor/Makefile.am1
-rw-r--r--src/utilities/imageeditor/canvas/Makefile.am28
-rw-r--r--src/utilities/imageeditor/canvas/canvas.cpp1421
-rw-r--r--src/utilities/imageeditor/canvas/canvas.h209
-rw-r--r--src/utilities/imageeditor/canvas/colorcorrectiondlg.cpp186
-rw-r--r--src/utilities/imageeditor/canvas/colorcorrectiondlg.h72
-rw-r--r--src/utilities/imageeditor/canvas/dimginterface.cpp1270
-rw-r--r--src/utilities/imageeditor/canvas/dimginterface.h200
-rw-r--r--src/utilities/imageeditor/canvas/iccsettingscontainer.h82
-rw-r--r--src/utilities/imageeditor/canvas/imageplugin.cpp68
-rw-r--r--src/utilities/imageeditor/canvas/imageplugin.h70
-rw-r--r--src/utilities/imageeditor/canvas/imagepluginloader.cpp278
-rw-r--r--src/utilities/imageeditor/canvas/imagepluginloader.h79
-rw-r--r--src/utilities/imageeditor/canvas/iofilesettingscontainer.h84
-rw-r--r--src/utilities/imageeditor/canvas/undoaction.cpp185
-rw-r--r--src/utilities/imageeditor/canvas/undoaction.h144
-rw-r--r--src/utilities/imageeditor/canvas/undocache.cpp178
-rw-r--r--src/utilities/imageeditor/canvas/undocache.h62
-rw-r--r--src/utilities/imageeditor/canvas/undomanager.cpp253
-rw-r--r--src/utilities/imageeditor/canvas/undomanager.h76
-rw-r--r--src/utilities/imageeditor/editor/Makefile.am51
-rw-r--r--src/utilities/imageeditor/editor/digikamimageplugin.desktop39
-rw-r--r--src/utilities/imageeditor/editor/digikamimagewindowui.rc125
-rw-r--r--src/utilities/imageeditor/editor/editorstackview.cpp233
-rw-r--r--src/utilities/imageeditor/editor/editorstackview.h97
-rw-r--r--src/utilities/imageeditor/editor/editortool.cpp436
-rw-r--r--src/utilities/imageeditor/editor/editortool.h164
-rw-r--r--src/utilities/imageeditor/editor/editortooliface.cpp147
-rw-r--r--src/utilities/imageeditor/editor/editortooliface.h76
-rw-r--r--src/utilities/imageeditor/editor/editortoolsettings.cpp331
-rw-r--r--src/utilities/imageeditor/editor/editortoolsettings.h110
-rw-r--r--src/utilities/imageeditor/editor/editorwindow.cpp1932
-rw-r--r--src/utilities/imageeditor/editor/editorwindow.h263
-rw-r--r--src/utilities/imageeditor/editor/editorwindowprivate.h143
-rw-r--r--src/utilities/imageeditor/editor/imageiface.cpp444
-rw-r--r--src/utilities/imageeditor/editor/imageiface.h198
-rw-r--r--src/utilities/imageeditor/editor/imagewindow.cpp1263
-rw-r--r--src/utilities/imageeditor/editor/imagewindow.h155
-rw-r--r--src/utilities/imageeditor/editor/savingcontextcontainer.h89
-rw-r--r--src/utilities/imageeditor/rawimport/Makefile.am27
-rw-r--r--src/utilities/imageeditor/rawimport/rawimport.cpp223
-rw-r--r--src/utilities/imageeditor/rawimport/rawimport.h88
-rw-r--r--src/utilities/imageeditor/rawimport/rawpostprocessing.cpp137
-rw-r--r--src/utilities/imageeditor/rawimport/rawpostprocessing.h63
-rw-r--r--src/utilities/imageeditor/rawimport/rawpreview.cpp336
-rw-r--r--src/utilities/imageeditor/rawimport/rawpreview.h108
-rw-r--r--src/utilities/imageeditor/rawimport/rawsettingsbox.cpp741
-rw-r--r--src/utilities/imageeditor/rawimport/rawsettingsbox.h91
-rw-r--r--src/utilities/imageeditor/tools/Makefile.am19
-rw-r--r--src/utilities/imageeditor/tools/imageprint.cpp814
-rw-r--r--src/utilities/imageeditor/tools/imageprint.h122
-rw-r--r--src/utilities/imageeditor/tools/imageresize.cpp650
-rw-r--r--src/utilities/imageeditor/tools/imageresize.h82
53 files changed, 14743 insertions, 0 deletions
diff --git a/src/utilities/imageeditor/Makefile.am b/src/utilities/imageeditor/Makefile.am
new file mode 100644
index 00000000..c324c683
--- /dev/null
+++ b/src/utilities/imageeditor/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = canvas tools rawimport editor
diff --git a/src/utilities/imageeditor/canvas/Makefile.am b/src/utilities/imageeditor/canvas/Makefile.am
new file mode 100644
index 00000000..740f854e
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/Makefile.am
@@ -0,0 +1,28 @@
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libdimgcanvas.la
+
+libdimgcanvas_la_SOURCES = dimginterface.cpp colorcorrectiondlg.cpp \
+ canvas.cpp undocache.cpp \
+ undoaction.cpp undomanager.cpp \
+ imagepluginloader.cpp imageplugin.cpp
+
+libdimgcanvas_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TIFF)
+
+INCLUDES = -I$(top_srcdir)/src/digikam \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/threadimageio \
+ -I$(top_srcdir)/src/utilities/splashscreen \
+ -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/rawimport \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ $(LIBKEXIV2_CFLAGS) $(LIBKDCRAW_CFLAGS) $(all_includes)
+
+digikaminclude_HEADERS = imageplugin.h
+
+digikamincludedir = $(includedir)/digikam
diff --git a/src/utilities/imageeditor/canvas/canvas.cpp b/src/utilities/imageeditor/canvas/canvas.cpp
new file mode 100644
index 00000000..89758c3d
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/canvas.cpp
@@ -0,0 +1,1421 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2003-01-09
+ * Description : image editor canvas management class
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-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.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstdio>
+#include <cmath>
+
+// TQt includes.
+
+#include <tqtooltip.h>
+#include <tqfile.h>
+#include <tqstring.h>
+#include <tqevent.h>
+#include <tqpoint.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqpixmap.h>
+#include <tqstyle.h>
+#include <tqapplication.h>
+#include <tqcursor.h>
+#include <tqimage.h>
+#include <tqregion.h>
+#include <tqtimer.h>
+#include <tqcache.h>
+#include <tqcolor.h>
+#include <tqdragobject.h>
+#include <tqclipboard.h>
+#include <tqtoolbutton.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <kdatetbl.h>
+#include <tdeglobalsettings.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imagehistogram.h"
+#include "imagepaniconwidget.h"
+#include "dimginterface.h"
+#include "iccsettingscontainer.h"
+#include "exposurecontainer.h"
+#include "iofilesettingscontainer.h"
+#include "loadingcacheinterface.h"
+#include "canvas.h"
+#include "canvas.moc"
+
+namespace Digikam
+{
+
+class CanvasPrivate
+{
+
+public:
+
+ CanvasPrivate() :
+ tileSize(128), minZoom(0.1), maxZoom(12.0), zoomMultiplier(1.2)
+ {
+ rubber = 0;
+ pressedMoved = false;
+ pressedMoving = false;
+ ltActive = false;
+ rtActive = false;
+ lbActive = false;
+ rbActive = false;
+ midButtonPressed = false;
+ midButtonX = 0;
+ midButtonY = 0;
+ panIconPopup = 0;
+ panIconWidget = 0;
+ cornerButton = 0;
+ parent = 0;
+ im = 0;
+ rubber = 0;
+ autoZoom = false;
+ fullScreen = false;
+ zoom = 1.0;
+ tileTmpPix = new TQPixmap(tileSize, tileSize);
+
+ tileCache.setMaxCost((10*1024*1024)/(tileSize*tileSize*4));
+ tileCache.setAutoDelete(true);
+ }
+
+ bool autoZoom;
+ bool fullScreen;
+ bool pressedMoved;
+ bool pressedMoving;
+ bool ltActive;
+ bool rtActive;
+ bool lbActive;
+ bool rbActive;
+ bool midButtonPressed;
+
+ const int tileSize;
+ int midButtonX;
+ int midButtonY;
+
+ double zoom;
+ const double minZoom;
+ const double maxZoom;
+ const double zoomMultiplier;
+
+ TQToolButton *cornerButton;
+
+ TQRect *rubber;
+ TQRect pixmapRect;
+
+ TQCache<TQPixmap> tileCache;
+
+ TQPixmap* tileTmpPix;
+ TQPixmap qcheck;
+
+ TQColor bgColor;
+
+ TQWidget *parent;
+
+ TDEPopupFrame *panIconPopup;
+
+ DImgInterface *im;
+
+ ImagePanIconWidget *panIconWidget;
+};
+
+Canvas::Canvas(TQWidget *parent)
+ : TQScrollView(parent)
+{
+ d = new CanvasPrivate;
+ d->im = new DImgInterface();
+ d->parent = parent;
+ d->bgColor.setRgb(0, 0, 0);
+
+ d->qcheck.resize(16, 16);
+ TQPainter p(&d->qcheck);
+ p.fillRect(0, 0, 8, 8, TQColor(144, 144, 144));
+ p.fillRect(8, 8, 8, 8, TQColor(144, 144, 144));
+ p.fillRect(0, 8, 8, 8, TQColor(100, 100, 100));
+ p.fillRect(8, 0, 8, 8, TQColor(100, 100, 100));
+ p.end();
+
+ d->cornerButton = new TQToolButton(this);
+ d->cornerButton->setIconSet(SmallIcon("move"));
+ d->cornerButton->hide();
+ TQToolTip::add(d->cornerButton, i18n("Pan the image to a region"));
+ setCornerWidget(d->cornerButton);
+
+ viewport()->setBackgroundMode(TQt::NoBackground);
+ viewport()->setMouseTracking(false);
+ setFrameStyle( TQFrame::NoFrame );
+
+ // ------------------------------------------------------------
+
+ connect(this, TQ_SIGNAL(signalZoomChanged(double)),
+ this, TQ_SLOT(slotZoomChanged(double)));
+
+ connect(d->cornerButton, TQ_SIGNAL(pressed()),
+ this, TQ_SLOT(slotCornerButtonPressed()));
+
+ connect(d->im, TQ_SIGNAL(signalModified()),
+ this, TQ_SLOT(slotModified()));
+
+ connect(d->im, TQ_SIGNAL(signalUndoStateChanged(bool, bool, bool)),
+ this, TQ_SIGNAL(signalUndoStateChanged(bool, bool, bool)));
+
+ connect(d->im, TQ_SIGNAL(signalLoadingStarted(const TQString&)),
+ this, TQ_SIGNAL(signalLoadingStarted(const TQString&)));
+
+ connect(d->im, TQ_SIGNAL(signalImageLoaded(const TQString&, bool)),
+ this, TQ_SLOT(slotImageLoaded(const TQString&, bool)));
+
+ connect(d->im, TQ_SIGNAL(signalImageSaved(const TQString&, bool)),
+ this, TQ_SLOT(slotImageSaved(const TQString&, bool)));
+
+ connect(d->im, TQ_SIGNAL(signalLoadingProgress(const TQString&, float)),
+ this, TQ_SIGNAL(signalLoadingProgress(const TQString&, float)));
+
+ connect(d->im, TQ_SIGNAL(signalSavingProgress(const TQString&, float)),
+ this, TQ_SIGNAL(signalSavingProgress(const TQString&, float)));
+
+ connect(this, TQ_SIGNAL(signalSelected(bool)),
+ this, TQ_SLOT(slotSelected()));
+}
+
+Canvas::~Canvas()
+{
+ delete d->tileTmpPix;
+ delete d->im;
+
+ if (d->rubber)
+ delete d->rubber;
+
+ delete d;
+}
+
+void Canvas::resetImage()
+{
+ reset();
+ viewport()->setUpdatesEnabled(false);
+ d->im->resetImage();
+}
+
+void Canvas::reset()
+{
+ if (d->rubber)
+ {
+ delete d->rubber;
+ d->rubber = 0;
+ if (d->im->imageValid())
+ emit signalSelected(false);
+ }
+
+ d->tileCache.clear();
+}
+
+void Canvas::load(const TQString& filename, IOFileSettingsContainer *IOFileSettings)
+{
+ reset();
+
+ viewport()->setUpdatesEnabled(false);
+
+ d->im->load( filename, IOFileSettings, d->parent );
+
+ emit signalPrepareToLoad();
+}
+
+void Canvas::slotImageLoaded(const TQString& filePath, bool success)
+{
+ d->zoom = 1.0;
+ d->im->zoom(d->zoom);
+
+ if (d->autoZoom)
+ updateAutoZoom();
+
+ updateContentsSize(true);
+
+ viewport()->setUpdatesEnabled(true);
+ viewport()->update();
+
+ emit signalZoomChanged(d->zoom);
+
+ emit signalLoadingFinished(filePath, success);
+}
+
+void Canvas::preload(const TQString& /*filename*/)
+{
+// d->im->preload(filename);
+}
+
+/*
+These code part are unused and untested
+void Canvas::save(const TQString& filename, IOFileSettingsContainer *IOFileSettings)
+{
+ d->im->save(filename, IOFileSettings);
+ emit signalSavingStarted(filename);
+}
+
+void Canvas::saveAs(const TQString& filename,IOFileSettingsContainer *IOFileSettings,
+ const TQString& mimeType)
+{
+ d->im->saveAs(filename, IOFileSettings, mimeType);
+ emit signalSavingStarted(filename);
+}
+*/
+
+void Canvas::saveAs(const TQString& filename, IOFileSettingsContainer *IOFileSettings,
+ bool setExifOrientationTag, const TQString& mimeType)
+{
+ d->im->saveAs(filename, IOFileSettings, setExifOrientationTag, mimeType);
+ emit signalSavingStarted(filename);
+}
+
+void Canvas::slotImageSaved(const TQString& filePath, bool success)
+{
+ emit signalSavingFinished(filePath, success);
+}
+
+void Canvas::switchToLastSaved(const TQString& newFilename)
+{
+ d->im->switchToLastSaved(newFilename);
+}
+
+void Canvas::abortSaving()
+{
+ d->im->abortSaving();
+}
+
+void Canvas::setModified()
+{
+ d->im->setModified();
+}
+
+void Canvas::readMetadataFromFile(const TQString &file)
+{
+ d->im->readMetadataFromFile(file);
+}
+
+void Canvas::clearUndoHistory()
+{
+ d->im->clearUndoManager();
+}
+
+void Canvas::setUndoHistoryOrigin()
+{
+ d->im->setUndoManagerOrigin();
+}
+
+void Canvas::updateUndoState()
+{
+ d->im->updateUndoState();
+}
+
+DImg Canvas::currentImage()
+{
+ return DImg(*d->im->getImg());
+}
+
+TQString Canvas::currentImageFileFormat()
+{
+ return d->im->getImageFormat();
+}
+
+TQString Canvas::currentImageFilePath()
+{
+ return d->im->getImageFilePath();
+}
+
+int Canvas::imageWidth()
+{
+ return d->im->origWidth();
+}
+
+int Canvas::imageHeight()
+{
+ return d->im->origHeight();
+}
+
+bool Canvas::isReadOnly()
+{
+ return d->im->isReadOnly();
+}
+
+TQRect Canvas::getSelectedArea()
+{
+ int x, y, w, h;
+ d->im->getSelectedArea(x, y, w, h);
+ return ( TQRect(x, y, w, h) );
+}
+
+DImgInterface *Canvas::interface() const
+{
+ return d->im;
+}
+
+void Canvas::makeDefaultEditingCanvas()
+{
+ DImgInterface::setDefaultInterface(d->im);
+}
+
+double Canvas::calcAutoZoomFactor()
+{
+ if (!d->im->imageValid()) return d->zoom;
+
+ double srcWidth = d->im->origWidth();
+ double srcHeight = d->im->origHeight();
+ double dstWidth = contentsRect().width();
+ double dstHeight = contentsRect().height();
+ return TQMIN(dstWidth/srcWidth, dstHeight/srcHeight);
+}
+
+void Canvas::updateAutoZoom()
+{
+ d->zoom = calcAutoZoomFactor();
+ d->im->zoom(d->zoom);
+ emit signalZoomChanged(d->zoom);
+}
+
+void Canvas::updateContentsSize(bool deleteRubber)
+{
+ viewport()->setUpdatesEnabled(false);
+
+ if (deleteRubber && d->rubber)
+ {
+ delete d->rubber;
+ d->rubber = 0;
+ d->ltActive = false;
+ d->rtActive = false;
+ d->lbActive = false;
+ d->rbActive = false;
+ d->pressedMoved = false;
+ viewport()->unsetCursor();
+ viewport()->setMouseTracking(false);
+ if (d->im->imageValid())
+ emit signalSelected(false);
+ }
+
+ int wZ = d->im->width();
+ int hZ = d->im->height();
+
+ if (visibleWidth() > wZ || visibleHeight() > hZ)
+ {
+ // Center the image
+ int centerx = contentsRect().width()/2;
+ int centery = contentsRect().height()/2;
+ int xoffset = int(centerx - wZ/2);
+ int yoffset = int(centery - hZ/2);
+ xoffset = TQMAX(xoffset, 0);
+ yoffset = TQMAX(yoffset, 0);
+
+ d->pixmapRect = TQRect(xoffset, yoffset, wZ, hZ);
+ }
+ else
+ {
+ d->pixmapRect = TQRect(0, 0, wZ, hZ);
+ }
+
+ if (!deleteRubber && d->rubber)
+ {
+ int xSel, ySel, wSel, hSel;
+ d->im->getSelectedArea(xSel, ySel, wSel, hSel);
+ xSel = (int)((xSel * d->tileSize) / floor(d->tileSize / d->zoom));
+ ySel = (int)((ySel * d->tileSize) / floor(d->tileSize / d->zoom));
+ wSel = (int)((wSel * d->tileSize) / floor(d->tileSize / d->zoom));
+ hSel = (int)((hSel * d->tileSize) / floor(d->tileSize / d->zoom));
+ d->rubber->setX(xSel);
+ d->rubber->setY(ySel);
+ d->rubber->setWidth(wSel);
+ d->rubber->setHeight(hSel);
+ d->rubber->moveBy(d->pixmapRect.x(), d->pixmapRect.y());
+ }
+
+ d->tileCache.clear();
+ resizeContents(wZ, hZ);
+ viewport()->setUpdatesEnabled(true);
+}
+
+void Canvas::resizeEvent(TQResizeEvent* e)
+{
+ if (!e)
+ return;
+
+ TQScrollView::resizeEvent(e);
+
+ if (d->autoZoom)
+ updateAutoZoom();
+
+ updateContentsSize(false);
+
+ // No need to repaint. its called
+ // automatically after resize
+
+ // To be sure than corner widget used to pan image will be hide/show
+ // accordinly with resize event.
+ slotZoomChanged(d->zoom);
+}
+
+void Canvas::viewportPaintEvent(TQPaintEvent *e)
+{
+ TQRect er(e->rect());
+ er = TQRect(TQMAX(er.x() - 1, 0),
+ TQMAX(er.y() - 1, 0),
+ TQMIN(er.width() + 2, contentsRect().width()),
+ TQMIN(er.height() + 2, contentsRect().height()));
+
+ paintViewport(er, (d->zoom <= 1.0) ? true : false);
+}
+
+void Canvas::paintViewport(const TQRect& er, bool antialias)
+{
+ TQRect o_cr(viewportToContents(er.topLeft()), viewportToContents(er.bottomRight()));
+ TQRect cr = o_cr;
+
+ TQRegion clipRegion(er);
+ cr = d->pixmapRect.intersect(cr);
+
+ if (!cr.isEmpty() && d->im->imageValid())
+ {
+ clipRegion -= TQRect(contentsToViewport(cr.topLeft()), cr.size());
+
+ TQRect pr = TQRect(cr.x() - d->pixmapRect.x(), cr.y() - d->pixmapRect.y(),
+ cr.width(), cr.height());
+
+ int x1 = (int)floor((double)pr.x() / (double)d->tileSize) * d->tileSize;
+ int y1 = (int)floor((double)pr.y() / (double)d->tileSize) * d->tileSize;
+ int x2 = (int)ceilf((double)pr.right() / (double)d->tileSize) * d->tileSize;
+ int y2 = (int)ceilf((double)pr.bottom() / (double)d->tileSize) * d->tileSize;
+
+ TQPixmap pix(d->tileSize, d->tileSize);
+ int sx, sy, sw, sh;
+ int step = (int)floor(d->tileSize / d->zoom);
+
+ bool hasRubber = (d->rubber && d->pressedMoved && d->pressedMoving && d->rubber->intersects(pr));
+ if (hasRubber)
+ {
+ // remove rubber
+ drawRubber();
+ }
+
+ for (int j = y1 ; j < y2 ; j += d->tileSize)
+ {
+ for (int i = x1 ; i < x2 ; i += d->tileSize)
+ {
+ TQString key = TQString("%1,%2").arg(i).arg(j);
+ TQPixmap *pix = d->tileCache.find(key);
+
+ if (!pix)
+ {
+ if (antialias)
+ {
+ pix = new TQPixmap(d->tileSize, d->tileSize);
+ d->tileCache.insert(key, pix);
+ }
+ else
+ {
+ pix = d->tileTmpPix;
+ }
+
+ if (d->im->hasAlpha())
+ {
+ TQPainter p(pix);
+ p.drawTiledPixmap(0, 0, d->tileSize, d->tileSize,
+ d->qcheck, 0, 0);
+ p.end();
+ }
+ else
+ {
+ pix->fill(d->bgColor);
+ }
+
+ // NOTE : with implementations <= 0.9.1, the canvas doesn't work properly using high zoom level (> 500).
+ // The sx, sy, sw, sh values haven't be computed properly and "tile" artefacts been appears
+ // over the image. Look the example here:
+ // http://digikam3rdparty.free.fr/Screenshots/editorhighzoomartefact.png
+ // Note than these "tile" artifacts are not the real tiles of canvas.
+ // The new implementation below fix this problem to handle properly the areas to
+ // use from the source image to generate the canvas pixmap tiles.
+
+ sx = (int)floor((double)i / d->tileSize) * step;
+ sy = (int)floor((double)j / d->tileSize) * step;
+ sw = step;
+ sh = step;
+
+ if (d->rubber && d->pressedMoved && !d->pressedMoving)
+ {
+ TQRect rr(d->rubber->normalize());
+ TQRect r(i, j, d->tileSize, d->tileSize);
+
+ d->im->paintOnDevice(pix, sx, sy, sw, sh,
+ 0, 0, d->tileSize, d->tileSize,
+ rr.x() - i - d->pixmapRect.x(),
+ rr.y() - j - d->pixmapRect.y(),
+ rr.width(), rr.height(),
+ antialias);
+
+ rr.moveBy(-i -d->pixmapRect.x(), -j -d->pixmapRect.y());
+
+ TQPainter p(pix);
+ p.setPen(TQPen(TQColor(250, 250, 255), 1));
+ p.drawRect(rr);
+ if (rr.width() >= 10 && rr.height() >= 10)
+ {
+ p.drawRect(rr.x(), rr.y(), 5, 5);
+ p.drawRect(rr.x(), rr.y()+rr.height()-5, 5, 5);
+ p.drawRect(rr.x()+rr.width()-5, rr.y()+rr.height()-5, 5, 5);
+ p.drawRect(rr.x()+rr.width()-5, rr.y(), 5, 5);
+ }
+ p.end();
+ }
+ else
+ {
+ d->im->paintOnDevice(pix, sx, sy, sw, sh,
+ 0, 0, d->tileSize, d->tileSize,
+ antialias);
+ }
+ }
+
+ TQRect r(i, j, d->tileSize, d->tileSize);
+ TQRect ir = pr.intersect(r);
+ TQPoint pt(contentsToViewport(TQPoint(ir.x() + d->pixmapRect.x(),
+ ir.y() + d->pixmapRect.y())));
+
+ bitBlt(viewport(), pt.x(), pt.y(),
+ pix,
+ ir.x()-r.x(), ir.y()-r.y(),
+ ir.width(), ir.height());
+ }
+ }
+
+ if (hasRubber)
+ {
+ // restore rubber
+ drawRubber();
+ }
+ }
+
+ TQPainter painter(viewport());
+ painter.setClipRegion(clipRegion);
+ painter.fillRect(er, d->bgColor);
+ painter.end();
+}
+
+void Canvas::drawRubber()
+{
+ if (!d->rubber || !d->im->imageValid())
+ return;
+
+ TQPainter p(viewport());
+ p.setRasterOp(TQt::NotROP );
+ p.setPen(TQPen(TQt::color0, 1));
+ p.setBrush(NoBrush);
+
+ TQRect r(d->rubber->normalize());
+ r = TQRect(contentsToViewport(TQPoint(r.x(), r.y())), r.size());
+
+ TQPoint pnt(r.x(), r.y());
+
+ style().drawPrimitive(TQStyle::PE_FocusRect, &p,
+ TQRect(pnt.x(), pnt.y(), r.width(), r.height()),
+ colorGroup(), TQStyle::Style_Default,
+ TQStyleOption(colorGroup().base()));
+ p.end();
+}
+
+void Canvas::contentsMousePressEvent(TQMouseEvent *e)
+{
+ if (!e || e->button() == TQt::RightButton)
+ return;
+
+ d->midButtonPressed = false;
+
+ if (e->button() == TQt::LeftButton)
+ {
+ if (d->ltActive || d->rtActive ||
+ d->lbActive || d->rbActive)
+ {
+ Q_ASSERT( d->rubber );
+ if (!d->rubber)
+ return;
+
+ // Set diagonally opposite corner as anchor
+
+ TQRect r(d->rubber->normalize());
+
+ if (d->ltActive)
+ {
+ d->rubber->setTopLeft(r.bottomRight());
+ d->rubber->setBottomRight(r.topLeft());
+ }
+ else if (d->rtActive)
+ {
+ d->rubber->setTopLeft(r.bottomLeft());
+ d->rubber->setBottomRight(r.topRight());
+ }
+ else if (d->lbActive)
+ {
+ d->rubber->setTopLeft(r.topRight());
+ d->rubber->setBottomRight(r.bottomLeft());
+ }
+ else if (d->rbActive)
+ {
+ d->rubber->setTopLeft(r.topLeft());
+ d->rubber->setBottomRight(r.bottomLeft());
+ }
+
+ viewport()->setMouseTracking(false);
+ d->pressedMoved = false;
+ d->pressedMoving = true;
+
+ d->tileCache.clear();
+ viewport()->repaint(false);
+
+ return;
+ }
+ }
+ else if (e->button() == TQt::MidButton)
+ {
+ if (visibleWidth() < d->im->width() ||
+ visibleHeight() < d->im->height())
+ {
+ viewport()->setCursor(TQt::SizeAllCursor);
+ d->midButtonPressed = true;
+ d->midButtonX = e->x();
+ d->midButtonY = e->y();
+ }
+ return;
+ }
+
+ if (d->rubber)
+ {
+ delete d->rubber;
+ d->rubber = 0;
+ }
+
+ d->rubber = new TQRect(e->x(), e->y(), 0, 0);
+
+ if (d->pressedMoved)
+ {
+ d->tileCache.clear();
+ viewport()->update();
+ }
+
+ d->pressedMoved = false;
+ d->pressedMoving = true;
+
+ viewport()->setMouseTracking(false);
+}
+
+void Canvas::contentsMouseMoveEvent(TQMouseEvent *e)
+{
+ if (!e)
+ return;
+
+ if (e->state() & TQt::MidButton)
+ {
+ if (d->midButtonPressed)
+ {
+ scrollBy(d->midButtonX - e->x(),
+ d->midButtonY - e->y());
+ }
+ }
+ else if (!viewport()->hasMouseTracking())
+ {
+ if (!d->rubber)
+ return;
+
+ if (e->state() != TQt::LeftButton &&
+ !(d->ltActive || d->rtActive ||
+ d->lbActive || d->rbActive))
+ return;
+
+ // Clear old rubber.
+ if (d->pressedMoved)
+ drawRubber();
+
+ // Move content if necessary.
+ blockSignals(true);
+ setUpdatesEnabled(false);
+ ensureVisible(e->x(), e->y(), 10, 10);
+ setUpdatesEnabled(true);
+ blockSignals(false);
+
+ // draw the new rubber position.
+ int r, b;
+ r = (e->x() > d->pixmapRect.left()) ? e->x() : d->pixmapRect.left();
+ r = (r < d->pixmapRect.right()) ? r : d->pixmapRect.right();
+ b = (e->y() > d->pixmapRect.top()) ? e->y() : d->pixmapRect.top();
+ b = (b < d->pixmapRect.bottom()) ? b : d->pixmapRect.bottom();
+ d->rubber->setRight(r);
+ d->rubber->setBottom(b);
+ drawRubber();
+
+ d->pressedMoved = true;
+ d->pressedMoving = true;
+
+ // To refresh editor status bar with current selection.
+ emit signalSelectionChanged(calcSeletedArea());
+ }
+ else
+ {
+ if (!d->rubber)
+ return;
+
+ TQRect r(d->rubber->normalize());
+
+ TQRect lt(r.x()-5, r.y()-5, 10, 10);
+ TQRect rt(r.x()+r.width()-5, r.y()-5, 10, 10);
+ TQRect lb(r.x()-5, r.y()+r.height()-5, 10, 10);
+ TQRect rb(r.x()+r.width()-5, r.y()+r.height()-5, 10, 10);
+
+ d->ltActive = false;
+ d->rtActive = false;
+ d->lbActive = false;
+ d->rbActive = false;
+
+ if (lt.contains(e->x(), e->y()))
+ {
+ viewport()->setCursor(TQt::SizeFDiagCursor);
+ d->ltActive = true;
+ }
+ else if (rb.contains(e->x(), e->y()))
+ {
+ viewport()->setCursor(TQt::SizeFDiagCursor);
+ d->rbActive = true;
+ }
+ else if (lb.contains(e->x(), e->y()))
+ {
+ viewport()->setCursor(TQt::SizeBDiagCursor);
+ d->lbActive = true;
+ }
+ else if (rt.contains(e->x(), e->y()))
+ {
+ viewport()->setCursor(TQt::SizeBDiagCursor);
+ d->rtActive = true;
+ }
+ else
+ viewport()->unsetCursor();
+ }
+}
+
+void Canvas::contentsMouseReleaseEvent(TQMouseEvent *e)
+{
+ if (!e)
+ return;
+
+ d->midButtonPressed = false;
+
+ if (d->pressedMoving)
+ {
+ d->pressedMoving = false;
+ viewport()->update();
+ }
+
+ if (d->pressedMoved && d->rubber)
+ {
+ // Normalize rubber rectangle to always have the selection into the image
+ TQRect rec = d->rubber->normalize();
+
+ if (rec.left() < d->pixmapRect.left()) rec.setLeft(d->pixmapRect.left());
+ if (rec.right() > d->pixmapRect.right()) rec.setRight(d->pixmapRect.right());
+ if (rec.top() < d->pixmapRect.top()) rec.setTop(d->pixmapRect.top());
+ if (rec.bottom() > d->pixmapRect.bottom()) rec.setBottom(d->pixmapRect.bottom());
+
+ d->rubber->setLeft(rec.left());
+ d->rubber->setRight(rec.right());
+ d->rubber->setTop(rec.top());
+ d->rubber->setBottom(rec.bottom());
+
+ d->tileCache.clear();
+ viewport()->setMouseTracking(true);
+ if (d->im->imageValid())
+ emit signalSelected(true);
+ }
+ else
+ {
+ d->ltActive = false;
+ d->rtActive = false;
+ d->lbActive = false;
+ d->rbActive = false;
+ viewport()->setMouseTracking(false);
+ viewport()->unsetCursor();
+ if (d->im->imageValid())
+ emit signalSelected(false);
+ }
+
+ if (e->button() != TQt::LeftButton)
+ {
+ viewport()->unsetCursor();
+ }
+
+ if (e->button() == TQt::RightButton)
+ {
+ emit signalRightButtonClicked();
+ }
+}
+
+void Canvas::contentsWheelEvent(TQWheelEvent *e)
+{
+ e->accept();
+
+ if (e->state() & TQt::ShiftButton)
+ {
+ if (e->delta() < 0)
+ emit signalShowNextImage();
+ else if (e->delta() > 0)
+ emit signalShowPrevImage();
+ return;
+ }
+ else if (e->state() & TQt::ControlButton)
+ {
+ if (e->delta() < 0)
+ slotDecreaseZoom();
+ else if (e->delta() > 0)
+ slotIncreaseZoom();
+ return;
+ }
+
+ TQScrollView::contentsWheelEvent(e);
+}
+
+bool Canvas::maxZoom()
+{
+ return ((d->zoom * d->zoomMultiplier) >= d->maxZoom);
+}
+
+bool Canvas::minZoom()
+{
+ return ((d->zoom / d->zoomMultiplier) <= d->minZoom);
+}
+
+bool Canvas::exifRotated()
+{
+ return d->im->exifRotated();
+}
+
+double Canvas::snapZoom(double zoom)
+{
+ // If the zoom value gets changed from d->zoom to zoom
+ // across 50%, 100% or fit-to-window, then return the
+ // the corresponding special value. Otherwise zoom is returned unchanged.
+ double fit = calcAutoZoomFactor();
+ TQValueList<double> snapValues;
+ snapValues.append(0.5);
+ snapValues.append(1.0);
+ snapValues.append(fit);
+
+ qHeapSort(snapValues);
+ TQValueList<double>::const_iterator it;
+
+ if (d->zoom < zoom)
+ {
+ for(it = snapValues.constBegin(); it != snapValues.constEnd(); ++it)
+ {
+ double z = *it;
+ if ((d->zoom < z) && (zoom > z))
+ {
+ zoom = z;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // We need to go through the list in reverse order,
+ // however, tqCopyBackward does not seem to work here, so
+ // a simple for loop over integers is used instead.
+ for(int i=snapValues.size()-1; i>=0; i--)
+ {
+ double z = snapValues[i];
+ if ((d->zoom > z) && (zoom < z))
+ {
+ zoom = z;
+ break;
+ }
+ }
+ }
+
+ return zoom;
+}
+
+void Canvas::slotIncreaseZoom()
+{
+ if (maxZoom())
+ return;
+
+ double zoom = d->zoom * d->zoomMultiplier;
+ zoom = snapZoom(zoom);
+ setZoomFactor(zoom);
+}
+
+void Canvas::slotDecreaseZoom()
+{
+ if (minZoom())
+ return;
+
+ double zoom = d->zoom / d->zoomMultiplier;
+ zoom = snapZoom(zoom);
+ setZoomFactor(zoom);
+}
+
+void Canvas::setZoomFactorSnapped(double zoom)
+{
+ double fit = calcAutoZoomFactor();
+
+ if (fabs(zoom-fit) < 0.05)
+ {
+ // If 1.0 or 0.5 are even closer to zoom than fit, then choose these.
+ if (fabs(zoom-fit) > fabs(zoom-1.0) )
+ {
+ zoom = 1.0;
+ }
+ else if (fabs(zoom-fit) > fabs(zoom-0.5) )
+ {
+ zoom = 0.5;
+ }
+ else
+ {
+ zoom = fit;
+ }
+ }
+ else
+ {
+ if (fabs(zoom-1.0) < 0.05)
+ {
+ zoom = 1.0;
+ }
+ if (fabs(zoom-0.5) < 0.05)
+ {
+ zoom = 0.5;
+ }
+ }
+ setZoomFactor(zoom);
+}
+
+double Canvas::zoomFactor()
+{
+ return d->zoom;
+}
+
+void Canvas::setZoomFactor(double zoom)
+{
+ if (d->autoZoom)
+ {
+ d->autoZoom = false;
+ emit signalToggleOffFitToWindow();
+ }
+
+ // Zoom using center of canvas and given zoom factor.
+
+ double cpx = contentsX() + visibleWidth() / 2.0;
+ double cpy = contentsY() + visibleHeight() / 2.0;
+
+ cpx = (cpx / d->tileSize) * floor(d->tileSize / d->zoom);
+ cpy = (cpy / d->tileSize) * floor(d->tileSize / d->zoom);
+
+ d->zoom = zoom;
+
+ d->im->zoom(d->zoom);
+ updateContentsSize(false);
+
+ viewport()->setUpdatesEnabled(false);
+ center((int)((cpx * d->tileSize) / floor(d->tileSize / d->zoom)),
+ (int)((cpy * d->tileSize) / floor(d->tileSize / d->zoom)));
+ viewport()->setUpdatesEnabled(true);
+ viewport()->update();
+
+ emit signalZoomChanged(d->zoom);
+}
+
+void Canvas::fitToSelect()
+{
+ int xSel, ySel, wSel, hSel;
+ d->im->getSelectedArea(xSel, ySel, wSel, hSel);
+
+ if (wSel && hSel )
+ {
+ // If selected area, use center of selection
+ // and recompute zoom factor accordinly.
+ double cpx = xSel + wSel / 2.0;
+ double cpy = ySel + hSel / 2.0;
+
+ double srcWidth = wSel;
+ double srcHeight = hSel;
+ double dstWidth = contentsRect().width();
+ double dstHeight = contentsRect().height();
+
+ d->zoom = TQMIN(dstWidth/srcWidth, dstHeight/srcHeight);
+
+ d->autoZoom = false;
+ emit signalToggleOffFitToWindow();
+ d->im->zoom(d->zoom);
+ updateContentsSize(true);
+
+ viewport()->setUpdatesEnabled(false);
+ center((int)((cpx * d->tileSize) / floor(d->tileSize / d->zoom)),
+ (int)((cpy * d->tileSize) / floor(d->tileSize / d->zoom)));
+ viewport()->setUpdatesEnabled(true);
+ viewport()->update();
+
+ emit signalZoomChanged(d->zoom);
+ }
+}
+
+bool Canvas::fitToWindow()
+{
+ return d->autoZoom;
+}
+
+void Canvas::toggleFitToWindow()
+{
+ d->autoZoom = !d->autoZoom;
+
+ if (d->autoZoom)
+ updateAutoZoom();
+ else
+ {
+ d->zoom = 1.0;
+ emit signalZoomChanged(d->zoom);
+ }
+
+ d->im->zoom(d->zoom);
+ updateContentsSize(false);
+ slotZoomChanged(d->zoom);
+ viewport()->update();
+}
+
+void Canvas::slotRotate90()
+{
+ d->im->rotate90();
+}
+
+void Canvas::slotRotate180()
+{
+ d->im->rotate180();
+}
+
+void Canvas::slotRotate270()
+{
+ d->im->rotate270();
+}
+
+void Canvas::slotFlipHoriz()
+{
+ d->im->flipHoriz();
+}
+
+void Canvas::slotFlipVert()
+{
+ d->im->flipVert();
+}
+
+void Canvas::slotCrop()
+{
+ int x, y, w, h;
+ d->im->getSelectedArea(x, y, w, h);
+
+ if (!w && !h ) // No current selection.
+ return;
+
+ d->im->crop(x, y, w, h);
+}
+
+void Canvas::resizeImage(int w, int h)
+{
+ d->im->resize(w, h);
+}
+
+void Canvas::setBackgroundColor(const TQColor& color)
+{
+ if (d->bgColor == color)
+ return;
+
+ d->bgColor = color;
+ viewport()->update();
+}
+
+void Canvas::setICCSettings(ICCSettingsContainer *cmSettings)
+{
+ d->im->setICCSettings(cmSettings);
+ d->tileCache.clear();
+ viewport()->update();
+}
+
+void Canvas::setExposureSettings(ExposureSettingsContainer *expoSettings)
+{
+ d->im->setExposureSettings(expoSettings);
+ d->tileCache.clear();
+ viewport()->update();
+}
+
+void Canvas::setExifOrient(bool exifOrient)
+{
+ d->im->setExifOrient(exifOrient);
+ viewport()->update();
+}
+
+void Canvas::increaseGamma()
+{
+ d->im->changeGamma(1);
+ d->tileCache.clear();
+ viewport()->update();
+}
+
+void Canvas::decreaseGamma()
+{
+ d->im->changeGamma(-1);
+ d->tileCache.clear();
+ viewport()->update();
+}
+
+void Canvas::increaseBrightness()
+{
+ d->im->changeBrightness(1);
+ d->tileCache.clear();
+ viewport()->update();
+}
+
+void Canvas::decreaseBrightness()
+{
+ d->im->changeBrightness(-1);
+ d->tileCache.clear();
+ viewport()->update();
+}
+
+void Canvas::increaseContrast()
+{
+ d->im->changeContrast(5);
+ d->tileCache.clear();
+ viewport()->update();
+}
+
+void Canvas::decreaseContrast()
+{
+ d->im->changeContrast(-5);
+ d->tileCache.clear();
+ viewport()->update();
+}
+
+void Canvas::slotRestore()
+{
+ d->im->restore();
+}
+
+void Canvas::slotUndo(int steps)
+{
+ while(steps > 0)
+ {
+ d->im->undo();
+ --steps;
+ }
+}
+
+void Canvas::getUndoHistory(TQStringList &titles)
+{
+ d->im->getUndoHistory(titles);
+}
+
+void Canvas::getRedoHistory(TQStringList &titles)
+{
+ d->im->getRedoHistory(titles);
+}
+
+void Canvas::slotRedo(int steps)
+{
+ while(steps > 0)
+ {
+ d->im->redo();
+ --steps;
+ }
+}
+
+void Canvas::slotCopy()
+{
+ int x, y, w, h;
+ d->im->getSelectedArea(x, y, w, h);
+
+ if (!w && !h ) // No current selection.
+ return;
+
+ TQApplication::setOverrideCursor (TQt::waitCursor);
+ uchar* data = d->im->getImageSelection();
+ DImg selDImg = DImg(w, h, d->im->sixteenBit(), d->im->hasAlpha(), data);
+ delete [] data;
+
+ TQImage selImg = selDImg.copyTQImage();
+ TQApplication::clipboard()->setData(new TQImageDrag(selImg), TQClipboard::Clipboard);
+ TQApplication::restoreOverrideCursor ();
+}
+
+void Canvas::slotSelected()
+{
+ int x=0, y=0, w=0, h=0;
+
+ if (d->rubber && d->pressedMoved)
+ {
+ TQRect sel = calcSeletedArea();
+ x = sel.x();
+ y = sel.y();
+ w = sel.width();
+ h = sel.height();
+ }
+
+ d->im->setSelectedArea(x, y, w, h);
+}
+
+TQRect Canvas::calcSeletedArea()
+{
+ int x=0, y=0, w=0, h=0;
+ TQRect r(d->rubber->normalize());
+
+ if (r.isValid())
+ {
+ r.moveBy(- d->pixmapRect.x(), - d->pixmapRect.y());
+
+ x = (int)(((double)r.x() / d->tileSize) * floor(d->tileSize / d->zoom));
+ y = (int)(((double)r.y() / d->tileSize) * floor(d->tileSize / d->zoom));
+ w = (int)(((double)r.width() / d->tileSize) * floor(d->tileSize / d->zoom));
+ h = (int)(((double)r.height() / d->tileSize) * floor(d->tileSize / d->zoom));
+
+ x = TQMIN(imageWidth(), TQMAX(x, 0));
+ y = TQMIN(imageHeight(), TQMAX(y, 0));
+ w = TQMIN(imageWidth(), TQMAX(w, 0));
+ h = TQMIN(imageHeight(), TQMAX(h, 0));
+
+ // Avoid empty selection by rubberband - at least mark one pixel
+ // At high zoom factors, the rubberband may operate at subpixel level!
+ if (w == 0)
+ w = 1;
+ if (h == 0)
+ h = 1;
+ }
+
+ return TQRect(x, y, w, h);
+}
+
+void Canvas::slotModified()
+{
+ if (d->autoZoom)
+ updateAutoZoom();
+ d->im->zoom(d->zoom);
+
+ updateContentsSize(true);
+ viewport()->update();
+
+ // To be sure than corner widget used to pan image will be hide/show
+ // accordinly with new image size (if changed).
+ slotZoomChanged(d->zoom);
+
+ emit signalChanged();
+}
+
+void Canvas::slotCornerButtonPressed()
+{
+ if (d->panIconPopup)
+ {
+ d->panIconPopup->hide();
+ delete d->panIconPopup;
+ d->panIconPopup = 0;
+ }
+
+ d->panIconPopup = new TDEPopupFrame(this);
+ ImagePanIconWidget *pan = new ImagePanIconWidget(180, 120, d->panIconPopup);
+ d->panIconPopup->setMainWidget(pan);
+
+ TQRect r((int)(contentsX() / d->zoom), (int)(contentsY() / d->zoom),
+ (int)(visibleWidth() / d->zoom), (int)(visibleHeight() / d->zoom));
+ 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 Canvas::slotPanIconHiden()
+{
+ d->cornerButton->blockSignals(true);
+ d->cornerButton->animateClick();
+ d->cornerButton->blockSignals(false);
+}
+
+void Canvas::slotPanIconSelectionMoved(const TQRect& r, bool b)
+{
+ setContentsPos((int)(r.x()*d->zoom), (int)(r.y()*d->zoom));
+
+ if (b)
+ {
+ d->panIconPopup->hide();
+ delete d->panIconPopup;
+ d->panIconPopup = 0;
+ slotPanIconHiden();
+ }
+}
+
+void Canvas::slotZoomChanged(double /*zoom*/)
+{
+ updateScrollBars();
+
+ if (horizontalScrollBar()->isVisible() || verticalScrollBar()->isVisible())
+ d->cornerButton->show();
+ else
+ d->cornerButton->hide();
+}
+
+void Canvas::slotSelectAll()
+{
+ if (d->rubber)
+ {
+ delete d->rubber;
+ d->rubber = 0;
+ }
+
+ d->rubber = new TQRect(d->pixmapRect);
+ d->pressedMoved = true;
+ d->tileCache.clear();
+ viewport()->setMouseTracking(true);
+ viewport()->update();
+
+ if (d->im->imageValid())
+ emit signalSelected(true);
+}
+
+void Canvas::slotSelectNone()
+{
+ reset();
+ viewport()->update();
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/canvas/canvas.h b/src/utilities/imageeditor/canvas/canvas.h
new file mode 100644
index 00000000..c772098d
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/canvas.h
@@ -0,0 +1,209 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2003-01-09
+ * Description : image editor canvas management class
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-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 CANVAS_H
+#define CANVAS_H
+
+// TQt includes.
+
+#include <tqscrollview.h>
+#include <tqrect.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+#include "dimg.h"
+
+class TQString;
+class TQStringList;
+class TQPixmap;
+class TQPaintEvent;
+class TQResizeEvent;
+class TQWheelEvent;
+class TQKeyEvent;
+class TQColor;
+
+namespace Digikam
+{
+
+class CanvasPrivate;
+class DImgInterface;
+class ExposureSettingsContainer;
+class ICCSettingsContainer;
+class IOFileSettingsContainer;
+
+class DIGIKAM_EXPORT Canvas : public TQScrollView
+{
+ TQ_OBJECT
+
+
+public:
+
+ Canvas(TQWidget *parent=0);
+ ~Canvas();
+
+ void load(const TQString& filename, IOFileSettingsContainer *IOFileSettings);
+ void preload(const TQString& filename);
+
+ void saveAs(const TQString& filename, IOFileSettingsContainer *IOFileSettings,
+ bool setExifOrientationTag, const TQString& mimeType=TQString());
+ void resetImage();
+ void switchToLastSaved(const TQString& newFilename);
+ void abortSaving();
+ void setModified();
+ void readMetadataFromFile(const TQString &file);
+ void clearUndoHistory();
+ void setUndoHistoryOrigin();
+ void updateUndoState();
+ DImg currentImage();
+ TQString currentImageFileFormat();
+ TQString currentImageFilePath();
+
+ DImgInterface *interface() const;
+ void makeDefaultEditingCanvas();
+
+ double snapZoom(double z);
+ void setZoomFactorSnapped(double zoom);
+
+ double zoomFactor();
+ void setZoomFactor(double z);
+ bool fitToWindow();
+ bool maxZoom();
+ bool minZoom();
+ bool exifRotated();
+ int imageWidth();
+ int imageHeight();
+ TQRect getSelectedArea();
+
+ // If current image file format is only available in read only,
+ // typicially all RAW image file formats.
+ bool isReadOnly();
+
+ void resizeImage(int w, int h);
+
+ void setBackgroundColor(const TQColor& color);
+ void setICCSettings(ICCSettingsContainer *cmSettings);
+ void setExposureSettings(ExposureSettingsContainer *expoSettings);
+
+ void setExifOrient(bool exifOrient);
+
+ void increaseGamma();
+ void decreaseGamma();
+ void increaseBrightness();
+ void decreaseBrightness();
+ void increaseContrast();
+ void decreaseContrast();
+
+ void getUndoHistory(TQStringList &titles);
+ void getRedoHistory(TQStringList &titles);
+
+ void toggleFitToWindow();
+ void fitToSelect();
+
+signals:
+
+ void signalZoomChanged(double zoom);
+ void signalMaxZoom();
+ void signalMinZoom();
+ void signalChanged();
+ void signalUndoStateChanged(bool, bool, bool);
+ void signalSelected(bool);
+ void signalRightButtonClicked();
+ void signalShowNextImage();
+ void signalShowPrevImage();
+ void signalPrepareToLoad();
+ void signalLoadingStarted(const TQString &filename);
+ void signalLoadingFinished(const TQString &filename, bool success);
+ void signalLoadingProgress(const TQString& filePath, float progress);
+ void signalSavingStarted(const TQString &filename);
+ void signalSavingFinished(const TQString &filename, bool success);
+ void signalSavingProgress(const TQString& filePath, float progress);
+ void signalSelectionChanged(const TQRect&);
+ void signalToggleOffFitToWindow();
+
+public slots:
+
+ void slotIncreaseZoom();
+ void slotDecreaseZoom();
+
+ // image modifiers
+ void slotRotate90();
+ void slotRotate180();
+ void slotRotate270();
+
+ void slotFlipHoriz();
+ void slotFlipVert();
+
+ void slotCrop();
+
+ void slotRestore();
+ void slotUndo(int steps=1);
+ void slotRedo(int steps=1);
+
+ void slotCopy();
+
+ void slotSelectAll();
+ void slotSelectNone();
+
+protected:
+
+ void resizeEvent(TQResizeEvent* e);
+ void viewportPaintEvent(TQPaintEvent *e);
+ void contentsMousePressEvent(TQMouseEvent *e);
+ void contentsMouseMoveEvent(TQMouseEvent *e);
+ void contentsMouseReleaseEvent(TQMouseEvent *e);
+ void contentsWheelEvent(TQWheelEvent *e);
+
+private:
+
+ TQRect calcSeletedArea();
+ double calcAutoZoomFactor();
+ void updateAutoZoom();
+ void updateContentsSize(bool deleteRubber);
+
+ void drawRubber();
+ void paintViewport(const TQRect& er, bool antialias);
+
+ void reset();
+
+private slots:
+
+ void slotSelected();
+ void slotModified();
+ void slotImageLoaded(const TQString& filePath, bool success);
+ void slotImageSaved(const TQString& filePath, bool success);
+ void slotCornerButtonPressed();
+ void slotZoomChanged(double);
+ void slotPanIconSelectionMoved(const TQRect&, bool);
+ void slotPanIconHiden();
+
+private:
+
+ CanvasPrivate *d;
+};
+
+} // namespace Digikam
+
+#endif /* CANVAS_H */
+
diff --git a/src/utilities/imageeditor/canvas/colorcorrectiondlg.cpp b/src/utilities/imageeditor/canvas/colorcorrectiondlg.cpp
new file mode 100644
index 00000000..1403773f
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/colorcorrectiondlg.cpp
@@ -0,0 +1,186 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-05-15
+ * Description : a dialog to see preview ICC color correction
+ * before to apply color profile.
+ *
+ * Copyright (C) 2006-2007 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 <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqstring.h>
+#include <tqfileinfo.h>
+#include <tqpushbutton.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kseparator.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "icctransform.h"
+#include "iccprofileinfodlg.h"
+#include "colorcorrectiondlg.h"
+#include "colorcorrectiondlg.moc"
+
+namespace Digikam
+{
+
+ColorCorrectionDlg::ColorCorrectionDlg(TQWidget* parent, DImg *preview,
+ IccTransform *iccTrans, const TQString& file)
+ : KDialogBase(parent, "", true, TQString(),
+ Help|Ok|Apply|Cancel, Ok, true)
+{
+ m_iccTrans = iccTrans;
+ m_parent = parent;
+ setHelp("iccprofile.anchor", "digikam");
+ setButtonText(Ok, i18n("Convert"));
+ setButtonTip(Ok, i18n("Apply the default color workspace profile to the image"));
+ setButtonText(Cancel, i18n("Do Nothing"));
+ setButtonTip(Cancel, i18n("Do not change the image"));
+ setButtonText(Apply, i18n("Assign"));
+ setButtonTip(Apply, i18n("Only embed the color workspace profile in the image, don't change the image"));
+
+ TQFileInfo fi(file);
+ setCaption(fi.fileName());
+
+ TQWidget *page = new TQWidget(this);
+ TQGridLayout* grid = new TQGridLayout(page, 3, 2, 0, KDialog::spacingHint());
+
+ TQLabel *originalTitle = new TQLabel(i18n("Original Image:"), page);
+ TQLabel *previewOriginal = new TQLabel(page);
+ TQLabel *targetTitle = new TQLabel(i18n("Corrected Image:"), page);
+ TQLabel *previewTarget = new TQLabel(page);
+ TQLabel *logo = new TQLabel(page);
+ TQLabel *message = new TQLabel(page);
+ TQLabel *currentProfileTitle = new TQLabel(i18n("Current workspace color profile:"), page);
+ TQLabel *currentProfileDesc = new TQLabel(TQString("<b>%1</b>").arg(m_iccTrans->getOutpoutProfileDescriptor()), page);
+ TQPushButton *currentProfInfo = new TQPushButton(i18n("Info..."), page);
+ TQLabel *embeddedProfileTitle = new TQLabel(i18n("Embedded color profile:"), page);
+ TQLabel *embeddedProfileDesc = new TQLabel(TQString("<b>%1</b>").arg(m_iccTrans->getEmbeddedProfileDescriptor()), page);
+ TQPushButton *embeddedProfInfo = new TQPushButton(i18n("Info..."), page);
+ KSeparator *line = new KSeparator(TQt::Horizontal, page);
+
+ if (m_iccTrans->embeddedProfile().isEmpty())
+ {
+ message->setText(i18n("<p>This image has not been assigned a color profile.</p>"
+ "<p>Do you want to convert it to your workspace color profile?</p>"));
+
+ line->hide();
+ embeddedProfileTitle->hide();
+ embeddedProfileDesc->hide();
+ embeddedProfInfo->hide();
+ }
+ else
+ {
+ message->setText(i18n("<p>This image has been assigned to a color profile that does not "
+ "match your default workspace color profile.</p>"
+ "<p>Do you want to convert it to your workspace color profile?</p>"));
+ }
+
+ previewOriginal->setPixmap(preview->convertToPixmap());
+ previewTarget->setPixmap(preview->convertToPixmap(m_iccTrans));
+ TDEIconLoader* iconLoader = TDEApplication::kApplication()->iconLoader();
+ logo->setPixmap(iconLoader->loadIcon("digikam", TDEIcon::NoGroup, 128, TDEIcon::DefaultState, 0, true));
+
+ grid->addMultiCellWidget(originalTitle, 0, 0, 0, 0);
+ grid->addMultiCellWidget(previewOriginal, 1, 1, 0, 0);
+ grid->addMultiCellWidget(targetTitle, 2, 2, 0, 0);
+ grid->addMultiCellWidget(previewTarget, 3, 3, 0, 0);
+
+ TQVBoxLayout *vlay = new TQVBoxLayout( KDialog::spacingHint() );
+ vlay->addWidget(logo);
+ vlay->addWidget(message);
+
+ vlay->addWidget(new KSeparator(TQt::Horizontal, page));
+ vlay->addWidget(currentProfileTitle);
+ vlay->addWidget(currentProfileDesc);
+
+ TQHBoxLayout *hlay1 = new TQHBoxLayout( KDialog::spacingHint() );
+ hlay1->addWidget(currentProfInfo);
+ hlay1->addStretch();
+ vlay->addLayout(hlay1);
+
+ vlay->addWidget(line);
+ vlay->addWidget(embeddedProfileTitle);
+ vlay->addWidget(embeddedProfileDesc);
+
+ TQHBoxLayout *hlay2 = new TQHBoxLayout( KDialog::spacingHint() );
+ hlay2->addWidget(embeddedProfInfo);
+ hlay2->addStretch();
+ vlay->addLayout(hlay2);
+ vlay->addStretch();
+
+ grid->addMultiCell(new TQSpacerItem(KDialog::spacingHint(), KDialog::spacingHint(),
+ TQSizePolicy::Minimum, TQSizePolicy::Expanding), 0, 3, 1, 1);
+ grid->addMultiCellLayout(vlay, 0, 3, 2, 2);
+
+ setMainWidget(page);
+
+ // --------------------------------------------------------------------
+
+ connect(currentProfInfo, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotCurrentProfInfo()) );
+
+ connect(embeddedProfInfo, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotEmbeddedProfInfo()) );
+
+ connect(this, TQ_SIGNAL(applyClicked()),
+ this, TQ_SLOT(slotApplyClicked()));
+}
+
+ColorCorrectionDlg::~ColorCorrectionDlg()
+{
+}
+
+void ColorCorrectionDlg::slotCurrentProfInfo()
+{
+ if (m_iccTrans->outputProfile().isEmpty())
+ return;
+
+ ICCProfileInfoDlg infoDlg(m_parent, TQString(), m_iccTrans->outputProfile());
+ infoDlg.exec();
+}
+
+void ColorCorrectionDlg::slotEmbeddedProfInfo()
+{
+ if (m_iccTrans->embeddedProfile().isEmpty())
+ return;
+
+ ICCProfileInfoDlg infoDlg(m_parent, TQString(), m_iccTrans->embeddedProfile());
+ infoDlg.exec();
+}
+
+void ColorCorrectionDlg::slotApplyClicked()
+{
+ DDebug() << "colorcorrectiondlg: Apply pressed" << endl;
+ done(-1);
+}
+
+} // NameSpace Digikam
+
diff --git a/src/utilities/imageeditor/canvas/colorcorrectiondlg.h b/src/utilities/imageeditor/canvas/colorcorrectiondlg.h
new file mode 100644
index 00000000..7cc4c19d
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/colorcorrectiondlg.h
@@ -0,0 +1,72 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-05-15
+ * Description : a dialog to see preview ICC color correction
+ * before to apply color profile.
+ *
+ * Copyright (C) 2006-2007 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 COLORCORRECTIONDLG_H
+#define COLORCORRECTIONDLG_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class IccTransform;
+class DImg;
+
+class DIGIKAM_EXPORT ColorCorrectionDlg : public KDialogBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ColorCorrectionDlg(TQWidget *parent, DImg *preview,
+ IccTransform *iccTrans, const TQString& file);
+ ~ColorCorrectionDlg();
+
+private slots:
+
+ void slotCurrentProfInfo();
+ void slotEmbeddedProfInfo();
+ void slotApplyClicked();
+
+private:
+
+ TQWidget *m_parent;
+
+ IccTransform *m_iccTrans;
+};
+
+} // Namespace Digikam
+
+#endif /* COLORCORRECTIONDLG_H */
diff --git a/src/utilities/imageeditor/canvas/dimginterface.cpp b/src/utilities/imageeditor/canvas/dimginterface.cpp
new file mode 100644
index 00000000..8ce1c114
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/dimginterface.cpp
@@ -0,0 +1,1270 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2003-01-15
+ * Description : DImg interface for image editor
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2009 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.
+ *
+ * ============================================================ */
+
+#define OPACITY 0.7
+#define RCOL 0xAA
+#define GCOL 0xAA
+#define BCOL 0xAA
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqimage.h>
+#include <tqpixmap.h>
+#include <tqbitmap.h>
+#include <tqcolor.h>
+#include <tqfile.h>
+#include <tqvariant.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <tdemessagebox.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "bcgmodifier.h"
+#include "colorcorrectiondlg.h"
+#include "undomanager.h"
+#include "undoaction.h"
+#include "iccsettingscontainer.h"
+#include "icctransform.h"
+#include "exposurecontainer.h"
+#include "iofilesettingscontainer.h"
+#include "rawimport.h"
+#include "editortooliface.h"
+#include "sharedloadsavethread.h"
+#include "dmetadata.h"
+#include "dimginterface.h"
+#include "dimginterface.moc"
+
+namespace Digikam
+{
+
+class UndoManager;
+
+class DImgInterfacePrivate
+{
+
+public:
+
+ DImgInterfacePrivate()
+ {
+ parent = 0;
+ undoMan = 0;
+ cmSettings = 0;
+ expoSettings = 0;
+ iofileSettings = 0;
+ thread = 0;
+ width = 0;
+ height = 0;
+ origWidth = 0;
+ origHeight = 0;
+ selX = 0;
+ selY = 0;
+ selW = 0;
+ selH = 0;
+ zoom = 1.0;
+ exifOrient = false;
+ valid = false;
+ rotatedOrFlipped = false;
+ }
+
+ bool valid;
+ bool rotatedOrFlipped;
+ bool exifOrient;
+ bool changedBCG;
+
+ int width;
+ int height;
+ int origWidth;
+ int origHeight;
+ int selX;
+ int selY;
+ int selW;
+ int selH;
+
+ float gamma;
+ float brightness;
+ float contrast;
+
+ double zoom;
+
+ // Used by ICC color profile dialog.
+ TQWidget *parent;
+
+ TQString filename;
+ TQString savingFilename;
+
+ DImg image;
+
+ UndoManager *undoMan;
+
+ BCGModifier cmod;
+
+ ICCSettingsContainer *cmSettings;
+
+ ExposureSettingsContainer *expoSettings;
+
+ IOFileSettingsContainer *iofileSettings;
+
+ SharedLoadSaveThread *thread;
+
+ IccTransform monitorICCtrans;
+};
+
+DImgInterface* DImgInterface::m_defaultInterface = 0;
+
+DImgInterface* DImgInterface::defaultInterface()
+{
+ return m_defaultInterface;
+}
+
+void DImgInterface::setDefaultInterface(DImgInterface *defaultInterface)
+{
+ m_defaultInterface = defaultInterface;
+}
+
+DImgInterface::DImgInterface()
+ : TQObject()
+{
+ d = new DImgInterfacePrivate;
+
+ d->undoMan = new UndoManager(this);
+ d->thread = new SharedLoadSaveThread;
+
+ connect( d->thread, TQ_SIGNAL(signalImageLoaded(const LoadingDescription &, const DImg&)),
+ this, TQ_SLOT(slotImageLoaded(const LoadingDescription &, const DImg&)) );
+
+ connect( d->thread, TQ_SIGNAL(signalImageSaved(const TQString&, bool)),
+ this, TQ_SLOT(slotImageSaved(const TQString&, bool)) );
+
+ connect( d->thread, TQ_SIGNAL(signalLoadingProgress(const LoadingDescription &, float)),
+ this, TQ_SLOT(slotLoadingProgress(const LoadingDescription &, float)) );
+
+ connect( d->thread, TQ_SIGNAL(signalSavingProgress(const TQString&, float)),
+ this, TQ_SLOT(slotSavingProgress(const TQString&, float)) );
+}
+
+DImgInterface::~DImgInterface()
+{
+ delete d->undoMan;
+ delete d->thread;
+ delete d;
+ if (m_defaultInterface == this)
+ m_defaultInterface = 0;
+}
+
+void DImgInterface::load(const TQString& filename, IOFileSettingsContainer *iofileSettings,
+ TQWidget *parent)
+{
+ // store here in case filename == d->fileName, and is then reset by resetValues
+ TQString newFileName = filename;
+
+ resetValues();
+
+ d->filename = newFileName;
+ d->iofileSettings = iofileSettings;
+ d->parent = parent;
+
+ if (d->iofileSettings->useRAWImport && DImg::fileFormat(d->filename) == DImg::RAW)
+ {
+ RawImport *rawImport = new RawImport(KURL(d->filename), this);
+ EditorToolIface::editorToolIface()->loadTool(rawImport);
+
+ connect(rawImport, TQ_SIGNAL(okClicked()),
+ this, TQ_SLOT(slotUseRawImportSettings()));
+
+ connect(rawImport, TQ_SIGNAL(cancelClicked()),
+ this, TQ_SLOT(slotUseDefaultSettings()));
+ }
+ else
+ {
+ slotUseDefaultSettings();
+ }
+}
+
+void DImgInterface::slotUseRawImportSettings()
+{
+ RawImport *rawImport = dynamic_cast<RawImport*>(EditorToolIface::editorToolIface()->currentTool());
+
+ d->thread->load(LoadingDescription(d->filename,
+ rawImport->rawDecodingSettings()),
+ SharedLoadSaveThread::AccessModeReadWrite,
+ SharedLoadSaveThread::LoadingPolicyFirstRemovePrevious);
+ emit signalLoadingStarted(d->filename);
+
+ EditorToolIface::editorToolIface()->unLoadTool();
+}
+
+void DImgInterface::slotUseDefaultSettings()
+{
+ d->thread->load(LoadingDescription(d->filename,
+ d->iofileSettings->rawDecodingSettings),
+ SharedLoadSaveThread::AccessModeReadWrite,
+ SharedLoadSaveThread::LoadingPolicyFirstRemovePrevious);
+ emit signalLoadingStarted(d->filename);
+
+ EditorToolIface::editorToolIface()->unLoadTool();
+}
+
+void DImgInterface::resetImage()
+{
+ EditorToolIface::editorToolIface()->unLoadTool();
+ resetValues();
+ d->image.reset();
+}
+
+void DImgInterface::resetValues()
+{
+ d->valid = false;
+ d->filename = TQString();
+ d->width = 0;
+ d->height = 0;
+ d->origWidth = 0;
+ d->origHeight = 0;
+ d->selX = 0;
+ d->selY = 0;
+ d->selW = 0;
+ d->selH = 0;
+ d->gamma = 1.0;
+ d->contrast = 1.0;
+ d->brightness = 0.0;
+ d->changedBCG = false;
+ d->iofileSettings = 0;
+ d->parent = 0;
+
+ d->cmod.reset();
+ d->undoMan->clear();
+}
+
+void DImgInterface::setICCSettings(ICCSettingsContainer *cmSettings)
+{
+ d->cmSettings = cmSettings;
+ d->monitorICCtrans.setProfiles(d->cmSettings->workspaceSetting, d->cmSettings->monitorSetting);
+}
+
+void DImgInterface::setExposureSettings(ExposureSettingsContainer *expoSettings)
+{
+ d->expoSettings = expoSettings;
+}
+
+void DImgInterface::slotImageLoaded(const LoadingDescription &loadingDescription, const DImg& img)
+{
+ const TQString &fileName = loadingDescription.filePath;
+
+ if (fileName != d->filename)
+ return;
+
+ bool valRet = false;
+ d->image = img;
+
+ if (!d->image.isNull())
+ {
+ d->origWidth = d->image.width();
+ d->origHeight = d->image.height();
+ d->valid = true;
+ d->width = d->origWidth;
+ d->height = d->origHeight;
+ valRet = true;
+
+ // Raw files are already rotated properlly by dcraw. Only perform auto-rotation with JPEG/PNG/TIFF file.
+ // We don't have a feedback from dcraw about auto-rotated RAW file during decoding. Well set transformed
+ // flag as well.
+
+ if (d->image.attribute("format").toString() == TQString("RAW"))
+ d->rotatedOrFlipped = true;
+
+ if (d->exifOrient &&
+ (d->image.attribute("format").toString() == TQString("JPEG") ||
+ d->image.attribute("format").toString() == TQString("PNG") ||
+ d->image.attribute("format").toString() == TQString("TIFF")))
+ exifRotate(d->filename);
+
+ if (d->cmSettings->enableCMSetting)
+ {
+ if (TQFile::exists(d->cmSettings->workspaceSetting))
+ {
+ IccTransform trans;
+ TQByteArray fakeProfile;
+
+ // First possibility: image has no embedded profile
+ if(d->image.getICCProfil().isNull())
+ {
+ // Ask or apply?
+ if (d->cmSettings->askOrApplySetting)
+ {
+ if (d->parent) d->parent->setCursor( KCursor::waitCursor() );
+ trans.setProfiles(TQFile::encodeName(d->cmSettings->inputSetting),
+ TQFile::encodeName(d->cmSettings->workspaceSetting));
+
+ // NOTE: If Input color profile do not exist, using built-in sRGB intead.
+ trans.apply(d->image, fakeProfile, d->cmSettings->renderingSetting,
+ d->cmSettings->BPCSetting, false,
+ TQFile::exists(d->cmSettings->inputSetting));
+
+ d->image.getICCProfilFromFile(TQFile::encodeName(d->cmSettings->workspaceSetting));
+ if (d->parent) d->parent->unsetCursor();
+ }
+ else
+ {
+ // To repaint image in canvas before to ask about to apply ICC profile.
+ emit signalImageLoaded(d->filename, valRet);
+
+ DImg preview = d->image.smoothScale(240, 180, TQSize::ScaleMin);
+ trans.setProfiles(TQFile::encodeName(d->cmSettings->inputSetting),
+ TQFile::encodeName(d->cmSettings->workspaceSetting));
+ ColorCorrectionDlg dlg(d->parent, &preview, &trans, fileName);
+
+ switch (dlg.exec())
+ {
+ case TQDialog::Accepted:
+ if (d->parent) d->parent->setCursor( KCursor::waitCursor() );
+
+ // NOTE: If Input color profile do not exist, using built-in sRGB intead.
+ trans.apply(d->image, fakeProfile, d->cmSettings->renderingSetting,
+ d->cmSettings->BPCSetting, false,
+ TQFile::exists(d->cmSettings->inputSetting));
+
+ d->image.getICCProfilFromFile(TQFile::encodeName(d->cmSettings->workspaceSetting));
+ if (d->parent) d->parent->unsetCursor();
+ break;
+ case -1:
+ if (d->parent) d->parent->setCursor( KCursor::waitCursor() );
+ d->image.getICCProfilFromFile(TQFile::encodeName(d->cmSettings->workspaceSetting));
+ if (d->parent) d->parent->unsetCursor();
+ DDebug() << "dimginterface.cpp: Apply pressed" << endl;
+ break;
+ }
+ }
+ }
+ // Second possibility: image has an embedded profile
+ else
+ {
+ trans.getEmbeddedProfile( d->image );
+
+ // Ask or apply?
+ if (d->cmSettings->askOrApplySetting)
+ {
+ if (d->parent) d->parent->setCursor( KCursor::waitCursor() );
+ trans.setProfiles(TQFile::encodeName(d->cmSettings->workspaceSetting));
+ trans.apply(d->image, fakeProfile, d->cmSettings->renderingSetting,
+ d->cmSettings->BPCSetting, false, false);
+ if (d->parent) d->parent->unsetCursor();
+ }
+ else
+ {
+ if (trans.getEmbeddedProfileDescriptor()
+ != trans.getProfileDescription( d->cmSettings->workspaceSetting ))
+ {
+ // Embedded profile and default workspace profile are different: ask to user!
+
+ DDebug() << "Embedded profile: " << trans.getEmbeddedProfileDescriptor() << endl;
+
+ // To repaint image in canvas before to ask about to apply ICC profile.
+ emit signalImageLoaded(d->filename, valRet);
+
+ DImg preview = d->image.smoothScale(240, 180, TQSize::ScaleMin);
+ trans.setProfiles(TQFile::encodeName(d->cmSettings->workspaceSetting));
+ ColorCorrectionDlg dlg(d->parent, &preview, &trans, fileName);
+
+ switch (dlg.exec())
+ {
+ case TQDialog::Accepted:
+ if (d->parent) d->parent->setCursor( KCursor::waitCursor() );
+ trans.apply(d->image, fakeProfile, d->cmSettings->renderingSetting,
+ d->cmSettings->BPCSetting, false, false);
+ d->image.getICCProfilFromFile(TQFile::encodeName(d->cmSettings->workspaceSetting));
+ if (d->parent) d->parent->unsetCursor();
+ break;
+ case -1:
+ if (d->parent) d->parent->setCursor( KCursor::waitCursor() );
+ d->image.getICCProfilFromFile(TQFile::encodeName(d->cmSettings->workspaceSetting));
+ if (d->parent) d->parent->unsetCursor();
+ DDebug() << "dimginterface.cpp: Apply pressed" << endl;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ TQString message = i18n("Cannot find the ICC color-space profile file. "
+ "The ICC profiles path seems to be invalid. "
+ "No color transform will be applied. "
+ "Please check the \"Color Management\" "
+ "configuration in digiKam's setup to verify the ICC path.");
+ KMessageBox::information(d->parent, message);
+ }
+ }
+ }
+ else
+ {
+ valRet = false;
+ }
+
+ emit signalImageLoaded(d->filename, valRet);
+ setModified();
+}
+
+void DImgInterface::slotLoadingProgress(const LoadingDescription &loadingDescription, float progress)
+{
+ if (loadingDescription.filePath == d->filename)
+ emit signalLoadingProgress(loadingDescription.filePath, progress);
+}
+
+bool DImgInterface::exifRotated()
+{
+ return d->rotatedOrFlipped;
+}
+
+void DImgInterface::exifRotate(const TQString& filename)
+{
+ // Rotate image based on EXIF rotate tag
+
+ DMetadata metadata(filename);
+ DMetadata::ImageOrientation orientation = metadata.getImageOrientation();
+
+ if(orientation != DMetadata::ORIENTATION_NORMAL)
+ {
+ switch (orientation)
+ {
+ case DMetadata::ORIENTATION_NORMAL:
+ case DMetadata::ORIENTATION_UNSPECIFIED:
+ break;
+
+ case DMetadata::ORIENTATION_HFLIP:
+ flipHoriz(false);
+ break;
+
+ case DMetadata::ORIENTATION_ROT_180:
+ rotate180(false);
+ break;
+
+ case DMetadata::ORIENTATION_VFLIP:
+ flipVert(false);
+ break;
+
+ case DMetadata::ORIENTATION_ROT_90_HFLIP:
+ rotate90(false);
+ flipHoriz(false);
+ break;
+
+ case DMetadata::ORIENTATION_ROT_90:
+ rotate90(false);
+ break;
+
+ case DMetadata::ORIENTATION_ROT_90_VFLIP:
+ rotate90(false);
+ flipVert(false);
+ break;
+
+ case DMetadata::ORIENTATION_ROT_270:
+ rotate270(false);
+ break;
+ }
+
+ d->rotatedOrFlipped = true;
+ }
+}
+
+void DImgInterface::setExifOrient(bool exifOrient)
+{
+ d->exifOrient = exifOrient;
+}
+
+void DImgInterface::undo()
+{
+ if (!d->undoMan->anyMoreUndo())
+ {
+ emit signalUndoStateChanged(false, d->undoMan->anyMoreRedo(), !d->undoMan->isAtOrigin());
+ return;
+ }
+
+ d->undoMan->undo();
+ emit signalUndoStateChanged(d->undoMan->anyMoreUndo(), d->undoMan->anyMoreRedo(), !d->undoMan->isAtOrigin());
+}
+
+void DImgInterface::redo()
+{
+ if (!d->undoMan->anyMoreRedo())
+ {
+ emit signalUndoStateChanged(d->undoMan->anyMoreUndo(), false, !d->undoMan->isAtOrigin());
+ return;
+ }
+
+ d->undoMan->redo();
+ emit signalUndoStateChanged(d->undoMan->anyMoreUndo(), d->undoMan->anyMoreRedo(), !d->undoMan->isAtOrigin());
+}
+
+void DImgInterface::restore()
+{
+ d->undoMan->clear();
+ load(d->filename, d->iofileSettings);
+}
+
+/*
+This code is unused and untested
+void DImgInterface::save(const TQString& file, IOFileSettingsContainer *iofileSettings)
+{
+ d->cmod.reset();
+ d->cmod.setGamma(d->gamma);
+ d->cmod.setBrightness(d->brightness);
+ d->cmod.setContrast(d->contrast);
+ d->cmod.applyBCG(d->image);
+
+ d->cmod.reset();
+ d->gamma = 1.0;
+ d->contrast = 1.0;
+ d->brightness = 0.0;
+
+ TQString currentMimeType(TQImageIO::imageFormat(d->filename));
+
+ d->needClearUndoManager = true;
+
+ saveAction(file, iofileSettings, currentMimeType);
+}
+*/
+
+void DImgInterface::saveAs(const TQString& fileName, IOFileSettingsContainer *iofileSettings,
+ bool setExifOrientationTag, const TQString& givenMimeType)
+{
+ // No need to toggle off undo, redo or save action during saving using
+ // signalUndoStateChanged(), this is will done by GUI implementation directly.
+
+ if (d->changedBCG)
+ {
+ d->cmod.reset();
+ d->cmod.setGamma(d->gamma);
+ d->cmod.setBrightness(d->brightness);
+ d->cmod.setContrast(d->contrast);
+ d->cmod.applyBCG(d->image);
+ }
+
+ // Try hard to find a mimetype.
+ TQString mimeType = givenMimeType;
+
+ // This is possibly empty
+ if (mimeType.isEmpty())
+ mimeType = getImageFormat();
+
+ DDebug() << "Saving to :" << TQFile::encodeName(fileName).data() << " ("
+ << mimeType << ")" << endl;
+
+ // JPEG file format.
+ if ( mimeType.upper() == TQString("JPG") || mimeType.upper() == TQString("JPEG") ||
+ mimeType.upper() == TQString("JPE"))
+ {
+ d->image.setAttribute("quality", iofileSettings->JPEGCompression);
+ d->image.setAttribute("subsampling", iofileSettings->JPEGSubSampling);
+ }
+
+ // PNG file format.
+ if ( mimeType.upper() == TQString("PNG") )
+ d->image.setAttribute("quality", iofileSettings->PNGCompression);
+
+ // TIFF file format.
+ if ( mimeType.upper() == TQString("TIFF") || mimeType.upper() == TQString("TIF") )
+ d->image.setAttribute("compress", iofileSettings->TIFFCompression);
+
+ // JPEG 2000 file format.
+ if ( mimeType.upper() == TQString("JP2") || mimeType.upper() == TQString("JPX") ||
+ mimeType.upper() == TQString("JPC") || mimeType.upper() == TQString("PGX"))
+ {
+ if (iofileSettings->JPEG2000LossLess)
+ d->image.setAttribute("quality", 100); // LossLess compression
+ else
+ d->image.setAttribute("quality", iofileSettings->JPEG2000Compression);
+ }
+
+ d->savingFilename = fileName;
+
+ // Get image Exif/Iptc data.
+ DMetadata meta;
+ meta.setExif(d->image.getExif());
+ meta.setIptc(d->image.getIptc());
+
+ // Update Iptc preview.
+ // NOTE: see B.K.O #130525. a JPEG segment is limited to 64K. If the IPTC byte array is
+ // bigger than 64K duing of image preview tag size, the target JPEG image will be
+ // broken. Note that IPTC image preview tag is limited to 256K!!!
+ // There is no limitation with TIFF and PNG about IPTC byte array size.
+
+ TQImage preview = d->image.smoothScale(1280, 1024, TQSize::ScaleMin).copyTQImage();
+
+ if ( mimeType.upper() != TQString("JPG") && mimeType.upper() != TQString("JPEG") &&
+ mimeType.upper() != TQString("JPE"))
+ {
+ // Non JPEG file, we update IPTC preview
+ meta.setImagePreview(preview);
+ }
+ else
+ {
+ // JPEG file, we remove IPTC preview.
+ meta.removeIptcTag("Iptc.Application2.Preview");
+ meta.removeIptcTag("Iptc.Application2.PreviewFormat");
+ meta.removeIptcTag("Iptc.Application2.PreviewVersion");
+ }
+
+ // Update Exif thumbnail.
+ TQImage thumb = preview.smoothScale(160, 120, TQImage::ScaleMin);
+ meta.setExifThumbnail(thumb);
+
+ // Update Exif Image dimensions.
+ meta.setImageDimensions(d->image.size());
+
+ // Update Exif Document Name tag with the original file name.
+ meta.setExifTagString("Exif.Image.DocumentName", getImageFileName());
+
+ // Update Exif Orientation tag if necessary.
+ if( setExifOrientationTag )
+ meta.setImageOrientation(DMetadata::ORIENTATION_NORMAL);
+
+ // Store new Exif/Iptc data into image.
+ d->image.setExif(meta.getExif());
+ d->image.setIptc(meta.getIptc());
+
+ d->thread->save(d->image, fileName, mimeType);
+}
+
+void DImgInterface::slotImageSaved(const TQString& filePath, bool success)
+{
+ if (filePath != d->savingFilename)
+ return;
+
+ if (!success)
+ DWarning() << "error saving image '" << TQFile::encodeName(filePath).data() << endl;
+
+ emit signalImageSaved(filePath, success);
+ emit signalUndoStateChanged(d->undoMan->anyMoreUndo(), d->undoMan->anyMoreRedo(), !d->undoMan->isAtOrigin());
+}
+
+void DImgInterface::slotSavingProgress(const TQString& filePath, float progress)
+{
+ if (filePath == d->savingFilename)
+ emit signalSavingProgress(filePath, progress);
+}
+
+void DImgInterface::abortSaving()
+{
+ // failure will be reported by a signal
+ d->thread->stopSaving(d->savingFilename);
+}
+
+void DImgInterface::switchToLastSaved(const TQString& newFilename)
+{
+ // Higher level wants to use the current DImg object to represent the file
+ // it has previously been saved to.
+ d->filename = newFilename;
+
+ // Currently the only place where a DImg is connected to the file it originates from
+ // is the format attribute.
+ TQString savedformat = d->image.attribute("savedformat").toString();
+ if (!savedformat.isEmpty())
+ d->image.setAttribute("format", savedformat);
+}
+
+void DImgInterface::setModified()
+{
+ emit signalModified();
+ emit signalUndoStateChanged(d->undoMan->anyMoreUndo(), d->undoMan->anyMoreRedo(), !d->undoMan->isAtOrigin());
+}
+
+void DImgInterface::readMetadataFromFile(const TQString &file)
+{
+ DMetadata meta(file);
+
+ //TODO: code is essentially the same as DImgLoader::readMetadata,
+ // put both in a common place.
+ if (!meta.getComments().isNull())
+ d->image.setComments(meta.getComments());
+ if (!meta.getExif().isNull())
+ d->image.setExif(meta.getExif());
+ if (!meta.getIptc().isNull())
+ d->image.setIptc(meta.getIptc());
+}
+
+void DImgInterface::clearUndoManager()
+{
+ d->undoMan->clear();
+ d->undoMan->setOrigin();
+ emit signalUndoStateChanged(false, false, false);
+}
+
+void DImgInterface::setUndoManagerOrigin()
+{
+ d->undoMan->setOrigin();
+ emit signalUndoStateChanged(d->undoMan->anyMoreUndo(), d->undoMan->anyMoreRedo(), !d->undoMan->isAtOrigin());
+}
+
+void DImgInterface::updateUndoState()
+{
+ emit signalUndoStateChanged(d->undoMan->anyMoreUndo(), d->undoMan->anyMoreRedo(), !d->undoMan->isAtOrigin());
+}
+
+bool DImgInterface::imageValid()
+{
+ return !d->image.isNull();
+}
+
+int DImgInterface::width()
+{
+ return d->width;
+}
+
+int DImgInterface::height()
+{
+ return d->height;
+}
+
+int DImgInterface::origWidth()
+{
+ return d->origWidth;
+}
+
+int DImgInterface::origHeight()
+{
+ return d->origHeight;
+}
+
+int DImgInterface::bytesDepth()
+{
+ return d->image.bytesDepth();
+}
+
+bool DImgInterface::sixteenBit()
+{
+ return d->image.sixteenBit();
+}
+
+bool DImgInterface::hasAlpha()
+{
+ return d->image.hasAlpha();
+}
+
+bool DImgInterface::isReadOnly()
+{
+ if (d->image.isNull())
+ return true;
+ else
+ return d->image.isReadOnly();
+}
+
+void DImgInterface::setSelectedArea(int x, int y, int w, int h)
+{
+ d->selX = x;
+ d->selY = y;
+ d->selW = w;
+ d->selH = h;
+}
+
+void DImgInterface::getSelectedArea(int& x, int& y, int& w, int& h)
+{
+ x = d->selX;
+ y = d->selY;
+ w = d->selW;
+ h = d->selH;
+}
+
+void DImgInterface::paintOnDevice(TQPaintDevice* p,
+ int sx, int sy, int sw, int sh,
+ int dx, int dy, int dw, int dh,
+ int /*antialias*/)
+{
+ if (d->image.isNull())
+ return;
+
+ DImg img = d->image.smoothScaleSection(sx, sy, sw, sh, dw, dh);
+ d->cmod.applyBCG(img);
+ img.convertDepth(32);
+
+ if (d->cmSettings->enableCMSetting && d->cmSettings->managedViewSetting)
+ {
+ TQPixmap pix(img.convertToPixmap(&d->monitorICCtrans));
+ bitBlt(p, dx, dy, &pix, 0, 0);
+ }
+ else
+ {
+ TQPixmap pix(img.convertToPixmap());
+ bitBlt(p, dx, dy, &pix, 0, 0);
+ }
+
+ // Show the Over/Under exposure pixels indicators
+
+ if (d->expoSettings->underExposureIndicator || d->expoSettings->overExposureIndicator)
+ {
+ TQImage pureColorMask = d->image.copy(sx, sy, sw, sh).pureColorMask(d->expoSettings);
+ TQPixmap pixMask(pureColorMask.scale(dw, dh));
+ bitBlt(p, dx, dy, &pixMask, 0, 0);
+ }
+}
+
+void DImgInterface::paintOnDevice(TQPaintDevice* p,
+ int sx, int sy, int sw, int sh,
+ int dx, int dy, int dw, int dh,
+ int mx, int my, int mw, int mh,
+ int /*antialias*/)
+{
+ if (d->image.isNull())
+ return;
+
+ DImg img = d->image.smoothScaleSection(sx, sy, sw, sh, dw, dh);
+ d->cmod.applyBCG(img);
+ img.convertDepth(32);
+
+ uint* data = (uint*)img.bits();
+ uchar r, g, b, a;
+
+ for (int j=0; j < (int)img.height(); j++)
+ {
+ for (int i=0; i < (int)img.width(); i++)
+ {
+ if (i < (mx-dx) || i > (mx-dx+mw-1) ||
+ j < (my-dy) || j > (my-dy+mh-1))
+ {
+ a = (*data >> 24) & 0xff;
+ r = (*data >> 16) & 0xff;
+ g = (*data >> 8) & 0xff;
+ b = (*data ) & 0xff;
+
+ r += (uchar)((RCOL - r) * OPACITY);
+ g += (uchar)((GCOL - g) * OPACITY);
+ b += (uchar)((BCOL - b) * OPACITY);
+
+ *data = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+
+ data++;
+ }
+ }
+
+ if (d->cmSettings->enableCMSetting && d->cmSettings->managedViewSetting)
+ {
+ TQPixmap pix(img.convertToPixmap(&d->monitorICCtrans));
+ bitBlt(p, dx, dy, &pix, 0, 0);
+ }
+ else
+ {
+ TQPixmap pix(img.convertToPixmap());
+ bitBlt(p, dx, dy, &pix, 0, 0);
+ }
+
+ // Show the Over/Under exposure pixels indicators
+
+ if (d->expoSettings->underExposureIndicator || d->expoSettings->overExposureIndicator)
+ {
+ TQImage pureColorMask = d->image.copy(sx, sy, sw, sh).pureColorMask(d->expoSettings);
+ TQPixmap pixMask(pureColorMask.scale(dw, dh));
+ bitBlt(p, dx, dy, &pixMask, 0, 0);
+ }
+}
+
+void DImgInterface::zoom(double val)
+{
+ d->zoom = val;
+ d->width = (int)(d->origWidth * val);
+ d->height = (int)(d->origHeight * val);
+}
+
+void DImgInterface::rotate90(bool saveUndo)
+{
+ if (saveUndo)
+ {
+ d->undoMan->addAction(new UndoActionRotate(this, UndoActionRotate::R90));
+ }
+
+ d->image.rotate(DImg::ROT90);
+ d->origWidth = d->image.width();
+ d->origHeight = d->image.height();
+
+ setModified();
+}
+
+void DImgInterface::rotate180(bool saveUndo)
+{
+ if (saveUndo)
+ {
+ d->undoMan->addAction(new UndoActionRotate(this, UndoActionRotate::R180));
+ }
+
+ d->image.rotate(DImg::ROT180);
+ d->origWidth = d->image.width();
+ d->origHeight = d->image.height();
+
+ setModified();
+}
+
+void DImgInterface::rotate270(bool saveUndo)
+{
+ if (saveUndo)
+ {
+ d->undoMan->addAction(new UndoActionRotate(this, UndoActionRotate::R270));
+ }
+
+ d->image.rotate(DImg::ROT270);
+ d->origWidth = d->image.width();
+ d->origHeight = d->image.height();
+
+ setModified();
+}
+
+void DImgInterface::flipHoriz(bool saveUndo)
+{
+ if (saveUndo)
+ {
+ d->undoMan->addAction(new UndoActionFlip(this, UndoActionFlip::Horizontal));
+ }
+
+ d->image.flip(DImg::HORIZONTAL);
+
+ setModified();
+}
+
+void DImgInterface::flipVert(bool saveUndo)
+{
+ if (saveUndo)
+ {
+ d->undoMan->addAction(new UndoActionFlip(this, UndoActionFlip::Vertical));
+ }
+
+ d->image.flip(DImg::VERTICAL);
+
+ setModified();
+}
+
+void DImgInterface::crop(int x, int y, int w, int h)
+{
+ d->undoMan->addAction(new UndoActionIrreversible(this, "Crop"));
+
+ d->image.crop(x, y, w, h);
+
+ d->origWidth = d->image.width();
+ d->origHeight = d->image.height();
+
+ setModified();
+}
+
+void DImgInterface::resize(int w, int h)
+{
+ d->undoMan->addAction(new UndoActionIrreversible(this, "Resize"));
+
+ d->image.resize(w, h);
+
+ d->origWidth = d->image.width();
+ d->origHeight = d->image.height();
+
+ setModified();
+}
+
+void DImgInterface::changeGamma(double gamma)
+{
+ d->undoMan->addAction(new UndoActionBCG(this, d->gamma, d->brightness,
+ d->contrast, gamma, d->brightness,
+ d->contrast));
+
+ d->gamma += gamma/10.0;
+
+ d->cmod.reset();
+ d->cmod.setGamma(d->gamma);
+ d->cmod.setBrightness(d->brightness);
+ d->cmod.setContrast(d->contrast);
+ d->changedBCG = true;
+
+ setModified();
+}
+
+void DImgInterface::changeBrightness(double brightness)
+{
+ d->undoMan->addAction(new UndoActionBCG(this, d->gamma, d->brightness,
+ d->contrast, d->gamma, brightness,
+ d->contrast));
+
+ d->brightness += brightness/100.0;
+
+ d->cmod.reset();
+ d->cmod.setGamma(d->gamma);
+ d->cmod.setBrightness(d->brightness);
+ d->cmod.setContrast(d->contrast);
+ d->changedBCG = true;
+
+ setModified();
+}
+
+void DImgInterface::changeContrast(double contrast)
+{
+ d->undoMan->addAction(new UndoActionBCG(this, d->gamma, d->brightness,
+ d->contrast, d->gamma, d->brightness,
+ contrast));
+
+ d->contrast += contrast/100.0;
+
+ d->cmod.reset();
+ d->cmod.setGamma(d->gamma);
+ d->cmod.setBrightness(d->brightness);
+ d->cmod.setContrast(d->contrast);
+ d->changedBCG = true;
+
+ setModified();
+}
+
+void DImgInterface::changeBCG(double gamma, double brightness, double contrast)
+{
+ d->gamma = gamma;
+ d->brightness = brightness;
+ d->contrast = contrast;
+
+ d->cmod.reset();
+ d->cmod.setGamma(d->gamma);
+ d->cmod.setBrightness(d->brightness);
+ d->cmod.setContrast(d->contrast);
+ d->changedBCG = true;
+
+ setModified();
+}
+
+void DImgInterface::setBCG(double brightness, double contrast, double gamma)
+{
+ d->undoMan->addAction(new UndoActionIrreversible(this, "Brightness, Contrast, Gamma"));
+
+ d->cmod.reset();
+ d->cmod.setGamma(gamma);
+ d->cmod.setBrightness(brightness);
+ d->cmod.setContrast(contrast);
+ d->cmod.applyBCG(d->image);
+
+ d->cmod.reset();
+ d->gamma = 1.0;
+ d->contrast = 1.0;
+ d->brightness = 0.0;
+ d->changedBCG = false;
+
+ setModified();
+}
+
+void DImgInterface::convertDepth(int depth)
+{
+ d->undoMan->addAction(new UndoActionIrreversible(this, "Convert Color Depth"));
+ d->image.convertDepth(depth);
+
+ setModified();
+}
+
+DImg* DImgInterface::getImg()
+{
+ if (!d->image.isNull())
+ {
+ return &d->image;
+ }
+ else
+ {
+ DWarning() << k_funcinfo << "d->image is NULL" << endl;
+ return 0;
+ }
+}
+
+uchar* DImgInterface::getImage()
+{
+ if (!d->image.isNull())
+ {
+ return d->image.bits();
+ }
+ else
+ {
+ DWarning() << k_funcinfo << "d->image is NULL" << endl;
+ return 0;
+ }
+}
+
+void DImgInterface::putImage(const TQString &caller, uchar* data, int w, int h)
+{
+ putImage(caller, data, w, h, d->image.sixteenBit());
+}
+
+void DImgInterface::putImage(const TQString &caller, uchar* data, int w, int h, bool sixteenBit)
+{
+ d->undoMan->addAction(new UndoActionIrreversible(this, caller));
+ putImage(data, w, h, sixteenBit);
+}
+
+void DImgInterface::putImage(uchar* data, int w, int h)
+{
+ putImage(data, w, h, d->image.sixteenBit());
+}
+
+void DImgInterface::putImage(uchar* data, int w, int h, bool sixteenBit)
+{
+ if (d->image.isNull())
+ {
+ DWarning() << k_funcinfo << "d->image is NULL" << endl;
+ return;
+ }
+
+ if (!data)
+ {
+ DWarning() << k_funcinfo << "New image is NULL" << endl;
+ return;
+ }
+
+ if (w == -1 && h == -1)
+ {
+ // New image size
+ w = d->origWidth;
+ h = d->origHeight;
+ }
+ else
+ {
+ // New image size == original size
+ d->origWidth = w;
+ d->origHeight = h;
+ }
+
+ //DDebug() << k_funcinfo << data << " " << w << " " << h << endl;
+ d->image.putImageData(w, h, sixteenBit, d->image.hasAlpha(), data);
+
+ setModified();
+}
+
+void DImgInterface::setEmbeddedICCToOriginalImage( TQString profilePath)
+{
+ if (d->image.isNull())
+ {
+ DWarning() << k_funcinfo << "d->image is NULL" << endl;
+ return;
+ }
+
+ DDebug() << k_funcinfo << "Embedding profile: " << profilePath << endl;
+ d->image.getICCProfilFromFile( TQFile::encodeName(profilePath));
+ setModified();
+}
+
+uchar* DImgInterface::getImageSelection()
+{
+ if (!d->selW || !d->selH)
+ return 0;
+
+ if (!d->image.isNull())
+ {
+ DImg im = d->image.copy(d->selX, d->selY, d->selW, d->selH);
+ return im.stripImageData();
+ }
+
+ return 0;
+}
+
+void DImgInterface::putImageSelection(const TQString &caller, uchar* data)
+{
+ if (!data || d->image.isNull())
+ return;
+
+ d->undoMan->addAction(new UndoActionIrreversible(this, caller));
+
+ d->image.bitBltImage(data, 0, 0, d->selW, d->selH, d->selX, d->selY, d->selW, d->selH, d->image.bytesDepth());
+
+ setModified();
+}
+
+void DImgInterface::getUndoHistory(TQStringList &titles)
+{
+ d->undoMan->getUndoHistory(titles);
+}
+
+void DImgInterface::getRedoHistory(TQStringList &titles)
+{
+ d->undoMan->getRedoHistory(titles);
+}
+
+TQByteArray DImgInterface::getEmbeddedICC()
+{
+ return d->image.getICCProfil();
+}
+
+TQByteArray DImgInterface::getExif()
+{
+ return d->image.getExif();
+}
+
+TQByteArray DImgInterface::getIptc()
+{
+ return d->image.getIptc();
+}
+
+TQString DImgInterface::getImageFilePath()
+{
+ return d->filename;
+}
+
+TQString DImgInterface::getImageFileName()
+{
+ return d->filename.section( '/', -1 );
+}
+
+TQString DImgInterface::getImageFormat()
+{
+ if (d->image.isNull())
+ return TQString();
+
+ TQString mimeType = d->image.attribute("format").toString();
+ // It is a bug in the loader if format attribute is not given
+ if (mimeType.isEmpty())
+ {
+ DWarning() << "DImg object does not contain attribute \"format\"" << endl;
+ mimeType = TQImageIO::imageFormat(d->filename);
+ }
+ return mimeType;
+}
+
+ICCSettingsContainer* DImgInterface::getICCSettings()
+{
+ return d->cmSettings;
+}
+
+TQPixmap DImgInterface::convertToPixmap(DImg& img)
+{
+ if (d->cmSettings->enableCMSetting && d->cmSettings->managedViewSetting)
+ return img.convertToPixmap(&d->monitorICCtrans);
+
+ return img.convertToPixmap();
+}
+
+TQColor DImgInterface::underExposureColor()
+{
+ return d->expoSettings->underExposureColor;
+}
+
+TQColor DImgInterface::overExposureColor()
+{
+ return d->expoSettings->overExposureColor;
+}
+
+} // namespace Digikam
+
diff --git a/src/utilities/imageeditor/canvas/dimginterface.h b/src/utilities/imageeditor/canvas/dimginterface.h
new file mode 100644
index 00000000..9a41eb05
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/dimginterface.h
@@ -0,0 +1,200 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2003-01-15
+ * Description : DImg interface for image editor
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2009 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 DIMGINTERFACE_H
+#define DIMGINTERFACE_H
+
+// TQt includes.
+
+#include <tqobject.h>
+#include <tqstring.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+#include "dimg.h"
+
+class TQWidget;
+class TQPixmap;
+
+namespace Digikam
+{
+
+class ICCSettingsContainer;
+class ExposureSettingsContainer;
+class IOFileSettingsContainer;
+class LoadingDescription;
+class DImgInterfacePrivate;
+
+class DIGIKAM_EXPORT DImgInterface : public TQObject
+{
+ TQ_OBJECT
+
+
+public:
+
+ static DImgInterface* defaultInterface();
+ static void setDefaultInterface(DImgInterface *defaultInterface);
+
+ DImgInterface();
+ ~DImgInterface();
+
+ void load(const TQString& filename, IOFileSettingsContainer *iofileSettings, TQWidget *parent=0);
+
+ void setICCSettings(ICCSettingsContainer *cmSettings);
+ void setExposureSettings(ExposureSettingsContainer *expoSettings);
+ void setExifOrient(bool exifOrient);
+
+ void undo();
+ void redo();
+ void restore();
+
+ void saveAs(const TQString& file, IOFileSettingsContainer *iofileSettings,
+ bool setExifOrientationTag, const TQString& mimeType=TQString());
+
+ void switchToLastSaved(const TQString& newFilename);
+ void abortSaving();
+ void setModified();
+ void readMetadataFromFile(const TQString &file);
+ void clearUndoManager();
+ void setUndoManagerOrigin();
+ void updateUndoState();
+ void resetImage();
+
+ void zoom(double val);
+
+ void paintOnDevice(TQPaintDevice* p,
+ int sx, int sy, int sw, int sh,
+ int dx, int dy, int dw, int dh,
+ int antialias);
+ void paintOnDevice(TQPaintDevice* p,
+ int sx, int sy, int sw, int sh,
+ int dx, int dy, int dw, int dh,
+ int mx, int my, int mw, int mh,
+ int antialias);
+
+ bool imageValid();
+ int width();
+ int height();
+ int origWidth();
+ int origHeight();
+ int bytesDepth();
+ bool hasAlpha();
+ bool sixteenBit();
+ bool exifRotated();
+ bool isReadOnly();
+
+ void setSelectedArea(int x, int y, int w, int h);
+ void getSelectedArea(int& x, int& y, int& w, int& h);
+
+ void rotate90(bool saveUndo=true);
+ void rotate180(bool saveUndo=true);
+ void rotate270(bool saveUndo=true);
+
+ void flipHoriz(bool saveUndo=true);
+ void flipVert(bool saveUndo=true);
+
+ void crop(int x, int y, int w, int h);
+
+ void resize(int w, int h);
+
+ void changeGamma(double gamma);
+ void changeBrightness(double brightness);
+ void changeContrast(double contrast);
+ void changeBCG(double gamma, double brightness, double contrast);
+
+ void setBCG(double brightness, double contrast, double gamma);
+
+ void convertDepth(int depth);
+
+ void getUndoHistory(TQStringList &titles);
+ void getRedoHistory(TQStringList &titles);
+
+ DImg* getImg();
+ uchar* getImage();
+
+ void putImage(uchar* data, int w, int h);
+ void putImage(uchar* data, int w, int h, bool sixteenBit);
+ void putImage(const TQString &caller, uchar* data, int w, int h);
+ void putImage(const TQString &caller, uchar* data, int w, int h, bool sixteenBit);
+
+ uchar* getImageSelection();
+ void putImageSelection(const TQString &caller, uchar* data);
+
+ void setEmbeddedICCToOriginalImage( TQString profilePath);
+
+ /** Convert a DImg image to a pixmap for screen using color
+ managemed view if necessary */
+ TQPixmap convertToPixmap(DImg& img);
+
+ TQByteArray getEmbeddedICC();
+ TQByteArray getExif();
+ TQByteArray getIptc();
+
+ ICCSettingsContainer *getICCSettings();
+
+ TQString getImageFileName();
+ TQString getImageFilePath();
+ TQString getImageFormat();
+
+ TQColor underExposureColor();
+ TQColor overExposureColor();
+
+protected slots:
+
+ void slotImageLoaded(const LoadingDescription &loadingDescription, const DImg& img);
+ void slotImageSaved(const TQString& filePath, bool success);
+ void slotLoadingProgress(const LoadingDescription &loadingDescription, float progress);
+ void slotSavingProgress(const TQString& filePath, float progress);
+
+signals:
+
+ void signalModified();
+ void signalUndoStateChanged(bool moreUndo, bool moreRedo, bool canSave);
+ void signalLoadingStarted(const TQString& filename);
+ void signalLoadingProgress(const TQString& filePath, float progress);
+ void signalImageLoaded(const TQString& filePath, bool success);
+ void signalSavingProgress(const TQString& filePath, float progress);
+ void signalImageSaved(const TQString& filePath, bool success);
+
+private slots:
+
+ void slotUseRawImportSettings();
+ void slotUseDefaultSettings();
+
+private:
+
+ void exifRotate(const TQString& filename);
+ void resetValues();
+
+private:
+
+ static DImgInterface *m_defaultInterface;
+
+ DImgInterfacePrivate *d;
+};
+
+} // namespace Digikam
+
+#endif /* DIMGINTERFACE_H */
diff --git a/src/utilities/imageeditor/canvas/iccsettingscontainer.h b/src/utilities/imageeditor/canvas/iccsettingscontainer.h
new file mode 100644
index 00000000..eadb12fb
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/iccsettingscontainer.h
@@ -0,0 +1,82 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-12-08
+ * Description : ICC Settings Container.
+ *
+ * Copyright (C) 2005-2007 by F.J. Cruz <fj.cruz@supercable.es>
+ * Copyright (C) 2005-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 ICCSETTINGSCONTAINER_H
+#define ICCSETTINGSCONTAINER_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT ICCSettingsContainer
+{
+
+public:
+
+ ICCSettingsContainer()
+ {
+ enableCMSetting = false; // NOTE: by default, ICC color management is disable.
+
+ askOrApplySetting = false;
+ BPCSetting = false;
+ managedViewSetting = false;
+
+ renderingSetting = 0;
+
+ workspaceSetting = TQString();
+ monitorSetting = TQString();
+ inputSetting = TQString();
+ proofSetting = TQString();
+ };
+
+ ~ICCSettingsContainer(){};
+
+public:
+
+ bool enableCMSetting;
+
+ // FALSE -> apply
+ // TRUE -> ask
+ bool askOrApplySetting;
+ bool BPCSetting;
+ bool managedViewSetting;
+
+ int renderingSetting;
+
+ TQString workspaceSetting;
+ TQString monitorSetting;
+ TQString inputSetting;
+ TQString proofSetting;
+};
+
+} // namespace Digikam
+
+#endif // ICCSETTINGSCONTAINER_H
diff --git a/src/utilities/imageeditor/canvas/imageplugin.cpp b/src/utilities/imageeditor/canvas/imageplugin.cpp
new file mode 100644
index 00000000..b330cb5a
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/imageplugin.cpp
@@ -0,0 +1,68 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-04
+ * Description : image plugins interface for image editor
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * 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.
+ *
+ * ============================================================ */
+
+// Local includes.
+
+#include "editortool.h"
+#include "editortooliface.h"
+#include "imageplugin.h"
+#include "imageplugin.moc"
+
+namespace Digikam
+{
+
+ImagePlugin::ImagePlugin(TQObject *parent, const char* name)
+ : TQObject(parent, name)
+{
+}
+
+ImagePlugin::~ImagePlugin()
+{
+}
+
+void ImagePlugin::setEnabledSelectionActions(bool)
+{
+}
+
+void ImagePlugin::setEnabledActions(bool)
+{
+}
+
+void ImagePlugin::loadTool(EditorTool* tool)
+{
+ EditorToolIface::editorToolIface()->loadTool(tool);
+
+ connect(tool, TQ_SIGNAL(okClicked()),
+ this, TQ_SLOT(slotToolDone()));
+
+ connect(tool, TQ_SIGNAL(cancelClicked()),
+ this, TQ_SLOT(slotToolDone()));
+}
+
+void ImagePlugin::slotToolDone()
+{
+ EditorToolIface::editorToolIface()->unLoadTool();
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/canvas/imageplugin.h b/src/utilities/imageeditor/canvas/imageplugin.h
new file mode 100644
index 00000000..ef506256
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/imageplugin.h
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-04
+ * Description : image plugins interface for image editor.
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_H
+#define IMAGEPLUGIN_H
+
+// TQt includes.
+
+#include <tqobject.h>
+
+// KDE includes.
+
+#include <kxmlguiclient.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+class TQWidget;
+
+namespace Digikam
+{
+
+class EditorTool;
+
+class DIGIKAM_EXPORT ImagePlugin : public TQObject, public KXMLGUIClient
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin(TQObject *parent, const char* name=0);
+ virtual ~ImagePlugin();
+
+ virtual void setEnabledSelectionActions(bool enable);
+ virtual void setEnabledActions(bool enable);
+
+ void loadTool(EditorTool* tool);
+
+private slots:
+
+ void slotToolDone();
+};
+
+} //namespace Digikam
+
+#endif /* IMAGEPLUGIN_H */
+
diff --git a/src/utilities/imageeditor/canvas/imagepluginloader.cpp b/src/utilities/imageeditor/canvas/imagepluginloader.cpp
new file mode 100644
index 00000000..43c8a16c
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/imagepluginloader.cpp
@@ -0,0 +1,278 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-04
+ * Description : image plugins loader for image editor.
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2007 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.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <ktrader.h>
+#include <tdeparts/componentfactory.h>
+#include <tdeapplication.h>
+#include <tdelocale.h>
+#include <kxmlguiclient.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "splashscreen.h"
+#include "imagepluginloader.h"
+
+namespace Digikam
+{
+
+// List of obsolete image plugins name.
+
+static const char* ObsoleteImagePluginsList[] =
+{
+ "digikamimageplugin_blowup", // Merged with "Resize" tool since 0.9.2.
+ "digikamimageplugin_solarize", // Renamed "ColorFx" since 0.9.2.
+ "digikamimageplugin_unsharp", // Merged with "Sharpen" tool since 0.9.2.
+ "digikamimageplugin_refocus", // Merged with "Sharpen" tool since 0.9.2.
+ "digikamimageplugin_despeckle", // Renamed "Noise Reduction" since 0.9.2.
+ "-1"
+};
+
+class ImagePluginLoaderPrivate
+{
+
+public:
+
+ typedef TQPair<TQString, ImagePlugin*> PluginType;
+ typedef TQValueList< PluginType > PluginList;
+
+public:
+
+ ImagePluginLoaderPrivate()
+ {
+ splash = 0;
+
+ for (int i=0 ; TQString(ObsoleteImagePluginsList[i]) != TQString("-1") ; i++)
+ obsoleteImagePluginsList << ObsoleteImagePluginsList[i];
+ }
+
+ TQStringList obsoleteImagePluginsList;
+
+ SplashScreen *splash;
+
+ PluginList pluginList;
+};
+
+ImagePluginLoader* ImagePluginLoader::m_instance=0;
+
+ImagePluginLoader* ImagePluginLoader::instance()
+{
+ return m_instance;
+}
+
+ImagePluginLoader::ImagePluginLoader(TQObject *parent, SplashScreen *splash)
+ : TQObject(parent)
+{
+ m_instance = this;
+ d = new ImagePluginLoaderPrivate;
+ d->splash = splash;
+
+ TQStringList imagePluginsList2Load;
+
+ TDETrader::OfferList offers = TDETrader::self()->query("Digikam/ImagePlugin");
+ TDETrader::OfferList::ConstIterator iter;
+
+ for (iter = offers.begin() ; iter != offers.end() ; ++iter)
+ {
+ KService::Ptr service = *iter;
+ if (!d->obsoleteImagePluginsList.contains(service->library()))
+ imagePluginsList2Load.append(service->library());
+ }
+
+ loadPluginsFromList(imagePluginsList2Load);
+}
+
+ImagePluginLoader::~ImagePluginLoader()
+{
+ delete d;
+ m_instance = 0;
+}
+
+void ImagePluginLoader::loadPluginsFromList(const TQStringList& list)
+{
+ if (d->splash)
+ d->splash->message(i18n("Loading Image Plugins"));
+
+ TDETrader::OfferList offers = TDETrader::self()->query("Digikam/ImagePlugin");
+ TDETrader::OfferList::ConstIterator iter;
+
+ int cpt = 0;
+
+ // Load plugin core at the first time.
+
+ for(iter = offers.begin(); iter != offers.end(); ++iter)
+ {
+ KService::Ptr service = *iter;
+ ImagePlugin *plugin;
+
+ if (service->library() == "digikamimageplugin_core")
+ {
+ if (!pluginIsLoaded(service->name()) )
+ {
+ int error=-1;
+ plugin = KParts::ComponentFactory::createInstanceFromService<ImagePlugin>(
+ service, this, service->name().local8Bit(), 0, &error);
+
+ if (plugin && (dynamic_cast<KXMLGUIClient*>(plugin) != 0))
+ {
+ d->pluginList.append(ImagePluginLoaderPrivate::PluginType(service->name(), plugin));
+
+ DDebug() << "ImagePluginLoader: Loaded plugin " << service->name() << endl;
+
+ ++cpt;
+ }
+ else
+ {
+ DWarning() << "ImagePluginLoader:: createInstanceFromLibrary returned 0 for "
+ << service->name()
+ << " (" << service->library() << ")"
+ << " with error code "
+ << error << endl;
+ if (error == KParts::ComponentFactory::ErrNoLibrary)
+ DWarning() << "KLibLoader says: "
+ << KLibLoader::self()->lastErrorMessage() << endl;
+ }
+ }
+ break;
+ }
+ }
+
+ // Load all other image plugins after (make a coherant menu construction in Image Editor).
+
+ for (iter = offers.begin(); iter != offers.end(); ++iter)
+ {
+ KService::Ptr service = *iter;
+ ImagePlugin *plugin;
+
+ if (!list.contains(service->library()) && service->library() != "digikamimageplugin_core")
+ {
+ if ((plugin = pluginIsLoaded(service->name())) != NULL)
+ d->pluginList.remove(ImagePluginLoaderPrivate::PluginType(service->name(),plugin));
+ }
+ else
+ {
+ if( pluginIsLoaded(service->name()) )
+ continue;
+ else
+ {
+ int error=-1;
+ plugin = KParts::ComponentFactory::createInstanceFromService<ImagePlugin>(
+ service, this, service->name().local8Bit(), 0);
+
+ if (plugin && (dynamic_cast<KXMLGUIClient*>(plugin) != 0))
+ {
+ d->pluginList.append(ImagePluginLoaderPrivate::PluginType(service->name(), plugin));
+
+ DDebug() << "ImagePluginLoader: Loaded plugin " << service->name() << endl;
+
+ ++cpt;
+ }
+ else
+ {
+ DWarning() << "ImagePluginLoader:: createInstanceFromLibrary returned 0 for "
+ << service->name()
+ << " (" << service->library() << ")"
+ << " with error code "
+ << error << endl;
+ if (error == KParts::ComponentFactory::ErrNoLibrary)
+ DWarning() << "KLibLoader says: "
+ << KLibLoader::self()->lastErrorMessage() << endl;
+ }
+ }
+ }
+ }
+
+ d->splash = 0; // Splashcreen is only lanched at the first time.
+ // If user change plugins list to use in setup, don't try to
+ // use the old splashscreen instance.
+}
+
+ImagePlugin* ImagePluginLoader::pluginIsLoaded(const TQString& name)
+{
+ if ( d->pluginList.isEmpty() )
+ return 0;
+
+ for (ImagePluginLoaderPrivate::PluginList::iterator it = d->pluginList.begin();
+ it != d->pluginList.end(); ++it)
+ {
+ if ((*it).first == name )
+ return (*it).second;
+ }
+
+ return 0;
+}
+
+ImagePlugin* ImagePluginLoader::pluginInstance(const TQString& libraryName)
+{
+ TDETrader::OfferList offers = TDETrader::self()->query("Digikam/ImagePlugin");
+ TDETrader::OfferList::ConstIterator iter;
+
+ for(iter = offers.begin(); iter != offers.end(); ++iter)
+ {
+ KService::Ptr service = *iter;
+
+ if(service->library() == libraryName)
+ {
+ return ( pluginIsLoaded(service->name()) );
+ }
+ }
+
+ return 0;
+}
+
+bool ImagePluginLoader::pluginLibraryIsLoaded(const TQString& libraryName)
+{
+ TDETrader::OfferList offers = TDETrader::self()->query("Digikam/ImagePlugin");
+ TDETrader::OfferList::ConstIterator iter;
+
+ for(iter = offers.begin(); iter != offers.end(); ++iter)
+ {
+ KService::Ptr service = *iter;
+
+ if(service->library() == libraryName)
+ {
+ if( pluginIsLoaded(service->name()) )
+ return true;
+ }
+ }
+
+ return false;
+}
+
+TQPtrList<ImagePlugin> ImagePluginLoader::pluginList()
+{
+ TQPtrList<ImagePlugin> list;
+
+ for (ImagePluginLoaderPrivate::PluginList::iterator it = d->pluginList.begin();
+ it != d->pluginList.end(); ++it)
+ {
+ list.append((*it).second);
+ }
+
+ return list;
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/canvas/imagepluginloader.h b/src/utilities/imageeditor/canvas/imagepluginloader.h
new file mode 100644
index 00000000..55ffe933
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/imagepluginloader.h
@@ -0,0 +1,79 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-04
+ * Description : image plugins loader for image editor.
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2007 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 IMAGEPLUGINLOADER_H
+#define IMAGEPLUGINLOADER_H
+
+// TQt includes.
+
+#include <tqobject.h>
+#include <tqptrlist.h>
+#include <tqstring.h>
+#include <tqvaluelist.h>
+#include <tqpair.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+#include "imageplugin.h"
+
+namespace Digikam
+{
+
+class SplashScreen;
+class ImagePluginLoaderPrivate;
+
+class DIGIKAM_EXPORT ImagePluginLoader : public TQObject
+{
+
+public:
+
+ ImagePluginLoader(TQObject *parent, SplashScreen *splash=0);
+ ~ImagePluginLoader();
+
+ static ImagePluginLoader* instance();
+
+ TQPtrList<ImagePlugin> pluginList();
+ void loadPluginsFromList(const TQStringList& list);
+
+ // Return true if plugin library is loaded in memory.
+ // 'libraryName' is internal plugin library name not i18n.
+ bool pluginLibraryIsLoaded(const TQString& libraryName);
+
+ ImagePlugin* pluginInstance(const TQString& libraryName);
+
+private:
+
+ ImagePlugin* pluginIsLoaded(const TQString& name);
+
+private:
+
+ static ImagePluginLoader *m_instance;
+
+ ImagePluginLoaderPrivate *d;
+};
+
+} // namespace Digikam
+
+#endif /* IMAGEPLUGINLOADER_H */
diff --git a/src/utilities/imageeditor/canvas/iofilesettingscontainer.h b/src/utilities/imageeditor/canvas/iofilesettingscontainer.h
new file mode 100644
index 00000000..360299b3
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/iofilesettingscontainer.h
@@ -0,0 +1,84 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-03
+ * Description : IO file Settings Container.
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef IOFILESETTINGSCONTAINER_H
+#define IOFILESETTINGSCONTAINER_H
+
+// Local includes.
+
+#include "drawdecoding.h"
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT IOFileSettingsContainer
+{
+
+public:
+
+ IOFileSettingsContainer()
+ {
+ JPEGCompression = 75;
+ JPEGSubSampling = 1; // Medium subsampling
+ PNGCompression = 9;
+ TIFFCompression = false;
+ JPEG2000Compression = 75;
+ JPEG2000LossLess = true;
+ useRAWImport = true;
+ };
+
+ ~IOFileSettingsContainer(){};
+
+public:
+
+ // JPEG quality value.
+ int JPEGCompression;
+
+ // JPEG chroma subsampling value.
+ int JPEGSubSampling;
+
+ // PNG compression value.
+ int PNGCompression;
+
+ // TIFF deflat compression.
+ bool TIFFCompression;
+
+ // JPEG2000 quality value.
+ int JPEG2000Compression;
+
+ // JPEG2000 lossless compression.
+ bool JPEG2000LossLess;
+
+ // Use Raw Import tool to load a RAW picture.
+ bool useRAWImport;
+
+ // ------------------------------------------------------
+ // RAW File decoding options :
+
+ DRawDecoding rawDecodingSettings;
+};
+
+} // namespace Digikam
+
+#endif // IOFILESETTINGSCONTAINER_H
diff --git a/src/utilities/imageeditor/canvas/undoaction.cpp b/src/utilities/imageeditor/canvas/undoaction.cpp
new file mode 100644
index 00000000..bb4ff756
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/undoaction.cpp
@@ -0,0 +1,185 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-06
+ * Description : undo actions manager for image editor.
+ *
+ * Copyright (C) 2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2005 by Joern Ahrens <joern.ahrens@kdemail.net>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimginterface.h"
+#include "undoaction.h"
+
+namespace Digikam
+{
+
+UndoAction::UndoAction(DImgInterface* iface)
+ : m_iface(iface)
+{
+ m_title = i18n("unknown");
+}
+
+UndoAction::~UndoAction()
+{
+}
+
+TQString UndoAction::getTitle() const
+{
+ return m_title;
+}
+
+UndoActionRotate::UndoActionRotate(DImgInterface* iface,
+ UndoActionRotate::Angle angle)
+ : UndoAction(iface), m_angle(angle)
+{
+ switch(m_angle)
+ {
+ case(R90):
+ m_title = i18n("Rotate 90 Degrees");
+ break;
+ case(R180):
+ m_title = i18n("Rotate 180 Degrees");
+ break;
+ case(R270):
+ m_title = i18n("Rotate 270 Degrees");
+ break;
+ }
+}
+
+UndoActionRotate::~UndoActionRotate()
+{
+}
+
+void UndoActionRotate::rollBack()
+{
+ switch(m_angle)
+ {
+ case(R90):
+ m_iface->rotate270(false);
+ return;
+ case(R180):
+ m_iface->rotate180(false);
+ return;
+ case(R270):
+ m_iface->rotate90(false);
+ return;
+ default:
+ DWarning() << "Unknown rotate angle specified" << endl;
+ }
+}
+
+void UndoActionRotate::execute()
+{
+ switch(m_angle)
+ {
+ case R90:
+ m_iface->rotate90(false);
+ return;
+ case R180:
+ m_iface->rotate180(false);
+ return;
+ case R270:
+ m_iface->rotate270(false);
+ return;
+ default:
+ DWarning() << "Unknown rotate angle specified" << endl;
+ }
+}
+
+UndoActionFlip::UndoActionFlip(DImgInterface* iface,
+ UndoActionFlip::Direction dir)
+ : UndoAction(iface), m_dir(dir)
+{
+ if(m_dir ==TQt::Horizontal)
+ m_title = i18n("Flip Horizontal");
+ else if(m_dir ==TQt::Vertical)
+ m_title = i18n("Flip Vertical");
+}
+
+UndoActionFlip::~UndoActionFlip()
+{
+}
+
+void UndoActionFlip::rollBack()
+{
+ switch(m_dir)
+ {
+ case TQt::Horizontal:
+ m_iface->flipHoriz(false);
+ return;
+ case TQt::Vertical:
+ m_iface->flipVert(false);
+ return;
+ default:
+ DWarning() << "Unknown flip direction specified" << endl;
+ }
+}
+
+void UndoActionFlip::execute()
+{
+ rollBack();
+}
+
+UndoActionBCG::UndoActionBCG(DImgInterface* iface,
+ double oldGamma, double oldBrightness,
+ double oldContrast, double newGamma,
+ double newBrightness, double newContrast)
+ : UndoAction(iface), m_oldGamma(oldGamma), m_oldBrightness(oldBrightness),
+ m_oldContrast(oldContrast), m_newGamma(newGamma), m_newBrightness(newBrightness),
+ m_newContrast(newContrast)
+{
+ m_title = i18n("Brightness,Contrast,Gamma");
+}
+
+UndoActionBCG::~UndoActionBCG()
+{
+}
+
+void UndoActionBCG::rollBack()
+{
+ m_iface->changeBCG(m_oldGamma, m_oldBrightness, m_oldContrast);
+}
+
+void UndoActionBCG::execute()
+{
+ m_iface->changeBCG(m_newGamma, m_newBrightness, m_newContrast);
+}
+
+UndoActionIrreversible::UndoActionIrreversible(DImgInterface* iface,
+ const TQString &title)
+ : UndoAction(iface)
+{
+ m_title = title;
+}
+
+UndoActionIrreversible::~UndoActionIrreversible()
+{
+}
+
+void UndoActionIrreversible::rollBack()
+{
+}
+
+void UndoActionIrreversible::execute()
+{
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/canvas/undoaction.h b/src/utilities/imageeditor/canvas/undoaction.h
new file mode 100644
index 00000000..5f29486e
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/undoaction.h
@@ -0,0 +1,144 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-06
+ * Description : undo actions manager for image editor.
+ *
+ * Copyright (C) 2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2005 by Joern Ahrens <joern.ahrens@kdemail.net>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef UNDOACTION_H
+#define UNDOACTION_H
+
+// KDE includes.
+
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DImgInterface;
+
+class DIGIKAM_EXPORT UndoAction
+{
+
+public:
+
+ UndoAction(DImgInterface* iface);
+ virtual ~UndoAction();
+
+ virtual void rollBack() = 0;
+ virtual void execute() = 0;
+
+ TQString getTitle() const;
+
+protected:
+
+ DImgInterface *m_iface;
+ TQString m_title;
+};
+
+class DIGIKAM_EXPORT UndoActionRotate : public UndoAction
+{
+
+public:
+
+ enum Angle
+ {
+ R90,
+ R180,
+ R270
+ };
+
+ UndoActionRotate(DImgInterface* iface, Angle angle);
+ ~UndoActionRotate();
+
+ void rollBack();
+ void execute();
+
+private:
+
+ int m_angle;
+};
+
+class DIGIKAM_EXPORT UndoActionFlip : public UndoAction
+{
+
+public:
+
+ enum Direction
+ {
+ Horizontal,
+ Vertical
+ };
+
+ UndoActionFlip(DImgInterface* iface, Direction dir);
+ ~UndoActionFlip();
+
+ void rollBack();
+ void execute();
+
+private:
+
+ int m_dir;
+};
+
+class DIGIKAM_EXPORT UndoActionBCG : public UndoAction
+{
+
+public:
+
+ UndoActionBCG(DImgInterface* iface,
+ double oldGamma, double oldBrightness,
+ double oldContrast, double newGamma,
+ double newBrightness, double newContrast);
+ ~UndoActionBCG();
+
+ void rollBack();
+ void execute();
+
+private:
+
+ double m_oldGamma;
+ double m_oldBrightness;
+ double m_oldContrast;
+ double m_newGamma;
+ double m_newBrightness;
+ double m_newContrast;
+};
+
+class DIGIKAM_EXPORT UndoActionIrreversible : public UndoAction
+{
+
+public:
+
+ UndoActionIrreversible(DImgInterface* iface,
+ const TQString &caller=i18n("Unknown"));
+ ~UndoActionIrreversible();
+
+ void rollBack();
+ void execute();
+};
+
+} // namespace Digikam
+
+#endif /* UNDOACTION_H */
diff --git a/src/utilities/imageeditor/canvas/undocache.cpp b/src/utilities/imageeditor/canvas/undocache.cpp
new file mode 100644
index 00000000..5f36ae75
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/undocache.cpp
@@ -0,0 +1,178 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-05
+ * Description : undo cache manager for image editor
+ *
+ * Copyright (C) 2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2005 by Joern Ahrens <joern.ahrens@kdemail.net>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <unistd.h>
+}
+
+// TQt includes.
+
+#include <tqcstring.h>
+#include <tqstring.h>
+#include <tqfile.h>
+#include <tqdatastream.h>
+#include <tqstringlist.h>
+
+// KDE includes.
+
+#include <kstandarddirs.h>
+#include <tdeaboutdata.h>
+#include <kinstance.h>
+#include <tdeglobal.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "undocache.h"
+
+namespace Digikam
+{
+
+class UndoCachePriv
+{
+public:
+
+ TQString cachePrefix;
+ TQStringList cacheFilenames;
+};
+
+UndoCache::UndoCache()
+{
+ d = new UndoCachePriv;
+
+ TQString cacheDir;
+ cacheDir = locateLocal("cache",
+ TDEGlobal::instance()->aboutData()->programName() + '/');
+
+ d->cachePrefix = TQString("%1undocache-%2")
+ .arg(cacheDir)
+ .arg(getpid());
+}
+
+UndoCache::~UndoCache()
+{
+ clear();
+ delete d;
+}
+
+/**
+ * delete all cache files
+ */
+void UndoCache::clear()
+{
+ for (TQStringList::iterator it = d->cacheFilenames.begin();
+ it != d->cacheFilenames.end(); ++it)
+ {
+ ::unlink(TQFile::encodeName(*it));
+ }
+
+ d->cacheFilenames.clear();
+}
+
+/**
+ * write the data into a cache file
+ */
+bool UndoCache::putData(int level, int w, int h, int bytesDepth, uchar* data)
+{
+ TQString cacheFile = TQString("%1-%2.bin")
+ .arg(d->cachePrefix)
+ .arg(level);
+
+ TQFile file(cacheFile);
+
+ if (file.exists() || !file.open(IO_WriteOnly))
+ return false;
+
+ TQDataStream ds(&file);
+ ds << w;
+ ds << h;
+ ds << bytesDepth;
+
+ TQByteArray ba(w*h*bytesDepth);
+ memcpy (ba.data(), data, w*h*bytesDepth);
+ ds << ba;
+
+ file.close();
+
+ d->cacheFilenames.append(cacheFile);
+
+ return true;
+}
+
+/**
+ * get the data from a cache file
+ */
+uchar* UndoCache::getData(int level, int& w, int& h, int& bytesDepth, bool del)
+{
+ TQString cacheFile = TQString("%1-%2.bin")
+ .arg(d->cachePrefix)
+ .arg(level);
+
+ TQFile file(cacheFile);
+ if (!file.open(IO_ReadOnly))
+ return 0;
+
+ TQDataStream ds(&file);
+ ds >> w;
+ ds >> h;
+ ds >> bytesDepth;
+
+ uchar *data = new uchar[w*h*bytesDepth];
+ if (!data)
+ return 0;
+
+ TQByteArray ba(w*h*bytesDepth);
+ ds >> ba;
+ memcpy (data, ba.data(), w*h*bytesDepth);
+
+ file.close();
+
+ if(del)
+ {
+ ::unlink(TQFile::encodeName(cacheFile));
+ d->cacheFilenames.remove(cacheFile);
+ }
+
+ return data;
+}
+
+/**
+ * delete a cache file
+ */
+void UndoCache::erase(int level)
+{
+ TQString cacheFile = TQString("%1-%2.bin")
+ .arg(d->cachePrefix)
+ .arg(level);
+
+ if(d->cacheFilenames.find(cacheFile) == d->cacheFilenames.end())
+ return;
+
+ ::unlink(TQFile::encodeName(cacheFile));
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/canvas/undocache.h b/src/utilities/imageeditor/canvas/undocache.h
new file mode 100644
index 00000000..732c7c3e
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/undocache.h
@@ -0,0 +1,62 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-05
+ * Description : undo cache manager for image editor.
+ *
+ * Copyright (C) 2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2005 by Joern Ahrens <joern.ahrens@kdemail.net>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef UNDOCACHE_H
+#define UNDOCACHE_H
+
+// TQt includes.
+
+#include <tqglobal.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class UndoCachePriv;
+
+class DIGIKAM_EXPORT UndoCache
+{
+
+public:
+
+ UndoCache();
+ ~UndoCache();
+
+ void clear();
+ bool putData(int level, int w, int h, int bytesDepth, uchar* data);
+ uchar *getData(int level, int& w, int& h, int& bytesDepth, bool del=true);
+
+ void erase(int level);
+
+private:
+
+ UndoCachePriv *d;
+};
+
+} // namespace Digikam
+
+#endif /* UNDOCACHE_H */
diff --git a/src/utilities/imageeditor/canvas/undomanager.cpp b/src/utilities/imageeditor/canvas/undomanager.cpp
new file mode 100644
index 00000000..87085d5d
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/undomanager.cpp
@@ -0,0 +1,253 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-06
+ * Description : an image editor actions undo/redo manager
+ *
+ * Copyright (C) 2005-2006 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2005-2006 Joern Ahrens <joern.ahrens@kdemail.net>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <typeinfo>
+#include <climits>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimginterface.h"
+#include "undoaction.h"
+#include "undocache.h"
+#include "undomanager.h"
+
+namespace Digikam
+{
+
+class UndoManagerPriv
+{
+
+public:
+
+ UndoManagerPriv()
+ {
+ dimgiface = 0;
+ undoCache = 0;
+ origin = 0;
+ }
+
+ TQValueList<UndoAction*> undoActions;
+ TQValueList<UndoAction*> redoActions;
+ int origin;
+
+ UndoCache *undoCache;
+
+ DImgInterface *dimgiface;
+};
+
+UndoManager::UndoManager(DImgInterface* iface)
+{
+ d = new UndoManagerPriv;
+ d->dimgiface = iface;
+ d->undoCache = new UndoCache;
+}
+
+UndoManager::~UndoManager()
+{
+ clear(true);
+ delete d->undoCache;
+ delete d;
+}
+
+void UndoManager::addAction(UndoAction* action)
+{
+ if (!action)
+ return;
+
+ // All redo actions are invalid now
+ clearRedoActions();
+
+ d->undoActions.push_back(action);
+
+ if (typeid(*action) == typeid(UndoActionIrreversible))
+ {
+ int w = d->dimgiface->origWidth();
+ int h = d->dimgiface->origHeight();
+ int bytesDepth = d->dimgiface->bytesDepth();
+ uchar* data = d->dimgiface->getImage();
+
+ d->undoCache->putData(d->undoActions.size(), w, h, bytesDepth, data);
+ }
+
+ // if origin is at one of the redo action that are now invalid,
+ // it is no longer reachable
+ if (d->origin < 0)
+ d->origin = INT_MAX;
+ else
+ d->origin++;
+}
+
+void UndoManager::undo()
+{
+ if (d->undoActions.isEmpty())
+ return;
+
+ UndoAction* action = d->undoActions.back();
+
+ if (typeid(*action) == typeid(UndoActionIrreversible))
+ {
+ // Save the current state for the redo operation
+
+ int w = d->dimgiface->origWidth();
+ int h = d->dimgiface->origHeight();
+ int bytesDepth = d->dimgiface->bytesDepth();
+ uchar* data = d->dimgiface->getImage();
+
+ d->undoCache->putData(d->undoActions.size() + 1, w, h, bytesDepth, data);
+
+ // And now, undo the action
+
+ int newW, newH, newBytesDepth;
+ uchar *newData = d->undoCache->getData(d->undoActions.size(), newW, newH, newBytesDepth, false);
+ if (newData)
+ {
+ d->dimgiface->putImage(newData, newW, newH, newBytesDepth == 8 ? true : false);
+ delete [] newData;
+ }
+ }
+ else
+ {
+ action->rollBack();
+ }
+
+ d->undoActions.pop_back();
+ d->redoActions.push_back(action);
+ d->origin--;
+}
+
+void UndoManager::redo()
+{
+ if(d->redoActions.isEmpty())
+ return;
+
+ UndoAction *action = d->redoActions.back();
+
+ if(typeid(*action) == typeid(UndoActionIrreversible))
+ {
+ int w, h, bytesDepth;
+ uchar *data = d->undoCache->getData(d->undoActions.size() + 2, w, h, bytesDepth, false);
+ if (data)
+ {
+ d->dimgiface->putImage(data, w, h, bytesDepth == 8 ? true : false);
+ delete[] data;
+ }
+ }
+ else
+ {
+ action->execute();
+ }
+
+ d->redoActions.pop_back();
+ d->undoActions.push_back(action);
+ d->origin++;
+}
+
+void UndoManager::clear(bool clearCache)
+{
+ clearUndoActions();
+ clearRedoActions();
+ setOrigin();
+
+ if(clearCache)
+ d->undoCache->clear();
+}
+
+void UndoManager::clearUndoActions()
+{
+ UndoAction *action;
+ TQValueList<UndoAction*>::iterator it;
+
+ for(it = d->undoActions.begin(); it != d->undoActions.end(); ++it)
+ {
+ action = *it;
+ delete action;
+ }
+ d->undoActions.clear();
+}
+
+void UndoManager::clearRedoActions()
+{
+ if(!anyMoreRedo())
+ return;
+
+ UndoAction *action;
+ TQValueList<UndoAction*>::iterator it;
+
+ // get the level of the first redo action
+ int level = d->undoActions.size() + 1;
+ for(it = d->redoActions.begin(); it != d->redoActions.end(); ++it)
+ {
+ action = *it;
+ d->undoCache->erase(level);
+ delete action;
+ level++;
+ }
+ d->undoCache->erase(level);
+ d->redoActions.clear();
+}
+
+bool UndoManager::anyMoreUndo()
+{
+ return !d->undoActions.isEmpty();
+}
+
+bool UndoManager::anyMoreRedo()
+{
+ return !d->redoActions.isEmpty();
+}
+
+void UndoManager::getUndoHistory(TQStringList &titles)
+{
+ TQValueList<UndoAction*>::iterator it;
+
+ for(it = d->undoActions.begin(); it != d->undoActions.end(); ++it)
+ {
+ titles.push_front((*it)->getTitle());
+ }
+}
+
+void UndoManager::getRedoHistory(TQStringList &titles)
+{
+ TQValueList<UndoAction*>::iterator it;
+
+ for(it = d->redoActions.begin(); it != d->redoActions.end(); ++it)
+ {
+ titles.push_front((*it)->getTitle());
+ }
+}
+
+bool UndoManager::isAtOrigin()
+{
+ return d->origin == 0;
+}
+
+void UndoManager::setOrigin()
+{
+ d->origin = 0;
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/canvas/undomanager.h b/src/utilities/imageeditor/canvas/undomanager.h
new file mode 100644
index 00000000..a36ba12f
--- /dev/null
+++ b/src/utilities/imageeditor/canvas/undomanager.h
@@ -0,0 +1,76 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-06
+ * Description : an image editor actions undo/redo manager
+ *
+ * Copyright (C) 2005-2006 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2005-2006 by Joern Ahrens <joern.ahrens@kdemail.net>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef UNDOMANAGER_H
+#define UNDOMANAGER_H
+
+// TQt includes.
+
+#include <tqstringlist.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DImgInterface;
+class UndoManagerPriv;
+class UndoAction;
+
+class DIGIKAM_EXPORT UndoManager
+{
+
+public:
+
+ UndoManager(DImgInterface* iface);
+ ~UndoManager();
+
+ void undo();
+ void redo();
+
+ void clear(bool clearCache=true);
+ bool anyMoreUndo();
+ bool anyMoreRedo();
+ void getUndoHistory(TQStringList &titles);
+ void getRedoHistory(TQStringList &titles);
+ bool isAtOrigin();
+ void setOrigin();
+
+ void addAction(UndoAction* action);
+
+private:
+
+ void clearUndoActions();
+ void clearRedoActions();
+
+private:
+
+ UndoManagerPriv *d;
+};
+
+} // namespace Digikam
+
+#endif /* UNDOMANAGER_H */
diff --git a/src/utilities/imageeditor/editor/Makefile.am b/src/utilities/imageeditor/editor/Makefile.am
new file mode 100644
index 00000000..71031991
--- /dev/null
+++ b/src/utilities/imageeditor/editor/Makefile.am
@@ -0,0 +1,51 @@
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libdimgeditor.la libshowfoto.la
+
+libdimgeditor_la_SOURCES = editorwindow.cpp imageiface.cpp imagewindow.cpp editorstackview.cpp \
+ editortooliface.cpp editortool.cpp editortoolsettings.cpp
+
+libdimgeditor_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TDEPRINT)
+
+libdimgeditor_la_LIBADD = $(top_builddir)/src/utilities/imageeditor/tools/libdimgeditortools.la \
+ $(top_builddir)/src/utilities/imageeditor/rawimport/librawimport.la
+
+libshowfoto_la_SOURCES = editorwindow.cpp imageiface.cpp editorstackview.cpp \
+ editortooliface.cpp editortool.cpp editortoolsettings.cpp
+
+libshowfoto_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TDEPRINT)
+
+libshowfoto_la_LIBADD = $(top_builddir)/src/libs/dimg/libdimg.la \
+ $(top_builddir)/src/libs/dialogs/libdialogshowfoto.la \
+ $(top_builddir)/src/libs/widgets/libwidgets.la \
+ $(top_builddir)/src/libs/greycstoration/libgreycstoration.la \
+ $(top_builddir)/src/utilities/imageeditor/canvas/libdimgcanvas.la \
+ $(top_builddir)/src/utilities/imageeditor/tools/libdimgeditortools.la \
+ $(top_builddir)/src/utilities/imageeditor/rawimport/librawimport.la
+
+INCLUDES = -I$(top_srcdir)/src/digikam \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -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/tools \
+ -I$(top_builddir)/src/libs/dialogs \
+ $(LIBKEXIV2_CFLAGS) $(LIBKDCRAW_CFLAGS) $(all_includes)
+
+digikaminclude_HEADERS = imageiface.h
+
+digikamincludedir = $(includedir)/digikam
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimagewindowui.rc
+
+kde_servicetypes_DATA = digikamimageplugin.desktop
+
diff --git a/src/utilities/imageeditor/editor/digikamimageplugin.desktop b/src/utilities/imageeditor/editor/digikamimageplugin.desktop
new file mode 100644
index 00000000..31bef621
--- /dev/null
+++ b/src/utilities/imageeditor/editor/digikamimageplugin.desktop
@@ -0,0 +1,39 @@
+[Desktop Entry]
+Encoding=UTF-8
+Type=ServiceType
+X-TDE-ServiceType=Digikam/ImagePlugin
+X-TDE-DerivedName=Digikam ImagePlugin
+Comment=A digiKam Image Plugin
+Comment[bg]=Приставка за снимки в digiKam
+Comment[br]=Ul lugent skeudenn digiKam
+Comment[ca]=Un connector d'imatges del digiKam
+Comment[cs]=Modul pro digiKam
+Comment[da]=Et Digikam billed-plugin
+Comment[de]=Ein Bild-Modul von digiKam
+Comment[el]=Ένα πρόσθετο εικόνας digiKam
+Comment[es]=Plugin de digiKam para imágenes
+Comment[et]=DigiKami pildiplugin
+Comment[fa]=یک وصلۀ تصویر digiKam
+Comment[fi]=digiKam-liitännäinen
+Comment[fr]=Un module externe pour digiKam
+Comment[gl]=Un plugin de Imaxe de digiKam
+Comment[hr]=digiKam dodatak za slike
+Comment[is]=digiKam ljósmynda-íforrit
+Comment[it]=Un plugin per le immagini di digiKam
+Comment[ja]=digiKam 画像プラグイン
+Comment[ms]=Plugin Imej digiKam
+Comment[nds]=En digiKam-Bildmoduul
+Comment[nl]=Een plugin voor Digikam
+Comment[pa]=ਇੱਕ ਡਿਜ਼ੀਕੈਮ ਚਿੱਤਰ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka obrazu digiKama
+Comment[pt]=Um 'Plugin' de Imagem do digiKam
+Comment[pt_BR]=Plugin de imagem digiKam
+Comment[ru]=Модуль изображений digiKam
+Comment[sk]=DigiKam obrázkový plugin
+Comment[sr]=digiKam-ов сликовни прикључак
+Comment[sr@Latn]=digiKam-ov slikovni priključak
+Comment[sv]=Ett bildinsticksprogram för Digikam
+Comment[tr]=Bir digiKam Resim Eklentisi
+Comment[uk]=Втулок зображень digiKam
+Comment[vi]=Một phần bổ sung ảnh digiKam
+Comment[xx]=xxA digiKam Image Pluginxx
diff --git a/src/utilities/imageeditor/editor/digikamimagewindowui.rc b/src/utilities/imageeditor/editor/digikamimagewindowui.rc
new file mode 100644
index 00000000..2c0314ad
--- /dev/null
+++ b/src/utilities/imageeditor/editor/digikamimagewindowui.rc
@@ -0,0 +1,125 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<gui version="24" name="digikamimagewindow" >
+
+<MenuBar>
+
+ <Menu name="File" ><text>&amp;File</text>
+ <Action name="editorwindow_backward" />
+ <Action name="editorwindow_forward" />
+ <Separator/>
+ <Action name="editorwindow_first" />
+ <Action name="editorwindow_last" />
+ <Separator/>
+ <Action name="editorwindow_print" />
+ <Separator/>
+ <Action name="editorwindow_save" />
+ <Action name="editorwindow_saveas" />
+ <Action name="editorwindow_revert" />
+ <Separator/>
+ <Action name="editorwindow_delete" />
+ <Separator/>
+ <Action name="editorwindow_close" />
+ </Menu>
+
+ <Menu name="Edit" ><text>&amp;Edit</text>
+ <Action name="editorwindow_copy" />
+ <Separator/>
+ <Action name="editorwindow_undo" />
+ <Action name="editorwindow_redo" />
+ <Separator/>
+ <Action name="editorwindow_selectAll" />
+ <Action name="editorwindow_selectNone" />
+ </Menu>
+
+ <Menu name="View" ><text>&amp;View</text>
+ <Action name="editorwindow_fullscreen" />
+ <Action name="editorwindow_slideshow" />
+ <Separator/>
+ <Action name="editorwindow_zoomplus" />
+ <Action name="editorwindow_zoomminus" />
+ <Action name="editorwindow_zoomto100percents" />
+ <Action name="editorwindow_zoomfit2window" />
+ <Action name="editorwindow_zoomfit2select" />
+ <Separator/>
+ <Action name="editorwindow_underexposure" />
+ <Action name="editorwindow_overexposure" />
+ <Action name="editorwindow_cmview" />
+ </Menu>
+
+ <Menu name="Color" ><text>&amp;Color</text>
+ </Menu>
+
+ <Menu name="Enhance" ><text>Enh&amp;ance</text>
+ </Menu>
+
+ <Menu name="Transform" ><text>Tra&amp;nsform</text>
+ <Action name="editorwindow_rotate_left" />
+ <Action name="editorwindow_rotate_right" />
+ <Separator/>
+ <Action name="editorwindow_flip_horiz" />
+ <Action name="editorwindow_flip_vert" />
+ <Separator/>
+ <Action name="editorwindow_crop" />
+ <Action name="editorwindow_resize" />
+ </Menu>
+
+ <Menu name="Decorate" ><text>&amp;Decorate</text>
+ </Menu>
+
+ <Menu name="Filters" ><text>F&amp;ilters</text>
+ </Menu>
+
+ <Menu name="help" ><text>&amp;Help</text>
+ <Action name="editorwindow_rawcameralist"/>
+ <Action name="editorwindow_donatemoney" />
+ <Action name="editorwindow_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="editorwindow_first" />
+ <Action name="editorwindow_backward" />
+ <Action name="editorwindow_forward" />
+ <Action name="editorwindow_last" />
+ <Separator/>
+ <Action name="editorwindow_save" />
+ <Action name="editorwindow_saveas" />
+ <Action name="editorwindow_undo" />
+ <Action name="editorwindow_redo" />
+ <Action name="editorwindow_revert" />
+ <Separator/>
+ <Action name="editorwindow_zoomplus" />
+ <Action name="editorwindow_zoomto" />
+ <Action name="editorwindow_zoomminus" />
+ <Action name="editorwindow_zoomfit2window" />
+ <Action name="editorwindow_zoomfit2select" />
+ <Separator/>
+ <Action name="editorwindow_rotate_left" />
+ <Action name="editorwindow_rotate_right" />
+ <Action name="editorwindow_crop" />
+ <Separator/>
+ <Action name="editorwindow_fullscreen" />
+ <Action name="editorwindow_slideshow" />
+ <Merge />
+ <WeakSeparator/>
+ <Action name="logo_action" />
+</ToolBar>
+
+<ActionProperties/>
+
+</gui>
diff --git a/src/utilities/imageeditor/editor/editorstackview.cpp b/src/utilities/imageeditor/editor/editorstackview.cpp
new file mode 100644
index 00000000..61550300
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editorstackview.cpp
@@ -0,0 +1,233 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-20
+ * Description : A widget stack to embed editor view.
+ *
+ * Copyright (C) 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.
+ *
+ * ============================================================ */
+
+// Local includes.
+
+#include "previewwidget.h"
+#include "imageregionwidget.h"
+#include "imagepanelwidget.h"
+#include "canvas.h"
+#include "editorstackview.h"
+#include "editorstackview.moc"
+
+namespace Digikam
+{
+
+class EditorStackViewPriv
+{
+
+public:
+
+ EditorStackViewPriv()
+ {
+ canvas = 0;
+ toolView = 0;
+ }
+
+ TQWidget *toolView;
+ Canvas *canvas;
+};
+
+EditorStackView::EditorStackView(TQWidget *parent)
+ : TQWidgetStack(parent, 0, TQt::WDestructiveClose)
+{
+ d = new EditorStackViewPriv;
+}
+
+EditorStackView::~EditorStackView()
+{
+ delete d;
+}
+
+void EditorStackView::setCanvas(Canvas* canvas)
+{
+ if (d->canvas) return;
+
+ d->canvas = canvas;
+ addWidget(d->canvas, CanvasMode);
+
+ connect(d->canvas, TQ_SIGNAL(signalZoomChanged(double)),
+ this, TQ_SLOT(slotZoomChanged(double)));
+}
+
+Canvas* EditorStackView::canvas() const
+{
+ return d->canvas;
+}
+
+void EditorStackView::setToolView(TQWidget* view)
+{
+ if (d->toolView)
+ removeWidget(d->toolView);
+
+ d->toolView = view;
+
+ if (d->toolView)
+ addWidget(d->toolView, ToolViewMode);
+
+ PreviewWidget *preview = previewWidget();
+ if (preview)
+ {
+ connect(preview, TQ_SIGNAL(signalZoomFactorChanged(double)),
+ this, TQ_SLOT(slotZoomChanged(double)));
+ }
+}
+
+TQWidget* EditorStackView::toolView() const
+{
+ return d->toolView;
+}
+
+int EditorStackView::viewMode()
+{
+ return id(visibleWidget());
+}
+
+void EditorStackView::setViewMode(int mode)
+{
+ if (mode != CanvasMode && mode != ToolViewMode)
+ return;
+
+ raiseWidget(mode);
+}
+
+void EditorStackView::increaseZoom()
+{
+ if (viewMode() == CanvasMode)
+ {
+ d->canvas->slotIncreaseZoom();
+ }
+ else
+ {
+ PreviewWidget *preview = previewWidget();
+ if (preview)
+ preview->slotIncreaseZoom();
+ }
+}
+
+void EditorStackView::decreaseZoom()
+{
+ if (viewMode() == CanvasMode)
+ {
+ d->canvas->slotDecreaseZoom();
+ }
+ else
+ {
+ PreviewWidget *preview = previewWidget();
+ if (preview)
+ preview->slotDecreaseZoom();
+ }
+}
+
+void EditorStackView::toggleFitToWindow()
+{
+ if (viewMode() == CanvasMode)
+ {
+ d->canvas->toggleFitToWindow();
+ }
+ else
+ {
+ PreviewWidget *preview = previewWidget();
+ if (preview)
+ preview->toggleFitToWindow();
+ }
+}
+
+void EditorStackView::fitToSelect()
+{
+ if (viewMode() == CanvasMode)
+ {
+ d->canvas->fitToSelect();
+ }
+}
+
+void EditorStackView::zoomTo100Percents()
+{
+ if (viewMode() == CanvasMode)
+ {
+ if (d->canvas->zoomFactor() == 1.0)
+ d->canvas->toggleFitToWindow();
+ else
+ d->canvas->setZoomFactor(1.0);
+ }
+ else
+ {
+ PreviewWidget *preview = previewWidget();
+ if (preview)
+ {
+ if (preview->zoomFactor() == 1.0)
+ preview->toggleFitToWindow();
+ else
+ preview->setZoomFactor(1.0);
+ }
+ }
+}
+
+void EditorStackView::setZoomFactor(double zoom)
+{
+ if (viewMode() == CanvasMode)
+ {
+ d->canvas->setZoomFactor(zoom);
+ }
+ else
+ {
+ PreviewWidget *preview = previewWidget();
+ if (preview)
+ preview->setZoomFactor(zoom);
+ }
+}
+
+void EditorStackView::slotZoomChanged(double zoom)
+{
+ bool max, min;
+
+ if (viewMode() == CanvasMode)
+ {
+ max = d->canvas->maxZoom();
+ min = d->canvas->minZoom();
+ emit signalZoomChanged(max, min, zoom);
+ }
+ else
+ {
+ PreviewWidget *preview = previewWidget();
+ if (preview)
+ {
+ max = preview->maxZoom();
+ min = preview->minZoom();
+ emit signalZoomChanged(max, min, zoom);
+ }
+ }
+}
+
+PreviewWidget* EditorStackView::previewWidget() const
+{
+ PreviewWidget *preview = dynamic_cast<PreviewWidget*>(d->toolView);
+ if (preview) return preview;
+
+ ImagePanelWidget *panel = dynamic_cast<ImagePanelWidget*>(d->toolView);
+ if (panel) return (dynamic_cast<PreviewWidget*>(panel->previewWidget()));
+
+ return 0;
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/editor/editorstackview.h b/src/utilities/imageeditor/editor/editorstackview.h
new file mode 100644
index 00000000..e428fcd7
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editorstackview.h
@@ -0,0 +1,97 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-20
+ * Description : A widget stack to embed editor view.
+ *
+ * Copyright (C) 2008-2009 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 EDITORSTACKVIEW_H
+#define EDITORSTACKVIEW_H
+
+// KDE includes.
+
+#include <tqwidgetstack.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class PreviewWidget;
+class Canvas;
+class EditorStackViewPriv;
+
+class DIGIKAM_EXPORT EditorStackView : public TQWidgetStack
+{
+TQ_OBJECT
+
+
+public:
+
+ enum StackViewMode
+ {
+ CanvasMode=0,
+ ToolViewMode
+ };
+
+public:
+
+ EditorStackView(TQWidget *parent=0);
+ ~EditorStackView();
+
+ void setCanvas(Canvas* canvas);
+ Canvas *canvas() const;
+
+ void setToolView(TQWidget* view);
+ TQWidget *toolView() const;
+
+ int viewMode();
+ void setViewMode(int mode);
+
+ void increaseZoom();
+ void decreaseZoom();
+ void toggleFitToWindow();
+ void fitToSelect();
+ void zoomTo100Percents();
+ void setZoomFactor(double zoom);
+
+ /** Two widgets are embedded in Editor Tool to perform preview with panning and zooming:
+ a PreviewWidget derivated class or ImagePanelWidget.
+ This method try to find the right PreviewWidget instance accordingly else return 0.
+ */
+ PreviewWidget* previewWidget() const;
+
+signals:
+
+ void signalZoomChanged(bool isMax, bool isMin, double zoom);
+
+private slots:
+
+ void slotZoomChanged(double);
+
+private:
+
+ EditorStackViewPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* EDITORSTACKVIEW_H */
diff --git a/src/utilities/imageeditor/editor/editortool.cpp b/src/utilities/imageeditor/editor/editortool.cpp
new file mode 100644
index 00000000..b840e673
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editortool.cpp
@@ -0,0 +1,436 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-20
+ * Description : editor tool template class.
+ *
+ * Copyright (C) 2008-2009 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 <tqwidget.h>
+#include <tqtimer.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imagewidget.h"
+#include "imageguidewidget.h"
+#include "imagepanelwidget.h"
+#include "dimgthreadedfilter.h"
+#include "editortoolsettings.h"
+#include "editortooliface.h"
+#include "editortool.h"
+#include "editortool.moc"
+
+namespace Digikam
+{
+
+class EditorToolPriv
+{
+
+public:
+
+ EditorToolPriv()
+ {
+ timer = 0;
+ view = 0;
+ settings = 0;
+ }
+
+ TQString helpAnchor;
+ TQString name;
+
+ TQWidget *view;
+
+ TQPixmap icon;
+
+ TQTimer *timer;
+
+ EditorToolSettings *settings;
+};
+
+EditorTool::EditorTool(TQObject *parent)
+ : TQObject(parent)
+{
+ d = new EditorToolPriv;
+ d->timer = new TQTimer(this);
+
+ connect(d->timer, TQ_SIGNAL(timeout()),
+ this, TQ_SLOT(slotEffect()));
+}
+
+EditorTool::~EditorTool()
+{
+ delete d;
+}
+
+void EditorTool::init()
+{
+ TQTimer::singleShot(0, this, TQ_SLOT(slotInit()));
+}
+
+TQPixmap EditorTool::toolIcon() const
+{
+ return d->icon;
+}
+
+void EditorTool::setToolIcon(const TQPixmap& icon)
+{
+ d->icon = icon;
+}
+
+TQString EditorTool::toolName() const
+{
+ return d->name;
+}
+
+void EditorTool::setToolName(const TQString& name)
+{
+ d->name = name;
+}
+
+TQWidget* EditorTool::toolView() const
+{
+ return d->view;
+}
+
+void EditorTool::setToolView(TQWidget *view)
+{
+ d->view = view;
+ // Will be unblocked in slotInit()
+ // This will prevent resize event signals emit during tool init.
+ d->view->blockSignals(true);
+}
+
+EditorToolSettings* EditorTool::toolSettings() const
+{
+ return d->settings;
+}
+
+void EditorTool::setToolSettings(EditorToolSettings *settings)
+{
+ d->settings = settings;
+
+ connect(d->settings, TQ_SIGNAL(signalOkClicked()),
+ this, TQ_SLOT(slotOk()));
+
+ connect(d->settings, TQ_SIGNAL(signalCancelClicked()),
+ this, TQ_SLOT(slotCancel()));
+
+ connect(d->settings, TQ_SIGNAL(signalDefaultClicked()),
+ this, TQ_SLOT(slotResetSettings()));
+
+ connect(d->settings, TQ_SIGNAL(signalSaveAsClicked()),
+ this, TQ_SLOT(slotSaveAsSettings()));
+
+ connect(d->settings, TQ_SIGNAL(signalLoadClicked()),
+ this, TQ_SLOT(slotLoadSettings()));
+
+ connect(d->settings, TQ_SIGNAL(signalTryClicked()),
+ this, TQ_SLOT(slotEffect()));
+
+ // Will be unblocked in slotInit()
+ // This will prevent signals emit during tool init.
+ d->settings->blockSignals(true);
+}
+
+void EditorTool::slotInit()
+{
+ readSettings();
+ // Unlock signals from preview and settings widgets when init is done.
+ d->view->blockSignals(false);
+ d->settings->blockSignals(false);
+}
+
+void EditorTool::setToolHelp(const TQString& anchor)
+{
+ d->helpAnchor = anchor;
+ // TODO: use this anchor with editor Help menu
+}
+
+TQString EditorTool::toolHelp() const
+{
+ if (d->helpAnchor.isEmpty())
+ return (name() + TQString(".anchor"));
+
+ return d->helpAnchor;
+}
+
+void EditorTool::setBusy(bool state)
+{
+ d->settings->setBusy(state);
+}
+
+void EditorTool::readSettings()
+{
+ d->settings->readSettings();
+}
+
+void EditorTool::writeSettings()
+{
+ d->settings->writeSettings();
+}
+
+void EditorTool::slotResetSettings()
+{
+ d->settings->resetSettings();
+}
+
+void EditorTool::slotTimer()
+{
+ d->timer->start(500, true);
+}
+
+void EditorTool::slotOk()
+{
+ writeSettings();
+ finalRendering();
+ emit okClicked();
+}
+
+void EditorTool::slotCancel()
+{
+ writeSettings();
+ emit cancelClicked();
+}
+
+// ----------------------------------------------------------------
+
+class EditorToolThreadedPriv
+{
+
+public:
+
+ EditorToolThreadedPriv()
+ {
+ threadedFilter = 0;
+ currentRenderingMode = EditorToolThreaded::NoneRendering;
+ }
+
+ EditorToolThreaded::RenderingMode currentRenderingMode;
+
+ TQString progressMess;
+
+ DImgThreadedFilter *threadedFilter;
+};
+
+EditorToolThreaded::EditorToolThreaded(TQObject *parent)
+ : EditorTool(parent)
+{
+ d = new EditorToolThreadedPriv;
+}
+
+EditorToolThreaded::~EditorToolThreaded()
+{
+ delete d->threadedFilter;
+ delete d;
+}
+
+EditorToolThreaded::RenderingMode EditorToolThreaded::renderingMode() const
+{
+ return d->currentRenderingMode;
+}
+
+void EditorToolThreaded::setProgressMessage(const TQString& mess)
+{
+ d->progressMess = mess;
+}
+
+DImgThreadedFilter* EditorToolThreaded::filter() const
+{
+ return d->threadedFilter;
+}
+
+void EditorToolThreaded::setFilter(DImgThreadedFilter *filter)
+{
+ d->threadedFilter = filter;
+}
+
+void EditorToolThreaded::slotResized()
+{
+ if (d->currentRenderingMode == EditorToolThreaded::FinalRendering)
+ {
+ toolView()->update();
+ return;
+ }
+ else if (d->currentRenderingMode == EditorToolThreaded::PreviewRendering)
+ {
+ if (filter())
+ filter()->stopComputation();
+ }
+
+ TQTimer::singleShot(0, this, TQ_SLOT(slotEffect()));
+}
+
+void EditorToolThreaded::slotAbort()
+{
+ d->currentRenderingMode = EditorToolThreaded::NoneRendering;
+
+ if (filter())
+ filter()->stopComputation();
+
+ EditorToolIface::editorToolIface()->setToolStopProgress();
+
+ toolSettings()->enableButton(EditorToolSettings::Ok, true);
+ toolSettings()->enableButton(EditorToolSettings::Load, true);
+ toolSettings()->enableButton(EditorToolSettings::SaveAs, true);
+ toolSettings()->enableButton(EditorToolSettings::Try, true);
+ toolSettings()->enableButton(EditorToolSettings::Default, true);
+
+ renderingFinished();
+}
+
+void EditorToolThreaded::customEvent(TQCustomEvent *e)
+{
+ if (!e) return;
+
+ DImgThreadedFilter::EventData *ed = (DImgThreadedFilter::EventData*)e->data();
+
+ if (!ed) return;
+
+ if (ed->starting) // Computation in progress !
+ {
+ EditorToolIface::editorToolIface()->setToolProgress(ed->progress);
+ }
+ else
+ {
+ if (ed->success) // Computation Completed !
+ {
+ switch (d->currentRenderingMode)
+ {
+ case EditorToolThreaded::PreviewRendering:
+ {
+ DDebug() << "Preview " << toolName() << " completed..." << endl;
+ putPreviewData();
+ slotAbort();
+ break;
+ }
+
+ case EditorToolThreaded::FinalRendering:
+ {
+ DDebug() << "Final" << toolName() << " completed..." << endl;
+ putFinalData();
+ EditorToolIface::editorToolIface()->setToolStopProgress();
+ kapp->restoreOverrideCursor();
+ emit okClicked();
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+ else // Computation Failed !
+ {
+ switch (d->currentRenderingMode)
+ {
+ case EditorToolThreaded::PreviewRendering:
+ {
+ DDebug() << "Preview " << toolName() << " failed..." << endl;
+ slotAbort();
+ break;
+ }
+
+ case EditorToolThreaded::FinalRendering:
+ default:
+ break;
+ }
+ }
+ }
+
+ delete ed;
+}
+
+void EditorToolThreaded::setToolView(TQWidget *view)
+{
+ EditorTool::setToolView(view);
+
+ if (dynamic_cast<ImageWidget*>(view) || dynamic_cast<ImageGuideWidget*>(view) ||
+ dynamic_cast<ImagePanelWidget*>(view))
+ {
+ connect(view, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotResized()));
+ }
+}
+
+void EditorToolThreaded::slotOk()
+{
+ writeSettings();
+
+ d->currentRenderingMode = EditorToolThreaded::FinalRendering;
+ DDebug() << "Final " << toolName() << " started..." << endl;
+ writeSettings();
+
+ toolSettings()->enableButton(EditorToolSettings::Ok, false);
+ toolSettings()->enableButton(EditorToolSettings::SaveAs, false);
+ toolSettings()->enableButton(EditorToolSettings::Load, false);
+ toolSettings()->enableButton(EditorToolSettings::Default, false);
+ toolSettings()->enableButton(EditorToolSettings::Try, false);
+
+ EditorToolIface::editorToolIface()->setToolStartProgress(d->progressMess.isEmpty() ? toolName() : d->progressMess);
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ if (d->threadedFilter)
+ {
+ delete d->threadedFilter;
+ d->threadedFilter = 0;
+ }
+
+ prepareFinal();
+}
+
+void EditorToolThreaded::slotEffect()
+{
+ // Computation already in process.
+ if (d->currentRenderingMode != EditorToolThreaded::NoneRendering)
+ return;
+
+ d->currentRenderingMode = EditorToolThreaded::PreviewRendering;
+ DDebug() << "Preview " << toolName() << " started..." << endl;
+
+ toolSettings()->enableButton(EditorToolSettings::Ok, false);
+ toolSettings()->enableButton(EditorToolSettings::SaveAs, false);
+ toolSettings()->enableButton(EditorToolSettings::Load, false);
+ toolSettings()->enableButton(EditorToolSettings::Default, false);
+ toolSettings()->enableButton(EditorToolSettings::Try, false);
+
+ EditorToolIface::editorToolIface()->setToolStartProgress(d->progressMess.isEmpty() ? toolName() : d->progressMess);
+
+ if (d->threadedFilter)
+ {
+ delete d->threadedFilter;
+ d->threadedFilter = 0;
+ }
+
+ prepareEffect();
+}
+
+void EditorToolThreaded::slotCancel()
+{
+ writeSettings();
+ slotAbort();
+ kapp->restoreOverrideCursor();
+ emit cancelClicked();
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/editor/editortool.h b/src/utilities/imageeditor/editor/editortool.h
new file mode 100644
index 00000000..120ff9f0
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editortool.h
@@ -0,0 +1,164 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-20
+ * Description : editor tool template class.
+ *
+ * Copyright (C) 2008-2009 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 EDITORTOOL_H
+#define EDITORTOOL_H
+
+// TQt includes.
+
+#include <tqobject.h>
+#include <tqstring.h>
+#include <tqpixmap.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DImgThreadedFilter;
+class EditorToolSettings;
+class EditorToolPriv;
+
+class DIGIKAM_EXPORT EditorTool : public TQObject
+{
+ TQ_OBJECT
+
+
+public:
+
+ EditorTool(TQObject *parent);
+ virtual ~EditorTool();
+
+ void init();
+
+ TQString toolHelp() const;
+ TQString toolName() const;
+ TQPixmap toolIcon() const;
+ TQWidget* toolView() const;
+ EditorToolSettings* toolSettings() const;
+
+signals:
+
+ void okClicked();
+ void cancelClicked();
+
+protected:
+
+ void setToolHelp(const TQString& anchor);
+ void setToolName(const TQString& name);
+ void setToolIcon(const TQPixmap& icon);
+
+ virtual void setToolView(TQWidget *view);
+ virtual void setToolSettings(EditorToolSettings *settings);
+ virtual void setBusy(bool);
+ virtual void readSettings();
+ virtual void writeSettings();
+ virtual void finalRendering(){};
+
+protected slots:
+
+ void slotTimer();
+
+ virtual void slotOk();
+ virtual void slotCancel();
+ virtual void slotInit();
+ virtual void slotLoadSettings(){};
+ virtual void slotSaveAsSettings(){};
+ virtual void slotResetSettings();
+ virtual void slotEffect(){};
+
+private:
+
+ EditorToolPriv *d;
+};
+
+// -----------------------------------------------------------------
+
+class EditorToolThreadedPriv;
+
+class DIGIKAM_EXPORT EditorToolThreaded : public EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ enum RenderingMode
+ {
+ NoneRendering=0,
+ PreviewRendering,
+ FinalRendering
+ };
+
+public:
+
+ EditorToolThreaded(TQObject *parent);
+ virtual ~EditorToolThreaded();
+
+ /** Set the small text to show in editor status progress bar during
+ tool computation. If it's not set, tool name is used instead.
+ */
+ void setProgressMessage(const TQString& mess);
+
+ /** return the current tool rendering mode.
+ */
+ RenderingMode renderingMode() const;
+
+public slots:
+
+ virtual void slotAbort();
+
+protected:
+
+ DImgThreadedFilter* filter() const;
+ void setFilter(DImgThreadedFilter *filter);
+
+ void customEvent(TQCustomEvent *event);
+
+ virtual void setToolView(TQWidget *view);
+ virtual void prepareEffect(){};
+ virtual void prepareFinal(){};
+ virtual void putPreviewData(){};
+ virtual void putFinalData(){};
+ virtual void renderingFinished(){};
+
+protected slots:
+
+ virtual void slotOk();
+ virtual void slotCancel();
+ virtual void slotEffect();
+
+private slots:
+
+ void slotResized();
+
+private:
+
+ EditorToolThreadedPriv *d;
+};
+
+} //namespace Digikam
+
+#endif /* IMAGEPLUGIN_H */
diff --git a/src/utilities/imageeditor/editor/editortooliface.cpp b/src/utilities/imageeditor/editor/editortooliface.cpp
new file mode 100644
index 00000000..f666bbf2
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editortooliface.cpp
@@ -0,0 +1,147 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-20
+ * Description : Image editor interface used by editor tools.
+ *
+ * Copyright (C) 2008-2009 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 <tqwidget.h>
+
+// Local includes.
+
+#include "sidebar.h"
+#include "canvas.h"
+#include "statusprogressbar.h"
+#include "editortool.h"
+#include "editortoolsettings.h"
+#include "editorstackview.h"
+#include "editorwindow.h"
+#include "editortooliface.h"
+#include "editortooliface.moc"
+
+namespace Digikam
+{
+
+class EditorToolIfacePriv
+{
+
+public:
+
+ EditorToolIfacePriv()
+ {
+ prevTab = 0;
+ editor = 0;
+ tool = 0;
+ }
+
+ TQWidget *prevTab;
+
+ EditorTool *tool;
+
+ EditorWindow *editor;
+};
+
+EditorToolIface* EditorToolIface::m_iface = 0;
+
+EditorToolIface* EditorToolIface::editorToolIface()
+{
+ return m_iface;
+}
+
+EditorToolIface::EditorToolIface(EditorWindow *editor)
+ : TQObject()
+{
+ d = new EditorToolIfacePriv;
+ d->editor = editor;
+ m_iface = this;
+}
+
+EditorToolIface::~EditorToolIface()
+{
+ delete d;
+ if (m_iface == this)
+ m_iface = 0;
+}
+
+EditorTool* EditorToolIface::currentTool() const
+{
+ return d->tool;
+}
+
+void EditorToolIface::loadTool(EditorTool* tool)
+{
+ if (d->tool) unLoadTool();
+
+ d->tool = tool;
+ d->editor->editorStackView()->setToolView(d->tool->toolView());
+ d->editor->editorStackView()->setViewMode(EditorStackView::ToolViewMode);
+ d->prevTab = d->editor->rightSideBar()->getActiveTab();
+ d->editor->rightSideBar()->appendTab(d->tool->toolSettings(), d->tool->toolIcon(), d->tool->toolName());
+ d->editor->rightSideBar()->setActiveTab(d->tool->toolSettings());
+ d->editor->toggleActions(false);
+
+ // If editor tool has zoomable preview, switch on zoom actions.
+ if (d->editor->editorStackView()->previewWidget())
+ d->editor->toggleZoomActions(true);
+}
+
+void EditorToolIface::unLoadTool()
+{
+ if (!d->tool) return;
+
+ d->editor->editorStackView()->setViewMode(EditorStackView::CanvasMode);
+ d->editor->editorStackView()->setToolView(0);
+ d->editor->rightSideBar()->deleteTab(d->tool->toolSettings());
+ d->editor->rightSideBar()->setActiveTab(d->prevTab);
+ d->editor->toggleActions(true);
+ // To restore canvas zoom level in zoom combobox.
+ if (!d->editor->editorStackView()->canvas()->fitToWindow())
+ d->editor->editorStackView()->setZoomFactor(d->editor->editorStackView()->canvas()->zoomFactor());
+ delete d->tool;
+ d->tool = 0;
+}
+
+void EditorToolIface::setToolStartProgress(const TQString& toolName)
+{
+ d->editor->setToolStartProgress(toolName);
+ if (d->editor->editorStackView()->previewWidget())
+ d->editor->toggleZoomActions(false);
+}
+
+void EditorToolIface::setToolProgress(int progress)
+{
+ d->editor->setToolProgress(progress);
+}
+
+void EditorToolIface::setToolStopProgress()
+{
+ d->editor->setToolStopProgress();
+ if (d->editor->editorStackView()->previewWidget())
+ d->editor->toggleZoomActions(true);
+}
+
+void EditorToolIface::slotToolAborted()
+{
+ EditorToolThreaded *tool = dynamic_cast<EditorToolThreaded*>(d->tool);
+ if (tool) tool->slotAbort();
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/editor/editortooliface.h b/src/utilities/imageeditor/editor/editortooliface.h
new file mode 100644
index 00000000..ce8708cf
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editortooliface.h
@@ -0,0 +1,76 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-20
+ * Description : Image editor interface used by editor tools.
+ *
+ * Copyright (C) 2008-2009 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 EDITORTOOLIFACE_H
+#define EDITORTOOLIFACE_H
+
+// TQt includes.
+
+#include <tqobject.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class EditorTool;
+class EditorWindow;
+class EditorToolIfacePriv;
+
+class DIGIKAM_EXPORT EditorToolIface : public TQObject
+{
+ TQ_OBJECT
+
+
+public:
+
+ static EditorToolIface* editorToolIface();
+
+ EditorToolIface(EditorWindow *editor);
+ ~EditorToolIface();
+
+ EditorTool* currentTool() const;
+
+ void loadTool(EditorTool* tool);
+ void unLoadTool();
+
+ void setToolStartProgress(const TQString& toolName);
+ void setToolProgress(int progress);
+ void setToolStopProgress();
+
+public slots:
+
+ void slotToolAborted();
+
+private:
+
+ static EditorToolIface *m_iface;
+
+ EditorToolIfacePriv *d;
+};
+
+} // namespace Digikam
+
+#endif /* EDITORTOOLIFACE_H */
diff --git a/src/utilities/imageeditor/editor/editortoolsettings.cpp b/src/utilities/imageeditor/editor/editortoolsettings.cpp
new file mode 100644
index 00000000..3ac45ccf
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editortoolsettings.cpp
@@ -0,0 +1,331 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-21
+ * Description : Editor tool settings template box
+ *
+ * Copyright (C) 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 <tqhbox.h>
+#include <tqvbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqstring.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <kcolorbutton.h>
+#include <kdialog.h>
+#include <tdeglobalsettings.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kpushbutton.h>
+#include <kstandarddirs.h>
+#include <kstdguiitem.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imagepaniconwidget.h"
+#include "editortoolsettings.h"
+#include "editortoolsettings.moc"
+
+using namespace KDcrawIface;
+
+namespace Digikam
+{
+
+class EditorToolSettingsPriv
+{
+
+public:
+
+ EditorToolSettingsPriv()
+ {
+ okBtn = 0;
+ cancelBtn = 0;
+ tryBtn = 0;
+ defaultBtn = 0;
+ mainVBox = 0;
+ plainPage = 0;
+ btnBox1 = 0;
+ btnBox2 = 0;
+ btnBox3 = 0;
+ saveAsBtn = 0;
+ loadBtn = 0;
+ guideBox = 0;
+ guideColorBt = 0;
+ guideSize = 0;
+ panIconView = 0;
+ }
+
+ TQHBox *btnBox1;
+ TQHBox *btnBox2;
+ TQHBox *btnBox3;
+ TQHBox *guideBox;
+
+ TQVBox *mainVBox;
+ TQWidget *plainPage;
+
+ KPushButton *okBtn;
+ KPushButton *cancelBtn;
+ KPushButton *tryBtn;
+ KPushButton *defaultBtn;
+ KPushButton *saveAsBtn;
+ KPushButton *loadBtn;
+
+ KColorButton *guideColorBt;
+
+ ImagePanIconWidget *panIconView;
+
+ RIntNumInput *guideSize;
+};
+
+EditorToolSettings::EditorToolSettings(int buttonMask, int toolMask, TQWidget *parent)
+ : TQScrollView(parent)
+{
+ d = new EditorToolSettingsPriv;
+
+ viewport()->setBackgroundMode(TQt::PaletteBackground);
+ setResizePolicy(TQScrollView::AutoOneFit);
+ setFrameStyle(TQFrame::NoFrame);
+
+ d->mainVBox = new TQVBox(viewport());
+ addChild(d->mainVBox);
+
+ // ---------------------------------------------------------------
+
+ TQFrame *frame = new TQFrame(d->mainVBox);
+ frame->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+ TQVBoxLayout* vlay = new TQVBoxLayout(frame, 5, 0);
+ d->panIconView = new ImagePanIconWidget(360, 240, frame);
+ TQWhatsThis::add(d->panIconView, i18n("<p>Here you can see the original image panel "
+ "which can help you to select the clip preview."
+ "<p>Click and drag the mouse cursor in the "
+ "red rectangle to change the clip focus."));
+ vlay->addWidget(d->panIconView, 0, TQt::AlignCenter);
+
+ if (!(toolMask & PanIcon))
+ frame->hide();
+
+ // ---------------------------------------------------------------
+
+ d->plainPage = new TQWidget(d->mainVBox);
+ d->guideBox = new TQHBox(d->mainVBox);
+ d->btnBox1 = new TQHBox(d->mainVBox);
+ d->btnBox2 = new TQHBox(d->mainVBox);
+
+ // ---------------------------------------------------------------
+
+ new TQLabel(i18n("Guide:"), d->guideBox);
+ TQLabel *space4 = new TQLabel(d->guideBox);
+ d->guideColorBt = new KColorButton(TQColor(TQt::red), d->guideBox);
+ TQWhatsThis::add(d->guideColorBt, i18n("<p>Set here the color used to draw guides dashed-lines."));
+ d->guideSize = new RIntNumInput(d->guideBox);
+ d->guideSize->setRange(1, 5, 1);
+ d->guideSize->setDefaultValue(1);
+ TQWhatsThis::add(d->guideSize, i18n("<p>Set here the width in pixels used to draw guides dashed-lines."));
+
+ d->guideBox->setStretchFactor(space4, 10);
+ d->guideBox->setSpacing(spacingHint());
+ d->guideBox->setMargin(0);
+
+ if (!(toolMask & ColorGuide))
+ d->guideBox->hide();
+
+ // ---------------------------------------------------------------
+
+ d->defaultBtn = new KPushButton(d->btnBox1);
+ d->defaultBtn->setGuiItem(KStdGuiItem::defaults());
+ d->defaultBtn->setIconSet(SmallIconSet("reload_page"));
+ TQToolTip::add(d->defaultBtn, i18n("<p>Reset all settings to their default values."));
+ if (!(buttonMask & Default))
+ d->defaultBtn->hide();
+
+ TQLabel *space = new TQLabel(d->btnBox1);
+
+ d->okBtn = new KPushButton(d->btnBox1);
+ d->okBtn->setGuiItem(KStdGuiItem::ok());
+ if (!(buttonMask & Ok))
+ d->okBtn->hide();
+
+ d->cancelBtn = new KPushButton(d->btnBox1);
+ d->cancelBtn->setGuiItem(KStdGuiItem::cancel());
+ if (!(buttonMask & Cancel))
+ d->cancelBtn->hide();
+
+ d->btnBox1->setStretchFactor(space, 10);
+ d->btnBox1->setSpacing(spacingHint());
+ d->btnBox1->setMargin(0);
+
+ if (!(buttonMask & Default) && !(buttonMask & Ok) && !(buttonMask & Cancel))
+ d->btnBox1->hide();
+
+ // ---------------------------------------------------------------
+
+ d->loadBtn = new KPushButton(d->btnBox2);
+ d->loadBtn->setGuiItem(KStdGuiItem::open());
+ d->loadBtn->setText(i18n("Load..."));
+ TQToolTip::add(d->loadBtn, i18n("<p>Load all parameters from settings text file."));
+ if (!(buttonMask & Load))
+ d->loadBtn->hide();
+
+ d->saveAsBtn = new KPushButton(d->btnBox2);
+ d->saveAsBtn->setGuiItem(KStdGuiItem::saveAs());
+ TQToolTip::add(d->saveAsBtn, i18n("<p>Save all parameters to settings text file."));
+ if (!(buttonMask & SaveAs))
+ d->saveAsBtn->hide();
+
+ TQLabel *space2 = new TQLabel(d->btnBox2);
+
+ d->tryBtn = new KPushButton(d->btnBox2);
+ d->tryBtn->setGuiItem(KStdGuiItem::apply());
+ d->tryBtn->setText(i18n("Try"));
+ TQToolTip::add(d->tryBtn, i18n("<p>Try all settings."));
+ if (!(buttonMask & Try))
+ d->tryBtn->hide();
+
+ d->btnBox2->setStretchFactor(space2, 10);
+ d->btnBox2->setSpacing(spacingHint());
+ d->btnBox2->setMargin(0);
+
+ if (!(buttonMask & Load) && !(buttonMask & SaveAs) && !(buttonMask & Try))
+ d->btnBox2->hide();
+
+ // ---------------------------------------------------------------
+
+ connect(d->okBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalOkClicked()));
+
+ connect(d->cancelBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalCancelClicked()));
+
+ connect(d->tryBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalTryClicked()));
+
+ connect(d->defaultBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalDefaultClicked()));
+
+ connect(d->saveAsBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalSaveAsClicked()));
+
+ connect(d->loadBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalLoadClicked()));
+
+ connect(d->guideColorBt, TQ_SIGNAL(changed(const TQColor&)),
+ this, TQ_SIGNAL(signalColorGuideChanged()));
+
+ connect(d->guideSize, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SIGNAL(signalColorGuideChanged()));
+}
+
+EditorToolSettings::~EditorToolSettings()
+{
+ delete d;
+}
+
+TQSize EditorToolSettings::minimumSizeHint() const
+{
+ // Editor Tools usually require a larger horizontal space than other widgets in right side bar
+ // Set scroll area to a horizontal minimum size sufficient for the settings.
+ // Do not touch vertical size hint.
+ // Limit to 40% of the desktop width.
+ TQSize hint = TQScrollView::minimumSizeHint();
+ TQRect desktopRect = TDEGlobalSettings::desktopGeometry(d->mainVBox);
+ hint.setWidth(TQMIN(d->mainVBox->minimumSizeHint().width(), desktopRect.width() * 2 / 5));
+ return hint;
+}
+
+int EditorToolSettings::marginHint()
+{
+ return KDialog::marginHint();
+}
+
+int EditorToolSettings::spacingHint()
+{
+ return KDialog::spacingHint();
+}
+
+TQWidget *EditorToolSettings::plainPage() const
+{
+ return d->plainPage;
+}
+
+ImagePanIconWidget* EditorToolSettings::panIconView() const
+{
+ return d->panIconView;
+}
+
+KPushButton* EditorToolSettings::button(int buttonCode) const
+{
+ if (buttonCode & Default)
+ return d->defaultBtn;
+
+ if (buttonCode & Try)
+ return d->tryBtn;
+
+ if (buttonCode & Ok)
+ return d->okBtn;
+
+ if (buttonCode & Cancel)
+ return d->cancelBtn;
+
+ if (buttonCode & Load)
+ return d->loadBtn;
+
+ if (buttonCode & SaveAs)
+ return d->saveAsBtn;
+
+ return 0;
+}
+
+void EditorToolSettings::enableButton(int buttonCode, bool state)
+{
+ KPushButton *btn = button(buttonCode);
+ if (btn) btn->setEnabled(state);
+}
+
+TQColor EditorToolSettings::guideColor() const
+{
+ return d->guideColorBt->color();
+}
+
+void EditorToolSettings::setGuideColor(const TQColor& color)
+{
+ d->guideColorBt->setColor(color);
+}
+
+int EditorToolSettings::guideSize() const
+{
+ return d->guideSize->value();
+}
+
+void EditorToolSettings::setGuideSize(int size)
+{
+ d->guideSize->setValue(size);
+}
+
+} // NameSpace Digikam
diff --git a/src/utilities/imageeditor/editor/editortoolsettings.h b/src/utilities/imageeditor/editor/editortoolsettings.h
new file mode 100644
index 00000000..062b2e34
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editortoolsettings.h
@@ -0,0 +1,110 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-21
+ * Description : Editor tool settings template box
+ *
+ * Copyright (C) 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 EDITORTOOLSETTINGS_H
+#define EDITORTOOLSETTINGS_H
+
+// TQt includes.
+
+#include <tqscrollview.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+class KPushButton;
+
+namespace Digikam
+{
+
+class ImagePanIconWidget;
+class EditorToolSettingsPriv;
+
+class DIGIKAM_EXPORT EditorToolSettings : public TQScrollView
+{
+ TQ_OBJECT
+
+
+public:
+
+ enum ButtonCode
+ {
+ Default = 0x00000001,
+ Try = 0x00000002,
+ Ok = 0x00000004,
+ Cancel = 0x00000008,
+ SaveAs = 0x00000010,
+ Load = 0x00000020
+ };
+
+ enum ToolCode
+ {
+ NoTool = 0x00000001,
+ ColorGuide = 0x00000002,
+ PanIcon = 0x00000004
+ };
+
+public:
+
+ EditorToolSettings(int buttonMask, int toolMask=NoTool, TQWidget *parent=0);
+ ~EditorToolSettings();
+
+ virtual void setBusy(bool){};
+ virtual void writeSettings(){};
+ virtual void readSettings(){};
+ virtual void resetSettings(){};
+
+ int marginHint();
+ int spacingHint();
+
+ TQWidget *plainPage() const;
+
+ TQColor guideColor() const;
+ void setGuideColor(const TQColor& color);
+
+ int guideSize() const;
+ void setGuideSize(int size);
+
+ ImagePanIconWidget* panIconView() const;
+ KPushButton* button(int buttonCode) const;
+ void enableButton(int buttonCode, bool state);
+
+ virtual TQSize minimumSizeHint() const;
+
+signals:
+
+ void signalOkClicked();
+ void signalCancelClicked();
+ void signalTryClicked();
+ void signalDefaultClicked();
+ void signalSaveAsClicked();
+ void signalLoadClicked();
+ void signalColorGuideChanged();
+
+private:
+
+ EditorToolSettingsPriv *d;
+};
+
+} // NameSpace Digikam
+
+#endif // EDITORTOOLSETTINGS_H
diff --git a/src/utilities/imageeditor/editor/editorwindow.cpp b/src/utilities/imageeditor/editor/editorwindow.cpp
new file mode 100644
index 00000000..eed7cfea
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editorwindow.cpp
@@ -0,0 +1,1932 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-20
+ * Description : main image editor GUI implementation
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <sys/types.h>
+#include <sys/stat.h>
+}
+
+// C++ includes.
+
+#include <cmath>
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqdockarea.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqtoolbutton.h>
+#include <tqsplitter.h>
+#include <tqdir.h>
+#include <tqfileinfo.h>
+#include <tqfile.h>
+#include <tqcursor.h>
+#include <tqtimer.h>
+#include <tqfileinfo.h>
+
+// KDE includes.
+
+#include <kprinter.h>
+#include <kkeydialog.h>
+#include <tdeversion.h>
+#include <tdeaction.h>
+#include <kedittoolbar.h>
+#include <tdeaboutdata.h>
+#include <kcursor.h>
+#include <kstdaction.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <tdefiledialog.h>
+#include <tdemenubar.h>
+#include <kimageio.h>
+#include <tdeaccel.h>
+#include <tdemessagebox.h>
+#include <tdeglobal.h>
+#include <kstandarddirs.h>
+#include <kiconloader.h>
+#include <tdeio/netaccess.h>
+#include <tdeio/job.h>
+#include <kprotocolinfo.h>
+#include <tdeglobalsettings.h>
+#include <tdetoolbar.h>
+#include <kstatusbar.h>
+#include <kprogress.h>
+#include <twin.h>
+#include <kcombobox.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dpopupmenu.h"
+#include "canvas.h"
+#include "dimginterface.h"
+#include "imagedialog.h"
+#include "imageplugin.h"
+#include "imagepluginloader.h"
+#include "imageresize.h"
+#include "imageprint.h"
+#include "filesaveoptionsbox.h"
+#include "statusprogressbar.h"
+#include "iccsettingscontainer.h"
+#include "exposurecontainer.h"
+#include "iofilesettingscontainer.h"
+#include "savingcontextcontainer.h"
+#include "loadingcacheinterface.h"
+#include "slideshowsettings.h"
+#include "themeengine.h"
+#include "rawcameradlg.h"
+#include "editorstackview.h"
+#include "editortooliface.h"
+#include "editorwindowprivate.h"
+#include "editorwindow.h"
+#include "editorwindow.moc"
+
+void tqt_enter_modal( TQWidget *widget );
+void tqt_leave_modal( TQWidget *widget );
+
+namespace Digikam
+{
+
+EditorWindow::EditorWindow(const char *name)
+ : TDEMainWindow(0, name, WType_TopLevel)
+{
+ d = new EditorWindowPriv;
+
+ m_themeMenuAction = 0;
+ m_contextMenu = 0;
+ m_canvas = 0;
+ m_imagePluginLoader = 0;
+ m_undoAction = 0;
+ m_redoAction = 0;
+ m_fullScreenAction = 0;
+ m_saveAction = 0;
+ m_saveAsAction = 0;
+ m_revertAction = 0;
+ m_fileDeleteAction = 0;
+ m_forwardAction = 0;
+ m_backwardAction = 0;
+ m_firstAction = 0;
+ m_lastAction = 0;
+ m_undoAction = 0;
+ m_redoAction = 0;
+ m_stackView = 0;
+ m_fullScreen = false;
+ m_rotatedOrFlipped = false;
+ m_setExifOrientationTag = true;
+ m_cancelSlideShow = false;
+
+ // Settings containers instance.
+
+ d->ICCSettings = new ICCSettingsContainer();
+ d->exposureSettings = new ExposureSettingsContainer();
+ d->toolIface = new EditorToolIface(this);
+ m_IOFileSettings = new IOFileSettingsContainer();
+ m_savingContext = new SavingContextContainer();
+}
+
+EditorWindow::~EditorWindow()
+{
+ delete m_canvas;
+ delete m_IOFileSettings;
+ delete m_savingContext;
+ delete d->ICCSettings;
+ delete d->exposureSettings;
+ delete d;
+}
+
+EditorStackView* EditorWindow::editorStackView() const
+{
+ return m_stackView;
+}
+
+void EditorWindow::setupContextMenu()
+{
+ m_contextMenu = new DPopupMenu(this);
+ TDEActionCollection *ac = actionCollection();
+ if( ac->action("editorwindow_backward") ) ac->action("editorwindow_backward")->plug(m_contextMenu);
+ if( ac->action("editorwindow_forward") ) ac->action("editorwindow_forward")->plug(m_contextMenu);
+ m_contextMenu->insertSeparator();
+ if( ac->action("editorwindow_slideshow") ) ac->action("editorwindow_slideshow")->plug(m_contextMenu);
+ if( ac->action("editorwindow_rotate_left") ) ac->action("editorwindow_rotate_left")->plug(m_contextMenu);
+ if( ac->action("editorwindow_rotate_right") ) ac->action("editorwindow_rotate_right")->plug(m_contextMenu);
+ if( ac->action("editorwindow_crop") ) ac->action("editorwindow_crop")->plug(m_contextMenu);
+ m_contextMenu->insertSeparator();
+ if( ac->action("editorwindow_delete") ) ac->action("editorwindow_delete")->plug(m_contextMenu);
+}
+
+void EditorWindow::setupStandardConnections()
+{
+ // -- Canvas connections ------------------------------------------------
+
+ connect(m_canvas, TQ_SIGNAL(signalToggleOffFitToWindow()),
+ this, TQ_SLOT(slotToggleOffFitToWindow()));
+
+ connect(m_canvas, TQ_SIGNAL(signalShowNextImage()),
+ this, TQ_SLOT(slotForward()));
+
+ connect(m_canvas, TQ_SIGNAL(signalShowPrevImage()),
+ this, TQ_SLOT(slotBackward()));
+
+ connect(m_canvas, TQ_SIGNAL(signalRightButtonClicked()),
+ this, TQ_SLOT(slotContextMenu()));
+
+ connect(m_stackView, TQ_SIGNAL(signalZoomChanged(bool, bool, double)),
+ this, TQ_SLOT(slotZoomChanged(bool, bool, double)));
+
+ connect(m_canvas, TQ_SIGNAL(signalChanged()),
+ this, TQ_SLOT(slotChanged()));
+
+ connect(m_canvas, TQ_SIGNAL(signalUndoStateChanged(bool, bool, bool)),
+ this, TQ_SLOT(slotUndoStateChanged(bool, bool, bool)));
+
+ connect(m_canvas, TQ_SIGNAL(signalSelected(bool)),
+ this, TQ_SLOT(slotSelected(bool)));
+
+ connect(m_canvas, TQ_SIGNAL(signalPrepareToLoad()),
+ this, TQ_SLOT(slotPrepareToLoad()));
+
+ connect(m_canvas, TQ_SIGNAL(signalLoadingStarted(const TQString &)),
+ this, TQ_SLOT(slotLoadingStarted(const TQString &)));
+
+ connect(m_canvas, TQ_SIGNAL(signalLoadingFinished(const TQString &, bool)),
+ this, TQ_SLOT(slotLoadingFinished(const TQString &, bool)));
+
+ connect(m_canvas, TQ_SIGNAL(signalLoadingProgress(const TQString &, float)),
+ this, TQ_SLOT(slotLoadingProgress(const TQString &, float)));
+
+ connect(m_canvas, TQ_SIGNAL(signalSavingStarted(const TQString&)),
+ this, TQ_SLOT(slotSavingStarted(const TQString&)));
+
+ connect(m_canvas, TQ_SIGNAL(signalSavingFinished(const TQString&, bool)),
+ this, TQ_SLOT(slotSavingFinished(const TQString&, bool)));
+
+ connect(m_canvas, TQ_SIGNAL(signalSavingProgress(const TQString&, float)),
+ this, TQ_SLOT(slotSavingProgress(const TQString&, float)));
+
+ connect(m_canvas, TQ_SIGNAL(signalSelectionChanged(const TQRect&)),
+ this, TQ_SLOT(slotSelectionChanged(const TQRect&)));
+
+ // -- if rotating/flipping set the rotatedflipped flag to true -----------
+
+ connect(d->rotateLeftAction, TQ_SIGNAL(activated()),
+ this, TQ_SLOT(slotRotatedOrFlipped()));
+
+ connect(d->rotateRightAction, TQ_SIGNAL(activated()),
+ this, TQ_SLOT(slotRotatedOrFlipped()));
+
+ connect(d->flipHorizAction, TQ_SIGNAL(activated()),
+ this, TQ_SLOT(slotRotatedOrFlipped()));
+
+ connect(d->flipVertAction, TQ_SIGNAL(activated()),
+ this, TQ_SLOT(slotRotatedOrFlipped()));
+
+ // -- status bar connections --------------------------------------
+
+ connect(m_nameLabel, TQ_SIGNAL(signalCancelButtonPressed()),
+ this, TQ_SLOT(slotNameLabelCancelButtonPressed()));
+
+ connect(m_nameLabel, TQ_SIGNAL(signalCancelButtonPressed()),
+ d->toolIface, TQ_SLOT(slotToolAborted()));
+}
+
+void EditorWindow::setupStandardActions()
+{
+ // -- Standard 'File' menu actions ---------------------------------------------
+
+ m_backwardAction = KStdAction::back(this, TQ_SLOT(slotBackward()),
+ actionCollection(), "editorwindow_backward");
+
+ m_forwardAction = KStdAction::forward(this, TQ_SLOT(slotForward()),
+ actionCollection(), "editorwindow_forward");
+
+ m_firstAction = new TDEAction(i18n("&First"), "go-first",
+ TDEStdAccel::shortcut( TDEStdAccel::Home),
+ this, TQ_SLOT(slotFirst()),
+ actionCollection(), "editorwindow_first");
+
+ m_lastAction = new TDEAction(i18n("&Last"), "go-last",
+ TDEStdAccel::shortcut( TDEStdAccel::End),
+ this, TQ_SLOT(slotLast()),
+ actionCollection(), "editorwindow_last");
+
+ m_saveAction = KStdAction::save(this, TQ_SLOT(slotSave()),
+ actionCollection(), "editorwindow_save");
+
+ m_saveAsAction = KStdAction::saveAs(this, TQ_SLOT(slotSaveAs()),
+ actionCollection(), "editorwindow_saveas");
+
+ m_revertAction = KStdAction::revert(this, TQ_SLOT(slotRevert()),
+ actionCollection(), "editorwindow_revert");
+
+ m_saveAction->setEnabled(false);
+ m_saveAsAction->setEnabled(false);
+ m_revertAction->setEnabled(false);
+
+ d->filePrintAction = new TDEAction(i18n("Print Image..."), "document-print",
+ CTRL+Key_P,
+ this, TQ_SLOT(slotFilePrint()),
+ actionCollection(), "editorwindow_print");
+
+ m_fileDeleteAction = new TDEAction(i18n("Move to Trash"), "edittrash",
+ Key_Delete,
+ this, TQ_SLOT(slotDeleteCurrentItem()),
+ actionCollection(), "editorwindow_delete");
+
+ KStdAction::close(this, TQ_SLOT(close()), actionCollection(), "editorwindow_close");
+
+ // -- Standard 'Edit' menu actions ---------------------------------------------
+
+ d->copyAction = KStdAction::copy(m_canvas, TQ_SLOT(slotCopy()),
+ actionCollection(), "editorwindow_copy");
+
+ d->copyAction->setEnabled(false);
+
+ m_undoAction = new TDEToolBarPopupAction(i18n("Undo"), "edit-undo",
+ TDEStdAccel::shortcut(TDEStdAccel::Undo),
+ m_canvas, TQ_SLOT(slotUndo()),
+ actionCollection(), "editorwindow_undo");
+
+ connect(m_undoAction->popupMenu(), TQ_SIGNAL(aboutToShow()),
+ this, TQ_SLOT(slotAboutToShowUndoMenu()));
+
+ connect(m_undoAction->popupMenu(), TQ_SIGNAL(activated(int)),
+ m_canvas, TQ_SLOT(slotUndo(int)));
+
+ m_undoAction->setEnabled(false);
+
+ m_redoAction = new TDEToolBarPopupAction(i18n("Redo"), "edit-redo",
+ TDEStdAccel::shortcut(TDEStdAccel::Redo),
+ m_canvas, TQ_SLOT(slotRedo()),
+ actionCollection(), "editorwindow_redo");
+
+ connect(m_redoAction->popupMenu(), TQ_SIGNAL(aboutToShow()),
+ this, TQ_SLOT(slotAboutToShowRedoMenu()));
+
+ connect(m_redoAction->popupMenu(), TQ_SIGNAL(activated(int)),
+ m_canvas, TQ_SLOT(slotRedo(int)));
+
+ m_redoAction->setEnabled(false);
+
+ d->selectAllAction = new TDEAction(i18n("Select All"),
+ 0,
+ CTRL+Key_A,
+ m_canvas,
+ TQ_SLOT(slotSelectAll()),
+ actionCollection(),
+ "editorwindow_selectAll");
+
+ d->selectNoneAction = new TDEAction(i18n("Select None"),
+ 0,
+ CTRL+SHIFT+Key_A,
+ m_canvas,
+ TQ_SLOT(slotSelectNone()),
+ actionCollection(),
+ "editorwindow_selectNone");
+
+ // -- Standard 'View' menu actions ---------------------------------------------
+
+ d->zoomPlusAction = KStdAction::zoomIn(this, TQ_SLOT(slotIncreaseZoom()),
+ actionCollection(), "editorwindow_zoomplus");
+
+ d->zoomMinusAction = KStdAction::zoomOut(this, TQ_SLOT(slotDecreaseZoom()),
+ actionCollection(), "editorwindow_zoomminus");
+
+ 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(), "editorwindow_zoomto100percents");
+
+
+ d->zoomFitToWindowAction = new TDEToggleAction(i18n("Fit to &Window"), "view_fit_window",
+ CTRL+SHIFT+Key_E, // NOTE: Gimp 2 use CTRL+SHIFT+E.
+ this, TQ_SLOT(slotToggleFitToWindow()),
+ actionCollection(), "editorwindow_zoomfit2window");
+
+ d->zoomFitToSelectAction = new TDEAction(i18n("Fit to &Selection"), "zoom-fit-best",
+ ALT+CTRL+Key_S, this, TQ_SLOT(slotFitToSelect()),
+ actionCollection(), "editorwindow_zoomfit2select");
+ d->zoomFitToSelectAction->setEnabled(false);
+ d->zoomFitToSelectAction->setWhatsThis(i18n("This option can be used to zoom the image to the "
+ "current selection area."));
+
+ d->zoomCombo = new KComboBox(true);
+ d->zoomCombo->setDuplicatesEnabled(false);
+ d->zoomCombo->setFocusPolicy(TQWidget::ClickFocus);
+ d->zoomCombo->setInsertionPolicy(TQComboBox::NoInsertion);
+ d->zoomComboAction = new KWidgetAction(d->zoomCombo, i18n("Zoom"), 0, 0, 0,
+ actionCollection(), "editorwindow_zoomto");
+
+ d->zoomCombo->insertItem(TQString("10%"));
+ d->zoomCombo->insertItem(TQString("25%"));
+ d->zoomCombo->insertItem(TQString("50%"));
+ d->zoomCombo->insertItem(TQString("75%"));
+ d->zoomCombo->insertItem(TQString("100%"));
+ d->zoomCombo->insertItem(TQString("150%"));
+ d->zoomCombo->insertItem(TQString("200%"));
+ d->zoomCombo->insertItem(TQString("300%"));
+ d->zoomCombo->insertItem(TQString("450%"));
+ d->zoomCombo->insertItem(TQString("600%"));
+ d->zoomCombo->insertItem(TQString("800%"));
+ d->zoomCombo->insertItem(TQString("1200%"));
+
+ connect(d->zoomCombo, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotZoomSelected()) );
+
+ connect(d->zoomCombo, TQ_SIGNAL(returnPressed(const TQString&)),
+ this, TQ_SLOT(slotZoomTextChanged(const TQString &)) );
+
+ // Do not use std KDE action for full screen because action text is too large for app. toolbar.
+ m_fullScreenAction = new TDEToggleAction(i18n("Full Screen"), "view-fullscreen",
+ CTRL+SHIFT+Key_F, this,
+ TQ_SLOT(slotToggleFullScreen()),
+ actionCollection(), "editorwindow_fullscreen");
+ m_fullScreenAction->setWhatsThis(i18n("Toggle the window to full screen mode"));
+
+ d->slideShowAction = new TDEAction(i18n("Slideshow"), "slideshow", Key_F9,
+ this, TQ_SLOT(slotToggleSlideShow()),
+ actionCollection(),"editorwindow_slideshow");
+
+ d->viewUnderExpoAction = new TDEToggleAction(i18n("Under-Exposure Indicator"), "underexposure",
+ Key_F10, this,
+ TQ_SLOT(slotToggleUnderExposureIndicator()),
+ actionCollection(),"editorwindow_underexposure");
+
+ d->viewOverExpoAction = new TDEToggleAction(i18n("Over-Exposure Indicator"), "overexposure",
+ Key_F11, this,
+ TQ_SLOT(slotToggleOverExposureIndicator()),
+ actionCollection(),"editorwindow_overexposure");
+
+ d->viewCMViewAction = new TDEToggleAction(i18n("Color Managed View"), "tv",
+ Key_F12, this,
+ TQ_SLOT(slotToggleColorManagedView()),
+ actionCollection(),"editorwindow_cmview");
+
+ // -- Standard 'Transform' menu actions ---------------------------------------------
+
+ d->resizeAction = new TDEAction(i18n("&Resize..."), "resize_image", 0,
+ this, TQ_SLOT(slotResize()),
+ actionCollection(), "editorwindow_resize");
+
+ d->cropAction = new TDEAction(i18n("Crop"), "crop",
+ CTRL+Key_X,
+ m_canvas, TQ_SLOT(slotCrop()),
+ actionCollection(), "editorwindow_crop");
+
+ d->cropAction->setEnabled(false);
+ d->cropAction->setWhatsThis(i18n("This option can be used to crop the image. "
+ "Select a region of the image to enable this action."));
+
+ // -- Standard 'Flip' menu actions ---------------------------------------------
+
+ d->flipHorizAction = new TDEAction(i18n("Flip Horizontally"), "mirror", CTRL+Key_Asterisk,
+ m_canvas, TQ_SLOT(slotFlipHoriz()),
+ actionCollection(), "editorwindow_flip_horiz");
+ d->flipHorizAction->setEnabled(false);
+
+ d->flipVertAction = new TDEAction(i18n("Flip Vertically"), "flip", CTRL+Key_Slash,
+ m_canvas, TQ_SLOT(slotFlipVert()),
+ actionCollection(), "editorwindow_flip_vert");
+ d->flipVertAction->setEnabled(false);
+
+ // -- Standard 'Rotate' menu actions ----------------------------------------
+
+ d->rotateLeftAction = new TDEAction(i18n("Rotate Left"),
+ "object-rotate-left", SHIFT+CTRL+Key_Left,
+ m_canvas, TQ_SLOT(slotRotate270()),
+ actionCollection(),
+ "editorwindow_rotate_left");
+ d->rotateLeftAction->setEnabled(false);
+ d->rotateRightAction = new TDEAction(i18n("Rotate Right"),
+ "object-rotate-right", SHIFT+CTRL+Key_Right,
+ m_canvas, TQ_SLOT(slotRotate90()),
+ actionCollection(),
+ "editorwindow_rotate_right");
+ d->rotateRightAction->setEnabled(false);
+
+ // -- 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());
+
+ // -----------------------------------------------------------------------------------------
+
+ m_themeMenuAction = new TDESelectAction(i18n("&Themes"), 0, actionCollection(), "theme_menu");
+ m_themeMenuAction->setItems(ThemeEngine::instance()->themeNames());
+
+ connect(m_themeMenuAction, TQ_SIGNAL(activated(const TQString&)),
+ this, TQ_SLOT(slotChangeTheme(const TQString&)));
+
+ connect(ThemeEngine::instance(), TQ_SIGNAL(signalThemeChanged()),
+ this, TQ_SLOT(slotThemeChanged()));
+
+ // -- Standard 'Help' menu actions ---------------------------------------------
+
+ d->donateMoneyAction = new TDEAction(i18n("Donate..."),
+ 0, 0,
+ this, TQ_SLOT(slotDonateMoney()),
+ actionCollection(),
+ "editorwindow_donatemoney");
+
+ d->contributeAction = new TDEAction(i18n("Contribute..."),
+ 0, 0,
+ this, TQ_SLOT(slotContribute()),
+ actionCollection(),
+ "editorwindow_contribute");
+
+ d->rawCameraListAction = new TDEAction(i18n("Supported RAW Cameras"),
+ "kdcraw",
+ 0,
+ this,
+ TQ_SLOT(slotRawCameraList()),
+ actionCollection(),
+ "editorwindow_rawcameralist");
+}
+
+void EditorWindow::setupStandardAccelerators()
+{
+ d->accelerators = new TDEAccel(this);
+
+ d->accelerators->insert("Exit fullscreen", i18n("Exit Fullscreen mode"),
+ i18n("Exit out of the fullscreen 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, this, TQ_SLOT(slotIncreaseZoom()),
+ false, true);
+
+ d->accelerators->insert("Zoom Plus Key_Minus", i18n("Zoom Out"),
+ i18n("Zoom out of Image"),
+ Key_Minus, this, TQ_SLOT(slotDecreaseZoom()),
+ false, true);
+
+ d->accelerators->insert("Redo CTRL+Key_Y", i18n("Redo"),
+ i18n("Redo Last action"),
+ CTRL+Key_Y, m_canvas, TQ_SLOT(slotRedo()),
+ false, true);
+}
+
+void EditorWindow::setupStatusBar()
+{
+ m_nameLabel = new StatusProgressBar(statusBar());
+ m_nameLabel->setAlignment(TQt::AlignCenter);
+ m_nameLabel->setMaximumHeight(fontMetrics().height()+2);
+ statusBar()->addWidget(m_nameLabel, 100);
+
+ d->selectLabel = new TQLabel(i18n("No selection"), statusBar());
+ d->selectLabel->setAlignment(TQt::AlignCenter);
+ d->selectLabel->setMaximumHeight(fontMetrics().height()+2);
+ statusBar()->addWidget(d->selectLabel, 100);
+ TQToolTip::add(d->selectLabel, i18n("Information about current selection area"));
+
+ m_resLabel = new TQLabel(statusBar());
+ m_resLabel->setAlignment(TQt::AlignCenter);
+ m_resLabel->setMaximumHeight(fontMetrics().height()+2);
+ statusBar()->addWidget(m_resLabel, 100);
+ TQToolTip::add(m_resLabel, i18n("Information about image size"));
+
+ d->underExposureIndicator = new TQToolButton(statusBar());
+ d->underExposureIndicator->setIconSet(SmallIcon("underexposure"));
+ d->underExposureIndicator->setToggleButton(true);
+ statusBar()->addWidget(d->underExposureIndicator, 1);
+
+ d->overExposureIndicator = new TQToolButton(statusBar());
+ d->overExposureIndicator->setIconSet(SmallIcon("overexposure"));
+ d->overExposureIndicator->setToggleButton(true);
+ statusBar()->addWidget(d->overExposureIndicator, 1);
+
+ d->cmViewIndicator = new TQToolButton(statusBar());
+ d->cmViewIndicator->setIconSet(SmallIcon("tv"));
+ d->cmViewIndicator->setToggleButton(true);
+ statusBar()->addWidget(d->cmViewIndicator, 1);
+
+ connect(d->underExposureIndicator, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotToggleUnderExposureIndicator()));
+
+ connect(d->overExposureIndicator, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotToggleOverExposureIndicator()));
+
+ connect(d->cmViewIndicator, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotToggleColorManagedView()));
+}
+
+void EditorWindow::printImage(KURL url)
+{
+ uchar* ptr = m_canvas->interface()->getImage();
+ int w = m_canvas->interface()->origWidth();
+ int h = m_canvas->interface()->origHeight();
+ bool hasAlpha = m_canvas->interface()->hasAlpha();
+ bool sixteenBit = m_canvas->interface()->sixteenBit();
+
+ if (!ptr || !w || !h)
+ return;
+
+ DImg image(w, h, sixteenBit, hasAlpha, ptr);
+
+ KPrinter printer;
+ TQString appName = TDEApplication::kApplication()->aboutData()->appName();
+ printer.setDocName( url.filename() );
+ printer.setCreator( appName );
+#if KDE_IS_VERSION(3,2,0)
+ printer.setUsePrinterResolution(true);
+#endif
+
+ KPrinter::addDialogPage( new ImageEditorPrintDialogPage(image, this, TQString(appName.append(" page")).ascii() ));
+
+ if ( printer.setup( this, i18n("Print %1").arg(printer.docName().section('/', -1)) ) )
+ {
+ ImagePrint printOperations(image, printer, url.filename());
+ if (!printOperations.printImageWithTQt())
+ {
+ KMessageBox::error(this, i18n("Failed to print file: '%1'")
+ .arg(url.filename()));
+ }
+ }
+}
+
+void EditorWindow::slotEditKeys()
+{
+ KKeyDialog dialog(true, this);
+ dialog.insert( actionCollection(), i18n( "General" ) );
+
+ TQPtrList<ImagePlugin> pluginList = ImagePluginLoader::instance()->pluginList();
+
+ for (ImagePlugin* plugin = pluginList.first();
+ plugin; plugin = pluginList.next())
+ {
+ if (plugin)
+ {
+ dialog.insert( plugin->actionCollection(), plugin->name() );
+ }
+ }
+
+ dialog.configure();
+}
+
+void EditorWindow::slotResize()
+{
+ ImageResize dlg(this);
+ dlg.exec();
+}
+
+void EditorWindow::slotAboutToShowUndoMenu()
+{
+ m_undoAction->popupMenu()->clear();
+ TQStringList titles;
+ m_canvas->getUndoHistory(titles);
+
+ if(!titles.isEmpty())
+ {
+ int id = 1;
+ TQStringList::Iterator iter = titles.begin();
+ for(; iter != titles.end(); ++iter,++id)
+ {
+ m_undoAction->popupMenu()->insertItem(*iter, id);
+ }
+ }
+}
+
+void EditorWindow::slotAboutToShowRedoMenu()
+{
+ m_redoAction->popupMenu()->clear();
+ TQStringList titles;
+ m_canvas->getRedoHistory(titles);
+
+ if(!titles.isEmpty())
+ {
+ int id = 1;
+ TQStringList::Iterator iter = titles.begin();
+ for(; iter != titles.end(); ++iter,++id)
+ {
+ m_redoAction->popupMenu()->insertItem(*iter, id);
+ }
+ }
+}
+
+void EditorWindow::slotConfToolbars()
+{
+ saveMainWindowSettings(TDEGlobal::config(), "ImageViewer Settings");
+ KEditToolbar dlg(factory(), this);
+
+ connect(&dlg, TQ_SIGNAL(newToolbarConfig()),
+ this, TQ_SLOT(slotNewToolbarConfig()));
+
+ dlg.exec();
+}
+
+void EditorWindow::slotNewToolbarConfig()
+{
+ applyMainWindowSettings(TDEGlobal::config(), "ImageViewer Settings");
+}
+
+void EditorWindow::slotIncreaseZoom()
+{
+ m_stackView->increaseZoom();
+}
+
+void EditorWindow::slotDecreaseZoom()
+{
+ m_stackView->decreaseZoom();
+}
+
+void EditorWindow::slotToggleFitToWindow()
+{
+ d->zoomPlusAction->setEnabled(true);
+ d->zoomComboAction->setEnabled(true);
+ d->zoomMinusAction->setEnabled(true);
+ m_stackView->toggleFitToWindow();
+}
+
+void EditorWindow::slotFitToSelect()
+{
+ d->zoomPlusAction->setEnabled(true);
+ d->zoomComboAction->setEnabled(true);
+ d->zoomMinusAction->setEnabled(true);
+ m_stackView->fitToSelect();
+}
+
+void EditorWindow::slotZoomTo100Percents()
+{
+ d->zoomPlusAction->setEnabled(true);
+ d->zoomComboAction->setEnabled(true);
+ d->zoomMinusAction->setEnabled(true);
+ m_stackView->zoomTo100Percents();
+}
+
+void EditorWindow::slotZoomSelected()
+{
+ TQString txt = d->zoomCombo->currentText();
+ txt = txt.left(txt.find('%'));
+ slotZoomTextChanged(txt);
+}
+
+void EditorWindow::slotZoomTextChanged(const TQString &txt)
+{
+ bool r = false;
+ double zoom = TDEGlobal::locale()->readNumber(txt, &r) / 100.0;
+ if (r && zoom > 0.0)
+ m_stackView->setZoomFactor(zoom);
+}
+
+void EditorWindow::slotZoomChanged(bool isMax, bool isMin, double zoom)
+{
+ d->zoomPlusAction->setEnabled(!isMax);
+ d->zoomMinusAction->setEnabled(!isMin);
+
+ d->zoomCombo->blockSignals(true);
+ d->zoomCombo->setCurrentText(TQString::number(lround(zoom*100.0)) + TQString("%"));
+ d->zoomCombo->blockSignals(false);
+}
+
+void EditorWindow::slotToggleOffFitToWindow()
+{
+ d->zoomFitToWindowAction->blockSignals(true);
+ d->zoomFitToWindowAction->setChecked(false);
+ d->zoomFitToWindowAction->blockSignals(false);
+}
+
+void EditorWindow::slotEscapePressed()
+{
+ if (m_fullScreen)
+ m_fullScreenAction->activate();
+}
+
+void EditorWindow::plugActionAccel(TDEAction* action)
+{
+ if (!action)
+ return;
+
+ d->accelerators->insert(action->text(),
+ action->text(),
+ action->whatsThis(),
+ action->shortcut(),
+ action,
+ TQ_SLOT(activate()));
+}
+
+void EditorWindow::unplugActionAccel(TDEAction* action)
+{
+ d->accelerators->remove(action->text());
+}
+
+void EditorWindow::loadImagePlugins()
+{
+ TQPtrList<ImagePlugin> pluginList = m_imagePluginLoader->pluginList();
+
+ for (ImagePlugin* plugin = pluginList.first();
+ plugin; plugin = pluginList.next())
+ {
+ if (plugin)
+ {
+ guiFactory()->addClient(plugin);
+ plugin->setEnabledSelectionActions(false);
+ }
+ else
+ DDebug() << "Invalid plugin to add!" << endl;
+ }
+}
+
+void EditorWindow::unLoadImagePlugins()
+{
+ TQPtrList<ImagePlugin> pluginList = m_imagePluginLoader->pluginList();
+
+ for (ImagePlugin* plugin = pluginList.first();
+ plugin; plugin = pluginList.next())
+ {
+ if (plugin)
+ {
+ guiFactory()->removeClient(plugin);
+ plugin->setEnabledSelectionActions(false);
+ }
+ }
+}
+
+void EditorWindow::readStandardSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("ImageViewer Settings");
+
+ // Restore full screen Mode ?
+
+ if (config->readBoolEntry("FullScreen", false))
+ {
+ m_fullScreenAction->activate();
+ m_fullScreen = true;
+ }
+
+ // Restore Auto zoom action ?
+ bool autoZoom = config->readBoolEntry("AutoZoom", true);
+ if (autoZoom)
+ d->zoomFitToWindowAction->activate();
+}
+
+void EditorWindow::applyStandardSettings()
+{
+ TDEConfig* config = kapp->config();
+
+ // -- Settings for Color Management stuff ----------------------------------------------
+
+ config->setGroup("Color Management");
+
+ d->ICCSettings->enableCMSetting = config->readBoolEntry("EnableCM", false);
+ d->ICCSettings->askOrApplySetting = config->readBoolEntry("BehaviourICC", false);
+ d->ICCSettings->BPCSetting = config->readBoolEntry("BPCAlgorithm",false);
+ d->ICCSettings->managedViewSetting = config->readBoolEntry("ManagedView", false);
+ d->ICCSettings->renderingSetting = config->readNumEntry("RenderingIntent");
+ d->ICCSettings->inputSetting = config->readPathEntry("InProfileFile", TQString());
+ d->ICCSettings->workspaceSetting = config->readPathEntry("WorkProfileFile", TQString());
+ d->ICCSettings->monitorSetting = config->readPathEntry("MonitorProfileFile", TQString());
+ d->ICCSettings->proofSetting = config->readPathEntry("ProofProfileFile", TQString());
+
+ d->viewCMViewAction->setEnabled(d->ICCSettings->enableCMSetting);
+ d->viewCMViewAction->setChecked(d->ICCSettings->managedViewSetting);
+ d->cmViewIndicator->setEnabled(d->ICCSettings->enableCMSetting);
+ d->cmViewIndicator->setOn(d->ICCSettings->managedViewSetting);
+ setColorManagedViewIndicatorToolTip(d->ICCSettings->enableCMSetting, d->ICCSettings->managedViewSetting);
+ m_canvas->setICCSettings(d->ICCSettings);
+
+ // -- JPEG, PNG, TIFF JPEG2000 files format settings --------------------------------------
+
+ config->setGroup("ImageViewer Settings");
+
+ // JPEG quality slider settings : 1 - 100 ==> libjpeg settings : 25 - 100.
+ m_IOFileSettings->JPEGCompression = (int)((75.0/100.0)*
+ (float)config->readNumEntry("JPEGCompression", 75)
+ + 26.0 - (75.0/100.0));
+
+ m_IOFileSettings->JPEGSubSampling = config->readNumEntry("JPEGSubSampling", 1); // Medium subsampling
+
+ // PNG compression slider settings : 1 - 9 ==> libpng settings : 100 - 1.
+ m_IOFileSettings->PNGCompression = (int)(((1.0-100.0)/8.0)*
+ (float)config->readNumEntry("PNGCompression", 1)
+ + 100.0 - ((1.0-100.0)/8.0));
+
+ // TIFF compression setting.
+ m_IOFileSettings->TIFFCompression = config->readBoolEntry("TIFFCompression", false);
+
+ // JPEG2000 quality slider settings : 1 - 100
+ m_IOFileSettings->JPEG2000Compression = config->readNumEntry("JPEG2000Compression", 100);
+
+ // JPEG2000 LossLess setting.
+ m_IOFileSettings->JPEG2000LossLess = config->readBoolEntry("JPEG2000LossLess", true);
+
+ // -- RAW images decoding settings ------------------------------------------------------
+
+ // If digiKam Color Management is enable, no need to correct color of decoded RAW image,
+ // else, sRGB color workspace will be used.
+
+ if (d->ICCSettings->enableCMSetting)
+ m_IOFileSettings->rawDecodingSettings.outputColorSpace = DRawDecoding::RAWCOLOR;
+ else
+ m_IOFileSettings->rawDecodingSettings.outputColorSpace = DRawDecoding::SRGB;
+
+ m_IOFileSettings->rawDecodingSettings.sixteenBitsImage = config->readBoolEntry("SixteenBitsImage", false);
+ m_IOFileSettings->rawDecodingSettings.whiteBalance = (DRawDecoding::WhiteBalance)config->readNumEntry("WhiteBalance",
+ DRawDecoding::CAMERA);
+ m_IOFileSettings->rawDecodingSettings.customWhiteBalance = config->readNumEntry("CustomWhiteBalance", 6500);
+ m_IOFileSettings->rawDecodingSettings.customWhiteBalanceGreen = config->readDoubleNumEntry("CustomWhiteBalanceGreen", 1.0);
+ m_IOFileSettings->rawDecodingSettings.RGBInterpolate4Colors = config->readBoolEntry("RGBInterpolate4Colors", false);
+ m_IOFileSettings->rawDecodingSettings.DontStretchPixels = config->readBoolEntry("DontStretchPixels", false);
+ m_IOFileSettings->rawDecodingSettings.enableNoiseReduction = config->readBoolEntry("EnableNoiseReduction", false);
+ m_IOFileSettings->rawDecodingSettings.unclipColors = config->readNumEntry("UnclipColors", 0);
+ m_IOFileSettings->rawDecodingSettings.RAWQuality = (DRawDecoding::DecodingQuality)config->readNumEntry("RAWQuality",
+ DRawDecoding::BILINEAR);
+ m_IOFileSettings->rawDecodingSettings.NRThreshold = config->readNumEntry("NRThreshold", 100);
+ m_IOFileSettings->rawDecodingSettings.enableCACorrection = config->readBoolEntry("EnableCACorrection", false);
+ m_IOFileSettings->rawDecodingSettings.caMultiplier[0] = config->readDoubleNumEntry("caRedMultiplier", 1.0);
+ m_IOFileSettings->rawDecodingSettings.caMultiplier[1] = config->readDoubleNumEntry("caBlueMultiplier", 1.0);
+ m_IOFileSettings->rawDecodingSettings.brightness = config->readDoubleNumEntry("RAWBrightness", 1.0);
+ m_IOFileSettings->rawDecodingSettings.medianFilterPasses = config->readNumEntry("MedianFilterPasses", 0);
+
+ m_IOFileSettings->useRAWImport = config->readBoolEntry("UseRawImportTool", false);
+
+ // -- GUI Settings -------------------------------------------------------
+
+ TQSizePolicy rightSzPolicy(TQSizePolicy::Preferred, TQSizePolicy::Expanding, 2, 1);
+ if(config->hasKey("Splitter Sizes"))
+ m_splitter->setSizes(config->readIntListEntry("Splitter Sizes"));
+ else
+ m_canvas->setSizePolicy(rightSzPolicy);
+
+ d->fullScreenHideToolBar = config->readBoolEntry("FullScreen Hide ToolBar", false);
+
+ slotThemeChanged();
+
+ // -- Exposure Indicators Settings ---------------------------------------
+
+ TQColor black(TQt::black);
+ TQColor white(TQt::white);
+ d->exposureSettings->underExposureIndicator = config->readBoolEntry("UnderExposureIndicator", false);
+ d->exposureSettings->overExposureIndicator = config->readBoolEntry("OverExposureIndicator", false);
+ d->exposureSettings->underExposureColor = config->readColorEntry("UnderExposureColor", &white);
+ d->exposureSettings->overExposureColor = config->readColorEntry("OverExposureColor", &black);
+
+ d->viewUnderExpoAction->setChecked(d->exposureSettings->underExposureIndicator);
+ d->viewOverExpoAction->setChecked(d->exposureSettings->overExposureIndicator);
+ d->underExposureIndicator->setOn(d->exposureSettings->underExposureIndicator);
+ d->overExposureIndicator->setOn(d->exposureSettings->overExposureIndicator);
+ setUnderExposureToolTip(d->exposureSettings->underExposureIndicator);
+ setOverExposureToolTip(d->exposureSettings->overExposureIndicator);
+ m_canvas->setExposureSettings(d->exposureSettings);
+}
+
+void EditorWindow::saveStandardSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("ImageViewer Settings");
+
+ config->writeEntry("AutoZoom", d->zoomFitToWindowAction->isChecked());
+ config->writeEntry("Splitter Sizes", m_splitter->sizes());
+
+ config->writeEntry("FullScreen", m_fullScreenAction->isChecked());
+ config->writeEntry("UnderExposureIndicator", d->exposureSettings->underExposureIndicator);
+ config->writeEntry("OverExposureIndicator", d->exposureSettings->overExposureIndicator);
+
+ config->sync();
+}
+
+/** Method used by Editor Tools. Only Zoom+ and Zoom- are currently supported.
+ TODO: Fix this behavour when editor tool preview widgets will be factored.
+ */
+void EditorWindow::toggleZoomActions(bool val)
+{
+ d->zoomMinusAction->setEnabled(val);
+ d->zoomPlusAction->setEnabled(val);
+}
+
+void EditorWindow::toggleStandardActions(bool val)
+{
+ d->zoomComboAction->setEnabled(val);
+ d->zoomTo100percents->setEnabled(val);
+ d->zoomFitToWindowAction->setEnabled(val);
+ d->zoomFitToSelectAction->setEnabled(val);
+ toggleZoomActions(val);
+
+ d->rotateLeftAction->setEnabled(val);
+ d->rotateRightAction->setEnabled(val);
+ d->flipHorizAction->setEnabled(val);
+ d->flipVertAction->setEnabled(val);
+ d->filePrintAction->setEnabled(val);
+ d->resizeAction->setEnabled(val);
+ m_fileDeleteAction->setEnabled(val);
+ m_saveAsAction->setEnabled(val);
+ d->selectAllAction->setEnabled(val);
+ d->selectNoneAction->setEnabled(val);
+ d->slideShowAction->setEnabled(val);
+
+ // these actions are special: They are turned off if val is false,
+ // but if val is true, they may be turned on or off.
+ if (val)
+ {
+ // Trigger sending of signalUndoStateChanged
+ // Note that for saving and loading, this is not necessary
+ // because the signal will be sent later anyway.
+ m_canvas->updateUndoState();
+ }
+ else
+ {
+ m_saveAction->setEnabled(val);
+ m_undoAction->setEnabled(val);
+ m_redoAction->setEnabled(val);
+ }
+
+ TQPtrList<ImagePlugin> pluginList = m_imagePluginLoader->pluginList();
+
+ for (ImagePlugin* plugin = pluginList.first();
+ plugin; plugin = pluginList.next())
+ {
+ if (plugin)
+ {
+ plugin->setEnabledActions(val);
+ }
+ }
+}
+
+void EditorWindow::slotToggleFullScreen()
+{
+ if (m_fullScreen) // out of fullscreen
+ {
+ m_canvas->setBackgroundColor(m_bgColor);
+
+ 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 (m_fullScreenAction->isPlugged(toolBar) && d->removeFullScreenButton)
+ m_fullScreenAction->unplug(toolBar);
+
+ if (toolBar->isHidden())
+ showToolBars();
+ }
+
+ // -- remove the gui action accels ----
+
+ unplugActionAccel(m_forwardAction);
+ unplugActionAccel(m_backwardAction);
+ unplugActionAccel(m_firstAction);
+ unplugActionAccel(m_lastAction);
+ unplugActionAccel(m_saveAction);
+ unplugActionAccel(m_saveAsAction);
+ unplugActionAccel(d->zoomPlusAction);
+ unplugActionAccel(d->zoomMinusAction);
+ unplugActionAccel(d->zoomFitToWindowAction);
+ unplugActionAccel(d->zoomFitToSelectAction);
+ unplugActionAccel(d->cropAction);
+ unplugActionAccel(d->filePrintAction);
+ unplugActionAccel(m_fileDeleteAction);
+ unplugActionAccel(d->selectAllAction);
+ unplugActionAccel(d->selectNoneAction);
+
+ toggleGUI2FullScreen();
+ m_fullScreen = false;
+ }
+ else // go to fullscreen
+ {
+ m_canvas->setBackgroundColor(TQColor(TQt::black));
+
+ // 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 ( !m_fullScreenAction->isPlugged(toolBar) )
+ {
+ m_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(m_forwardAction);
+ plugActionAccel(m_backwardAction);
+ plugActionAccel(m_firstAction);
+ plugActionAccel(m_lastAction);
+ plugActionAccel(m_saveAction);
+ plugActionAccel(m_saveAsAction);
+ plugActionAccel(d->zoomPlusAction);
+ plugActionAccel(d->zoomMinusAction);
+ plugActionAccel(d->zoomFitToWindowAction);
+ plugActionAccel(d->zoomFitToSelectAction);
+ plugActionAccel(d->cropAction);
+ plugActionAccel(d->filePrintAction);
+ plugActionAccel(m_fileDeleteAction);
+ plugActionAccel(d->selectAllAction);
+ plugActionAccel(d->selectNoneAction);
+
+ toggleGUI2FullScreen();
+ showFullScreen();
+ m_fullScreen = true;
+ }
+}
+
+void EditorWindow::slotRotatedOrFlipped()
+{
+ m_rotatedOrFlipped = true;
+}
+
+void EditorWindow::slotLoadingProgress(const TQString&, float progress)
+{
+ m_nameLabel->setProgressValue((int)(progress*100.0));
+}
+
+void EditorWindow::slotSavingProgress(const TQString&, float progress)
+{
+ m_nameLabel->setProgressValue((int)(progress*100.0));
+}
+
+bool EditorWindow::promptForOverWrite()
+{
+ TQFileInfo fi(m_canvas->currentImageFilePath());
+ TQString warnMsg(i18n("About to overwrite file \"%1\"\nAre you sure?")
+ .arg(fi.fileName()));
+ return (KMessageBox::warningContinueCancel(this,
+ warnMsg,
+ i18n("Warning"),
+ i18n("Overwrite"),
+ "editorWindowSaveOverwrite")
+ == KMessageBox::Continue);
+}
+
+bool EditorWindow::promptUserSave(const KURL& url)
+{
+ if (m_saveAction->isEnabled())
+ {
+ // if window is iconified, show it
+ if (isMinimized())
+ {
+ KWin::deIconifyWindow(winId());
+ }
+
+ int result = KMessageBox::warningYesNoCancel(this,
+ i18n("The image '%1' has been modified.\n"
+ "Do you want to save it?")
+ .arg(url.filename()),
+ TQString(),
+ KStdGuiItem::save(),
+ KStdGuiItem::discard());
+
+ if (result == KMessageBox::Yes)
+ {
+ bool saving = false;
+
+ if (m_canvas->isReadOnly())
+ saving = saveAs();
+ else if (promptForOverWrite())
+ saving = save();
+
+ // save and saveAs return false if they were cancelled and did not enter saving at all
+ // In this case, do not call enter_loop because exit_loop will not be called.
+ if (saving)
+ {
+ // Waiting for asynchronous image file saving operation runing in separate thread.
+ m_savingContext->synchronizingState = SavingContextContainer::SynchronousSaving;
+ enter_loop();
+ m_savingContext->synchronizingState = SavingContextContainer::NormalSaving;
+ return m_savingContext->synchronousSavingResult;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (result == KMessageBox::No)
+ {
+ m_saveAction->setEnabled(false);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool EditorWindow::waitForSavingToComplete()
+{
+ // avoid reentrancy - return false means we have reentered the loop already.
+ if (m_savingContext->synchronizingState == SavingContextContainer::SynchronousSaving)
+ return false;
+
+ if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
+ {
+ // Waiting for asynchronous image file saving operation runing in separate thread.
+ m_savingContext->synchronizingState = SavingContextContainer::SynchronousSaving;
+ KMessageBox::queuedMessageBox(this,
+ KMessageBox::Information,
+ i18n("Please wait while the image is being saved..."));
+ enter_loop();
+ m_savingContext->synchronizingState = SavingContextContainer::NormalSaving;
+ }
+ return true;
+}
+
+void EditorWindow::enter_loop()
+{
+ TQWidget dummy(0, 0, WType_Dialog | WShowModal);
+ dummy.setFocusPolicy( TQWidget::NoFocus );
+ tqt_enter_modal(&dummy);
+ tqApp->enter_loop();
+ tqt_leave_modal(&dummy);
+}
+
+void EditorWindow::slotSelected(bool val)
+{
+ // Update menu actions.
+ d->cropAction->setEnabled(val);
+ d->zoomFitToSelectAction->setEnabled(val);
+ d->copyAction->setEnabled(val);
+
+ for (ImagePlugin* plugin = m_imagePluginLoader->pluginList().first();
+ plugin; plugin = m_imagePluginLoader->pluginList().next())
+ {
+ if (plugin)
+ {
+ plugin->setEnabledSelectionActions(val);
+ }
+ }
+
+ TQRect sel = m_canvas->getSelectedArea();
+ // Update histogram into sidebar.
+ emit signalSelectionChanged(sel);
+
+ // Update status bar
+ if (val)
+ d->selectLabel->setText(TQString("(%1, %2) (%3 x %4)").arg(sel.x()).arg(sel.y())
+ .arg(sel.width()).arg(sel.height()));
+ else
+ d->selectLabel->setText(i18n("No selection"));
+}
+
+void EditorWindow::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 EditorWindow::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 EditorWindow::slotPrepareToLoad()
+{
+ // Disable actions as appropriate during loading
+ emit signalNoCurrentItem();
+ toggleActions(false);
+ slotUpdateItemInfo();
+}
+
+void EditorWindow::slotLoadingStarted(const TQString& /*filename*/)
+{
+ setCursor( KCursor::waitCursor() );
+
+ m_nameLabel->progressBarMode(StatusProgressBar::ProgressBarMode, i18n("Loading: "));
+}
+
+void EditorWindow::slotLoadingFinished(const TQString& filename, bool success)
+{
+ m_nameLabel->progressBarMode(StatusProgressBar::TextMode);
+ slotUpdateItemInfo();
+
+ // Enable actions as appropriate after loading
+ // No need to re-enable image properties sidebar here, it's will be done
+ // automatically by a signal from canvas
+ toggleActions(success);
+ unsetCursor();
+
+ // Note: in showfoto, we using a null filename to clear canvas.
+ if (!success && filename != TQString())
+ {
+ TQFileInfo fi(filename);
+ TQString message = i18n("Failed to load image \"%1\"").arg(fi.fileName());
+ KMessageBox::error(this, message);
+ DWarning() << "Failed to load image " << fi.fileName() << endl;
+ }
+}
+
+void EditorWindow::slotNameLabelCancelButtonPressed()
+{
+ // If we saving an image...
+ if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
+ {
+ m_savingContext->abortingSaving = true;
+ m_canvas->abortSaving();
+ }
+
+ // If we preparing SlideShow...
+ m_cancelSlideShow = true;
+}
+
+void EditorWindow::slotSave()
+{
+ if (m_canvas->isReadOnly())
+ saveAs();
+ else if (promptForOverWrite())
+ save();
+}
+
+void EditorWindow::slotSavingStarted(const TQString& /*filename*/)
+{
+ setCursor( KCursor::waitCursor() );
+
+ // Disable actions as appropriate during saving
+ emit signalNoCurrentItem();
+ toggleActions(false);
+
+ m_nameLabel->progressBarMode(StatusProgressBar::CancelProgressBarMode, i18n("Saving: "));
+}
+
+void EditorWindow::slotSavingFinished(const TQString& filename, bool success)
+{
+ if (m_savingContext->savingState == SavingContextContainer::SavingStateSave)
+ {
+ // from save()
+ m_savingContext->savingState = SavingContextContainer::SavingStateNone;
+
+ if (!success)
+ {
+ if (!m_savingContext->abortingSaving)
+ {
+ KMessageBox::error(this, i18n("Failed to save file\n\"%1\"\nto\n\"%2\".")
+ .arg(m_savingContext->destinationURL.filename())
+ .arg(m_savingContext->destinationURL.path()));
+ }
+ finishSaving(false);
+ return;
+ }
+
+ DDebug() << "renaming to " << m_savingContext->destinationURL.path() << endl;
+
+ if (!moveFile())
+ {
+ finishSaving(false);
+ return;
+ }
+
+ m_canvas->setUndoHistoryOrigin();
+
+ // remove image from cache since it has changed
+ LoadingCacheInterface::cleanFromCache(m_savingContext->destinationURL.path());
+ // this won't be in the cache, but does not hurt to do it anyway
+ LoadingCacheInterface::cleanFromCache(filename);
+
+ // restore state of disabled actions. saveIsComplete can start any other task
+ // (loading!) which might itself in turn change states
+ finishSaving(true);
+
+ saveIsComplete();
+
+ // Take all actions necessary to update information and re-enable sidebar
+ slotChanged();
+ }
+ else if (m_savingContext->savingState == SavingContextContainer::SavingStateSaveAs)
+ {
+ m_savingContext->savingState = SavingContextContainer::SavingStateNone;
+
+ // from saveAs()
+ if (!success)
+ {
+ if (!m_savingContext->abortingSaving)
+ {
+ KMessageBox::error(this, i18n("Failed to save file\n\"%1\"\nto\n\"%2\".")
+ .arg(m_savingContext->destinationURL.filename())
+ .arg(m_savingContext->destinationURL.path()));
+ }
+ finishSaving(false);
+ return;
+ }
+
+ // Only try to write exif if both src and destination are jpeg files
+
+ DDebug() << "renaming to " << m_savingContext->destinationURL.path() << endl;
+
+ if (!moveFile())
+ {
+ finishSaving(false);
+ return;
+ }
+
+ m_canvas->setUndoHistoryOrigin();
+
+ LoadingCacheInterface::cleanFromCache(m_savingContext->destinationURL.path());
+ LoadingCacheInterface::cleanFromCache(filename);
+
+ finishSaving(true);
+ saveAsIsComplete();
+
+ // Take all actions necessary to update information and re-enable sidebar
+ slotChanged();
+ }
+}
+
+void EditorWindow::finishSaving(bool success)
+{
+ m_savingContext->synchronousSavingResult = success;
+
+ if (m_savingContext->saveTempFile)
+ {
+ delete m_savingContext->saveTempFile;
+ m_savingContext->saveTempFile = 0;
+ }
+
+ // Exit of internal TQt event loop to unlock promptUserSave() method.
+ if (m_savingContext->synchronizingState == SavingContextContainer::SynchronousSaving)
+ tqApp->exit_loop();
+
+ // Enable actions as appropriate after saving
+ toggleActions(true);
+ unsetCursor();
+
+ m_nameLabel->progressBarMode(StatusProgressBar::TextMode);
+
+ // On error, continue using current image
+ if (!success)
+ {
+ m_canvas->switchToLastSaved(m_savingContext->srcURL.path());
+ }
+}
+
+void EditorWindow::startingSave(const KURL& url)
+{
+ // avoid any reentrancy. Should be impossible anyway since actions will be disabled.
+ if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
+ return;
+
+ if (!checkPermissions(url))
+ return;
+
+ m_savingContext->srcURL = url;
+ m_savingContext->destinationURL = m_savingContext->srcURL;
+ m_savingContext->destinationExisted = true;
+ m_savingContext->originalFormat = m_canvas->currentImageFileFormat();
+ m_savingContext->format = m_savingContext->originalFormat;
+ m_savingContext->abortingSaving = false;
+ m_savingContext->savingState = SavingContextContainer::SavingStateSave;
+ // use magic file extension which tells the digikamalbums ioslave to ignore the file
+ m_savingContext->saveTempFile = new KTempFile(m_savingContext->srcURL.directory(false),
+ ".digikamtempfile.tmp");
+ m_savingContext->saveTempFile->setAutoDelete(true);
+
+ m_canvas->saveAs(m_savingContext->saveTempFile->name(), m_IOFileSettings,
+ m_setExifOrientationTag && (m_rotatedOrFlipped || m_canvas->exifRotated()));
+}
+
+bool EditorWindow::startingSaveAs(const KURL& url)
+{
+ if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
+ return false;
+
+ TQString mimetypes = KImageIO::mimeTypes(KImageIO::Writing).join(" ");
+ mimetypes.append(" image/tiff");
+ DDebug () << "mimetypes=" << mimetypes << endl;
+
+ m_savingContext->srcURL = url;
+
+ FileSaveOptionsBox *options = new FileSaveOptionsBox();
+ KFileDialog imageFileSaveDialog(m_savingContext->srcURL.isLocalFile() ?
+ m_savingContext->srcURL.directory() : TQDir::homeDirPath(),
+ TQString(),
+ this,
+ "imageFileSaveDialog",
+ false,
+ options);
+
+ connect(&imageFileSaveDialog, TQ_SIGNAL(filterChanged(const TQString &)),
+ options, TQ_SLOT(slotImageFileFormatChanged(const TQString &)));
+
+ connect(&imageFileSaveDialog, TQ_SIGNAL(fileSelected(const TQString &)),
+ options, TQ_SLOT(slotImageFileSelected(const TQString &)));
+
+ ImageDialogPreview *preview = new ImageDialogPreview(&imageFileSaveDialog);
+ imageFileSaveDialog.setPreviewWidget(preview);
+ imageFileSaveDialog.setOperationMode(KFileDialog::Saving);
+ imageFileSaveDialog.setMode(KFile::File);
+ imageFileSaveDialog.setCaption(i18n("New Image File Name"));
+ imageFileSaveDialog.setFilter(mimetypes);
+
+ TQFileInfo info(m_savingContext->srcURL.fileName());
+ TDEConfig* config = kapp->config();
+ config->setGroup("ImageViewer Settings");
+ TQString ext = config->readEntry("LastSavedImageTypeMime", "png");
+ TQString fileName = info.baseName(false) + TQString(".") + ext;
+ imageFileSaveDialog.setSelection(fileName);
+
+ // Start dialog and check if canceled.
+ if ( imageFileSaveDialog.exec() != KFileDialog::Accepted )
+ return false;
+
+ // Update file save settings in editor instance.
+ options->applySettings();
+ applyStandardSettings();
+
+ KURL newURL = imageFileSaveDialog.selectedURL();
+
+ // Check if target image format have been selected from Combo List of SaveAs dialog.
+ m_savingContext->format = KImageIO::typeForMime(imageFileSaveDialog.currentMimeFilter());
+
+ if ( m_savingContext->format.isEmpty() )
+ {
+ // Else, check if target image format have been add to target image file name using extension.
+
+ TQFileInfo fi(newURL.path());
+ m_savingContext->format = fi.extension(false);
+
+ if ( m_savingContext->format.isEmpty() )
+ {
+ // If format is empty then file format is same as that of the original file.
+ m_savingContext->format = TQImageIO::imageFormat(m_savingContext->srcURL.path());
+ }
+ else
+ {
+ // Else, check if format from file name extension is include on file mime type list.
+
+ TQString imgExtPattern;
+ TQStringList imgExtList = TQStringList::split(" ", mimetypes);
+ for (TQStringList::ConstIterator it = imgExtList.begin() ; it != imgExtList.end() ; ++it)
+ {
+ imgExtPattern.append (KImageIO::typeForMime(*it).upper());
+ imgExtPattern.append (" ");
+ }
+ imgExtPattern.append (" TIF TIFF");
+ if ( imgExtPattern.contains("JPEG") )
+ {
+ imgExtPattern.append (" JPG");
+ imgExtPattern.append (" JPE");
+ }
+
+ if ( !imgExtPattern.contains( m_savingContext->format.upper() ) )
+ {
+ KMessageBox::error(this, i18n("Target image file format \"%1\" unsupported.")
+ .arg(m_savingContext->format));
+ DWarning() << k_funcinfo << "target image file format " << m_savingContext->format << " unsupported!" << endl;
+ return false;
+ }
+ }
+ }
+
+ if (!newURL.isValid())
+ {
+ KMessageBox::error(this, i18n("Failed to save file\n\"%1\" to\n\"%2\".")
+ .arg(newURL.filename())
+ .arg(newURL.path().section('/', -2, -2)));
+ DWarning() << k_funcinfo << "target URL is not valid !" << endl;
+ return false;
+ }
+
+ config->writeEntry("LastSavedImageTypeMime", m_savingContext->format);
+ config->sync();
+
+ // if new and original url are equal use slotSave() ------------------------------
+
+ KURL currURL(m_savingContext->srcURL);
+ currURL.cleanPath();
+ newURL.cleanPath();
+
+ if (currURL.equals(newURL))
+ {
+ slotSave();
+ return false;
+ }
+
+ // Check for overwrite ----------------------------------------------------------
+
+ TQFileInfo fi(newURL.path());
+ m_savingContext->destinationExisted = fi.exists();
+ if ( m_savingContext->destinationExisted )
+ {
+ int result =
+
+ KMessageBox::warningYesNo( this, i18n("A file named \"%1\" already "
+ "exists. Are you sure you want "
+ "to overwrite it?")
+ .arg(newURL.filename()),
+ i18n("Overwrite File?"),
+ i18n("Overwrite"),
+ KStdGuiItem::cancel() );
+
+ if (result != KMessageBox::Yes)
+ return false;
+
+ // There will be two message boxes if the file is not writable.
+ // This may be controversial, and it may be changed, but it was a deliberate decision.
+ if (!checkPermissions(newURL))
+ return false;
+ }
+
+ // Now do the actual saving -----------------------------------------------------
+
+ // use magic file extension which tells the digikamalbums ioslave to ignore the file
+ m_savingContext->saveTempFile = new KTempFile(newURL.directory(false), ".digikamtempfile.tmp");
+ m_savingContext->destinationURL = newURL;
+ m_savingContext->originalFormat = m_canvas->currentImageFileFormat();
+ m_savingContext->savingState = SavingContextContainer::SavingStateSaveAs;
+ m_savingContext->saveTempFile->setAutoDelete(true);
+ m_savingContext->abortingSaving = false;
+
+ m_canvas->saveAs(m_savingContext->saveTempFile->name(), m_IOFileSettings,
+ m_setExifOrientationTag && (m_rotatedOrFlipped || m_canvas->exifRotated()),
+ m_savingContext->format.lower());
+
+ return true;
+}
+
+bool EditorWindow::checkPermissions(const KURL& url)
+{
+ //TODO: Check that the permissions can actually be changed
+ // if write permissions are not available.
+
+ TQFileInfo fi(url.path());
+
+ if (fi.exists() && !fi.isWritable())
+ {
+ int result =
+
+ KMessageBox::warningYesNo( this, i18n("You do not have write permissions "
+ "for the file named \"%1\". "
+ "Are you sure you want "
+ "to overwrite it?")
+ .arg(url.filename()),
+ i18n("Overwrite File?"),
+ i18n("Overwrite"),
+ KStdGuiItem::cancel() );
+
+ if (result != KMessageBox::Yes)
+ return false;
+ }
+
+ return true;
+}
+
+bool EditorWindow::moveFile()
+{
+ TQCString dstFileName = TQFile::encodeName(m_savingContext->destinationURL.path());
+
+ // Store old permissions:
+ // Just get the current umask.
+ mode_t curr_umask = umask(S_IREAD | S_IWRITE);
+ // Restore the umask.
+ umask(curr_umask);
+
+ // For new files respect the umask setting.
+ mode_t filePermissions = (S_IREAD | S_IWRITE | S_IROTH | S_IWOTH | S_IRGRP | S_IWGRP) & ~curr_umask;
+
+ // For existing files, use the mode of the original file.
+ if (m_savingContext->destinationExisted)
+ {
+ struct stat stbuf;
+ if (::stat(dstFileName, &stbuf) == 0)
+ {
+ filePermissions = stbuf.st_mode;
+ }
+ }
+
+ // rename tmp file to dest
+ if (::rename(TQFile::encodeName(m_savingContext->saveTempFile->name()), dstFileName) != 0)
+ {
+ KMessageBox::error(this, i18n("Failed to overwrite original file"),
+ i18n("Error Saving File"));
+ return false;
+ }
+
+ // restore permissions
+ if (::chmod(dstFileName, filePermissions) != 0)
+ {
+ DWarning() << "Failed to restore file permissions for file " << dstFileName << endl;
+ }
+
+ return true;
+}
+
+void EditorWindow::slotToggleColorManagedView()
+{
+ d->cmViewIndicator->blockSignals(true);
+ d->viewCMViewAction->blockSignals(true);
+ bool cmv = false;
+ if (d->ICCSettings->enableCMSetting)
+ {
+ cmv = !d->ICCSettings->managedViewSetting;
+ d->ICCSettings->managedViewSetting = cmv;
+ m_canvas->setICCSettings(d->ICCSettings);
+
+ // Save Color Managed View setting in config file. For performance
+ // reason, no need to flush file, it cached in memory and will be flushed
+ // to disk at end of session.
+ TDEConfig* config = kapp->config();
+ config->setGroup("Color Management");
+ config->writeEntry("ManagedView", cmv);
+ }
+
+ d->cmViewIndicator->setOn(cmv);
+ d->viewCMViewAction->setChecked(cmv);
+ setColorManagedViewIndicatorToolTip(d->ICCSettings->enableCMSetting, cmv);
+ d->cmViewIndicator->blockSignals(false);
+ d->viewCMViewAction->blockSignals(false);
+}
+
+void EditorWindow::setColorManagedViewIndicatorToolTip(bool available, bool cmv)
+{
+ TQToolTip::remove(d->cmViewIndicator);
+ TQString tooltip;
+ if (available)
+ {
+ if (cmv)
+ tooltip = i18n("Color Managed View is enabled");
+ else
+ tooltip = i18n("Color Managed View is disabled");
+ }
+ else
+ {
+ tooltip = i18n("Color Management is not configured, so the Color Managed View is not available");
+ }
+ TQToolTip::add(d->cmViewIndicator, tooltip);
+}
+
+void EditorWindow::slotToggleUnderExposureIndicator()
+{
+ d->underExposureIndicator->blockSignals(true);
+ d->viewUnderExpoAction->blockSignals(true);
+ bool uei = !d->exposureSettings->underExposureIndicator;
+ d->underExposureIndicator->setOn(uei);
+ d->viewUnderExpoAction->setChecked(uei);
+ d->exposureSettings->underExposureIndicator = uei;
+ m_canvas->setExposureSettings(d->exposureSettings);
+ setUnderExposureToolTip(uei);
+ d->underExposureIndicator->blockSignals(false);
+ d->viewUnderExpoAction->blockSignals(false);
+}
+
+void EditorWindow::setUnderExposureToolTip(bool uei)
+{
+ TQToolTip::remove(d->underExposureIndicator);
+ TQToolTip::add(d->underExposureIndicator,
+ uei ? i18n("Under-Exposure indicator is enabled")
+ : i18n("Under-Exposure indicator is disabled"));
+}
+
+void EditorWindow::slotToggleOverExposureIndicator()
+{
+ d->overExposureIndicator->blockSignals(true);
+ d->viewOverExpoAction->blockSignals(true);
+ bool oei = !d->exposureSettings->overExposureIndicator;
+ d->overExposureIndicator->setOn(oei);
+ d->viewOverExpoAction->setChecked(oei);
+ d->exposureSettings->overExposureIndicator = oei;
+ m_canvas->setExposureSettings(d->exposureSettings);
+ setOverExposureToolTip(oei);
+ d->overExposureIndicator->blockSignals(false);
+ d->viewOverExpoAction->blockSignals(false);
+}
+
+void EditorWindow::setOverExposureToolTip(bool oei)
+{
+ TQToolTip::remove(d->overExposureIndicator);
+ TQToolTip::add(d->overExposureIndicator,
+ oei ? i18n("Over-Exposure indicator is enabled")
+ : i18n("Over-Exposure indicator is disabled"));
+}
+
+void EditorWindow::slotDonateMoney()
+{
+ TDEApplication::kApplication()->invokeBrowser("http://www.digikam.org/?q=donation");
+}
+
+void EditorWindow::slotContribute()
+{
+ TDEApplication::kApplication()->invokeBrowser("http://www.digikam.org/?q=contrib");
+}
+
+void EditorWindow::slotToggleSlideShow()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("ImageViewer Settings");
+ bool startWithCurrent = config->readBoolEntry("SlideShowStartCurrent", false);
+
+ SlideShowSettings settings;
+ 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 EditorWindow::slotSelectionChanged(const TQRect& sel)
+{
+ d->selectLabel->setText(TQString("(%1, %2) (%3 x %4)").arg(sel.x()).arg(sel.y())
+ .arg(sel.width()).arg(sel.height()));
+}
+
+void EditorWindow::slotRawCameraList()
+{
+ RawCameraDlg dlg(this);
+ dlg.exec();
+}
+
+void EditorWindow::slotThemeChanged()
+{
+ TQStringList themes(ThemeEngine::instance()->themeNames());
+ int index = themes.findIndex(ThemeEngine::instance()->getCurrentThemeName());
+ if (index == -1)
+ index = themes.findIndex(i18n("Default"));
+
+ m_themeMenuAction->setCurrentItem(index);
+
+ TDEConfig* config = kapp->config();
+ config->setGroup("ImageViewer Settings");
+
+ if (!config->readBoolEntry("UseThemeBackgroundColor", true))
+ m_bgColor = config->readColorEntry("BackgroundColor", &TQt::black);
+ else
+ m_bgColor = ThemeEngine::instance()->baseColor();
+
+ m_canvas->setBackgroundColor(m_bgColor);
+}
+
+void EditorWindow::slotChangeTheme(const TQString& theme)
+{
+ ThemeEngine::instance()->slotChangeTheme(theme);
+}
+
+void EditorWindow::setToolStartProgress(const TQString& toolName)
+{
+ m_nameLabel->setProgressValue(0);
+ m_nameLabel->progressBarMode(StatusProgressBar::CancelProgressBarMode, TQString("%1: ").arg(toolName));
+}
+
+void EditorWindow::setToolProgress(int progress)
+{
+ m_nameLabel->setProgressValue(progress);
+}
+
+void EditorWindow::setToolStopProgress()
+{
+ m_nameLabel->setProgressValue(0);
+ m_nameLabel->progressBarMode(StatusProgressBar::TextMode);
+ slotUpdateItemInfo();
+}
+
+
+void EditorWindow::slotShowMenuBar()
+{
+ if (menuBar()->isVisible())
+ menuBar()->hide();
+ else
+ menuBar()->show();
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/editor/editorwindow.h b/src/utilities/imageeditor/editor/editorwindow.h
new file mode 100644
index 00000000..cbb06221
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editorwindow.h
@@ -0,0 +1,263 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-20
+ * Description : main image editor GUI implementation
+ *
+ * Copyright (C) 2006-2009 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 EDITORWINDOW_H
+#define EDITORWINDOW_H
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqstring.h>
+#include <tqrect.h>
+
+// KDE includes.
+
+#include <tdemainwindow.h>
+#include <kurl.h>
+
+// Local includes.
+
+#include "sidebar.h"
+#include "digikam_export.h"
+
+class TQSplitter;
+class TQPopupMenu;
+class TQLabel;
+
+class TDEToolBarPopupAction;
+class TDEToggleAction;
+class TDEAction;
+class TDESelectAction;
+
+namespace Digikam
+{
+
+class Sidebar;
+class DPopupMenu;
+class Canvas;
+class ImagePluginLoader;
+class IOFileSettingsContainer;
+class SavingContextContainer;
+class StatusProgressBar;
+class SlideShowSettings;
+class EditorStackView;
+class EditorWindowPriv;
+
+class DIGIKAM_EXPORT EditorWindow : public TDEMainWindow
+{
+ TQ_OBJECT
+
+
+public:
+
+ EditorWindow(const char *name);
+ ~EditorWindow();
+
+ virtual void applySettings(){};
+ virtual bool setup(bool iccSetupPage=false)=0;
+
+signals:
+
+ void signalSelectionChanged( const TQRect & );
+ void signalNoCurrentItem();
+
+protected:
+
+ bool m_cancelSlideShow;
+ bool m_fullScreen;
+ bool m_rotatedOrFlipped;
+ bool m_setExifOrientationTag;
+
+ TQLabel *m_resLabel;
+
+ TQColor m_bgColor;
+
+ TQSplitter *m_splitter;
+
+ TDEAction *m_saveAction;
+ TDEAction *m_saveAsAction;
+ TDEAction *m_revertAction;
+ TDEAction *m_fileDeleteAction;
+ TDEAction *m_forwardAction;
+ TDEAction *m_backwardAction;
+ TDEAction *m_firstAction;
+ TDEAction *m_lastAction;
+
+ TDEToggleAction *m_fullScreenAction;
+
+ TDESelectAction *m_themeMenuAction;
+
+ TDEToolBarPopupAction *m_undoAction;
+ TDEToolBarPopupAction *m_redoAction;
+
+ DPopupMenu *m_contextMenu;
+ EditorStackView *m_stackView;
+ Canvas *m_canvas;
+ ImagePluginLoader *m_imagePluginLoader;
+ StatusProgressBar *m_nameLabel;
+ IOFileSettingsContainer *m_IOFileSettings;
+ SavingContextContainer *m_savingContext;
+
+protected:
+
+ void saveStandardSettings();
+ void readStandardSettings();
+ void applyStandardSettings();
+
+ void setupStandardConnections();
+ void setupStandardActions();
+ void setupStandardAccelerators();
+ void setupStatusBar();
+ void setupContextMenu();
+ void toggleStandardActions(bool val);
+ void toggleZoomActions(bool val);
+
+ void printImage(KURL url);
+
+ void plugActionAccel(TDEAction* action);
+ void unplugActionAccel(TDEAction* action);
+
+ void unLoadImagePlugins();
+ void loadImagePlugins();
+
+ bool promptForOverWrite();
+ bool promptUserSave(const KURL& url);
+ bool waitForSavingToComplete();
+ void startingSave(const KURL& url);
+ bool startingSaveAs(const KURL& url);
+ bool checkPermissions(const KURL& url);
+ bool moveFile();
+
+ EditorStackView* editorStackView() const;
+
+ virtual void finishSaving(bool success);
+
+ virtual void readSettings() { readStandardSettings(); };
+ virtual void saveSettings() { saveStandardSettings(); };
+ virtual void toggleActions(bool val) { toggleStandardActions(val); };
+ virtual void toggleGUI2FullScreen() {};
+
+ virtual void slideShow(bool startWithCurrent, SlideShowSettings& settings)=0;
+
+ virtual void setupConnections()=0;
+ virtual void setupActions()=0;
+ virtual void setupUserArea()=0;
+ virtual bool saveAs()=0;
+ virtual bool save()=0;
+
+ virtual void saveIsComplete()=0;
+ virtual void saveAsIsComplete()=0;
+
+ virtual Sidebar *rightSideBar() const=0;
+
+protected slots:
+
+ void slotSave();
+ void slotSaveAs() { saveAs(); };
+
+ void slotEditKeys();
+ void slotResize();
+
+ void slotAboutToShowUndoMenu();
+ void slotAboutToShowRedoMenu();
+
+ void slotConfToolbars();
+ void slotNewToolbarConfig();
+
+ void slotToggleFullScreen();
+ void slotEscapePressed();
+
+ void slotSelected(bool);
+
+ void slotLoadingProgress(const TQString& filePath, float progress);
+ void slotSavingProgress(const TQString& filePath, float progress);
+
+ void slotNameLabelCancelButtonPressed();
+
+ void slotThemeChanged();
+
+ virtual void slotLoadingStarted(const TQString& filename);
+ virtual void slotLoadingFinished(const TQString &filename, bool success);
+ virtual void slotSavingStarted(const TQString &filename);
+
+ virtual void slotSetup(){ setup(); };
+ virtual void slotChangeTheme(const TQString& theme);
+
+ virtual void slotFilePrint()=0;
+ virtual void slotDeleteCurrentItem()=0;
+ virtual void slotBackward()=0;
+ virtual void slotForward()=0;
+ virtual void slotFirst()=0;
+ virtual void slotLast()=0;
+ virtual void slotUpdateItemInfo()=0;
+ virtual void slotChanged()=0;
+ virtual void slotContextMenu()=0;
+ virtual void slotRevert()=0;
+
+private slots:
+
+ void slotToggleUnderExposureIndicator();
+ void slotToggleOverExposureIndicator();
+ void slotToggleColorManagedView();
+ void slotRotatedOrFlipped();
+ void slotSavingFinished(const TQString &filename, bool success);
+ void slotDonateMoney();
+ void slotContribute();
+ void slotToggleSlideShow();
+ void slotZoomTo100Percents();
+ void slotZoomSelected();
+ void slotZoomTextChanged(const TQString &);
+ void slotZoomChanged(bool isMax, bool isMin, double zoom);
+ void slotSelectionChanged(const TQRect& sel);
+ void slotToggleFitToWindow();
+ void slotToggleOffFitToWindow();
+ void slotFitToSelect();
+ void slotIncreaseZoom();
+ void slotDecreaseZoom();
+ void slotRawCameraList();
+ void slotPrepareToLoad();
+ void slotShowMenuBar();
+
+private:
+
+ void enter_loop();
+ void hideToolBars();
+ void showToolBars();
+ void setColorManagedViewIndicatorToolTip(bool available, bool cmv);
+ void setUnderExposureToolTip(bool uei);
+ void setOverExposureToolTip(bool oei);
+
+ void setToolStartProgress(const TQString& toolName);
+ void setToolProgress(int progress);
+ void setToolStopProgress();
+
+private:
+
+ EditorWindowPriv *d;
+
+ friend class EditorToolIface;
+};
+
+} // namespace Digikam
+
+#endif /* EDITORWINDOW_H */
diff --git a/src/utilities/imageeditor/editor/editorwindowprivate.h b/src/utilities/imageeditor/editor/editorwindowprivate.h
new file mode 100644
index 00000000..df07d0bd
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editorwindowprivate.h
@@ -0,0 +1,143 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-20
+ * Description : main image editor GUI implementation
+ * private data.
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef EDITORWINDOWPRIVATE_H
+#define EDITORWINDOWPRIVATE_H
+
+class TQToolButton;
+class TQLabel;
+
+class KComboBox;
+class TDEAction;
+class TDEToggleAction;
+class KWidgetAction;
+class TDESelectAction;
+class TDEActionMenu;
+class TDEAccel;
+
+namespace Digikam
+{
+
+class EditorToolIface;
+class ExposureSettingsContainer;
+class ICCSettingsContainer;
+
+class EditorWindowPriv
+{
+
+public:
+
+ EditorWindowPriv()
+ {
+ removeFullScreenButton = false;
+ fullScreenHideToolBar = false;
+ selectLabel = 0;
+ donateMoneyAction = 0;
+ accelerators = 0;
+ viewCMViewAction = 0;
+ filePrintAction = 0;
+ copyAction = 0;
+ resizeAction = 0;
+ cropAction = 0;
+ rotateLeftAction = 0;
+ rotateRightAction = 0;
+ flipHorizAction = 0;
+ flipVertAction = 0;
+ ICCSettings = 0;
+ exposureSettings = 0;
+ underExposureIndicator = 0;
+ overExposureIndicator = 0;
+ cmViewIndicator = 0;
+ viewUnderExpoAction = 0;
+ viewOverExpoAction = 0;
+ slideShowAction = 0;
+ zoomFitToWindowAction = 0;
+ zoomFitToSelectAction = 0;
+ zoomPlusAction = 0;
+ zoomMinusAction = 0;
+ zoomTo100percents = 0;
+ zoomCombo = 0;
+ zoomComboAction = 0;
+ selectAllAction = 0;
+ selectNoneAction = 0;
+ rawCameraListAction = 0;
+ contributeAction = 0;
+ toolIface = 0;
+ showMenuBarAction = 0;
+ }
+
+ ~EditorWindowPriv()
+ {
+ }
+
+ bool removeFullScreenButton;
+ bool fullScreenHideToolBar;
+
+ TQLabel *selectLabel;
+
+ TQToolButton *cmViewIndicator;
+ TQToolButton *underExposureIndicator;
+ TQToolButton *overExposureIndicator;
+
+ TDEAction *rawCameraListAction;
+ TDEAction *donateMoneyAction;
+ TDEAction *contributeAction;
+ TDEAction *filePrintAction;
+ TDEAction *copyAction;
+ TDEAction *resizeAction;
+ TDEAction *cropAction;
+ TDEAction *zoomPlusAction;
+ TDEAction *zoomMinusAction;
+ TDEAction *zoomTo100percents;
+ TDEAction *zoomFitToSelectAction;
+ TDEAction *rotateLeftAction;
+ TDEAction *rotateRightAction;
+ TDEAction *flipHorizAction;
+ TDEAction *flipVertAction;
+ TDEAction *slideShowAction;
+ TDEAction *selectAllAction;
+ TDEAction *selectNoneAction;
+
+ TDEToggleAction *zoomFitToWindowAction;
+ TDEToggleAction *viewCMViewAction;
+ TDEToggleAction *viewUnderExpoAction;
+ TDEToggleAction *viewOverExpoAction;
+ TDEToggleAction *showMenuBarAction;
+
+ KWidgetAction *zoomComboAction;
+
+ KComboBox *zoomCombo;
+
+ TDEAccel *accelerators;
+
+ ICCSettingsContainer *ICCSettings;
+
+ ExposureSettingsContainer *exposureSettings;
+
+ EditorToolIface *toolIface;
+};
+
+} // NameSpace Digikam
+
+#endif /* EDITORWINDOWPRIVATE_H */
diff --git a/src/utilities/imageeditor/editor/imageiface.cpp b/src/utilities/imageeditor/editor/imageiface.cpp
new file mode 100644
index 00000000..56cb559c
--- /dev/null
+++ b/src/utilities/imageeditor/editor/imageiface.cpp
@@ -0,0 +1,444 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-02-14
+ * Description : image data interface for image plugins
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2009 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 <tqwidget.h>
+#include <tqsize.h>
+#include <tqpixmap.h>
+#include <tqbitmap.h>
+#include <tqpainter.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "exposurecontainer.h"
+#include "iccsettingscontainer.h"
+#include "icctransform.h"
+#include "dimginterface.h"
+#include "bcgmodifier.h"
+#include "dmetadata.h"
+#include "imageiface.h"
+
+namespace Digikam
+{
+
+class ImageIfacePriv
+{
+public:
+
+ ImageIfacePriv()
+ {
+ usePreviewSelection = false;
+ previewWidth = 0;
+ previewHeight = 0;
+ }
+
+ bool usePreviewSelection;
+
+ int originalWidth;
+ int originalHeight;
+ int originalBytesDepth;
+
+ int constrainWidth;
+ int constrainHeight;
+
+ int previewWidth;
+ int previewHeight;
+
+ TQPixmap qcheck;
+ TQPixmap qpix;
+ TQBitmap qmask;
+
+ DImg previewImage;
+ DImg targetPreviewImage;
+};
+
+ImageIface::ImageIface(int w, int h)
+{
+ d = new ImageIfacePriv;
+
+ d->constrainWidth = w;
+ d->constrainHeight = h;
+
+ d->originalWidth = DImgInterface::defaultInterface()->origWidth();
+ d->originalHeight = DImgInterface::defaultInterface()->origHeight();
+ d->originalBytesDepth = DImgInterface::defaultInterface()->bytesDepth();
+
+ d->qpix.setMask(d->qmask);
+ d->qcheck.resize(8, 8);
+
+ TQPainter p;
+ p.begin(&d->qcheck);
+ p.fillRect(0, 0, 4, 4, TQColor(144,144,144));
+ p.fillRect(4, 4, 4, 4, TQColor(144,144,144));
+ p.fillRect(0, 4, 4, 4, TQColor(100,100,100));
+ p.fillRect(4, 0, 4, 4, TQColor(100,100,100));
+ p.end();
+}
+
+ImageIface::~ImageIface()
+{
+ delete d;
+}
+
+void ImageIface::setPreviewType(bool useSelect)
+{
+ d->usePreviewSelection = useSelect;
+}
+
+bool ImageIface::previewType()
+{
+ return d->usePreviewSelection;
+}
+
+DColor ImageIface::getColorInfoFromOriginalImage(const TQPoint& point)
+{
+ if ( !DImgInterface::defaultInterface()->getImage() || point.x() > originalWidth() || point.y() > originalHeight() )
+ {
+ DWarning() << k_funcinfo << "Coordinate out of range or no image data available!" << endl;
+ return DColor();
+ }
+
+ return DImgInterface::defaultInterface()->getImg()->getPixelColor(point.x(), point.y());
+}
+
+DColor ImageIface::getColorInfoFromPreviewImage(const TQPoint& point)
+{
+ if ( d->previewImage.isNull() || point.x() > previewWidth() || point.y() > previewHeight() )
+ {
+ DWarning() << k_funcinfo << "Coordinate out of range or no image data available!" << endl;
+ return DColor();
+ }
+
+ return d->previewImage.getPixelColor(point.x(), point.y());
+}
+
+DColor ImageIface::getColorInfoFromTargetPreviewImage(const TQPoint& point)
+{
+ if ( d->targetPreviewImage.isNull() || point.x() > previewWidth() || point.y() > previewHeight() )
+ {
+ DWarning() << k_funcinfo << "Coordinate out of range or no image data available!" << endl;
+ return DColor();
+ }
+
+ return d->targetPreviewImage.getPixelColor(point.x(), point.y());
+}
+
+uchar* ImageIface::setPreviewImageSize(int w, int h) const
+{
+ d->previewImage.reset();
+ d->targetPreviewImage.reset();
+
+ d->constrainWidth = w;
+ d->constrainHeight = h;
+
+ return (getPreviewImage());
+}
+
+uchar* ImageIface::getPreviewImage() const
+{
+ if (d->previewImage.isNull())
+ {
+ DImg *im = 0;
+
+ if (!d->usePreviewSelection)
+ {
+ im = DImgInterface::defaultInterface()->getImg();
+ if (!im || im->isNull())
+ return 0;
+ }
+ else
+ {
+ int x, y, w, h;
+ bool s = DImgInterface::defaultInterface()->sixteenBit();
+ bool a = DImgInterface::defaultInterface()->hasAlpha();
+ uchar *data = DImgInterface::defaultInterface()->getImageSelection();
+ DImgInterface::defaultInterface()->getSelectedArea(x, y, w, h);
+ im = new DImg(w, h, s, a, data, true);
+ delete [] data;
+
+ if (!im)
+ return 0;
+
+ if (im->isNull())
+ {
+ delete im;
+ return 0;
+ }
+ }
+
+ TQSize sz(im->width(), im->height());
+ sz.scale(d->constrainWidth, d->constrainHeight, TQSize::ScaleMin);
+
+ d->previewImage = im->smoothScale(sz.width(), sz.height());
+ d->previewWidth = d->previewImage.width();
+ d->previewHeight = d->previewImage.height();
+
+ // only create another copy if needed, in putPreviewImage
+ d->targetPreviewImage = d->previewImage;
+
+ d->qmask.resize(d->previewWidth, d->previewHeight);
+ d->qpix.resize(d->previewWidth, d->previewHeight);
+
+ if (d->usePreviewSelection)
+ delete im;
+ }
+
+ DImg previewData = d->previewImage.copyImageData();
+ return previewData.stripImageData();
+}
+
+uchar* ImageIface::getOriginalImage() const
+{
+ DImg *im = DImgInterface::defaultInterface()->getImg();
+
+ if (!im || im->isNull())
+ return 0;
+
+ DImg origData = im->copyImageData();
+ return origData.stripImageData();
+}
+
+DImg* ImageIface::getOriginalImg() const
+{
+ return DImgInterface::defaultInterface()->getImg();
+}
+
+uchar* ImageIface::getImageSelection() const
+{
+ return DImgInterface::defaultInterface()->getImageSelection();
+}
+
+void ImageIface::putPreviewImage(uchar* data)
+{
+ if (!data)
+ return;
+
+ if (d->targetPreviewImage == d->previewImage)
+ {
+ d->targetPreviewImage = DImg(d->previewImage.width(), d->previewImage.height(),
+ d->previewImage.sixteenBit(), d->previewImage.hasAlpha(), data);
+ d->targetPreviewImage.setICCProfil( d->previewImage.getICCProfil() );
+ }
+ else
+ {
+ d->targetPreviewImage.putImageData(data);
+ }
+}
+
+void ImageIface::putOriginalImage(const TQString &caller, uchar* data, int w, int h)
+{
+ if (!data)
+ return;
+
+ DImgInterface::defaultInterface()->putImage(caller, data, w, h);
+}
+
+void ImageIface::setEmbeddedICCToOriginalImage(const TQString& profilePath)
+{
+ DImgInterface::defaultInterface()->setEmbeddedICCToOriginalImage( profilePath );
+}
+
+void ImageIface::putImageSelection(const TQString &caller, uchar* data)
+{
+ if (!data)
+ return;
+
+ DImgInterface::defaultInterface()->putImageSelection(caller, data);
+}
+
+int ImageIface::previewWidth()
+{
+ return d->previewWidth;
+}
+
+int ImageIface::previewHeight()
+{
+ return d->previewHeight;
+}
+
+bool ImageIface::previewSixteenBit()
+{
+ return originalSixteenBit();
+}
+
+bool ImageIface::previewHasAlpha()
+{
+ return originalHasAlpha();
+}
+
+int ImageIface::originalWidth()
+{
+ return DImgInterface::defaultInterface()->origWidth();
+}
+
+int ImageIface::originalHeight()
+{
+ return DImgInterface::defaultInterface()->origHeight();
+}
+
+bool ImageIface::originalSixteenBit()
+{
+ return DImgInterface::defaultInterface()->sixteenBit();
+}
+
+bool ImageIface::originalHasAlpha()
+{
+ return DImgInterface::defaultInterface()->hasAlpha();
+}
+
+int ImageIface::selectedWidth()
+{
+ int x, y, w, h;
+ DImgInterface::defaultInterface()->getSelectedArea(x, y, w, h);
+ return w;
+}
+
+int ImageIface::selectedHeight()
+{
+ int x, y, w, h;
+ DImgInterface::defaultInterface()->getSelectedArea(x, y, w, h);
+ return h;
+}
+
+int ImageIface::selectedXOrg()
+{
+ int x, y, w, h;
+ DImgInterface::defaultInterface()->getSelectedArea(x, y, w, h);
+ return x;
+}
+
+int ImageIface::selectedYOrg()
+{
+ int x, y, w, h;
+ DImgInterface::defaultInterface()->getSelectedArea(x, y, w, h);
+ return y;
+}
+
+void ImageIface::setPreviewBCG(double brightness, double contrast, double gamma)
+{
+ DImg preview = d->targetPreviewImage.copyImageData();
+ BCGModifier cmod;
+ cmod.setGamma(gamma);
+ cmod.setBrightness(brightness);
+ cmod.setContrast(contrast);
+ cmod.applyBCG(preview);
+ putPreviewImage(preview.bits());
+}
+
+void ImageIface::setOriginalBCG(double brightness, double contrast, double gamma)
+{
+ DImgInterface::defaultInterface()->setBCG(brightness, contrast, gamma);
+}
+
+void ImageIface::convertOriginalColorDepth(int depth)
+{
+ DImgInterface::defaultInterface()->convertDepth(depth);
+}
+
+TQPixmap ImageIface::convertToPixmap(DImg& img)
+{
+ return DImgInterface::defaultInterface()->convertToPixmap(img);
+}
+
+TQByteArray ImageIface::getEmbeddedICCFromOriginalImage()
+{
+ return DImgInterface::defaultInterface()->getEmbeddedICC();
+}
+
+TQByteArray ImageIface::getExifFromOriginalImage()
+{
+ return DImgInterface::defaultInterface()->getExif();
+}
+
+TQByteArray ImageIface::getIptcFromOriginalImage()
+{
+ return DImgInterface::defaultInterface()->getIptc();
+}
+
+PhotoInfoContainer ImageIface::getPhotographInformations() const
+{
+ DMetadata meta;
+ meta.setExif(DImgInterface::defaultInterface()->getExif());
+ meta.setIptc(DImgInterface::defaultInterface()->getIptc());
+ return meta.getPhotographInformations();
+}
+
+void ImageIface::paint(TQPaintDevice* device, int x, int y, int w, int h,
+ bool underExposure, bool overExposure)
+{
+ if ( !d->targetPreviewImage.isNull() )
+ {
+ if (d->targetPreviewImage.hasAlpha())
+ {
+ TQPainter p(&d->qpix);
+ p.drawTiledPixmap(0, 0, d->qpix.width(), d->qpix.height(), d->qcheck);
+ p.end();
+ }
+
+ TQPixmap pixImage;
+ ICCSettingsContainer *iccSettings = DImgInterface::defaultInterface()->getICCSettings();
+
+ if (iccSettings)
+ {
+ IccTransform monitorICCtrans;
+ monitorICCtrans.setProfiles(iccSettings->workspaceSetting, iccSettings->monitorSetting);
+
+ if (iccSettings->enableCMSetting && iccSettings->managedViewSetting)
+ {
+ pixImage = d->targetPreviewImage.convertToPixmap(&monitorICCtrans);
+ }
+ else
+ {
+ pixImage = d->targetPreviewImage.convertToPixmap();
+ }
+ }
+ else
+ {
+ pixImage = d->targetPreviewImage.convertToPixmap();
+ }
+
+ bitBlt(&d->qpix, 0, 0, static_cast<TQPaintDevice*>(&pixImage), 0, 0, w, h, TQt::CopyROP, false);
+
+ // Show the Over/Under exposure pixels indicators
+
+ if (underExposure || overExposure)
+ {
+ ExposureSettingsContainer expoSettings;
+ expoSettings.underExposureIndicator = underExposure;
+ expoSettings.overExposureIndicator = overExposure;
+ expoSettings.underExposureColor = DImgInterface::defaultInterface()->underExposureColor();
+ expoSettings.overExposureColor = DImgInterface::defaultInterface()->overExposureColor();
+
+ TQImage pureColorMask = d->targetPreviewImage.pureColorMask(&expoSettings);
+ TQPixmap pixMask(pureColorMask);
+ bitBlt(&d->qpix, 0, 0, static_cast<TQPaintDevice*>(&pixMask), 0, 0, w, h, TQt::CopyROP, false);
+ }
+ }
+
+ bitBlt(device, x, y, static_cast<TQPaintDevice*>(&d->qpix), 0, 0, -1, -1, TQt::CopyROP, false);
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/editor/imageiface.h b/src/utilities/imageeditor/editor/imageiface.h
new file mode 100644
index 00000000..272c62a5
--- /dev/null
+++ b/src/utilities/imageeditor/editor/imageiface.h
@@ -0,0 +1,198 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-02-14
+ * Description : image data interface for image plugins
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2009 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 IMAGEIFACE_H
+#define IMAGEIFACE_H
+
+// TQt includes.
+
+#include <tqglobal.h>
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "dcolor.h"
+#include "photoinfocontainer.h"
+#include "digikam_export.h"
+
+#define MAX3(a, b, c) (TQMAX(TQMAX(a,b),b))
+#define MIN3(a, b, c) (TQMIN(TQMIN(a,b),b))
+#define ROUND(x) ((int) ((x) + 0.5))
+
+class TQPaintDevice;
+
+namespace Digikam
+{
+
+class ImageIfacePriv;
+
+class DIGIKAM_EXPORT ImageIface
+{
+public:
+
+ ImageIface(int w=0, int h=0);
+ ~ImageIface();
+
+ /** Use this method to use the current selection in editor instead the full
+ image to render the preview.
+ */
+ void setPreviewType(bool useSelect=false);
+
+ /** Return 'true' if the preview is rendered using the current selection in editor.
+ Return 'false' if the preview is rendered using the full image in editor.
+ */
+ bool previewType();
+
+ /** Return image data for the current, scaled preview image.
+ The preview...() methods provide the characteristics of the data
+ (width, heigh, sixteen bit, alpha).
+ Ownership of the returned buffer is passed to the caller.
+ */
+ uchar* getPreviewImage() const;
+
+ /** Return image data for the current original image selection.
+ The selectionWidth(), selectionHeight(), originalSixteenBit()
+ and originalHasAlpha() methods provide the characteristics of the data.
+ Ownership of the returned buffer is passed to the caller.
+ */
+ uchar* getImageSelection() const;
+
+ /** Return image data for the original image.
+ The preview...() methods provide the characteristics of the data.
+ Ownership of the returned buffer is passed to the caller.
+ */
+ uchar* getOriginalImage() const;
+
+ /** Return a pointer to the DImg object representing the original image.
+ This object may not be modified or stored. Make copies if you need.
+ */
+ DImg* getOriginalImg() const;
+
+ /** Replace the image data of the original image with the given data.
+ The characteristics of the data must match the characteristics of
+ the original image as returned by the original...() methods,
+ respectively the given width and height parameters.
+ No ownership of the data pointer is assumed.
+ If w == -1 and h == -1, the size is unchanged.
+ Caller is an i18n'ed string that will be shown as the undo/redo action name.
+ */
+ void putOriginalImage(const TQString &caller, uchar* data, int w=-1, int h=-1);
+
+ /** Embed the Color Profile we have used in ICC plugin when this option is
+ selected
+ */
+ void setEmbeddedICCToOriginalImage(const TQString& profilePath);
+
+ /** Replace the data of the current original image selection with the given data.
+ The characteristics of the data must match the characteristics of the current
+ selection as returned by the selectionWidth(), selectionHeight(),
+ originalSixteenBit() and originalHasAlpha() methods.
+ No ownership of the data pointer is assumed.
+ Caller is an i18n'ed string that will be shown as the undo/redo action name.
+ */
+ void putImageSelection(const TQString &caller, uchar* data);
+
+ /** Replace the stored target preview data with the given data.
+ The characteristics of the data must match the characteristics of the current
+ as returned by the preview...() methods.
+ The target preview data is used by the paint() and
+ getColorInfoFromTargetPreviewImage() methods.
+ The data returned by getPreviewImage() is unaffected.
+ No ownership of the data pointer is assumed.
+ */
+ void putPreviewImage(uchar* data);
+
+ /** Get colors from original, (unchanged) preview
+ or target preview (set by putPreviewImage) image.
+ */
+
+ DColor getColorInfoFromOriginalImage(const TQPoint& point);
+ DColor getColorInfoFromPreviewImage(const TQPoint& point);
+ DColor getColorInfoFromTargetPreviewImage(const TQPoint& point);
+
+ /** Original image information.*/
+ int originalWidth();
+ int originalHeight();
+ bool originalSixteenBit();
+ bool originalHasAlpha();
+
+ /** Original image metadata.*/
+ TQByteArray getEmbeddedICCFromOriginalImage();
+ TQByteArray getExifFromOriginalImage();
+ TQByteArray getIptcFromOriginalImage();
+
+ /** Get photograph information from original image.*/
+ PhotoInfoContainer getPhotographInformations() const;
+
+ /** Standard methods to get/set preview information.*/
+ int previewWidth();
+ int previewHeight();
+ bool previewHasAlpha();
+ bool previewSixteenBit();
+
+ /** Sets preview size and returns new preview data as with getPreviewImage.
+ The parameters are only hints, previewWidth() and previewHeight()
+ may differ from w and h.
+ */
+ uchar* setPreviewImageSize(int w, int h) const;
+
+ /** Standard methods to get image selection information.*/
+ int selectedWidth();
+ int selectedHeight();
+
+ /** Get selected (X, Y) position on the top/left corner of the original image.*/
+ int selectedXOrg();
+ int selectedYOrg();
+
+ /** Set BCG correction for preview and original image */
+ void setPreviewBCG(double brightness, double contrast, double gamma);
+ void setOriginalBCG(double brightness, double contrast, double gamma);
+
+ /** Convert depth of original image */
+ void convertOriginalColorDepth(int depth);
+
+ /** Convert a DImg image to a pixmap for screen using color
+ managemed view if necessary */
+ TQPixmap convertToPixmap(DImg& img);
+
+ /** Paint the current target preview image (or the preview image,
+ if putPreviewImage has not been called) on the given paint device.
+ at x|y, with given maximum width and height.
+ */
+ void paint(TQPaintDevice* device, int x, int y, int w, int h,
+ bool underExposure=false, bool overExposure=false);
+
+private:
+
+ ImageIfacePriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* IMAGEIFACE_H */
diff --git a/src/utilities/imageeditor/editor/imagewindow.cpp b/src/utilities/imageeditor/editor/imagewindow.cpp
new file mode 100644
index 00000000..2c10a6f6
--- /dev/null
+++ b/src/utilities/imageeditor/editor/imagewindow.cpp
@@ -0,0 +1,1263 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-02-12
+ * Description : digiKam image editor GUI
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-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.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstdio>
+
+// TQt includes.
+
+#include <tqcursor.h>
+#include <tqtimer.h>
+#include <tqlabel.h>
+#include <tqimage.h>
+#include <tqsplitter.h>
+#include <tqpainter.h>
+#include <tqpixmap.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <tdeconfig.h>
+#include <kstandarddirs.h>
+#include <tdeapplication.h>
+#include <tdemessagebox.h>
+#include <tdetempfile.h>
+#include <kimageio.h>
+#include <tdefiledialog.h>
+#include <tdeversion.h>
+#include <tdemenubar.h>
+#include <tdetoolbar.h>
+#include <tdeaccel.h>
+#include <tdeaction.h>
+#include <tdestdaccel.h>
+#include <kstdaction.h>
+#include <kstdguiitem.h>
+#include <kstatusbar.h>
+#include <kprogress.h>
+#include <twin.h>
+
+// Local includes.
+
+#include "constants.h"
+#include "ddebug.h"
+#include "dlogoaction.h"
+#include "dpopupmenu.h"
+#include "dragobjects.h"
+#include "canvas.h"
+#include "dimginterface.h"
+#include "dimg.h"
+#include "dmetadata.h"
+#include "imageplugin.h"
+#include "imagepluginloader.h"
+#include "imageprint.h"
+#include "albummanager.h"
+#include "album.h"
+#include "albumdb.h"
+#include "albumsettings.h"
+#include "syncjob.h"
+#include "imageinfo.h"
+#include "imagepropertiessidebardb.h"
+#include "tagspopupmenu.h"
+#include "ratingpopupmenu.h"
+#include "slideshow.h"
+#include "setup.h"
+#include "iccsettingscontainer.h"
+#include "iofilesettingscontainer.h"
+#include "loadingcacheinterface.h"
+#include "savingcontextcontainer.h"
+#include "statusprogressbar.h"
+#include "imageattributeswatch.h"
+#include "deletedialog.h"
+#include "metadatahub.h"
+#include "themeengine.h"
+#include "editorstackview.h"
+#include "imagewindow.h"
+#include "imagewindow.moc"
+
+namespace Digikam
+{
+
+class ImageWindowPriv
+{
+
+public:
+
+ ImageWindowPriv()
+ {
+ allowSaving = true;
+ star0 = 0;
+ star1 = 0;
+ star2 = 0;
+ star3 = 0;
+ star4 = 0;
+ star5 = 0;
+ fileDeletePermanentlyAction = 0;
+ fileDeletePermanentlyDirectlyAction = 0;
+ fileTrashDirectlyAction = 0;
+ imageInfoCurrent = 0;
+ rightSidebar = 0;
+ }
+
+ // If image editor is launched by camera interface, current
+ // image cannot be saved.
+ bool allowSaving;
+
+ KURL::List urlList;
+ KURL urlCurrent;
+
+ // Rating actions.
+ TDEAction *star0;
+ TDEAction *star1;
+ TDEAction *star2;
+ TDEAction *star3;
+ TDEAction *star4;
+ TDEAction *star5;
+
+ // Delete actions
+ TDEAction *fileDeletePermanentlyAction;
+ TDEAction *fileDeletePermanentlyDirectlyAction;
+ TDEAction *fileTrashDirectlyAction;
+
+ ImageInfoList imageInfoList;
+ ImageInfo *imageInfoCurrent;
+
+ ImagePropertiesSideBarDB *rightSidebar;
+};
+
+ImageWindow* ImageWindow::m_instance = 0;
+
+ImageWindow* ImageWindow::imagewindow()
+{
+ if (!m_instance)
+ new ImageWindow();
+
+ return m_instance;
+}
+
+bool ImageWindow::imagewindowCreated()
+{
+ return m_instance;
+}
+
+ImageWindow::ImageWindow()
+ : EditorWindow( "Image Editor" )
+{
+ d = new ImageWindowPriv;
+ m_instance = this;
+ setAcceptDrops(true);
+
+ // -- Build the GUI -------------------------------
+
+ setupUserArea();
+ setupStatusBar();
+ setupActions();
+
+ // Load image plugins to GUI
+
+ m_imagePluginLoader = ImagePluginLoader::instance();
+ loadImagePlugins();
+
+ // Create context menu.
+
+ setupContextMenu();
+
+ // Make signals/slots connections
+
+ setupConnections();
+
+ // -- Read settings --------------------------------
+
+ readSettings();
+ applySettings();
+ setAutoSaveSettings("ImageViewer Settings");
+
+ //-------------------------------------------------------------
+
+ d->rightSidebar->loadViewState();
+ d->rightSidebar->populateTags();
+}
+
+ImageWindow::~ImageWindow()
+{
+ m_instance = 0;
+
+ unLoadImagePlugins();
+
+ // No need to delete m_imagePluginLoader instance here, it will be done by main interface.
+
+ delete d->rightSidebar;
+ delete d;
+}
+
+Sidebar* ImageWindow::rightSideBar() const
+{
+ return dynamic_cast<Sidebar*>(d->rightSidebar);
+}
+
+void ImageWindow::closeEvent(TQCloseEvent* e)
+{
+ if (!e)
+ return;
+
+ if (!queryClose())
+ return;
+
+ // put right side bar in a defined state
+ emit signalNoCurrentItem();
+
+ m_canvas->resetImage();
+
+ saveSettings();
+
+ e->accept();
+}
+
+bool ImageWindow::queryClose()
+{
+ // Note: we reimplement closeEvent above for this window.
+ // Additionally, queryClose is called from DigikamApp.
+
+ // wait if a save operation is currently running
+ if (!waitForSavingToComplete())
+ return false;
+
+ return promptUserSave(d->urlCurrent);
+}
+
+void ImageWindow::setupConnections()
+{
+ setupStandardConnections();
+
+ // To toggle properly keyboards shortcuts from comments & tags side bar tab.
+
+ connect(d->rightSidebar, TQ_SIGNAL(signalNextItem()),
+ this, TQ_SLOT(slotForward()));
+
+ connect(d->rightSidebar, TQ_SIGNAL(signalPrevItem()),
+ this, TQ_SLOT(slotBackward()));
+
+ connect(this, TQ_SIGNAL(signalSelectionChanged( const TQRect &)),
+ d->rightSidebar, TQ_SLOT(slotImageSelectionChanged( const TQRect &)));
+
+ connect(this, TQ_SIGNAL(signalNoCurrentItem()),
+ d->rightSidebar, TQ_SLOT(slotNoCurrentItem()));
+
+ ImageAttributesWatch *watch = ImageAttributesWatch::instance();
+
+ connect(watch, TQ_SIGNAL(signalFileMetadataChanged(const KURL &)),
+ this, TQ_SLOT(slotFileMetadataChanged(const KURL &)));
+}
+
+void ImageWindow::setupUserArea()
+{
+ TQWidget* widget = new TQWidget(this);
+ TQHBoxLayout *lay = new TQHBoxLayout(widget);
+
+ m_splitter = new TQSplitter(widget);
+ m_stackView = new EditorStackView(m_splitter);
+ m_canvas = new Canvas(m_stackView);
+ m_stackView->setCanvas(m_canvas);
+ m_stackView->setViewMode(EditorStackView::CanvasMode);
+
+ m_canvas->makeDefaultEditingCanvas();
+
+ TQSizePolicy rightSzPolicy(TQSizePolicy::Preferred, TQSizePolicy::Expanding, 2, 1);
+ m_canvas->setSizePolicy(rightSzPolicy);
+
+ d->rightSidebar = new ImagePropertiesSideBarDB(widget, "ImageEditor Right Sidebar", m_splitter,
+ Sidebar::Right, true);
+ lay->addWidget(m_splitter);
+ lay->addWidget(d->rightSidebar);
+
+ m_splitter->setFrameStyle( TQFrame::NoFrame );
+ m_splitter->setFrameShadow( TQFrame::Plain );
+ m_splitter->setFrameShape( TQFrame::NoFrame );
+ m_splitter->setOpaqueResize(false);
+ setCentralWidget(widget);
+}
+
+void ImageWindow::setupActions()
+{
+ setupStandardActions();
+
+ // 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,
+ this, TQ_SLOT(slotAssignRatingNoStar()),
+ actionCollection(), "imageview_ratenostar");
+ d->star1 = new TDEAction(i18n("Assign Rating \"One Star\""), CTRL+Key_1,
+ this, TQ_SLOT(slotAssignRatingOneStar()),
+ actionCollection(), "imageview_rateonestar");
+ d->star2 = new TDEAction(i18n("Assign Rating \"Two Stars\""), CTRL+Key_2,
+ this, TQ_SLOT(slotAssignRatingTwoStar()),
+ actionCollection(), "imageview_ratetwostar");
+ d->star3 = new TDEAction(i18n("Assign Rating \"Three Stars\""), CTRL+Key_3,
+ this, TQ_SLOT(slotAssignRatingThreeStar()),
+ actionCollection(), "imageview_ratethreestar");
+ d->star4 = new TDEAction(i18n("Assign Rating \"Four Stars\""), CTRL+Key_4,
+ this, TQ_SLOT(slotAssignRatingFourStar()),
+ actionCollection(), "imageview_ratefourstar");
+ d->star5 = new TDEAction(i18n("Assign Rating \"Five Stars\""), CTRL+Key_5,
+ this, TQ_SLOT(slotAssignRatingFiveStar()),
+ actionCollection(), "imageview_ratefivestar");
+
+ // -- Special Delete actions ---------------------------------------------------------------
+
+ // Pop up dialog to ask user whether to permanently delete
+ d->fileDeletePermanentlyAction = new TDEAction(i18n("Delete File Permanently"),
+ "edit-delete",
+ SHIFT+Key_Delete,
+ this,
+ TQ_SLOT(slotDeleteCurrentItemPermanently()),
+ actionCollection(),
+ "image_delete_permanently");
+
+ // These two actions are hidden, no menu entry, no toolbar entry, no shortcut.
+ // Power users may add them.
+ d->fileDeletePermanentlyDirectlyAction = new TDEAction(i18n("Delete Permanently without Confirmation"),
+ "edit-delete",
+ 0,
+ this,
+ TQ_SLOT(slotDeleteCurrentItemPermanentlyDirectly()),
+ actionCollection(),
+ "image_delete_permanently_directly");
+
+ d->fileTrashDirectlyAction = new TDEAction(i18n("Move to Trash without Confirmation"),
+ "edittrash",
+ 0,
+ this,
+ TQ_SLOT(slotTrashCurrentItemDirectly()),
+ actionCollection(),
+ "image_trash_directly");
+
+ // ---------------------------------------------------------------------------------
+
+ new DLogoAction(actionCollection(), "logo_action");
+
+ createGUI("digikamimagewindowui.rc", false);
+
+ setupStandardAccelerators();
+}
+
+void ImageWindow::applySettings()
+{
+ applyStandardSettings();
+
+ AlbumSettings *settings = AlbumSettings::instance();
+ m_canvas->setExifOrient(settings->getExifRotate());
+ m_setExifOrientationTag = settings->getExifSetOrientation();
+ refreshView();
+}
+
+void ImageWindow::refreshView()
+{
+ d->rightSidebar->refreshTagsView();
+}
+
+void ImageWindow::loadURL(const KURL::List& urlList, const KURL& urlCurrent,
+ const TQString& caption, bool allowSaving)
+{
+ if (!promptUserSave(d->urlCurrent))
+ return;
+
+ d->urlList = urlList;
+ d->urlCurrent = urlCurrent;
+ d->imageInfoList = ImageInfoList();
+ d->imageInfoCurrent = 0;
+
+ loadCurrentList(caption, allowSaving);
+}
+
+void ImageWindow::loadImageInfos(const ImageInfoList &imageInfoList, ImageInfo *imageInfoCurrent,
+ const TQString& caption, bool allowSaving)
+{
+ // The ownership of objects of imageInfoList is passed to us.
+ // imageInfoCurrent is contained in imageInfoList.
+
+ // Very first thing is to check for changes, user may choose to cancel operation
+ if (!promptUserSave(d->urlCurrent))
+ {
+ // delete objects from list
+ for (ImageInfoList::iterator it = imageInfoList.begin(); it != imageInfoList.end(); ++it)
+ delete *it;
+ return;
+ }
+
+ // take over ImageInfo list
+ d->imageInfoList = imageInfoList;
+ d->imageInfoCurrent = imageInfoCurrent;
+
+ d->imageInfoList.setAutoDelete(true);
+
+ // create URL list
+ d->urlList = KURL::List();
+
+ ImageInfoListIterator it(d->imageInfoList);
+ ImageInfo *info;
+ for (; (info = it.current()); ++it)
+ {
+ d->urlList.append(info->kurl());
+ }
+
+ d->urlCurrent = d->imageInfoCurrent->kurl();
+
+ loadCurrentList(caption, allowSaving);
+}
+
+void ImageWindow::loadCurrentList(const TQString& caption, bool allowSaving)
+{
+ // this method contains the code shared by loadURL and loadImageInfos
+
+ // if window is iconified, show it
+ if (isMinimized())
+ {
+ KWin::deIconifyWindow(winId());
+ }
+
+ if (!caption.isEmpty())
+ setCaption(i18n("Image Editor - %1").arg(caption));
+ else
+ setCaption(i18n("Image Editor"));
+
+ d->allowSaving = allowSaving;
+
+ m_saveAction->setEnabled(false);
+ m_revertAction->setEnabled(false);
+ m_undoAction->setEnabled(false);
+ m_redoAction->setEnabled(false);
+
+ TQTimer::singleShot(0, this, TQ_SLOT(slotLoadCurrent()));
+}
+
+void ImageWindow::slotLoadCurrent()
+{
+ KURL::List::iterator it = d->urlList.find(d->urlCurrent);
+
+ if (it != d->urlList.end())
+ {
+ m_canvas->load(d->urlCurrent.path(), m_IOFileSettings);
+
+ ++it;
+ if (it != d->urlList.end())
+ m_canvas->preload((*it).path());
+ }
+
+ // Do this _after_ the canvas->load(), so that the main view histogram does not load
+ // a smaller version if a raw image, and after that the DImgInterface loads the full version.
+ // So first let DImgInterface create its loading task, only then any external objects.
+ setViewToURL(d->urlCurrent);
+}
+
+void ImageWindow::setViewToURL(const KURL &url)
+{
+ emit signalURLChanged(url);
+}
+
+void ImageWindow::slotForward()
+{
+ if(!promptUserSave(d->urlCurrent))
+ return;
+
+ KURL::List::iterator it = d->urlList.find(d->urlCurrent);
+ int index = d->imageInfoList.find(d->imageInfoCurrent);
+
+ if (it != d->urlList.end())
+ {
+ if (d->urlCurrent != d->urlList.last())
+ {
+ KURL urlNext = *(++it);
+ d->imageInfoCurrent = d->imageInfoList.at(index + 1);
+ d->urlCurrent = urlNext;
+ slotLoadCurrent();
+ }
+ }
+}
+
+void ImageWindow::slotBackward()
+{
+ if(!promptUserSave(d->urlCurrent))
+ return;
+
+ KURL::List::iterator it = d->urlList.find(d->urlCurrent);
+ int index = d->imageInfoList.find(d->imageInfoCurrent);
+
+ if (it != d->urlList.begin())
+ {
+ if (d->urlCurrent != d->urlList.first())
+ {
+ KURL urlPrev = *(--it);
+ d->imageInfoCurrent = d->imageInfoList.at(index - 1);
+ d->urlCurrent = urlPrev;
+ slotLoadCurrent();
+ }
+ }
+}
+
+void ImageWindow::slotFirst()
+{
+ if(!promptUserSave(d->urlCurrent))
+ return;
+
+ d->urlCurrent = d->urlList.first();
+ d->imageInfoCurrent = d->imageInfoList.first();
+ slotLoadCurrent();
+}
+
+void ImageWindow::slotLast()
+{
+ if(!promptUserSave(d->urlCurrent))
+ return;
+
+ d->urlCurrent = d->urlList.last();
+ d->imageInfoCurrent = d->imageInfoList.last();
+ slotLoadCurrent();
+}
+
+void ImageWindow::slotContextMenu()
+{
+ if (m_contextMenu)
+ {
+ RatingPopupMenu *ratingMenu = 0;
+ TagsPopupMenu *assignTagsMenu = 0;
+ TagsPopupMenu *removeTagsMenu = 0;
+ int separatorID1 = -1;
+ int separatorID2 = -1;
+
+ if (d->imageInfoCurrent)
+ {
+ // Bulk assignment/removal of tags --------------------------
+
+ TQ_LLONG id = d->imageInfoCurrent->id();
+ TQValueList<TQ_LLONG> idList;
+ idList.append(id);
+
+ assignTagsMenu = new TagsPopupMenu(idList, 1000, TagsPopupMenu::ASSIGN);
+ removeTagsMenu = new TagsPopupMenu(idList, 2000, TagsPopupMenu::REMOVE);
+
+ separatorID1 = m_contextMenu->insertSeparator();
+
+ m_contextMenu->insertItem(i18n("Assign Tag"), assignTagsMenu);
+ int i = m_contextMenu->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 ))
+ m_contextMenu->setItemEnabled(i, false);
+
+ separatorID2 = m_contextMenu->insertSeparator();
+
+ // Assign Star Rating -------------------------------------------
+
+ ratingMenu = new RatingPopupMenu();
+
+ connect(ratingMenu, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotAssignRating(int)));
+
+ m_contextMenu->insertItem(i18n("Assign Rating"), ratingMenu);
+ }
+
+ m_contextMenu->exec(TQCursor::pos());
+
+ if (separatorID1 != -1)
+ m_contextMenu->removeItem(separatorID1);
+ if (separatorID2 != -1)
+ m_contextMenu->removeItem(separatorID2);
+
+ delete assignTagsMenu;
+ delete removeTagsMenu;
+ delete ratingMenu;
+ }
+}
+
+void ImageWindow::slotChanged()
+{
+ TQString mpixels;
+ TQSize dims(m_canvas->imageWidth(), m_canvas->imageHeight());
+ mpixels.setNum(dims.width()*dims.height()/1000000.0, 'f', 2);
+ TQString str = (!dims.isValid()) ? i18n("Unknown") : i18n("%1x%2 (%3Mpx)")
+ .arg(dims.width()).arg(dims.height()).arg(mpixels);
+ m_resLabel->setText(str);
+
+ if (d->urlCurrent.isValid())
+ {
+ KURL u(d->urlCurrent.directory());
+
+ DImg* img = m_canvas->interface()->getImg();
+
+ if (d->imageInfoCurrent)
+ {
+ d->rightSidebar->itemChanged(d->imageInfoCurrent,
+ m_canvas->getSelectedArea(), img);
+ }
+ else
+ {
+ d->rightSidebar->itemChanged(d->urlCurrent, m_canvas->getSelectedArea(), img);
+ }
+ }
+}
+
+void ImageWindow::slotUndoStateChanged(bool moreUndo, bool moreRedo, bool canSave)
+{
+ m_revertAction->setEnabled(canSave);
+ m_undoAction->setEnabled(moreUndo);
+ m_redoAction->setEnabled(moreRedo);
+
+ if (d->allowSaving)
+ m_saveAction->setEnabled(canSave);
+
+ if (!moreUndo)
+ m_rotatedOrFlipped = false;
+}
+
+void ImageWindow::slotAssignTag(int tagID)
+{
+ if (d->imageInfoCurrent)
+ {
+ MetadataHub hub;
+ hub.load(d->imageInfoCurrent);
+ hub.setTag(tagID, true);
+ hub.write(d->imageInfoCurrent, MetadataHub::PartialWrite);
+ hub.write(d->imageInfoCurrent->filePath(), MetadataHub::FullWriteIfChanged);
+ }
+}
+
+void ImageWindow::slotRemoveTag(int tagID)
+{
+ if (d->imageInfoCurrent)
+ {
+ MetadataHub hub;
+ hub.load(d->imageInfoCurrent);
+ hub.setTag(tagID, false);
+ hub.write(d->imageInfoCurrent, MetadataHub::PartialWrite);
+ hub.write(d->imageInfoCurrent->filePath(), MetadataHub::FullWriteIfChanged);
+ }
+}
+
+void ImageWindow::slotAssignRatingNoStar()
+{
+ slotAssignRating(0);
+}
+
+void ImageWindow::slotAssignRatingOneStar()
+{
+ slotAssignRating(1);
+}
+
+void ImageWindow::slotAssignRatingTwoStar()
+{
+ slotAssignRating(2);
+}
+
+void ImageWindow::slotAssignRatingThreeStar()
+{
+ slotAssignRating(3);
+}
+
+void ImageWindow::slotAssignRatingFourStar()
+{
+ slotAssignRating(4);
+}
+
+void ImageWindow::slotAssignRatingFiveStar()
+{
+ slotAssignRating(5);
+}
+
+void ImageWindow::slotAssignRating(int rating)
+{
+ rating = TQMIN(RatingMax, TQMAX(RatingMin, rating));
+ if (d->imageInfoCurrent)
+ {
+ MetadataHub hub;
+ hub.load(d->imageInfoCurrent);
+ hub.setRating(rating);
+ hub.write(d->imageInfoCurrent, MetadataHub::PartialWrite);
+ hub.write(d->imageInfoCurrent->filePath(), MetadataHub::FullWriteIfChanged);
+ }
+}
+
+void ImageWindow::slotUpdateItemInfo()
+{
+ uint index = d->urlList.findIndex(d->urlCurrent);
+
+ m_rotatedOrFlipped = false;
+
+ TQString text = d->urlCurrent.filename() + i18n(" (%2 of %3)")
+ .arg(TQString::number(index+1))
+ .arg(TQString::number(d->urlList.count()));
+ m_nameLabel->setText(text);
+
+ if (d->urlList.count() == 1)
+ {
+ m_backwardAction->setEnabled(false);
+ m_forwardAction->setEnabled(false);
+ m_firstAction->setEnabled(false);
+ m_lastAction->setEnabled(false);
+ }
+ else
+ {
+ m_backwardAction->setEnabled(true);
+ m_forwardAction->setEnabled(true);
+ m_firstAction->setEnabled(true);
+ m_lastAction->setEnabled(true);
+ }
+
+ if (index == 0)
+ {
+ m_backwardAction->setEnabled(false);
+ m_firstAction->setEnabled(false);
+ }
+
+ if (index == d->urlList.count()-1)
+ {
+ m_forwardAction->setEnabled(false);
+ m_lastAction->setEnabled(false);
+ }
+
+ // Disable some menu actions if the current root image URL
+ // is not include in the digiKam Albums library database.
+ // This is necessary when ImageEditor is opened from cameraclient.
+
+ KURL u(d->urlCurrent.directory());
+ PAlbum *palbum = AlbumManager::instance()->findPAlbum(u);
+
+ if (!palbum)
+ {
+ m_fileDeleteAction->setEnabled(false);
+ }
+ else
+ {
+ m_fileDeleteAction->setEnabled(true);
+ }
+}
+
+bool ImageWindow::setup(bool iccSetupPage)
+{
+ Setup setup(this, 0, iccSetupPage ? Setup::IccProfiles : Setup::LastPageUsed);
+
+ if (setup.exec() != TQDialog::Accepted)
+ return false;
+
+ kapp->config()->sync();
+
+ applySettings();
+ return true;
+}
+
+void ImageWindow::toggleGUI2FullScreen()
+{
+ if (m_fullScreen)
+ d->rightSidebar->restore();
+ else
+ d->rightSidebar->backup();
+}
+
+void ImageWindow::saveIsComplete()
+{
+ // With save(), we do not reload the image but just continue using the data.
+ // This means that a saving operation does not lead to quality loss for
+ // subsequent editing operations.
+
+ // put image in cache, the LoadingCacheInterface cares for the details
+ LoadingCacheInterface::putImage(m_savingContext->destinationURL.path(), m_canvas->currentImage());
+
+ // notify main app that file changed
+ emit signalFileModified(m_savingContext->destinationURL);
+
+ // all that is done in slotLoadCurrent, except for loading
+ KURL::List::iterator it = d->urlList.find(d->urlCurrent);
+ setViewToURL(*it);
+
+ if (++it != d->urlList.end())
+ {
+ m_canvas->preload((*it).path());
+ }
+ //slotLoadCurrent();
+}
+
+void ImageWindow::saveAsIsComplete()
+{
+ // Nothing to be done if operating without database
+ if (!d->imageInfoCurrent)
+ return;
+
+ // Find the src and dest albums ------------------------------------------
+
+ KURL srcDirURL(TQDir::cleanDirPath(m_savingContext->srcURL.directory()));
+ PAlbum* srcAlbum = AlbumManager::instance()->findPAlbum(srcDirURL);
+
+ KURL dstDirURL(TQDir::cleanDirPath(m_savingContext->destinationURL.directory()));
+ PAlbum* dstAlbum = AlbumManager::instance()->findPAlbum(dstDirURL);
+
+ if (dstAlbum && srcAlbum)
+ {
+ // Now copy the metadata of the original file to the new file ------------
+
+ ImageInfo newInfo(d->imageInfoCurrent->copyItem(dstAlbum, m_savingContext->destinationURL.fileName()));
+
+ if ( d->urlList.find(m_savingContext->destinationURL) == d->urlList.end() )
+ { // The image file did not exist in the list.
+ KURL::List::iterator it = d->urlList.find(m_savingContext->srcURL);
+ int index = d->urlList.findIndex(m_savingContext->srcURL);
+ d->urlList.insert(it, m_savingContext->destinationURL);
+ d->imageInfoCurrent = new ImageInfo(newInfo);
+ d->imageInfoList.insert(index, d->imageInfoCurrent);
+ }
+ else if (d->urlCurrent != m_savingContext->destinationURL)
+ {
+ for (ImageInfo *info = d->imageInfoList.first(); info; info = d->imageInfoList.next())
+ {
+ if (info->kurl() == m_savingContext->destinationURL)
+ {
+ d->imageInfoCurrent = new ImageInfo(newInfo);
+ // setAutoDelete is true
+ d->imageInfoList.replace(d->imageInfoList.at(), d->imageInfoCurrent);
+ break;
+ }
+ }
+ }
+
+ d->urlCurrent = m_savingContext->destinationURL;
+ m_canvas->switchToLastSaved(m_savingContext->destinationURL.path());
+
+ slotUpdateItemInfo();
+
+ // If the DImg is put in the cache under the new name, this means the new file will not be reloaded.
+ // This may irritate users who want to check for quality loss in lossy formats.
+ // In any case, only do that if the format did not change - too many assumptions otherwise (see bug #138949).
+ if (m_savingContext->originalFormat == m_savingContext->format)
+ LoadingCacheInterface::putImage(m_savingContext->destinationURL.path(), m_canvas->currentImage());
+
+ // notify main app that file changed or a file is added
+ if(m_savingContext->destinationExisted)
+ emit signalFileModified(m_savingContext->destinationURL);
+ else
+ emit signalFileAdded(m_savingContext->destinationURL);
+
+ // all that is done in slotLoadCurrent, except for loading
+ KURL::List::iterator it = d->urlList.find(d->urlCurrent);
+
+ if (it != d->urlList.end())
+ {
+ setViewToURL(*it);
+ m_canvas->preload((*++it).path());
+ }
+ }
+ else
+ {
+ //TODO: make the user aware that the new path has not been used as new current filename
+ // because it is outside the digikam album hierachy
+ }
+}
+
+bool ImageWindow::save()
+{
+ // Sanity check. Just to be homogenous with SaveAs.
+ if (d->imageInfoCurrent)
+ {
+ // Write metadata from database to DImg
+ MetadataHub hub;
+ hub.load(d->imageInfoCurrent);
+ DImg image(m_canvas->currentImage());
+ hub.write(image, MetadataHub::FullWrite);
+ }
+
+ startingSave(d->urlCurrent);
+ return true;
+}
+
+bool ImageWindow::saveAs()
+{
+ // If image editor is started from CameraGUI, there is no ImageInfo instance to use.
+ if (d->imageInfoCurrent)
+ {
+ // Write metadata from database to DImg
+ MetadataHub hub;
+ hub.load(d->imageInfoCurrent);
+ DImg image(m_canvas->currentImage());
+ hub.write(image, MetadataHub::FullWrite);
+ }
+
+ return ( startingSaveAs(d->urlCurrent) );
+}
+
+void ImageWindow::slotDeleteCurrentItem()
+{
+ deleteCurrentItem(true, false);
+}
+
+void ImageWindow::slotDeleteCurrentItemPermanently()
+{
+ deleteCurrentItem(true, true);
+}
+
+void ImageWindow::slotDeleteCurrentItemPermanentlyDirectly()
+{
+ deleteCurrentItem(false, true);
+}
+
+void ImageWindow::slotTrashCurrentItemDirectly()
+{
+ deleteCurrentItem(false, false);
+}
+
+void ImageWindow::deleteCurrentItem(bool ask, bool permanently)
+{
+ // This function implements all four of the above slots.
+ // The meaning of permanently differs depending on the value of ask
+
+ KURL u;
+ u.setPath(d->urlCurrent.directory());
+ PAlbum *palbum = AlbumManager::instance()->findPAlbum(u);
+
+ // if available, provide a digikamalbums:// URL to TDEIO
+ KURL kioURL;
+ if (d->imageInfoCurrent)
+ kioURL = d->imageInfoCurrent->kurlForKIO();
+ else
+ kioURL = d->urlCurrent;
+ KURL fileURL = d->urlCurrent;
+
+ if (!palbum)
+ return;
+
+ bool useTrash;
+
+ if (ask)
+ {
+ bool preselectDeletePermanently = permanently;
+
+ DeleteDialog dialog(this);
+
+ KURL::List urlList;
+ urlList.append(d->urlCurrent);
+ if (!dialog.confirmDeleteList(urlList,
+ DeleteDialogMode::Files,
+ preselectDeletePermanently ?
+ DeleteDialogMode::NoChoiceDeletePermanently : DeleteDialogMode::NoChoiceTrash))
+ return;
+
+ useTrash = !dialog.shouldDelete();
+ }
+ else
+ {
+ useTrash = !permanently;
+ }
+
+ // bring all (sidebar) to a defined state without letting them sit on the deleted file
+ emit signalNoCurrentItem();
+
+ // 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(d->urlCurrent);
+
+ KURL CurrentToRemove = d->urlCurrent;
+ KURL::List::iterator it = d->urlList.find(d->urlCurrent);
+ int index = d->imageInfoList.find(d->imageInfoCurrent);
+
+ if (it != d->urlList.end())
+ {
+ if (d->urlCurrent != d->urlList.last())
+ {
+ // Try to get the next image in the current Album...
+
+ KURL urlNext = *(++it);
+ d->urlCurrent = urlNext;
+ d->imageInfoCurrent = d->imageInfoList.at(index + 1);
+ d->urlList.remove(CurrentToRemove);
+ d->imageInfoList.remove(index);
+ slotLoadCurrent();
+ return;
+ }
+ else if (d->urlCurrent != d->urlList.first())
+ {
+ // Try to get the previous image in the current Album.
+
+ KURL urlPrev = *(--it);
+ d->urlCurrent = urlPrev;
+ d->imageInfoCurrent = d->imageInfoList.at(index - 1);
+ d->urlList.remove(CurrentToRemove);
+ d->imageInfoList.remove(index);
+ slotLoadCurrent();
+ return;
+ }
+ }
+
+ // No image in the current Album -> Quit ImageEditor...
+
+ KMessageBox::information(this,
+ i18n("There is no image to show in the current album.\n"
+ "The image editor will be closed."),
+ i18n("No Image in Current Album"));
+
+ close();
+}
+
+void ImageWindow::slotFileMetadataChanged(const KURL &url)
+{
+ if (url == d->urlCurrent)
+ {
+ m_canvas->readMetadataFromFile(url.path());
+ }
+}
+
+void ImageWindow::slotFilePrint()
+{
+ printImage(d->urlCurrent);
+};
+
+void ImageWindow::slideShow(bool startWithCurrent, SlideShowSettings& settings)
+{
+ float cnt;
+ DMetadata meta;
+ int i = 0;
+ m_cancelSlideShow = false;
+ settings.exifRotate = AlbumSettings::instance()->getExifRotate();
+
+ if (!d->imageInfoList.isEmpty())
+ {
+ // We have started image editor from Album GUI. we get picture comments from database.
+
+ m_nameLabel->progressBarMode(StatusProgressBar::CancelProgressBarMode,
+ i18n("Preparing slideshow. Please wait..."));
+
+ cnt = (float)d->imageInfoList.count();
+
+ for (ImageInfo *info = d->imageInfoList.first() ;
+ !m_cancelSlideShow && info ; info = d->imageInfoList.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);
+
+ m_nameLabel->setProgressValue((int)((i++/cnt)*100.0));
+ kapp->processEvents();
+ }
+ }
+ else
+ {
+ // We have started image editor from Camera GUI. we get picture comments from metadata.
+
+ m_nameLabel->progressBarMode(StatusProgressBar::CancelProgressBarMode,
+ i18n("Preparing slideshow. Please wait..."));
+
+ cnt = (float)d->urlList.count();
+
+ for (KURL::List::Iterator it = d->urlList.begin() ;
+ !m_cancelSlideShow && (it != d->urlList.end()) ; ++it)
+ {
+ SlidePictureInfo pictInfo;
+ meta.load((*it).path());
+ pictInfo.comment = meta.getImageComment();
+ pictInfo.photoInfo = meta.getPhotographInformations();
+ settings.pictInfoMap.insert(*it, pictInfo);
+
+ m_nameLabel->setProgressValue((int)((i++/cnt)*100.0));
+ kapp->processEvents();
+ }
+ }
+
+ m_nameLabel->progressBarMode(StatusProgressBar::TextMode, TQString());
+
+ if (!m_cancelSlideShow)
+ {
+ settings.exifRotate = AlbumSettings::instance()->getExifRotate();
+ settings.fileList = d->urlList;
+
+ SlideShow *slide = new SlideShow(settings);
+ if (startWithCurrent)
+ slide->setCurrent(d->urlCurrent);
+
+ slide->show();
+ }
+}
+
+void ImageWindow::dragMoveEvent(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 ImageWindow::dropEvent(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);
+ imageInfoList.append(info);
+ }
+
+ if (imageInfoList.isEmpty())
+ {
+ e->ignore();
+ return;
+ }
+
+ TQString ATitle;
+ AlbumManager* man = AlbumManager::instance();
+ PAlbum* palbum = man->findPAlbum(albumIDs.first());
+ if (palbum) ATitle = palbum->title();
+
+ TAlbum* talbum = man->findTAlbum(albumIDs.first());
+ if (talbum) ATitle = talbum->title();
+
+ loadImageInfos(imageInfoList, imageInfoList.first(),
+ i18n("Album \"%1\"").arg(ATitle), true);
+ e->accept();
+ }
+ else if (AlbumDrag::decode(e, urls, albumID))
+ {
+ AlbumManager* man = AlbumManager::instance();
+ TQValueList<TQ_LLONG> itemIDs = man->albumDB()->getItemIDsInAlbum(albumID);
+ ImageInfoList imageInfoList;
+
+ for (TQValueList<TQ_LLONG>::const_iterator it = itemIDs.begin();
+ it != itemIDs.end(); ++it)
+ {
+ ImageInfo *info = new ImageInfo(*it);
+ imageInfoList.append(info);
+ }
+
+ if (imageInfoList.isEmpty())
+ {
+ e->ignore();
+ return;
+ }
+
+ TQString ATitle;
+ PAlbum* palbum = man->findPAlbum(albumIDs.first());
+ if (palbum) ATitle = palbum->title();
+
+ loadImageInfos(imageInfoList, imageInfoList.first(),
+ i18n("Album \"%1\"").arg(ATitle), true);
+ 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);
+ imageInfoList.append(info);
+ }
+
+ if (imageInfoList.isEmpty())
+ {
+ e->ignore();
+ return;
+ }
+
+ TQString ATitle;
+ TAlbum* talbum = man->findTAlbum(tagID);
+ if (talbum) ATitle = talbum->title();
+
+ loadImageInfos(imageInfoList, imageInfoList.first(),
+ i18n("Album \"%1\"").arg(ATitle), true);
+ e->accept();
+ }
+ else
+ {
+ e->ignore();
+ }
+}
+
+void ImageWindow::slotRevert()
+{
+ if(!promptUserSave(d->urlCurrent))
+ return;
+
+ m_canvas->slotRestore();
+}
+
+void ImageWindow::slotChangeTheme(const TQString& theme)
+{
+ AlbumSettings::instance()->setCurrentTheme(theme);
+ ThemeEngine::instance()->slotChangeTheme(theme);
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/editor/imagewindow.h b/src/utilities/imageeditor/editor/imagewindow.h
new file mode 100644
index 00000000..389518a8
--- /dev/null
+++ b/src/utilities/imageeditor/editor/imagewindow.h
@@ -0,0 +1,155 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-02-12
+ * Description : digiKam image editor GUI
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-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 IMAGEWINDOW_H
+#define IMAGEWINDOW_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Local includes.
+
+#include "editorwindow.h"
+#include "imageinfo.h"
+
+class TQDragMoveEvent;
+class TQDropEvent;
+
+namespace Digikam
+{
+
+class AlbumIconView;
+class ImageWindowPriv;
+class SlideShowSettings;
+
+class ImageWindow : public EditorWindow
+{
+ TQ_OBJECT
+
+
+public:
+
+ ~ImageWindow();
+
+ void loadURL(const KURL::List& urlList, const KURL& urlCurrent,
+ const TQString& caption=TQString(),
+ bool allowSaving=true);
+
+ void loadImageInfos(const ImageInfoList &imageInfoList,
+ ImageInfo *imageInfoCurrent,
+ const TQString& caption, bool allowSaving);
+
+ static ImageWindow* imagewindow();
+ static bool imagewindowCreated();
+
+ void applySettings();
+ void refreshView();
+ bool setup(bool iccSetupPage=false);
+
+ bool queryClose();
+
+signals:
+
+ void signalFileDeleted(const KURL& url);
+ void signalFileAdded(const KURL& url);
+ void signalFileModified(const KURL& url);
+ void signalURLChanged(const KURL& url);
+
+private:
+
+ void loadCurrentList(const TQString& caption, bool allowSaving);
+ void closeEvent(TQCloseEvent* e);
+
+ void dragMoveEvent(TQDragMoveEvent *e);
+ void dropEvent(TQDropEvent *e);
+
+ void setupActions();
+ void setupConnections();
+ void setupUserArea();
+ void toggleGUI2FullScreen();
+
+ bool save();
+ bool saveAs();
+
+ void saveIsComplete();
+ void saveAsIsComplete();
+ void setViewToURL(const KURL &url);
+ void deleteCurrentItem(bool ask, bool permanently);
+
+ void slideShow(bool startWithCurrent, SlideShowSettings& settings);
+
+ Sidebar* rightSideBar() const;
+
+ ImageWindow();
+
+private slots:
+
+ void slotForward();
+ void slotBackward();
+ void slotFirst();
+ void slotLast();
+ void slotFilePrint();
+
+ void slotLoadCurrent();
+ void slotDeleteCurrentItem();
+ void slotDeleteCurrentItemPermanently();
+ void slotDeleteCurrentItemPermanentlyDirectly();
+ void slotTrashCurrentItemDirectly();
+
+ void slotChanged();
+ void slotUndoStateChanged(bool, bool, bool);
+ void slotUpdateItemInfo();
+
+ void slotContextMenu();
+ void slotRevert();
+
+ void slotAssignTag(int tagID);
+ void slotRemoveTag(int tagID);
+
+ void slotAssignRatingNoStar();
+ void slotAssignRatingOneStar();
+ void slotAssignRatingTwoStar();
+ void slotAssignRatingThreeStar();
+ void slotAssignRatingFourStar();
+ void slotAssignRatingFiveStar();
+ void slotAssignRating(int rating);
+
+ void slotFileMetadataChanged(const KURL &);
+ void slotChangeTheme(const TQString& theme);
+
+private:
+
+ ImageWindowPriv *d;
+
+ static ImageWindow *m_instance;
+};
+
+} // namespace Digikam
+
+#endif /* IMAGEWINDOW_H */
diff --git a/src/utilities/imageeditor/editor/savingcontextcontainer.h b/src/utilities/imageeditor/editor/savingcontextcontainer.h
new file mode 100644
index 00000000..c747a357
--- /dev/null
+++ b/src/utilities/imageeditor/editor/savingcontextcontainer.h
@@ -0,0 +1,89 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-20
+ * Description : image editor GUI saving context container
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel.wiesweg@gmx.de>
+ *
+ * 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 SAVINGCONTEXTCONTAINER_H
+#define SAVINGCONTEXTCONTAINER_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <kurl.h>
+#include <tdetempfile.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT SavingContextContainer
+{
+
+public:
+
+ SavingContextContainer()
+ {
+ savingState = SavingStateNone;
+ synchronizingState = NormalSaving;
+ saveTempFile = 0;
+ destinationExisted = false;
+ synchronousSavingResult = false;
+ abortingSaving = false;
+ }
+
+ enum SavingState
+ {
+ SavingStateNone,
+ SavingStateSave,
+ SavingStateSaveAs
+ };
+
+ enum SynchronizingState
+ {
+ NormalSaving,
+ SynchronousSaving
+ };
+
+ SavingState savingState;
+ SynchronizingState synchronizingState;
+ bool synchronousSavingResult;
+ bool destinationExisted;
+ bool abortingSaving;
+
+ TQString originalFormat;
+ TQString format;
+
+ KURL srcURL;
+ KURL destinationURL;
+
+ KTempFile *saveTempFile;
+};
+
+} // namespace Digikam
+
+#endif /* SAVINGCONTEXTCONTAINER_H */
diff --git a/src/utilities/imageeditor/rawimport/Makefile.am b/src/utilities/imageeditor/rawimport/Makefile.am
new file mode 100644
index 00000000..19071935
--- /dev/null
+++ b/src/utilities/imageeditor/rawimport/Makefile.am
@@ -0,0 +1,27 @@
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = librawimport.la
+
+librawimport_la_SOURCES = rawpreview.cpp rawsettingsbox.cpp rawimport.cpp \
+ rawpostprocessing.cpp
+
+librawimport_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TDEPRINT)
+
+INCLUDES= -I$(top_srcdir)/src/digikam \
+ -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/threadimageio \
+ -I$(top_srcdir)/src/libs/themeengine \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
diff --git a/src/utilities/imageeditor/rawimport/rawimport.cpp b/src/utilities/imageeditor/rawimport/rawimport.cpp
new file mode 100644
index 00000000..a9254ce8
--- /dev/null
+++ b/src/utilities/imageeditor/rawimport/rawimport.cpp
@@ -0,0 +1,223 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-20
+ * Description : Raw import tool
+ *
+ * Copyright (C) 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 <tqstring.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <tdeconfig.h>
+#include <tdeapplication.h>
+#include <kiconloader.h>
+#include <kstandarddirs.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "drawdecoding.h"
+#include "histogramwidget.h"
+#include "curveswidget.h"
+#include "imagehistogram.h"
+#include "rawsettingsbox.h"
+#include "rawpostprocessing.h"
+#include "editortooliface.h"
+#include "rawpreview.h"
+#include "rawimport.h"
+#include "rawimport.moc"
+
+namespace Digikam
+{
+
+class RawImportPriv
+{
+public:
+
+ RawImportPriv()
+ {
+ previewWidget = 0;
+ settingsBox = 0;
+ }
+
+ RawSettingsBox *settingsBox;
+
+ RawPreview *previewWidget;
+};
+
+RawImport::RawImport(const KURL& url, TQObject *parent)
+ : EditorToolThreaded(parent)
+{
+ d = new RawImportPriv;
+ d->previewWidget = new RawPreview(url, 0);
+ d->settingsBox = new RawSettingsBox(url, 0);
+
+ setToolName(i18n("Raw Import"));
+ setToolIcon(SmallIcon("kdcraw"));
+ setProgressMessage(i18n("Post Processing"));
+ setToolView(d->previewWidget);
+ setToolSettings(d->settingsBox);
+
+ init();
+}
+
+RawImport::~RawImport()
+{
+ delete d;
+}
+
+void RawImport::slotInit()
+{
+ EditorToolThreaded::slotInit();
+
+ // ---------------------------------------------------------------
+
+ connect(d->previewWidget, TQ_SIGNAL(signalLoadingStarted()),
+ this, TQ_SLOT(slotLoadingStarted()));
+
+ connect(d->previewWidget, TQ_SIGNAL(signalDemosaicedImage()),
+ this, TQ_SLOT(slotDemosaicedImage()));
+
+ connect(d->previewWidget, TQ_SIGNAL(signalLoadingStarted()),
+ this, TQ_SLOT(slotLoadingStarted()));
+
+ connect(d->previewWidget, TQ_SIGNAL(signalLoadingProgress(float)),
+ this, TQ_SLOT(slotLoadingProgress(float)));
+
+ connect(d->previewWidget, TQ_SIGNAL(signalLoadingFailed()),
+ this, TQ_SLOT(slotLoadingFailed()));
+
+ connect(d->settingsBox, TQ_SIGNAL(signalDemosaicingChanged()),
+ this, TQ_SLOT(slotDemosaicingChanged()));
+
+ connect(d->settingsBox, TQ_SIGNAL(signalPostProcessingChanged()),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(d->settingsBox, TQ_SIGNAL(signalUpdatePreview()),
+ this, TQ_SLOT(slotUpdatePreview()));
+
+ connect(d->settingsBox, TQ_SIGNAL(signalAbortPreview()),
+ this, TQ_SLOT(slotAbort()));
+
+ // ---------------------------------------------------------------
+
+ setBusy(true);
+ slotUpdatePreview();
+}
+
+void RawImport::setBusy(bool val)
+{
+ if (val) d->previewWidget->setCursor(KCursor::waitCursor());
+ else d->previewWidget->unsetCursor();
+ d->settingsBox->setBusy(val);
+}
+
+DRawDecoding RawImport::rawDecodingSettings()
+{
+ return d->settingsBox->settings();
+}
+
+void RawImport::slotUpdatePreview()
+{
+ DRawDecoding settings = rawDecodingSettings();
+ // We will load an half size image to speed up preview computing.
+ settings.halfSizeColorImage = true;
+
+ d->previewWidget->setDecodingSettings(settings);
+}
+
+void RawImport::slotAbort()
+{
+ // If preview loading, don't play with threaded filter interface.
+ if (renderingMode() == EditorToolThreaded::NoneRendering)
+ {
+ d->previewWidget->cancelLoading();
+ d->settingsBox->histogram()->stopHistogramComputation();
+ EditorToolIface::editorToolIface()->setToolStopProgress();
+ setBusy(false);
+ return;
+ }
+
+ EditorToolThreaded::slotAbort();
+}
+
+void RawImport::slotLoadingStarted()
+{
+ d->settingsBox->enableUpdateBtn(false);
+ d->settingsBox->histogram()->setDataLoading();
+ d->settingsBox->curve()->setDataLoading();
+ EditorToolIface::editorToolIface()->setToolStartProgress(i18n("Raw Decoding"));
+ setBusy(true);
+}
+
+void RawImport::slotDemosaicedImage()
+{
+ d->settingsBox->setDemosaicedImage(d->previewWidget->demosaicedImage());
+ slotEffect();
+}
+
+void RawImport::prepareEffect()
+{
+ DImg postImg = d->previewWidget->demosaicedImage();
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new RawPostProcessing(&postImg, this, rawDecodingSettings())));
+}
+
+void RawImport::putPreviewData()
+{
+ d->previewWidget->setPostProcessedImage(filter()->getTargetImage());
+ d->settingsBox->setPostProcessedImage(d->previewWidget->postProcessedImage());
+ EditorToolIface::editorToolIface()->setToolStopProgress();
+ setBusy(false);
+}
+
+void RawImport::slotLoadingFailed()
+{
+ d->settingsBox->histogram()->setLoadingFailed();
+ EditorToolIface::editorToolIface()->setToolStopProgress();
+ setBusy(false);
+}
+
+void RawImport::slotDemosaicingChanged()
+{
+ d->settingsBox->enableUpdateBtn(true);
+}
+
+void RawImport::slotLoadingProgress(float v)
+{
+ EditorToolIface::editorToolIface()->setToolProgress((int)(v*100));
+}
+
+void RawImport::slotOk()
+{
+ EditorTool::slotOk();
+}
+
+void RawImport::slotCancel()
+{
+ EditorTool::slotCancel();
+}
+
+} // NameSpace Digikam
diff --git a/src/utilities/imageeditor/rawimport/rawimport.h b/src/utilities/imageeditor/rawimport/rawimport.h
new file mode 100644
index 00000000..85255bc8
--- /dev/null
+++ b/src/utilities/imageeditor/rawimport/rawimport.h
@@ -0,0 +1,88 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-20
+ * Description : Raw import tool
+ *
+ * Copyright (C) 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 RAWIMPORTDLG_H
+#define RAWIMPORTDLG_H
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Local includes.
+
+#include "editortool.h"
+#include "dimg.h"
+#include "digikam_export.h"
+
+namespace KDcrawIface
+{
+class RawDecodingSettings;
+}
+
+namespace Digikam
+{
+
+class RawImportPriv;
+
+class DIGIKAM_EXPORT RawImport : public EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ RawImport(const KURL& url, TQObject *parent);
+ ~RawImport();
+
+ DRawDecoding rawDecodingSettings();
+
+private:
+
+ void setBusy(bool busy);
+ void prepareEffect();
+ void putPreviewData();
+
+private slots:
+
+ void slotInit();
+
+ void slotLoadingStarted();
+ void slotDemosaicedImage();
+ void slotLoadingFailed();
+ void slotLoadingProgress(float);
+
+ void slotUpdatePreview();
+ void slotAbort();
+
+ void slotDemosaicingChanged();
+
+ void slotOk();
+ void slotCancel();
+
+private:
+
+ RawImportPriv *d;
+};
+
+} // NameSpace Digikam
+
+#endif // RAWIMPORTDLG_H
diff --git a/src/utilities/imageeditor/rawimport/rawpostprocessing.cpp b/src/utilities/imageeditor/rawimport/rawpostprocessing.cpp
new file mode 100644
index 00000000..d45dd5e4
--- /dev/null
+++ b/src/utilities/imageeditor/rawimport/rawpostprocessing.cpp
@@ -0,0 +1,137 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-13-08
+ * Description : Raw post processing corrections.
+ *
+ * Copyright (C) 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.
+ *
+ * ============================================================ */
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imagehistogram.h"
+#include "imagecurves.h"
+#include "imagelevels.h"
+#include "bcgmodifier.h"
+#include "whitebalance.h"
+#include "dimgimagefilters.h"
+#include "rawpostprocessing.h"
+
+namespace Digikam
+{
+
+RawPostProcessing::RawPostProcessing(DImg *orgImage, TQObject *parent, const DRawDecoding& settings)
+ : DImgThreadedFilter(orgImage, parent, "RawPostProcessing")
+{
+ m_customRawSettings = settings;
+ initFilter();
+}
+
+RawPostProcessing::RawPostProcessing(DImgThreadedFilter *parentFilter,
+ const DImg &orgImage, const DImg &destImage,
+ int progressBegin, int progressEnd, const DRawDecoding& settings)
+ : DImgThreadedFilter(parentFilter, orgImage, destImage, progressBegin, progressEnd,
+ parentFilter->filterName() + ": RawPostProcessing")
+{
+ m_customRawSettings = settings;
+ filterImage();
+}
+
+void RawPostProcessing::filterImage()
+{
+ rawPostProcessing();
+}
+
+void RawPostProcessing::rawPostProcessing()
+{
+ if (!m_orgImage.bits() || !m_orgImage.width() || !m_orgImage.height())
+ {
+ DWarning() << ("RawPostProcessing::rawPostProcessing: no image m_orgImage.bits() available!")
+ << endl;
+ return;
+ }
+
+ if (!m_customRawSettings.postProcessingSettingsIsDirty())
+ {
+ m_destImage = m_orgImage;
+ return;
+ }
+
+ postProgress(15);
+
+ if (m_customRawSettings.exposureComp != 0.0 || m_customRawSettings.saturation != 1.0)
+ {
+ WhiteBalance wb(m_orgImage.sixteenBit());
+ wb.whiteBalance(m_orgImage.bits(), m_orgImage.width(), m_orgImage.height(), m_orgImage.sixteenBit(),
+ 0.0, // black
+ m_customRawSettings.exposureComp, // exposure
+ 6500.0, // temperature (neutral)
+ 1.0, // green
+ 0.5, // dark
+ 1.0, // gamma
+ m_customRawSettings.saturation); // saturation
+ }
+ postProgress(30);
+
+ if (m_customRawSettings.lightness != 0.0 || m_customRawSettings.contrast != 1.0 || m_customRawSettings.gamma != 1.0)
+ {
+ BCGModifier bcg;
+ bcg.setBrightness(m_customRawSettings.lightness);
+ bcg.setContrast(m_customRawSettings.contrast);
+ bcg.setGamma(m_customRawSettings.gamma);
+ bcg.applyBCG(m_orgImage.bits(), m_orgImage.width(), m_orgImage.height(), m_orgImage.sixteenBit());
+ }
+ postProgress(45);
+
+ if (!m_customRawSettings.curveAdjust.isEmpty())
+ {
+ DImg tmp(m_orgImage.width(), m_orgImage.height(), m_orgImage.sixteenBit());
+ ImageCurves curves(m_orgImage.sixteenBit());
+ curves.setCurvePoints(ImageHistogram::ValueChannel, m_customRawSettings.curveAdjust);
+ curves.curvesCalculateCurve(ImageHistogram::ValueChannel);
+ curves.curvesLutSetup(ImageHistogram::AlphaChannel);
+ curves.curvesLutProcess(m_orgImage.bits(), tmp.bits(), m_orgImage.width(), m_orgImage.height());
+ memcpy(m_orgImage.bits(), tmp.bits(), tmp.numBytes());
+ }
+ postProgress(60);
+
+ if (!m_customRawSettings.levelsAdjust.isEmpty())
+ {
+ DImg tmp(m_orgImage.width(), m_orgImage.height(), m_orgImage.sixteenBit());
+ ImageLevels levels(m_orgImage.sixteenBit());
+ int j=0;
+ for (int i = 0 ; i < 4; i++)
+ {
+ levels.setLevelLowInputValue(i, m_customRawSettings.levelsAdjust[j++]);
+ levels.setLevelHighInputValue(i, m_customRawSettings.levelsAdjust[j++]);
+ levels.setLevelLowOutputValue(i, m_customRawSettings.levelsAdjust[j++]);
+ levels.setLevelHighOutputValue(i, m_customRawSettings.levelsAdjust[j++]);
+ }
+
+ levels.levelsLutSetup(ImageHistogram::AlphaChannel);
+ levels.levelsLutProcess(m_orgImage.bits(), tmp.bits(), m_orgImage.width(), m_orgImage.height());
+ memcpy(m_orgImage.bits(), tmp.bits(), tmp.numBytes());
+ }
+ postProgress(75);
+
+ m_destImage = m_orgImage;
+
+ postProgress(100);
+}
+
+} // NameSpace Digikam
diff --git a/src/utilities/imageeditor/rawimport/rawpostprocessing.h b/src/utilities/imageeditor/rawimport/rawpostprocessing.h
new file mode 100644
index 00000000..3b3c7761
--- /dev/null
+++ b/src/utilities/imageeditor/rawimport/rawpostprocessing.h
@@ -0,0 +1,63 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-13-08
+ * Description : Raw post processing corrections.
+ *
+ * Copyright (C) 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 RAWPOSTPROCESSING_H
+#define RAWPOSTPROCESSING_H
+
+// Digikam includes.
+
+#include "digikam_export.h"
+
+// Local includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT RawPostProcessing : public DImgThreadedFilter
+{
+
+public:
+
+ RawPostProcessing(DImg *orgImage, TQObject *parent=0, const DRawDecoding& settings=DRawDecoding());
+
+ // Constructor for slave mode: execute immediately in current thread with specified master filter
+ RawPostProcessing(DImgThreadedFilter *parentFilter, const DImg &orgImage, const DImg &destImage,
+ int progressBegin=0, int progressEnd=100, const DRawDecoding& settings=DRawDecoding());
+
+ ~RawPostProcessing(){};
+
+private:
+
+ virtual void filterImage();
+ void rawPostProcessing();
+
+private:
+
+ DRawDecoding m_customRawSettings;
+};
+
+} // NameSpace Digikam
+
+#endif /* RAWPOSTPROCESSING_H */
diff --git a/src/utilities/imageeditor/rawimport/rawpreview.cpp b/src/utilities/imageeditor/rawimport/rawpreview.cpp
new file mode 100644
index 00000000..3207ba14
--- /dev/null
+++ b/src/utilities/imageeditor/rawimport/rawpreview.cpp
@@ -0,0 +1,336 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-04
+ * Description : RAW postProcessedImg widget.
+ *
+ * Copyright (C) 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.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqstring.h>
+#include <tqpainter.h>
+#include <tqtoolbutton.h>
+#include <tqtooltip.h>
+#include <tqpixmap.h>
+#include <tqfileinfo.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kcursor.h>
+#include <kdatetbl.h>
+#include <kiconloader.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "paniconwidget.h"
+#include "managedloadsavethread.h"
+#include "loadingdescription.h"
+#include "themeengine.h"
+#include "rawpreview.h"
+#include "rawpreview.moc"
+
+namespace Digikam
+{
+
+class RawPreviewPriv
+{
+public:
+
+ RawPreviewPriv()
+ {
+ panIconPopup = 0;
+ panIconWidget = 0;
+ cornerButton = 0;
+ thread = 0;
+ url = 0;
+ currentFitWindowZoom = 0;
+ }
+
+ double currentFitWindowZoom;
+
+ TQToolButton *cornerButton;
+
+ TDEPopupFrame *panIconPopup;
+
+ KURL url;
+
+ PanIconWidget *panIconWidget;
+
+ DImg demosaicedImg;
+
+ DImg postProcessedImg;
+
+ DRawDecoding settings;
+
+ ManagedLoadSaveThread *thread;
+
+ LoadingDescription loadingDesc;
+};
+
+RawPreview::RawPreview(const KURL& url, TQWidget *parent)
+ : PreviewWidget(parent)
+{
+ d = new RawPreviewPriv;
+ d->thread = new ManagedLoadSaveThread;
+ d->url = url;
+
+ setMinimumWidth(500);
+ 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 to a region"));
+ setCornerWidget(d->cornerButton);
+
+ // ------------------------------------------------------------
+
+ connect(d->thread, TQ_SIGNAL(signalImageLoaded(const LoadingDescription&, const DImg&)),
+ this, TQ_SLOT(slotImageLoaded(const LoadingDescription&, const DImg&)));
+
+ connect(d->thread, TQ_SIGNAL(signalLoadingProgress(const LoadingDescription&, float)),
+ this, TQ_SLOT(slotLoadingProgress(const LoadingDescription&, float)));
+
+ connect(d->cornerButton, TQ_SIGNAL(pressed()),
+ this, TQ_SLOT(slotCornerButtonPressed()));
+
+ connect(ThemeEngine::instance(), TQ_SIGNAL(signalThemeChanged()),
+ this, TQ_SLOT(slotThemeChanged()));
+
+ // ------------------------------------------------------------
+
+ slotReset();
+}
+
+RawPreview::~RawPreview()
+{
+ delete d;
+}
+
+void RawPreview::setPostProcessedImage(const DImg& image)
+{
+ d->postProcessedImg = image;
+
+ updateZoomAndSize(false);
+
+ viewport()->setUpdatesEnabled(true);
+ viewport()->update();
+}
+
+DImg& RawPreview::postProcessedImage() const
+{
+ return d->postProcessedImg;
+}
+
+DImg& RawPreview::demosaicedImage() const
+{
+ return d->demosaicedImg;
+}
+
+void RawPreview::setDecodingSettings(const DRawDecoding& settings)
+{
+ // Save post processing settings.
+ d->settings = settings;
+
+ // All post processing settings will be used after demosaicing.
+ DRawDecoding demosaisedSettings = settings;
+ demosaisedSettings.resetPostProcessingSettings();
+
+ d->loadingDesc = LoadingDescription(d->url.path(), demosaisedSettings);
+ d->thread->load(d->loadingDesc, ManagedLoadSaveThread::LoadingPolicyFirstRemovePrevious);
+ emit signalLoadingStarted();
+}
+
+void RawPreview::cancelLoading()
+{
+ d->thread->stopLoading(d->loadingDesc);
+}
+
+void RawPreview::slotLoadingProgress(const LoadingDescription& description, float progress)
+{
+ if (description.filePath != d->loadingDesc.filePath)
+ return;
+
+ emit signalLoadingProgress(progress);
+}
+
+void RawPreview::slotImageLoaded(const LoadingDescription& description, const DImg& image)
+{
+ if (description.filePath != d->loadingDesc.filePath)
+ return;
+
+ if (image.isNull())
+ {
+ 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("Cannot decode RAW image for\n\"%1\"")
+ .arg(TQFileInfo(d->loadingDesc.filePath).fileName()));
+ p.end();
+ // three copies - but the image is small
+ setPostProcessedImage(DImg(pix.convertToImage()));
+ emit signalLoadingFailed();
+ }
+ else
+ {
+ d->demosaicedImg = image;
+ emit signalDemosaicedImage();
+ // NOTE: we will apply all Raw post processing corrections into RawImport class.
+ }
+}
+
+void RawPreview::slotThemeChanged()
+{
+ setBackgroundColor(ThemeEngine::instance()->baseColor());
+}
+
+void RawPreview::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, postProcessedImage());
+ 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 RawPreview::slotPanIconHiden()
+{
+ d->cornerButton->blockSignals(true);
+ d->cornerButton->animateClick();
+ d->cornerButton->blockSignals(false);
+}
+
+void RawPreview::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 RawPreview::zoomFactorChanged(double zoom)
+{
+ updateScrollBars();
+
+ if (horizontalScrollBar()->isVisible() || verticalScrollBar()->isVisible())
+ d->cornerButton->show();
+ else
+ d->cornerButton->hide();
+
+ PreviewWidget::zoomFactorChanged(zoom);
+}
+
+void RawPreview::resizeEvent(TQResizeEvent* e)
+{
+ if (!e) return;
+
+ TQScrollView::resizeEvent(e);
+
+ if (!d->loadingDesc.filePath.isEmpty())
+ d->cornerButton->hide();
+
+ updateZoomAndSize(false);
+}
+
+void RawPreview::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 RawPreview::previewWidth()
+{
+ return d->postProcessedImg.width();
+}
+
+int RawPreview::previewHeight()
+{
+ return d->postProcessedImg.height();
+}
+
+bool RawPreview::previewIsNull()
+{
+ return d->postProcessedImg.isNull();
+}
+
+void RawPreview::resetPreview()
+{
+ d->postProcessedImg = DImg();
+ d->loadingDesc = LoadingDescription();
+
+ updateZoomAndSize(false);
+}
+
+void RawPreview::paintPreview(TQPixmap *pix, int sx, int sy, int sw, int sh)
+{
+ DImg img = d->postProcessedImg.smoothScaleSection(sx, sy, sw, sh, tileSize(), tileSize());
+ TQPixmap pix2 = img.convertToPixmap();
+ bitBlt(pix, 0, 0, &pix2, 0, 0);
+}
+
+} // NameSpace Digikam
diff --git a/src/utilities/imageeditor/rawimport/rawpreview.h b/src/utilities/imageeditor/rawimport/rawpreview.h
new file mode 100644
index 00000000..6c7e5379
--- /dev/null
+++ b/src/utilities/imageeditor/rawimport/rawpreview.h
@@ -0,0 +1,108 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-04
+ * Description : RAW preview widget.
+ *
+ * Copyright (C) 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 RAWPREVIEW_H
+#define RAWPREVIEW_H
+
+// TQt includes.
+
+#include <tqimage.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "previewwidget.h"
+#include "digikam_export.h"
+
+class TQPixmap;
+
+namespace Digikam
+{
+
+class LoadingDescription;
+class RawPreviewPriv;
+
+class DIGIKAM_EXPORT RawPreview : public PreviewWidget
+{
+
+TQ_OBJECT
+
+
+public:
+
+ RawPreview(const KURL& url, TQWidget *parent);
+ ~RawPreview();
+
+ DImg& demosaicedImage() const;
+ DImg& postProcessedImage() const;
+
+ void setDecodingSettings(const DRawDecoding& settings);
+ void setPostProcessedImage(const DImg& image);
+
+ void cancelLoading();
+
+signals:
+
+ void signalLoadingStarted();
+ void signalLoadingProgress(float);
+ void signalLoadingFailed();
+ void signalDemosaicedImage();
+ void signalPostProcessedImage();
+
+protected:
+
+ void resizeEvent(TQResizeEvent* e);
+
+private slots:
+
+ void slotLoadingProgress(const LoadingDescription& description, float progress);
+ void slotImageLoaded(const LoadingDescription& description, const DImg &image);
+ void slotThemeChanged();
+ void slotCornerButtonPressed();
+ void slotPanIconSelectionMoved(const TQRect&, bool);
+ void slotPanIconHiden();
+
+private:
+
+ void setdemosaicedImg(const DImg& image);
+ void postProcessing(const DRawDecoding& settings);
+ 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);
+
+private:
+
+ RawPreviewPriv* d;
+};
+
+} // NameSpace Digikam
+
+#endif /* RAWPREVIEW_H */
diff --git a/src/utilities/imageeditor/rawimport/rawsettingsbox.cpp b/src/utilities/imageeditor/rawimport/rawsettingsbox.cpp
new file mode 100644
index 00000000..bf0ee67e
--- /dev/null
+++ b/src/utilities/imageeditor/rawimport/rawsettingsbox.cpp
@@ -0,0 +1,741 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-11
+ * Description : Raw import settings box
+ *
+ * Copyright (C) 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 <tqstring.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqhbuttongroup.h>
+#include <tqcombobox.h>
+#include <tqlabel.h>
+#include <tqvbox.h>
+#include <tqtoolbutton.h>
+#include <tqtoolbox.h>
+#include <tqpushbutton.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <ktabwidget.h>
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <tdeconfig.h>
+#include <kstandarddirs.h>
+#include <tdefiledialog.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/dcrawsettingswidget.h>
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imagedialog.h"
+#include "imagehistogram.h"
+#include "imagecurves.h"
+#include "iccpreviewwidget.h"
+#include "histogramwidget.h"
+#include "curveswidget.h"
+#include "colorgradientwidget.h"
+#include "rawsettingsbox.h"
+#include "rawsettingsbox.moc"
+
+using namespace KDcrawIface;
+
+namespace Digikam
+{
+
+class RawSettingsBoxPriv
+{
+public:
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel,
+ ColorChannels
+ };
+
+ enum AllColorsColorType
+ {
+ AllColorsRed=0,
+ AllColorsGreen,
+ AllColorsBlue
+ };
+
+public:
+
+ RawSettingsBoxPriv()
+ {
+ channelCB = 0;
+ colorsCB = 0;
+ scaleBG = 0;
+ hGradient = 0;
+ histogramWidget = 0;
+ infoBox = 0;
+ advExposureBox = 0;
+ gammaLabel = 0;
+ gammaInput = 0;
+ saturationLabel = 0;
+ saturationInput = 0;
+ fineExposureLabel = 0;
+ fineExposureInput = 0;
+ contrastInput = 0;
+ contrastLabel = 0;
+ curveBox = 0;
+ curveWidget = 0;
+ resetCurveBtn = 0;
+ decodingSettingsBox = 0;
+ postProcessSettingsBox = 0;
+ tabView = 0;
+ abortBtn = 0;
+ updateBtn = 0;
+ rawdecodingBox = 0;
+ brightnessLabel = 0;
+ brightnessInput = 0;
+ }
+
+ TQWidget *advExposureBox;
+ TQWidget *curveBox;
+ TQWidget *rawdecodingBox;
+
+ TQComboBox *channelCB;
+ TQComboBox *colorsCB;
+
+ TQLabel *brightnessLabel;
+ TQLabel *contrastLabel;
+ TQLabel *gammaLabel;
+ TQLabel *saturationLabel;
+ TQLabel *fineExposureLabel;
+
+ TQHButtonGroup *scaleBG;
+
+ TQPushButton *abortBtn;
+ TQPushButton *updateBtn;
+
+ TQToolButton *resetCurveBtn;
+
+ TQToolBox *postProcessSettingsBox;
+
+ KTabWidget *tabView;
+
+ ColorGradientWidget *hGradient;
+
+ CurvesWidget *curveWidget;
+
+ HistogramWidget *histogramWidget;
+
+ ImageDialogPreview *infoBox;
+
+ RIntNumInput *contrastInput;
+ RIntNumInput *brightnessInput;
+
+ RDoubleNumInput *gammaInput;
+ RDoubleNumInput *saturationInput;
+ RDoubleNumInput *fineExposureInput;
+
+ DcrawSettingsWidget *decodingSettingsBox;
+};
+
+RawSettingsBox::RawSettingsBox(const KURL& url, TQWidget *parent)
+ : EditorToolSettings(Default|Ok|Cancel, NoTool, parent)
+{
+ d = new RawSettingsBoxPriv;
+
+ // ---------------------------------------------------------------
+
+ TQGridLayout* gridSettings = new TQGridLayout(plainPage(), 5, 4);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), plainPage());
+ label1->setAlignment( TQt::AlignRight | TQt::AlignVCenter );
+ d->channelCB = new TQComboBox(false, plainPage());
+ d->channelCB->insertItem( i18n("Luminosity") );
+ d->channelCB->insertItem( i18n("Red") );
+ d->channelCB->insertItem( i18n("Green") );
+ d->channelCB->insertItem( i18n("Blue") );
+ d->channelCB->insertItem( i18n("Colors") );
+ TQWhatsThis::add(d->channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"
+ "<b>Colors</b>: Display all color channel values at the same time."));
+
+ d->scaleBG = new TQHButtonGroup(plainPage());
+ d->scaleBG->setExclusive(true);
+ d->scaleBG->setFrameShape(TQFrame::NoFrame);
+ d->scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add(d->scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( d->scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ d->scaleBG->insert(linHistoButton, HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( d->scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ d->scaleBG->insert(logHistoButton, HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQLabel *label10 = new TQLabel(i18n("Colors:"), plainPage());
+ label10->setAlignment( TQt::AlignRight | TQt::AlignVCenter );
+ d->colorsCB = new TQComboBox(false, plainPage());
+ d->colorsCB->insertItem( i18n("Red") );
+ d->colorsCB->insertItem( i18n("Green") );
+ d->colorsCB->insertItem( i18n("Blue") );
+ d->colorsCB->setEnabled( false );
+ TQWhatsThis::add( d->colorsCB, i18n("<p>Select the main color displayed with Colors Channel mode here:<p>"
+ "<b>Red</b>: Draw the red image channel in the foreground.<p>"
+ "<b>Green</b>: Draw the green image channel in the foreground.<p>"
+ "<b>Blue</b>: Draw the blue image channel in the foreground.<p>"));
+
+ // ---------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(plainPage());
+ d->histogramWidget = new HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add(d->histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ d->hGradient = new ColorGradientWidget( ColorGradientWidget::Horizontal, 10, histoBox );
+ d->hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ // ---------------------------------------------------------------
+
+ d->tabView = new KTabWidget(plainPage());
+ d->rawdecodingBox = new TQWidget(d->tabView);
+ TQGridLayout* rawGrid = new TQGridLayout(d->rawdecodingBox, 1, 2);
+ d->decodingSettingsBox = new DcrawSettingsWidget(d->rawdecodingBox, true, true, false);
+
+ KFileDialog *inputDlg = d->decodingSettingsBox->inputProfileUrlEdit()->fileDialog();
+ inputDlg->setPreviewWidget(new ICCPreviewWidget(inputDlg));
+
+ KFileDialog *outputDlg = d->decodingSettingsBox->outputProfileUrlEdit()->fileDialog();
+ outputDlg->setPreviewWidget(new ICCPreviewWidget(outputDlg));
+
+ d->abortBtn = new TQPushButton(d->rawdecodingBox);
+ d->abortBtn->setText(i18n("Abort"));
+ d->abortBtn->setIconSet(SmallIconSet("process-stop"));
+ d->abortBtn->setEnabled(false);
+ TQToolTip::add(d->abortBtn, i18n("Abort the current Raw image preview."));
+
+ d->updateBtn = new TQPushButton(d->rawdecodingBox);
+ d->updateBtn->setText(i18n("Update"));
+ d->updateBtn->setIconSet(SmallIconSet("reload_page"));
+ d->updateBtn->setEnabled(false);
+ TQToolTip::add(d->updateBtn, i18n("Generate a Raw image preview using current settings."));
+
+ rawGrid->addMultiCellWidget(d->decodingSettingsBox, 0, 0, 0, 2);
+ rawGrid->addMultiCellWidget(d->abortBtn, 1, 1, 0, 0);
+ rawGrid->addMultiCellWidget(d->updateBtn, 1, 1, 2, 2);
+ rawGrid->setColStretch(1, 10);
+ rawGrid->setSpacing(spacingHint());
+ rawGrid->setMargin(spacingHint());
+
+ // ---------------------------------------------------------------
+
+ d->postProcessSettingsBox = new TQToolBox(d->tabView);
+ d->infoBox = new ImageDialogPreview(d->postProcessSettingsBox);
+ d->infoBox->showPreview(url);
+
+ // ---------------------------------------------------------------
+
+ d->advExposureBox = new TQWidget(d->postProcessSettingsBox);
+ TQGridLayout* advExposureLayout = new TQGridLayout(d->advExposureBox, 5, 2);
+
+ d->brightnessLabel = new TQLabel(i18n("Brightness:"), d->advExposureBox);
+ d->brightnessInput = new RIntNumInput(d->advExposureBox);
+ d->brightnessInput->setRange(-100, 100, 1);
+ d->brightnessInput->setDefaultValue(0);
+ TQWhatsThis::add(d->brightnessInput->input(), i18n("<p>Set here the brightness adjustment of the image."));
+
+ d->contrastLabel = new TQLabel(i18n("Contrast:"), d->advExposureBox);
+ d->contrastInput = new RIntNumInput(d->advExposureBox);
+ d->contrastInput->setRange(-100, 100, 1);
+ d->contrastInput->setDefaultValue(0);
+ TQWhatsThis::add(d->contrastInput->input(), i18n("<p>Set here the contrast adjustment of the image."));
+
+ d->gammaLabel = new TQLabel(i18n("Gamma:"), d->advExposureBox);
+ d->gammaInput = new RDoubleNumInput(d->advExposureBox);
+ d->gammaInput->setPrecision(2);
+ d->gammaInput->setRange(0.1, 3.0, 0.01);
+ d->gammaInput->setDefaultValue(1.0);
+ TQWhatsThis::add(d->gammaInput->input(), i18n("Set here the gamma adjustement of the image"));
+
+ d->saturationLabel = new TQLabel(i18n("Saturation:"), d->advExposureBox);
+ d->saturationInput = new RDoubleNumInput(d->advExposureBox);
+ d->saturationInput->setPrecision(2);
+ d->saturationInput->setRange(0.0, 2.0, 0.01);
+ d->saturationInput->setDefaultValue(1.0);
+ TQWhatsThis::add(d->saturationInput->input(), i18n("<p>Set here the color saturation correction."));
+
+ d->fineExposureLabel = new TQLabel(i18n("Exposure (E.V):"), d->advExposureBox);
+ d->fineExposureInput = new RDoubleNumInput(d->advExposureBox);
+ d->fineExposureInput->setPrecision(2);
+ d->fineExposureInput->setRange(-3.0, 3.0, 0.1);
+ d->fineExposureInput->setDefaultValue(0.0);
+ TQWhatsThis::add(d->fineExposureInput->input(), i18n("<p>This value in E.V will be used to perform "
+ "an exposure compensation of the image."));
+
+ advExposureLayout->addMultiCellWidget(d->brightnessLabel, 0, 0, 0, 0);
+ advExposureLayout->addMultiCellWidget(d->brightnessInput, 0, 0, 1, 2);
+ advExposureLayout->addMultiCellWidget(d->contrastLabel, 1, 1, 0, 0);
+ advExposureLayout->addMultiCellWidget(d->contrastInput, 1, 1, 1, 2);
+ advExposureLayout->addMultiCellWidget(d->gammaLabel, 2, 2, 0, 0);
+ advExposureLayout->addMultiCellWidget(d->gammaInput, 2, 2, 1, 2);
+ advExposureLayout->addMultiCellWidget(d->saturationLabel, 3, 3, 0, 0);
+ advExposureLayout->addMultiCellWidget(d->saturationInput, 3, 3, 1, 2);
+ advExposureLayout->addMultiCellWidget(d->fineExposureLabel, 4, 4, 0, 0);
+ advExposureLayout->addMultiCellWidget(d->fineExposureInput, 4, 4, 1, 2);
+ advExposureLayout->setRowStretch(5, 10);
+ advExposureLayout->setSpacing(0);
+ advExposureLayout->setMargin(spacingHint());
+
+ // ---------------------------------------------------------------
+
+ d->curveBox = new TQWidget(d->postProcessSettingsBox);
+ TQGridLayout* curveLayout = new TQGridLayout(d->curveBox, 3, 2);
+
+ ColorGradientWidget* vGradient = new ColorGradientWidget(ColorGradientWidget::Vertical, 10, d->curveBox);
+ vGradient->setColors( TQColor( "white" ), TQColor( "black" ) );
+
+ TQLabel *spacev = new TQLabel(d->curveBox);
+ spacev->setFixedWidth(1);
+
+ d->curveWidget = new CurvesWidget(256, 192, d->curveBox);
+ TQWhatsThis::add(d->curveWidget, i18n("<p>This is the curve adjustment of the image luminosity"));
+
+ d->resetCurveBtn = new TQToolButton(d->curveBox);
+ d->resetCurveBtn->setFixedSize(11, 11);
+ d->resetCurveBtn->setIconSet(SmallIconSet("reload_page", 8));
+ d->resetCurveBtn->setFocusPolicy(TQWidget::NoFocus);
+ d->resetCurveBtn->setAutoRaise(true);
+ TQToolTip::add(d->resetCurveBtn, i18n("Reset curve to linear"));
+
+ TQLabel *spaceh = new TQLabel(d->curveBox);
+ spaceh->setFixedHeight(1);
+
+ ColorGradientWidget *hGradient = new ColorGradientWidget(ColorGradientWidget::Horizontal, 10, d->curveBox);
+ hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ curveLayout->addMultiCellWidget(vGradient, 0, 0, 0, 0);
+ curveLayout->addMultiCellWidget(spacev, 0, 0, 1, 1);
+ curveLayout->addMultiCellWidget(d->curveWidget, 0, 0, 2, 2);
+ curveLayout->addMultiCellWidget(spaceh, 1, 1, 2, 2);
+ curveLayout->addMultiCellWidget(d->resetCurveBtn, 1, 2, 0, 1);
+ curveLayout->addMultiCellWidget(hGradient, 2, 2, 2, 2);
+ curveLayout->setRowStretch(3, 10);
+ curveLayout->setSpacing(0);
+ curveLayout->setMargin(spacingHint());
+
+ // ---------------------------------------------------------------
+
+ d->postProcessSettingsBox->addItem(d->advExposureBox, i18n("Exposure"));
+ d->postProcessSettingsBox->addItem(d->curveBox, i18n("Luminosity Curve"));
+ d->postProcessSettingsBox->setItemIconSet(0, SmallIconSet("contrast"));
+ d->postProcessSettingsBox->setItemIconSet(1, SmallIconSet("adjustcurves"));
+
+ d->decodingSettingsBox->setItemIconSet(DcrawSettingsWidget::DEMOSAICING, SmallIconSet("kdcraw"));
+ d->decodingSettingsBox->setItemIconSet(DcrawSettingsWidget::WHITEBALANCE, SmallIconSet("whitebalance"));
+ d->decodingSettingsBox->setItemIconSet(DcrawSettingsWidget::CORRECTIONS, SmallIconSet("lensdistortion"));
+ d->decodingSettingsBox->setItemIconSet(DcrawSettingsWidget::COLORMANAGEMENT, SmallIconSet("colormanagement"));
+ d->decodingSettingsBox->updateMinimumWidth();
+
+ d->tabView->insertTab(d->rawdecodingBox, i18n("Raw Decoding"), 0);
+ d->tabView->insertTab(d->postProcessSettingsBox, i18n("Post Processing"), 1);
+ d->tabView->insertTab(d->infoBox, i18n("Info"), 2);
+
+ // ---------------------------------------------------------------
+
+ button(Default)->setText(i18n("Reset"));
+ button(Default)->setIconSet(SmallIconSet("reload_page"));
+ TQToolTip::add(button(Default), i18n("<p>Reset all settings to default values."));
+
+ button(Ok)->setText(i18n("Import"));
+ button(Ok)->setIconSet(SmallIconSet("ok"));
+ TQToolTip::add(button(Ok), i18n("<p>Import image to editor using current settings."));
+
+ button(Cancel)->setText(i18n("Use Default"));
+ button(Cancel)->setIconSet(SmallIconSet("go-home"));
+ TQToolTip::add(button(Cancel), i18n("<p>Use general Raw decoding settings to load this image in editor."));
+
+ // ---------------------------------------------------------------
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 0);
+ gridSettings->addMultiCellWidget(d->channelCB, 0, 0, 1, 1);
+ gridSettings->addMultiCellWidget(d->scaleBG, 0, 0, 4, 4);
+ gridSettings->addMultiCellWidget(label10, 1, 1, 0, 0);
+ gridSettings->addMultiCellWidget(d->colorsCB, 1, 1, 1, 1);
+ gridSettings->addMultiCellWidget(histoBox, 2, 3, 0, 4);
+ gridSettings->addMultiCellWidget(d->tabView, 4, 4, 0, 4);
+ gridSettings->setRowStretch(5, 10);
+ gridSettings->setColStretch(2, 10);
+ gridSettings->setSpacing(spacingHint());
+ gridSettings->setMargin(0);
+
+ // ---------------------------------------------------------------
+
+ connect(d->channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(d->scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(d->colorsCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotColorsChanged(int)));
+
+ connect(d->resetCurveBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotResetCurve()));
+
+ connect(d->updateBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalUpdatePreview()));
+
+ connect(d->abortBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalAbortPreview()));
+
+ connect(d->decodingSettingsBox, TQ_SIGNAL(signalSettingsChanged()),
+ this, TQ_SIGNAL(signalDemosaicingChanged()));
+
+ connect(d->curveWidget, TQ_SIGNAL(signalCurvesChanged()),
+ this, TQ_SIGNAL(signalPostProcessingChanged()));
+
+ connect(d->brightnessInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SIGNAL(signalPostProcessingChanged()));
+
+ connect(d->contrastInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SIGNAL(signalPostProcessingChanged()));
+
+ connect(d->gammaInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SIGNAL(signalPostProcessingChanged()));
+
+ connect(d->saturationInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SIGNAL(signalPostProcessingChanged()));
+
+ connect(d->fineExposureInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SIGNAL(signalPostProcessingChanged()));
+}
+
+RawSettingsBox::~RawSettingsBox()
+{
+ delete d->curveWidget;
+ delete d;
+}
+
+void RawSettingsBox::enableUpdateBtn(bool b)
+{
+ d->updateBtn->setEnabled(b);
+}
+
+void RawSettingsBox::setBusy(bool b)
+{
+ d->decodingSettingsBox->setEnabled(!b);
+ d->abortBtn->setEnabled(b);
+}
+
+void RawSettingsBox::setDemosaicedImage(DImg& img)
+{
+ d->curveWidget->stopHistogramComputation();
+ d->curveWidget->updateData(img.bits(), img.width(), img.height(), img.sixteenBit());
+}
+
+void RawSettingsBox::setPostProcessedImage(DImg& img)
+{
+ d->histogramWidget->stopHistogramComputation();
+ d->histogramWidget->updateData(img.bits(), img.width(), img.height(), img.sixteenBit());
+}
+
+void RawSettingsBox::resetSettings()
+{
+ d->decodingSettingsBox->setDefaultSettings();
+ d->brightnessInput->slotReset();
+ d->contrastInput->slotReset();
+ d->gammaInput->slotReset();
+ d->saturationInput->slotReset();
+ d->fineExposureInput->slotReset();
+ slotResetCurve();
+}
+
+void RawSettingsBox::slotResetCurve()
+{
+ d->curveWidget->reset();
+ emit signalPostProcessingChanged();
+}
+
+HistogramWidget* RawSettingsBox::histogram() const
+{
+ return d->histogramWidget;
+}
+
+CurvesWidget* RawSettingsBox::curve() const
+{
+ return d->curveWidget;
+}
+
+void RawSettingsBox::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("RAW Import Settings");
+
+ d->channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", RawSettingsBoxPriv::LuminosityChannel));
+ d->scaleBG->setButton(config->readNumEntry("Histogram Scale", HistogramWidget::LogScaleHistogram));
+ d->colorsCB->setCurrentItem(config->readNumEntry("Histogram Color", RawSettingsBoxPriv::AllColorsRed));
+
+ d->decodingSettingsBox->setSixteenBits(config->readBoolEntry("SixteenBitsImage", false));
+ d->decodingSettingsBox->setWhiteBalance((DRawDecoding::WhiteBalance)
+ config->readNumEntry("White Balance",
+ DRawDecoding::CAMERA));
+ d->decodingSettingsBox->setCustomWhiteBalance(config->readNumEntry("Custom White Balance", 6500));
+ d->decodingSettingsBox->setCustomWhiteBalanceGreen(config->readDoubleNumEntry("Custom White Balance Green", 1.0));
+ d->decodingSettingsBox->setFourColor(config->readBoolEntry("Four Color RGB", false));
+ d->decodingSettingsBox->setUnclipColor(config->readNumEntry("Unclip Color", 0));
+ d->decodingSettingsBox->setDontStretchPixels(config->readBoolEntry("Dont Stretch Pixels", false));
+ d->decodingSettingsBox->setNoiseReduction(config->readBoolEntry("Use Noise Reduction", false));
+ d->decodingSettingsBox->setUseBlackPoint(config->readBoolEntry("Use Black Point", false));
+ d->decodingSettingsBox->setBlackPoint(config->readNumEntry("Black Point", 0));
+ d->decodingSettingsBox->setUseWhitePoint(config->readBoolEntry("Use White Point", false));
+ d->decodingSettingsBox->setWhitePoint(config->readNumEntry("White Point", 0));
+ d->decodingSettingsBox->setMedianFilterPasses(config->readNumEntry("Median Filter Passes", 0));
+ d->decodingSettingsBox->setNRThreshold(config->readNumEntry("NR Threshold", 100));
+ d->decodingSettingsBox->setUseCACorrection(config->readBoolEntry("EnableCACorrection", false));
+ d->decodingSettingsBox->setcaRedMultiplier(config->readDoubleNumEntry("caRedMultiplier", 1.0));
+ d->decodingSettingsBox->setcaBlueMultiplier(config->readDoubleNumEntry("caBlueMultiplier", 1.0));
+
+ d->decodingSettingsBox->setQuality(
+ (DRawDecoding::DecodingQuality)config->readNumEntry("Decoding Quality",
+ (int)(DRawDecoding::BILINEAR)));
+
+ d->decodingSettingsBox->setInputColorSpace(
+ (DRawDecoding::InputColorSpace)config->readNumEntry("Input Color Space",
+ (int)(DRawDecoding::NOINPUTCS)));
+
+ d->decodingSettingsBox->setOutputColorSpace(
+ (DRawDecoding::OutputColorSpace)config->readNumEntry("Output Color Space",
+ (int)(DRawDecoding::SRGB)));
+
+ d->decodingSettingsBox->setInputColorProfile(config->readPathEntry("Input Color Profile", TQString()));
+ d->decodingSettingsBox->setOutputColorProfile(config->readPathEntry("Output Color Profile", TQString()));
+
+ d->brightnessInput->setValue(config->readNumEntry("Brightness", 0));
+ d->contrastInput->setValue(config->readNumEntry("Contrast", 0));
+ d->gammaInput->setValue(config->readDoubleNumEntry("Gamma", 1.0));
+ d->saturationInput->setValue(config->readDoubleNumEntry("Saturation", 1.0));
+ d->fineExposureInput->setValue(config->readDoubleNumEntry("FineExposure", 0.0));
+
+ d->curveWidget->reset();
+
+ for (int j = 0 ; j <= 17 ; j++)
+ {
+ TQPoint disable(-1, -1);
+ TQPoint p = config->readPointEntry(TQString("CurveAjustmentPoint%1").arg(j), &disable);
+ if (!d->decodingSettingsBox->sixteenBits() && p != disable)
+ {
+ // Restore point as 16 bits depth.
+ p.setX(p.x()/255);
+ p.setY(p.y()/255);
+ }
+ d->curveWidget->curves()->setCurvePoint(ImageHistogram::ValueChannel, j, p);
+ }
+ d->curveWidget->curves()->curvesCalculateCurve(ImageHistogram::ValueChannel);
+
+ d->tabView->setCurrentPage(config->readNumEntry("Settings Page", 0));
+ d->decodingSettingsBox->setCurrentIndex(config->readNumEntry("Decoding Settings Tab", DcrawSettingsWidget::DEMOSAICING));
+ d->postProcessSettingsBox->setCurrentIndex(config->readNumEntry("Post Processing Settings Tab", 0));
+
+ slotChannelChanged(d->channelCB->currentItem());
+ slotScaleChanged(d->scaleBG->selectedId());
+ slotColorsChanged(d->colorsCB->currentItem());
+}
+
+void RawSettingsBox::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("RAW Import Settings");
+
+ config->writeEntry("Histogram Channel", d->channelCB->currentItem());
+ config->writeEntry("Histogram Scale", d->scaleBG->selectedId());
+ config->writeEntry("Histogram Color", d->colorsCB->currentItem());
+
+ config->writeEntry("SixteenBitsImage", d->decodingSettingsBox->sixteenBits());
+ config->writeEntry("White Balance", d->decodingSettingsBox->whiteBalance());
+ config->writeEntry("Custom White Balance", d->decodingSettingsBox->customWhiteBalance());
+ config->writeEntry("Custom White Balance Green", d->decodingSettingsBox->customWhiteBalanceGreen());
+ config->writeEntry("Four Color RGB", d->decodingSettingsBox->useFourColor());
+ config->writeEntry("Unclip Color", d->decodingSettingsBox->unclipColor());
+ config->writeEntry("Dont Stretch Pixels", d->decodingSettingsBox->useDontStretchPixels());
+ config->writeEntry("Use Noise Reduction", d->decodingSettingsBox->useNoiseReduction());
+ config->writeEntry("Use Black Point", d->decodingSettingsBox->useBlackPoint());
+ config->writeEntry("Black Point", d->decodingSettingsBox->blackPoint());
+ config->writeEntry("Use White Point", d->decodingSettingsBox->useWhitePoint());
+ config->writeEntry("White Point", d->decodingSettingsBox->whitePoint());
+ config->writeEntry("MedianFilterPasses", d->decodingSettingsBox->medianFilterPasses());
+ config->writeEntry("NR Threshold", d->decodingSettingsBox->NRThreshold());
+ config->writeEntry("EnableCACorrection", d->decodingSettingsBox->useCACorrection());
+ config->writeEntry("caRedMultiplier", d->decodingSettingsBox->caRedMultiplier());
+ config->writeEntry("caBlueMultiplier", d->decodingSettingsBox->caBlueMultiplier());
+ config->writeEntry("Decoding Quality", (int)d->decodingSettingsBox->quality());
+ config->writeEntry("Input Color Space", (int)d->decodingSettingsBox->inputColorSpace());
+ config->writeEntry("Output Color Space", (int)d->decodingSettingsBox->outputColorSpace());
+ config->writeEntry("Input Color Profile", d->decodingSettingsBox->inputColorProfile());
+ config->writeEntry("Output Color Profile", d->decodingSettingsBox->outputColorProfile());
+
+ config->writeEntry("Brightness", d->brightnessInput->value());
+ config->writeEntry("Contrast", d->contrastInput->value());
+ config->writeEntry("Gamma", d->gammaInput->value());
+ config->writeEntry("Saturation", d->saturationInput->value());
+ config->writeEntry("FineExposure", d->fineExposureInput->value());
+
+ for (int j = 0 ; j <= 17 ; j++)
+ {
+ TQPoint p = d->curveWidget->curves()->getCurvePoint(ImageHistogram::ValueChannel, j);
+ if (!d->curveWidget->curves()->isSixteenBits())
+ {
+ // Store point as 16 bits depth.
+ p.setX(p.x()*255);
+ p.setY(p.y()*255);
+ }
+ config->writeEntry(TQString("CurveAjustmentPoint%1").arg(j), p);
+ }
+
+ config->writeEntry("Settings Page", d->tabView->currentPage());
+ config->writeEntry("Decoding Settings Tab", d->decodingSettingsBox->currentIndex());
+ config->writeEntry("Post Processing Settings Tab", d->postProcessSettingsBox->currentIndex());
+ config->sync();
+}
+
+DRawDecoding RawSettingsBox::settings()
+{
+ DRawDecoding settings;
+ settings.sixteenBitsImage = d->decodingSettingsBox->sixteenBits();
+ settings.whiteBalance = d->decodingSettingsBox->whiteBalance();
+ settings.customWhiteBalance = d->decodingSettingsBox->customWhiteBalance();
+ settings.customWhiteBalanceGreen = d->decodingSettingsBox->customWhiteBalanceGreen();
+ settings.RGBInterpolate4Colors = d->decodingSettingsBox->useFourColor();
+ settings.unclipColors = d->decodingSettingsBox->unclipColor();
+ settings.DontStretchPixels = d->decodingSettingsBox->useDontStretchPixels();
+ settings.enableNoiseReduction = d->decodingSettingsBox->useNoiseReduction();
+ settings.enableBlackPoint = d->decodingSettingsBox->useBlackPoint();
+ settings.blackPoint = d->decodingSettingsBox->blackPoint();
+ settings.enableWhitePoint = d->decodingSettingsBox->useWhitePoint();
+ settings.whitePoint = d->decodingSettingsBox->whitePoint();
+ settings.medianFilterPasses = d->decodingSettingsBox->medianFilterPasses();
+ settings.NRThreshold = d->decodingSettingsBox->NRThreshold();
+ settings.enableCACorrection = d->decodingSettingsBox->useCACorrection();
+ settings.caMultiplier[0] = d->decodingSettingsBox->caRedMultiplier();
+ settings.caMultiplier[1] = d->decodingSettingsBox->caBlueMultiplier();
+ settings.RAWQuality = d->decodingSettingsBox->quality();
+ settings.inputColorSpace = d->decodingSettingsBox->inputColorSpace();
+ settings.outputColorSpace = d->decodingSettingsBox->outputColorSpace();
+ settings.inputProfile = d->decodingSettingsBox->inputColorProfile();
+ settings.outputProfile = d->decodingSettingsBox->outputColorProfile();
+
+ settings.lightness = (double)d->brightnessInput->value()/250.0;
+ settings.contrast = (double)(d->contrastInput->value()/100.0) + 1.00;
+ settings.gamma = d->gammaInput->value();
+ settings.saturation = d->saturationInput->value();
+ settings.exposureComp = d->fineExposureInput->value();
+
+ if (d->curveWidget->curves()->isDirty())
+ settings.curveAdjust = d->curveWidget->curves()->getCurvePoints(ImageHistogram::ValueChannel);
+
+ return settings;
+}
+
+void RawSettingsBox::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case RawSettingsBoxPriv::LuminosityChannel:
+ d->histogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ d->hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ d->colorsCB->setEnabled(false);
+ break;
+
+ case RawSettingsBoxPriv::RedChannel:
+ d->histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ d->hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ d->colorsCB->setEnabled(false);
+ break;
+
+ case RawSettingsBoxPriv::GreenChannel:
+ d->histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ d->hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ d->colorsCB->setEnabled(false);
+ break;
+
+ case RawSettingsBoxPriv::BlueChannel:
+ d->histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ d->hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ d->colorsCB->setEnabled(false);
+ break;
+
+ case RawSettingsBoxPriv::ColorChannels:
+ d->histogramWidget->m_channelType = HistogramWidget::ColorChannelsHistogram;
+ d->hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ d->colorsCB->setEnabled(true);
+ break;
+ }
+
+ d->histogramWidget->repaint(false);
+}
+
+void RawSettingsBox::slotScaleChanged(int scale)
+{
+ d->histogramWidget->m_scaleType = scale;
+ d->histogramWidget->repaint(false);
+}
+
+void RawSettingsBox::slotColorsChanged(int color)
+{
+ switch(color)
+ {
+ case RawSettingsBoxPriv::AllColorsGreen:
+ d->histogramWidget->m_colorType = HistogramWidget::GreenColor;
+ break;
+
+ case RawSettingsBoxPriv::AllColorsBlue:
+ d->histogramWidget->m_colorType = HistogramWidget::BlueColor;
+ break;
+
+ default: // Red.
+ d->histogramWidget->m_colorType = HistogramWidget::RedColor;
+ break;
+ }
+
+ d->histogramWidget->repaint(false);
+}
+
+} // NameSpace Digikam
diff --git a/src/utilities/imageeditor/rawimport/rawsettingsbox.h b/src/utilities/imageeditor/rawimport/rawsettingsbox.h
new file mode 100644
index 00000000..546ce1e5
--- /dev/null
+++ b/src/utilities/imageeditor/rawimport/rawsettingsbox.h
@@ -0,0 +1,91 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-11
+ * Description : Raw import settings box
+ *
+ * Copyright (C) 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 RAWSETTINGSBOX_H
+#define RAWSETTINGSBOX_H
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Local includes.
+
+#include "editortoolsettings.h"
+#include "dimg.h"
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class HistogramWidget;
+class CurvesWidget;
+class RawSettingsBoxPriv;
+
+class DIGIKAM_EXPORT RawSettingsBox : public EditorToolSettings
+{
+ TQ_OBJECT
+
+
+public:
+
+ RawSettingsBox(const KURL& url, TQWidget *parent);
+ ~RawSettingsBox();
+
+ void setBusy(bool b);
+
+ HistogramWidget* histogram() const;
+ CurvesWidget* curve() const;
+ DRawDecoding settings();
+
+ void writeSettings();
+ void readSettings();
+
+ void setDemosaicedImage(DImg& img);
+ void setPostProcessedImage(DImg& img);
+
+ void enableUpdateBtn(bool b);
+
+ void resetSettings();
+
+signals:
+
+ void signalUpdatePreview();
+ void signalAbortPreview();
+ void signalDemosaicingChanged();
+ void signalPostProcessingChanged();
+
+private slots:
+
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotColorsChanged(int color);
+
+ void slotResetCurve();
+
+private:
+
+ RawSettingsBoxPriv *d;
+};
+
+} // NameSpace Digikam
+
+#endif // RAWSETTINGSBOX_H
diff --git a/src/utilities/imageeditor/tools/Makefile.am b/src/utilities/imageeditor/tools/Makefile.am
new file mode 100644
index 00000000..b76207ff
--- /dev/null
+++ b/src/utilities/imageeditor/tools/Makefile.am
@@ -0,0 +1,19 @@
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libdimgeditortools.la
+
+libdimgeditortools_la_SOURCES = imageresize.cpp imageprint.cpp
+
+libdimgeditortools_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TDEPRINT)
+
+INCLUDES= -I$(top_srcdir)/src/digikam \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/greycstoration \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
diff --git a/src/utilities/imageeditor/tools/imageprint.cpp b/src/utilities/imageeditor/tools/imageprint.cpp
new file mode 100644
index 00000000..5cab236b
--- /dev/null
+++ b/src/utilities/imageeditor/tools/imageprint.cpp
@@ -0,0 +1,814 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-13
+ * Description : image editor printing interface.
+ *
+ * Copyright (C) 2006 by F.J. Cruz <fj.cruz@supercable.es>
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * KeepRatio and Alignment options imported from Gwenview program.
+ * Copyright (c) 2003 Angelo Naselli <anaselli at linux dot it>
+ *
+ * Original printing code from Kuickshow program.
+ * Copyright (C) 2002 Carsten Pfeiffer <pfeiffer at kde.org>
+ *
+ * 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 <tqobject.h>
+#include <tqpixmap.h>
+#include <tqlayout.h>
+#include <tqgroupbox.h>
+#include <tqbuttongroup.h>
+#include <tqstring.h>
+#include <tqsize.h>
+#include <tqcursor.h>
+#include <tqlabel.h>
+#include <tqhbox.h>
+#include <tqcheckbox.h>
+#include <tqfont.h>
+#include <tqgrid.h>
+#include <tqimage.h>
+#include <tqpaintdevicemetrics.h>
+#include <tqpainter.h>
+#include <tqradiobutton.h>
+#include <tqvbuttongroup.h>
+#include <tqcolor.h>
+#include <tqcombobox.h>
+#include <tqstyle.h>
+#include <tqpushbutton.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <kstandarddirs.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kimageio.h>
+#include <kcombobox.h>
+#include <tdeglobalsettings.h>
+#include <knuminput.h>
+#include <kprinter.h>
+#include <tdetempfile.h>
+#include <kpropertiesdialog.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "editorwindow.h"
+#include "icctransform.h"
+#include "imageprint.h"
+#include "imageprint.moc"
+
+namespace Digikam
+{
+
+class ImagePrintPrivate
+{
+
+public:
+
+ ImagePrintPrivate(){}
+
+ TQString filename;
+ TQString inProfilePath;
+ TQString outputProfilePath;
+
+ DImg image;
+};
+
+ImagePrint::ImagePrint(DImg& image, KPrinter& printer, const TQString& filename)
+ : m_printer(printer)
+{
+ d = new ImagePrintPrivate();
+ d->image = image;
+ d->filename = filename;
+}
+
+ImagePrint::~ImagePrint()
+{
+ delete d;
+}
+
+bool ImagePrint::printImageWithTQt()
+{
+ if ( d->image.isNull() )
+ {
+ DWarning() << "Supplied Image for printing is null" << endl;
+ return false;
+ }
+
+ TQString t = "true";
+ TQString f = "false";
+
+ if (m_printer.option( "app-imageeditor-color-managed") != f)
+ {
+ IccTransform *transform = new IccTransform();
+ readSettings();
+
+ if (d->image.getICCProfil().isNull())
+ {
+ transform->setProfiles( d->inProfilePath, d->outputProfilePath );
+ }
+ else
+ {
+ transform->setProfiles(d->outputProfilePath);
+ }
+
+ transform->apply( d->image );
+ }
+
+ TQImage image2Print = d->image.copyTQImage();
+
+ // Black & white print ?
+ if ( m_printer.option( "app-imageeditor-blackwhite" ) != f)
+ {
+ image2Print = image2Print.convertDepth( 1, TQt::MonoOnly |
+ TQt::ThresholdDither |
+ TQt::AvoidDither );
+ }
+
+ TQPainter p;
+ p.begin( &m_printer );
+
+ TQPaintDeviceMetrics metrics( &m_printer );
+ p.setFont( TDEGlobalSettings::generalFont() );
+ TQFontMetrics fm = p.fontMetrics();
+
+ int w, h; // will be set to the width and height of the printer
+ // when the orientation is decided.
+ w = metrics.width();
+ h = metrics.height();
+ int filenameOffset = 0;
+
+ TQSize size = image2Print.size();
+
+ bool printFilename = m_printer.option( "app-imageeditor-printFilename" ) != f;
+ if ( printFilename )
+ {
+ // filename goes into one line!
+ filenameOffset = fm.lineSpacing() + 14;
+ h -= filenameOffset;
+ }
+
+ if ( m_printer.option( "app-imageeditor-scaleToFit" ) != f )
+ {
+ if ( m_printer.option( "app-imageeditor-auto-rotate" ) == t )
+ m_printer.setOrientation( size.width() <= size.height() ? KPrinter::Portrait
+ : KPrinter::Landscape );
+
+ // Scale image to fit pagesize
+ size.scale( w, h, TQSize::ScaleMin );
+ }
+ else
+ {
+ int unit = (m_printer.option("app-imageeditor-scale-unit").isEmpty() ?
+ ImageEditorPrintDialogPage::DK_INCHES : m_printer.option("app-imageeditor-scale-unit").toInt());
+ double inches = 1;
+
+ if (unit == ImageEditorPrintDialogPage::DK_MILLIMETERS)
+ {
+ inches = 1/25.4;
+ }
+ else if (unit == ImageEditorPrintDialogPage::DK_CENTIMETERS)
+ {
+ inches = 1/2.54;
+ }
+
+ double wImg = (m_printer.option("app-imageeditor-scale-width").isEmpty() ?
+ 1 : m_printer.option("app-imageeditor-scale-width").toDouble()) * inches;
+ double hImg = (m_printer.option("app-imageeditor-scale-height").isEmpty() ?
+ 1 : m_printer.option("app-imageeditor-scale-height").toDouble()) * inches;
+ size.setWidth( int(wImg * m_printer.resolution()) );
+ size.setHeight( int(hImg * m_printer.resolution()) );
+
+ if ( m_printer.option( "app-imageeditor-auto-rotate" ) == t )
+ m_printer.setOrientation( wImg <= hImg ? KPrinter::Portrait : KPrinter::Landscape );
+
+ if (size.width() > w || size.height() > h)
+ {
+ int resp = KMessageBox::warningYesNoCancel(TDEApplication::kApplication()->mainWidget(),
+ i18n("The image will not fit on the page, what do you want to do?"),
+ TQString(),KStdGuiItem::cont(),
+ i18n("Shrink") );
+
+ if (resp==KMessageBox::Cancel)
+ {
+ m_printer.abort();
+ // no need to return false, user decided to abort
+ return true;
+ }
+ else if (resp == KMessageBox::No)
+ { // Shrink
+ size.scale(w, h, TQSize::ScaleMin);
+ }
+ }
+ }
+
+ // Align image.
+ int alignment = (m_printer.option("app-imageeditor-alignment").isEmpty() ?
+ TQt::AlignCenter : m_printer.option("app-imageeditor-alignment").toInt());
+
+ int x = 0;
+ int y = 0;
+
+ // x - alignment
+ if ( alignment & TQt::AlignHCenter )
+ x = (w - size.width())/2;
+ else if ( alignment & TQt::AlignLeft )
+ x = 0;
+ else if ( alignment & TQt::AlignRight )
+ x = w - size.width();
+
+ // y - alignment
+ if ( alignment & TQt::AlignVCenter )
+ y = (h - size.height())/2;
+ else if ( alignment & TQt::AlignTop )
+ y = 0;
+ else if ( alignment & TQt::AlignBottom )
+ y = h - size.height();
+
+ // Perform the actual drawing.
+ p.drawImage( TQRect( x, y, size.width(), size.height()), image2Print );
+
+ if ( printFilename )
+ {
+ TQString fname = minimizeString( d->filename, fm, w );
+
+ if ( !fname.isEmpty() )
+ {
+ int fw = fm.width( fname );
+ int x = (w - fw)/2;
+ int y = metrics.height() - filenameOffset/2;
+ p.drawText( x, y, fname );
+ }
+ }
+
+ p.end();
+
+ return true;
+}
+
+TQString ImagePrint::minimizeString( TQString text, const TQFontMetrics& metrics,
+ int maxWidth )
+{
+ // no sense to cut that tiny little string
+ if ( text.length() <= 5 )
+ return TQString();
+
+ bool changed = false;
+
+ while ( metrics.width( text ) > maxWidth )
+ {
+ int mid = text.length() / 2;
+ // remove 2 characters in the middle
+ text.remove( mid, 2 );
+ changed = true;
+ }
+
+ // add "..." in the middle
+ if ( changed )
+ {
+ int mid = text.length() / 2;
+
+ // sanity check
+ if ( mid <= 5 )
+ return TQString();
+
+ text.replace( mid - 1, 3, "..." );
+ }
+
+ return text;
+}
+
+void ImagePrint::readSettings()
+{
+ TDEConfig* config = kapp->config();
+
+ config->setGroup("Color Management");
+
+ d->inProfilePath = config->readPathEntry("WorkSpaceProfile");
+ d->outputProfilePath = config->readPathEntry("ProofProfileFile");
+}
+
+// Image print dialog class -------------------------------------------------------------
+
+class ImageEditorPrintDialogPagePrivate
+{
+
+public:
+
+ ImageEditorPrintDialogPagePrivate()
+ {
+ cmEnabled = false;
+ position = 0;
+ keepRatio = 0;
+ scaleToFit = 0;
+ scale = 0;
+ addFileName = 0;
+ blackwhite = 0;
+ autoRotate = 0;
+ colorManaged = 0;
+ cmPreferences = 0;
+ parent = 0;
+ width = 0;
+ height = 0;
+ units = 0;
+ }
+
+ bool cmEnabled;
+
+ TQRadioButton *scaleToFit;
+ TQRadioButton *scale;
+
+ TQCheckBox *keepRatio;
+ TQCheckBox *addFileName;
+ TQCheckBox *blackwhite;
+ TQCheckBox *autoRotate;
+ TQCheckBox *colorManaged;
+
+ TQPushButton *cmPreferences;
+
+ TQWidget *parent;
+
+ KDoubleNumInput *width;
+ KDoubleNumInput *height;
+
+ KComboBox *position;
+ KComboBox *units;
+
+ DImg image;
+
+ ImageEditorPrintDialogPage::Unit previousUnit;
+};
+
+ImageEditorPrintDialogPage::ImageEditorPrintDialogPage(DImg& image, TQWidget *parent, const char *name )
+ : KPrintDialogPage( parent, name )
+{
+ d = new ImageEditorPrintDialogPagePrivate;
+ d->image = image;
+ d->parent = parent;
+ setTitle( i18n("Image Settings") );
+
+ readSettings();
+
+ TQVBoxLayout *layout = new TQVBoxLayout( this );
+ layout->setMargin( KDialog::marginHint() );
+ layout->setSpacing( KDialog::spacingHint() );
+
+ // ------------------------------------------------------------------------
+
+ TQHBoxLayout *layout2 = new TQHBoxLayout( layout );
+ layout2->setSpacing(3);
+
+ TQLabel* textLabel = new TQLabel( this, "Image position:" );
+ textLabel->setText( i18n( "Image position:" ) );
+ layout2->addWidget( textLabel );
+ d->position = new KComboBox( false, this, "Print position" );
+ d->position->clear();
+ d->position->insertItem( i18n( "Top-Left" ) );
+ d->position->insertItem( i18n( "Top-Central" ) );
+ d->position->insertItem( i18n( "Top-Right" ) );
+ d->position->insertItem( i18n( "Central-Left" ) );
+ d->position->insertItem( i18n( "Central" ) );
+ d->position->insertItem( i18n( "Central-Right" ) );
+ d->position->insertItem( i18n( "Bottom-Left" ) );
+ d->position->insertItem( i18n( "Bottom-Central" ) );
+ d->position->insertItem( i18n( "Bottom-Right" ) );
+ layout2->addWidget( d->position );
+ TQSpacerItem *spacer1 = new TQSpacerItem( 101, 21, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+ layout2->addItem( spacer1 );
+
+ d->addFileName = new TQCheckBox( i18n("Print fi&lename below image"), this);
+ d->addFileName->setChecked( false );
+ layout->addWidget( d->addFileName );
+
+ d->blackwhite = new TQCheckBox ( i18n("Print image in &black and white"), this);
+ d->blackwhite->setChecked( false );
+ layout->addWidget (d->blackwhite );
+
+ d->autoRotate = new TQCheckBox( i18n("&Auto-rotate page"), this );
+ d->autoRotate->setChecked( false );
+ layout->addWidget( d->autoRotate );
+
+ // ------------------------------------------------------------------------
+
+ TQHBox *cmbox = new TQHBox(this);
+
+ d->colorManaged = new TQCheckBox(i18n("Use Color Management for Printing"), cmbox);
+ d->colorManaged->setChecked( false );
+
+ d->cmPreferences = new TQPushButton(i18n("Settings..."), cmbox);
+
+ TQWidget *space = new TQWidget(cmbox);
+ cmbox->setStretchFactor(space, 10);
+ cmbox->setSpacing(KDialog::spacingHint());
+
+ layout->addWidget(cmbox);
+
+ // ------------------------------------------------------------------------
+
+ TQVButtonGroup *group = new TQVButtonGroup( i18n("Scaling"), this );
+ group->setRadioButtonExclusive( true );
+ layout->addWidget( group );
+
+ d->scaleToFit = new TQRadioButton( i18n("Scale image to &fit"), group );
+ d->scaleToFit->setChecked( true );
+
+ d->scale = new TQRadioButton( i18n("Print e&xact size: "), group );
+
+ TQHBox *hb = new TQHBox( group );
+ hb->setSpacing( KDialog::spacingHint() );
+ TQWidget *w = new TQWidget(hb);
+ w->setFixedWidth(d->scale->style().subRect( TQStyle::SR_RadioButtonIndicator, d->scale ).width());
+
+ d->width = new KDoubleNumInput( hb, "exact width" );
+ d->width->setMinValue( 1 );
+
+ new TQLabel( "x", hb );
+
+ d->height = new KDoubleNumInput( hb, "exact height" );
+ d->height->setMinValue( 1 );
+
+ d->units = new KComboBox( false, hb, "unit combobox" );
+ d->units->insertItem( i18n("Millimeters") );
+ d->units->insertItem( i18n("Centimeters") );
+ d->units->insertItem( i18n("Inches") );
+
+ d->keepRatio = new TQCheckBox( i18n("Keep ratio"), hb);
+
+ w = new TQWidget(hb);
+ hb->setStretchFactor( w, 1 );
+ d->previousUnit = DK_MILLIMETERS;
+
+ // ------------------------------------------------------------------------
+
+ connect( d->colorManaged, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotAlertSettings( bool )) );
+
+ connect( d->cmPreferences, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotSetupDlg()) );
+
+ connect( d->scale, TQ_SIGNAL( toggled( bool )),
+ this, TQ_SLOT( toggleScaling( bool )));
+
+ connect(d->width, TQ_SIGNAL( valueChanged( double )),
+ this, TQ_SLOT( slotWidthChanged( double )));
+
+ connect(d->height, TQ_SIGNAL( valueChanged( double )),
+ this, TQ_SLOT( slotHeightChanged( double )));
+
+ connect(d->keepRatio, TQ_SIGNAL( toggled( bool )),
+ this, TQ_SLOT( toggleRatio( bool )));
+
+ connect(d->units, TQ_SIGNAL(activated(const TQString &)),
+ this, TQ_SLOT(slotUnitChanged(const TQString& )));
+}
+
+ImageEditorPrintDialogPage::~ImageEditorPrintDialogPage()
+{
+ delete d;
+}
+
+void ImageEditorPrintDialogPage::getOptions( TQMap<TQString,TQString>& opts, bool /*incldef*/ )
+{
+ TQString t = "true";
+ TQString f = "false";
+
+ opts["app-imageeditor-alignment"] = TQString::number(getPosition(d->position->currentText()));
+ opts["app-imageeditor-printFilename"] = d->addFileName->isChecked() ? t : f;
+ opts["app-imageeditor-blackwhite"] = d->blackwhite->isChecked() ? t : f;
+ opts["app-imageeditor-scaleToFit"] = d->scaleToFit->isChecked() ? t : f;
+ opts["app-imageeditor-scale"] = d->scale->isChecked() ? t : f;
+ opts["app-imageeditor-scale-unit"] = TQString::number(stringToUnit(d->units->currentText()));
+ opts["app-imageeditor-scale-width"] = TQString::number( d->width->value() );
+ opts["app-imageeditor-scale-height"] = TQString::number( d->height->value() );
+ opts["app-imageeditor-scale-KeepRatio"] = d->keepRatio->isChecked() ? t : f;
+ opts["app-imageeditor-auto-rotate"] = d->autoRotate->isChecked() ? t : f;
+ opts["app-imageeditor-color-managed"] = d->colorManaged->isChecked() ? t : f;
+}
+
+void ImageEditorPrintDialogPage::setOptions( const TQMap<TQString,TQString>& opts )
+{
+ TQString t = "true";
+ TQString f = "false";
+ TQString stVal;
+ bool ok;
+ double dVal;
+ int iVal;
+
+ iVal = opts["app-imageeditor-alignment"].toInt( &ok );
+ if (ok)
+ {
+ stVal = setPosition(iVal);
+ d->position->setCurrentItem(stVal);
+ }
+
+ d->addFileName->setChecked( opts["app-imageeditor-printFilename"] != f );
+ // This sound strange, but if I copy the code on the line above, the checkbox
+ // was always checked. And this is not the wanted behavior. So, with this works.
+ // KPrint magic ;-)
+ d->blackwhite->setChecked ( false );
+ d->scaleToFit->setChecked( opts["app-imageeditor-scaleToFit"] != f );
+ d->scale->setChecked( opts["app-imageeditor-scale"] == t );
+ d->autoRotate->setChecked( opts["app-imageeditor-auto-rotate"] == t );
+
+ d->colorManaged->setChecked( false );
+
+ Unit unit = static_cast<Unit>( opts["app-imageeditor-scale-unit"].toInt( &ok ) );
+ if (ok)
+ {
+ stVal = unitToString(unit);
+ d->units->setCurrentItem(stVal);
+ d->previousUnit = unit;
+ }
+ else
+ {
+ //for back compatibility
+ d->units->setCurrentItem(i18n("Millimeters"));
+ }
+
+ dVal = opts["app-imageeditor-scale-width"].toDouble( &ok );
+
+ if ( ok )
+ d->width->setValue( dVal );
+
+ dVal = opts["app-imageeditor-scale-height"].toDouble( &ok );
+
+ if ( ok )
+ d->height->setValue( dVal );
+
+ if ( d->scale->isChecked() == d->scaleToFit->isChecked() )
+ d->scaleToFit->setChecked( !d->scale->isChecked() );
+
+ d->keepRatio->setChecked( opts["app-imageeditor-scale-KeepRatio"] == t );
+
+}
+int ImageEditorPrintDialogPage::getPosition(const TQString& align)
+{
+ int alignment;
+
+ if (align == i18n("Central-Left"))
+ {
+ alignment = TQt::AlignLeft | TQt::AlignVCenter;
+ }
+ else if (align == i18n("Central-Right"))
+ {
+ alignment = TQt::AlignRight | TQt::AlignVCenter;
+ }
+ else if (align == i18n("Top-Left"))
+ {
+ alignment = TQt::AlignTop | TQt::AlignLeft;
+ }
+ else if (align == i18n("Top-Right"))
+ {
+ alignment = TQt::AlignTop | TQt::AlignRight;
+ }
+ else if (align == i18n("Bottom-Left"))
+ {
+ alignment = TQt::AlignBottom | TQt::AlignLeft;
+ }
+ else if (align == i18n("Bottom-Right"))
+ {
+ alignment = TQt::AlignBottom | TQt::AlignRight;
+ }
+ else if (align == i18n("Top-Central"))
+ {
+ alignment = TQt::AlignTop | TQt::AlignHCenter;
+ }
+ else if (align == i18n("Bottom-Central"))
+ {
+ alignment = TQt::AlignBottom | TQt::AlignHCenter;
+ }
+ else
+ {
+ // Central
+ alignment = TQt::AlignCenter; // TQt::AlignHCenter || TQt::AlignVCenter
+ }
+
+ return alignment;
+}
+
+TQString ImageEditorPrintDialogPage::setPosition(int align)
+{
+ TQString alignment;
+
+ if (align == (TQt::AlignLeft | TQt::AlignVCenter))
+ {
+ alignment = i18n("Central-Left");
+ }
+ else if (align == (TQt::AlignRight | TQt::AlignVCenter))
+ {
+ alignment = i18n("Central-Right");
+ }
+ else if (align == (TQt::AlignTop | TQt::AlignLeft))
+ {
+ alignment = i18n("Top-Left");
+ }
+ else if (align == (TQt::AlignTop | TQt::AlignRight))
+ {
+ alignment = i18n("Top-Right");
+ }
+ else if (align == (TQt::AlignBottom | TQt::AlignLeft))
+ {
+ alignment = i18n("Bottom-Left");
+ }
+ else if (align == (TQt::AlignBottom | TQt::AlignRight))
+ {
+ alignment = i18n("Bottom-Right");
+ }
+ else if (align == (TQt::AlignTop | TQt::AlignHCenter))
+ {
+ alignment = i18n("Top-Central");
+ }
+ else if (align == (TQt::AlignBottom | TQt::AlignHCenter))
+ {
+ alignment = i18n("Bottom-Central");
+ }
+ else
+ {
+ // Central: TQt::AlignCenter or (TQt::AlignHCenter || TQt::AlignVCenter)
+ alignment = i18n("Central");
+ }
+
+ return alignment;
+}
+
+void ImageEditorPrintDialogPage::toggleScaling( bool enable )
+{
+ d->width->setEnabled( enable );
+ d->height->setEnabled( enable );
+ d->units->setEnabled( enable );
+ d->keepRatio->setEnabled( enable );
+}
+
+void ImageEditorPrintDialogPage::slotHeightChanged (double value)
+{
+ d->width->blockSignals(true);
+ d->height->blockSignals(true);
+
+ if (d->keepRatio->isChecked())
+ {
+ double width = (d->image.width() * value) / d->image.height();
+ d->width->setValue( width ? width : 1.);
+ }
+ d->height->setValue(value);
+
+ d->width->blockSignals(false);
+ d->height->blockSignals(false);
+}
+
+void ImageEditorPrintDialogPage::slotWidthChanged (double value)
+{
+ d->width->blockSignals(true);
+ d->height->blockSignals(true);
+
+ if (d->keepRatio->isChecked())
+ {
+ double height = (d->image.height() * value) / d->image.width();
+ d->height->setValue( height ? height : 1);
+ }
+ d->width->setValue(value);
+
+ d->width->blockSignals(false);
+ d->height->blockSignals(false);
+}
+
+void ImageEditorPrintDialogPage::toggleRatio( bool enable )
+{
+ if (!enable) return;
+ // choosing a startup value of 15x10 cm (common photo dimention)
+ // mContent->mHeight->value() or mContent->mWidth->value()
+ // are usually empty at startup and hxw (0x0) is not good IMO keeping ratio
+ double hValue, wValue;
+ if (d->image.height() > d->image.width())
+ {
+ hValue = d->height->value();
+ if (!hValue) hValue = 150*unitToMM(d->previousUnit);
+ wValue = (d->image.width() * hValue)/ d->image.height();
+ }
+ else
+ {
+ wValue = d->width->value();
+ if (!wValue) wValue = 150*unitToMM(d->previousUnit);
+ hValue = (d->image.height() * wValue)/ d->image.width();
+ }
+
+ d->width->blockSignals(true);
+ d->height->blockSignals(true);
+
+ d->width->setValue(wValue);
+ d->height->setValue(hValue);
+
+ d->width->blockSignals(false);
+ d->height->blockSignals(false);
+}
+
+void ImageEditorPrintDialogPage::slotUnitChanged(const TQString& string)
+{
+ Unit newUnit = stringToUnit(string);
+ double ratio = unitToMM(d->previousUnit) / unitToMM(newUnit);
+
+ d->width->blockSignals(true);
+ d->height->blockSignals(true);
+
+ d->width->setValue( d->width->value() * ratio);
+ d->height->setValue( d->height->value() * ratio);
+
+ d->width->blockSignals(false);
+ d->height->blockSignals(false);
+
+ d->previousUnit = newUnit;
+}
+
+void ImageEditorPrintDialogPage::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("Color Management");
+ d->cmEnabled = config->readBoolEntry("EnableCM", false);
+}
+
+void ImageEditorPrintDialogPage::slotSetupDlg()
+{
+ EditorWindow* editor = dynamic_cast<EditorWindow*>(d->parent);
+ editor->setup(true);
+}
+
+void ImageEditorPrintDialogPage::slotAlertSettings( bool t)
+{
+ if (t && !d->cmEnabled)
+ {
+ TQString message = i18n("<p>Color Management is disabled.</p> \
+ <p>You can enable it now by clicking on the \"Settings\" button.</p>");
+ KMessageBox::information(this, message);
+ d->colorManaged->setChecked(!t);
+ }
+}
+
+double ImageEditorPrintDialogPage::unitToMM(Unit unit)
+{
+ if (unit == DK_MILLIMETERS)
+ {
+ return 1.;
+ }
+ else if (unit == DK_CENTIMETERS)
+ {
+ return 10.;
+ }
+ else
+ { //DK_INCHES
+ return 25.4;
+ }
+}
+
+ImageEditorPrintDialogPage::Unit ImageEditorPrintDialogPage::stringToUnit(const TQString& unit)
+{
+ if (unit == i18n("Millimeters"))
+ {
+ return DK_MILLIMETERS;
+ }
+ else if (unit == i18n("Centimeters"))
+ {
+ return DK_CENTIMETERS;
+ }
+ else
+ {//Inches
+ return DK_INCHES;
+ }
+}
+
+TQString ImageEditorPrintDialogPage::unitToString(Unit unit)
+{
+ if (unit == DK_MILLIMETERS)
+ {
+ return i18n("Millimeters");
+ }
+ else if (unit == DK_CENTIMETERS)
+ {
+ return i18n("Centimeters");
+ }
+ else
+ { //DK_INCHES
+ return i18n("Inches");
+ }
+}
+
+} // namespace Digikam
+
diff --git a/src/utilities/imageeditor/tools/imageprint.h b/src/utilities/imageeditor/tools/imageprint.h
new file mode 100644
index 00000000..66276701
--- /dev/null
+++ b/src/utilities/imageeditor/tools/imageprint.h
@@ -0,0 +1,122 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-13
+ * Description : image editor printing interface.
+ *
+ * Copyright (C) 2006 by F.J. Cruz <fj.cruz@supercable.es>
+ * Copyright (C) 2004-2007 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 IMAGEPRINT_H
+#define IMAGEPRINT_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <kurl.h>
+#include <kprinter.h>
+#include <tdeprint/kprintdialogpage.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class ImagePrintPrivate;
+
+class DIGIKAM_EXPORT ImagePrint
+{
+public:
+
+ ImagePrint(DImg& image, KPrinter& printer, const TQString& fileName);
+ ~ImagePrint();
+
+ bool printImageWithTQt();
+
+private:
+
+ TQString minimizeString(TQString text, const TQFontMetrics& metrics, int maxWidth);
+ void readSettings();
+
+private:
+
+ KPrinter& m_printer;
+
+ ImagePrintPrivate *d;
+};
+
+//-----------------------------------------------------------------------------
+
+class ImageEditorPrintDialogPagePrivate;
+
+class DIGIKAM_EXPORT ImageEditorPrintDialogPage : public KPrintDialogPage
+{
+ TQ_OBJECT
+
+
+public:
+
+ enum Unit
+ {
+ DK_MILLIMETERS = 1,
+ DK_CENTIMETERS,
+ DK_INCHES
+ };
+
+ static inline double unitToMM(Unit unit);
+ static inline Unit stringToUnit(const TQString& unit);
+ static inline TQString unitToString(Unit unit);
+
+public:
+
+ ImageEditorPrintDialogPage(DImg& image, TQWidget *parent=0L, const char *name=0);
+ ~ImageEditorPrintDialogPage();
+
+ virtual void getOptions(TQMap<TQString,TQString>& opts, bool incldef = false);
+ virtual void setOptions(const TQMap<TQString,TQString>& opts);
+
+private slots:
+
+ void toggleScaling( bool enable );
+ void toggleRatio( bool enable );
+ void slotUnitChanged(const TQString& string);
+ void slotHeightChanged(double value);
+ void slotWidthChanged(double value);
+ void slotSetupDlg();
+ void slotAlertSettings(bool t);
+
+private:
+
+ void readSettings();
+ int getPosition(const TQString& align);
+ TQString setPosition(int align);
+
+private:
+
+ ImageEditorPrintDialogPagePrivate *d;
+};
+
+} // namespace Digikam
+
+#endif // IMAGEPRINT_H
diff --git a/src/utilities/imageeditor/tools/imageresize.cpp b/src/utilities/imageeditor/tools/imageresize.cpp
new file mode 100644
index 00000000..c779b71e
--- /dev/null
+++ b/src/utilities/imageeditor/tools/imageresize.cpp
@@ -0,0 +1,650 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-04-07
+ * Description : a tool to resize an image
+ *
+ * Copyright (C) 2005-2009 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.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+
+// TQt includes.
+
+#include <tqvgroupbox.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqtabwidget.h>
+#include <tqtimer.h>
+#include <tqevent.h>
+#include <tqpixmap.h>
+#include <tqbrush.h>
+#include <tqfile.h>
+#include <tqimage.h>
+
+// KDE includes.
+
+#include <kseparator.h>
+#include <kcursor.h>
+#include <kurllabel.h>
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdefiledialog.h>
+#include <kstandarddirs.h>
+#include <kprogress.h>
+#include <tdemessagebox.h>
+#include <knuminput.h>
+#include <tdeglobalsettings.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Digikam includes.
+
+#include "dimg.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "dimgthreadedfilter.h"
+#include "greycstorationiface.h"
+#include "greycstorationwidget.h"
+#include "greycstorationsettings.h"
+
+// Local includes.
+
+#include "imageresize.h"
+#include "imageresize.moc"
+
+using namespace KDcrawIface;
+
+namespace Digikam
+{
+
+class ImageResizePriv
+{
+public:
+
+ enum RunningMode
+ {
+ NoneRendering=0,
+ FinalRendering
+ };
+
+ ImageResizePriv()
+ {
+ currentRenderingMode = NoneRendering;
+ parent = 0;
+ preserveRatioBox = 0;
+ useGreycstorationBox = 0;
+ mainTab = 0;
+ wInput = 0;
+ hInput = 0;
+ wpInput = 0;
+ hpInput = 0;
+ progressBar = 0;
+ greycstorationIface = 0;
+ settingsWidget = 0;
+ cimgLogoLabel = 0;
+ restorationTips = 0;
+ }
+
+ int currentRenderingMode;
+ int orgWidth;
+ int orgHeight;
+ int prevW;
+ int prevH;
+
+ double prevWP;
+ double prevHP;
+
+ TQWidget *parent;
+
+ TQLabel *restorationTips;
+
+ TQCheckBox *preserveRatioBox;
+ TQCheckBox *useGreycstorationBox;
+
+ TQTabWidget *mainTab;
+
+ RIntNumInput *wInput;
+ RIntNumInput *hInput;
+
+ RDoubleNumInput *wpInput;
+ RDoubleNumInput *hpInput;
+
+ KProgress *progressBar;
+
+ KURLLabel *cimgLogoLabel;
+
+ GreycstorationIface *greycstorationIface;
+ GreycstorationWidget *settingsWidget;
+};
+
+ImageResize::ImageResize(TQWidget* parent)
+ : KDialogBase(Plain, i18n("Resize Image"),
+ Help|Default|User2|User3|Ok|Cancel, Ok,
+ parent, 0, true, false,
+ TQString(),
+ i18n("&Save As..."),
+ i18n("&Load..."))
+{
+ d = new ImageResizePriv;
+ d->parent = parent;
+ setHelp("resizetool.anchor", "digikam");
+ TQString whatsThis;
+ setButtonWhatsThis( Default, i18n("<p>Reset all filter parameters to their default values.") );
+ setButtonWhatsThis( User3, i18n("<p>Load all filter parameters from settings text file.") );
+ setButtonWhatsThis( User2, i18n("<p>Save all filter parameters to settings text file.") );
+ enableButton(Ok, false);
+
+ ImageIface iface(0, 0);
+ d->orgWidth = iface.originalWidth();
+ d->orgHeight = iface.originalHeight();
+ d->prevW = d->orgWidth;
+ d->prevH = d->orgHeight;
+ d->prevWP = 100.0;
+ d->prevHP = 100.0;
+
+ // -------------------------------------------------------------
+
+ TQVBoxLayout *vlay = new TQVBoxLayout(plainPage(), 0, spacingHint());
+ d->mainTab = new TQTabWidget( plainPage() );
+
+ TQWidget* firstPage = new TQWidget( d->mainTab );
+ TQGridLayout* grid = new TQGridLayout( firstPage, 8, 2, spacingHint());
+ d->mainTab->addTab( firstPage, i18n("New Size") );
+
+ TQLabel *label1 = new TQLabel(i18n("Width:"), firstPage);
+ d->wInput = new RIntNumInput(firstPage);
+ d->wInput->setRange(1, TQMAX(d->orgWidth * 10, 9999), 1);
+ d->wInput->setName("d->wInput");
+ d->wInput->setDefaultValue(d->orgWidth);
+ TQWhatsThis::add( d->wInput, i18n("<p>Set here the new image width in pixels."));
+
+ TQLabel *label2 = new TQLabel(i18n("Height:"), firstPage);
+ d->hInput = new RIntNumInput(firstPage);
+ d->hInput->setRange(1, TQMAX(d->orgHeight * 10, 9999), 1);
+ d->hInput->setName("d->hInput");
+ d->hInput->setDefaultValue(d->orgHeight);
+ TQWhatsThis::add( d->hInput, i18n("<p>Set here the new image height in pixels."));
+
+ TQLabel *label3 = new TQLabel(i18n("Width (%):"), firstPage);
+ d->wpInput = new RDoubleNumInput(firstPage);
+ d->wpInput->setRange(1.0, 999.0, 1.0);
+ d->wpInput->setName("d->wpInput");
+ d->wpInput->setDefaultValue(100.0);
+ TQWhatsThis::add( d->wpInput, i18n("<p>Set here the new image width in percent."));
+
+ TQLabel *label4 = new TQLabel(i18n("Height (%):"), firstPage);
+ d->hpInput = new RDoubleNumInput(firstPage);
+ d->hpInput->setRange(1.0, 999.0, 1.0);
+ d->hpInput->setName("d->hpInput");
+ d->hpInput->setDefaultValue(100.0);
+ TQWhatsThis::add( d->hpInput, i18n("<p>Set here the new image height in percent."));
+
+ d->preserveRatioBox = new TQCheckBox(i18n("Maintain aspect ratio"), firstPage);
+ TQWhatsThis::add( d->preserveRatioBox, i18n("<p>Enable this option to maintain aspect "
+ "ratio with new image sizes."));
+
+ d->cimgLogoLabel = new KURLLabel(firstPage);
+ d->cimgLogoLabel->setText(TQString());
+ d->cimgLogoLabel->setURL("http://cimg.sourceforge.net");
+ TDEGlobal::dirs()->addResourceType("logo-cimg", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("logo-cimg", "logo-cimg.png");
+ d->cimgLogoLabel->setPixmap( TQPixmap( directory + "logo-cimg.png" ) );
+ TQToolTip::add(d->cimgLogoLabel, i18n("Visit CImg library website"));
+
+ d->useGreycstorationBox = new TQCheckBox(i18n("Restore photograph"), firstPage);
+ TQWhatsThis::add( d->useGreycstorationBox, i18n("<p>Enable this option to restore photograph content. "
+ "This way is usefull to scale-up an image to an huge size. "
+ "Warning: this process can take a while."));
+
+ d->restorationTips = new TQLabel(i18n("<b>Note: use Restoration Mode to only scale-up an image to huge size. "
+ "Warning, this process can take a while.</b>"), firstPage);
+
+ d->progressBar = new KProgress(100, firstPage);
+ d->progressBar->setValue(0);
+ TQWhatsThis::add(d->progressBar, i18n("<p>This shows the current progress when you use Restoration mode."));
+
+ grid->addMultiCellWidget(d->preserveRatioBox, 0, 0, 0, 2);
+ grid->addMultiCellWidget(label1, 1, 1, 0, 0);
+ grid->addMultiCellWidget(d->wInput, 1, 1, 1, 2);
+ grid->addMultiCellWidget(label2, 2, 2, 0, 0);
+ grid->addMultiCellWidget(d->hInput, 2, 2, 1, 2);
+ grid->addMultiCellWidget(label3, 3, 3, 0, 0);
+ grid->addMultiCellWidget(d->wpInput, 3, 3, 1, 2);
+ grid->addMultiCellWidget(label4, 4, 4, 0, 0);
+ grid->addMultiCellWidget(d->hpInput, 4, 4, 1, 2);
+ grid->addMultiCellWidget(new KSeparator(firstPage), 5, 5, 0, 2);
+ grid->addMultiCellWidget(d->cimgLogoLabel, 6, 8, 0, 0);
+ grid->addMultiCellWidget(d->useGreycstorationBox, 6, 6, 1, 2);
+ grid->addMultiCellWidget(d->restorationTips, 7, 7, 1, 2);
+ grid->addMultiCellWidget(d->progressBar, 8, 8, 1, 2);
+ grid->setRowStretch(8, 10);
+
+ // -------------------------------------------------------------
+
+ d->settingsWidget = new GreycstorationWidget(d->mainTab);
+ vlay->addWidget(d->mainTab);
+
+ // -------------------------------------------------------------
+
+ adjustSize();
+ disableResize();
+ TQTimer::singleShot(0, this, TQ_SLOT(readUserSettings()));
+
+ // -------------------------------------------------------------
+
+ connect(d->cimgLogoLabel, TQ_SIGNAL(leftClickedURL(const TQString&)),
+ this, TQ_SLOT(processCImgURL(const TQString&)));
+
+ connect(d->wInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotValuesChanged()));
+
+ connect(d->hInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotValuesChanged()));
+
+ connect(d->wpInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotValuesChanged()));
+
+ connect(d->hpInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotValuesChanged()));
+
+ connect(d->useGreycstorationBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotRestorationToggled(bool)) );
+
+ // -------------------------------------------------------------
+
+ Digikam::GreycstorationSettings defaults;
+ defaults.setResizeDefaultSettings();
+ d->settingsWidget->setDefaultSettings(defaults);
+}
+
+ImageResize::~ImageResize()
+{
+ if (d->greycstorationIface)
+ delete d->greycstorationIface;
+
+ delete d;
+}
+
+void ImageResize::slotRestorationToggled(bool b)
+{
+ d->settingsWidget->setEnabled(b);
+ d->progressBar->setEnabled(b);
+ d->cimgLogoLabel->setEnabled(b);
+ enableButton(User2, b);
+ enableButton(User3, b);
+}
+
+void ImageResize::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("resize Tool Dialog");
+
+ GreycstorationSettings settings;
+ GreycstorationSettings defaults;
+ defaults.setResizeDefaultSettings();
+
+ settings.fastApprox = config->readBoolEntry("FastApprox", defaults.fastApprox);
+ settings.interp = config->readNumEntry("Interpolation", defaults.interp);
+ settings.amplitude = config->readDoubleNumEntry("Amplitude", defaults.amplitude);
+ settings.sharpness = config->readDoubleNumEntry("Sharpness", defaults.sharpness);
+ settings.anisotropy = config->readDoubleNumEntry("Anisotropy", defaults.anisotropy);
+ settings.alpha = config->readDoubleNumEntry("Alpha", defaults.alpha);
+ settings.sigma = config->readDoubleNumEntry("Sigma", defaults.sigma);
+ settings.gaussPrec = config->readDoubleNumEntry("GaussPrec", defaults.gaussPrec);
+ settings.dl = config->readDoubleNumEntry("Dl", defaults.dl);
+ settings.da = config->readDoubleNumEntry("Da", defaults.da);
+ settings.nbIter = config->readNumEntry("Iteration", defaults.nbIter);
+ settings.tile = config->readNumEntry("Tile", defaults.tile);
+ settings.btile = config->readNumEntry("BTile", defaults.btile);
+ d->settingsWidget->setSettings(settings);
+
+ d->useGreycstorationBox->setChecked(config->readBoolEntry("RestorePhotograph", false));
+ slotRestorationToggled(d->useGreycstorationBox->isChecked());
+
+ d->preserveRatioBox->blockSignals(true);
+ d->wInput->blockSignals(true);
+ d->hInput->blockSignals(true);
+ d->wpInput->blockSignals(true);
+ d->hpInput->blockSignals(true);
+
+ d->preserveRatioBox->setChecked(true);
+ d->wInput->slotReset();
+ d->hInput->slotReset();
+ d->wpInput->slotReset();
+ d->hpInput->slotReset();
+
+ d->preserveRatioBox->blockSignals(false);
+ d->wInput->blockSignals(false);
+ d->hInput->blockSignals(false);
+ d->wpInput->blockSignals(false);
+ d->hpInput->blockSignals(false);
+}
+
+void ImageResize::writeUserSettings()
+{
+ GreycstorationSettings settings = d->settingsWidget->getSettings();
+ TDEConfig* config = kapp->config();
+ config->setGroup("resize Tool Dialog");
+ config->writeEntry("FastApprox", settings.fastApprox);
+ config->writeEntry("Interpolation", settings.interp);
+ config->writeEntry("Amplitude", settings.amplitude);
+ config->writeEntry("Sharpness", settings.sharpness);
+ config->writeEntry("Anisotropy", settings.anisotropy);
+ config->writeEntry("Alpha", settings.alpha);
+ config->writeEntry("Sigma", settings.sigma);
+ config->writeEntry("GaussPrec", settings.gaussPrec);
+ config->writeEntry("Dl", settings.dl);
+ config->writeEntry("Da", settings.da);
+ config->writeEntry("Iteration", settings.nbIter);
+ config->writeEntry("Tile", settings.tile);
+ config->writeEntry("BTile", settings.btile);
+ config->writeEntry("RestorePhotograph", d->useGreycstorationBox->isChecked());
+ config->sync();
+}
+
+void ImageResize::slotDefault()
+{
+ GreycstorationSettings settings;
+ settings.setResizeDefaultSettings();
+
+ d->settingsWidget->setSettings(settings);
+ d->useGreycstorationBox->setChecked(false);
+ slotRestorationToggled(d->useGreycstorationBox->isChecked());
+
+ d->preserveRatioBox->blockSignals(true);
+ d->wInput->blockSignals(true);
+ d->hInput->blockSignals(true);
+ d->wpInput->blockSignals(true);
+ d->hpInput->blockSignals(true);
+ d->preserveRatioBox->setChecked(true);
+ d->wInput->setValue(d->orgWidth);
+ d->hInput->setValue(d->orgHeight);
+ d->wpInput->setValue(100.0);
+ d->hpInput->setValue(100.0);
+ d->preserveRatioBox->blockSignals(false);
+ d->wInput->blockSignals(false);
+ d->hInput->blockSignals(false);
+ d->wpInput->blockSignals(false);
+ d->hpInput->blockSignals(false);
+}
+
+void ImageResize::slotValuesChanged()
+{
+ enableButton(Ok, true);
+ d->wInput->blockSignals(true);
+ d->hInput->blockSignals(true);
+ d->wpInput->blockSignals(true);
+ d->hpInput->blockSignals(true);
+
+ TQString s(sender()->name());
+
+ if (s == "d->wInput")
+ {
+ double val = d->wInput->value();
+ double wp = val/(double)(d->orgWidth) * 100.0;
+ d->wpInput->setValue(wp);
+
+ if (d->preserveRatioBox->isChecked())
+ {
+ d->hpInput->setValue(wp);
+ int h = (int)(wp*d->orgHeight/100);
+ d->hInput->setValue(h);
+ }
+ }
+ else if (s == "d->hInput")
+ {
+ double val = d->hInput->value();
+ double hp = val/(double)(d->orgHeight) * 100.0;
+ d->hpInput->setValue(hp);
+
+ if (d->preserveRatioBox->isChecked())
+ {
+ d->wpInput->setValue(hp);
+ int w = (int)(hp*d->orgWidth/100);
+ d->wInput->setValue(w);
+ }
+ }
+ else if (s == "d->wpInput")
+ {
+ double val = d->wpInput->value();
+ int w = (int)(val*d->orgWidth/100);
+ d->wInput->setValue(w);
+
+ if (d->preserveRatioBox->isChecked())
+ {
+ d->hpInput->setValue(val);
+ int h = (int)(val*d->orgHeight/100);
+ d->hInput->setValue(h);
+ }
+ }
+ else if (s == "d->hpInput")
+ {
+ double val = d->hpInput->value();
+ int h = (int)(val*d->orgHeight/100);
+ d->hInput->setValue(h);
+
+ if (d->preserveRatioBox->isChecked())
+ {
+ d->wpInput->setValue(val);
+ int w = (int)(val*d->orgWidth/100);
+ d->wInput->setValue(w);
+ }
+ }
+
+ d->prevW = d->wInput->value();
+ d->prevH = d->hInput->value();
+ d->prevWP = d->wpInput->value();
+ d->prevHP = d->hpInput->value();
+
+ d->wInput->blockSignals(false);
+ d->hInput->blockSignals(false);
+ d->wpInput->blockSignals(false);
+ d->hpInput->blockSignals(false);
+}
+
+void ImageResize::slotCancel()
+{
+ if (d->currentRenderingMode != ImageResizePriv::NoneRendering)
+ {
+ d->greycstorationIface->stopComputation();
+ d->parent->unsetCursor();
+ }
+
+ done(Cancel);
+}
+
+void ImageResize::processCImgURL(const TQString& url)
+{
+ TDEApplication::kApplication()->invokeBrowser(url);
+}
+
+void ImageResize::closeEvent(TQCloseEvent *e)
+{
+ if (d->currentRenderingMode != ImageResizePriv::NoneRendering)
+ {
+ d->greycstorationIface->stopComputation();
+ d->parent->unsetCursor();
+ }
+
+ e->accept();
+}
+
+void ImageResize::slotOk()
+{
+ if (d->prevW != d->wInput->value() || d->prevH != d->hInput->value() ||
+ d->prevWP != d->wpInput->value() || d->prevHP != d->hpInput->value())
+ slotValuesChanged();
+
+ d->currentRenderingMode = ImageResizePriv::FinalRendering;
+ d->mainTab->setCurrentPage(0);
+ d->settingsWidget->setEnabled(false);
+ d->preserveRatioBox->setEnabled(false);
+ d->useGreycstorationBox->setEnabled(false);
+ d->wInput->setEnabled(false);
+ d->hInput->setEnabled(false);
+ d->wpInput->setEnabled(false);
+ d->hpInput->setEnabled(false);
+ enableButton(Ok, false);
+ enableButton(Default, false);
+ enableButton(User2, false);
+ enableButton(User3, false);
+
+ d->parent->setCursor( KCursor::waitCursor() );
+ writeUserSettings();
+ ImageIface iface(0, 0);
+ uchar *data = iface.getOriginalImage();
+ DImg image = DImg(iface.originalWidth(), iface.originalHeight(),
+ iface.originalSixteenBit(), iface.originalHasAlpha(), data);
+ delete [] data;
+
+ if (d->useGreycstorationBox->isChecked())
+ {
+ d->progressBar->setValue(0);
+ d->progressBar->setEnabled(true);
+
+ if (d->greycstorationIface)
+ {
+ delete d->greycstorationIface;
+ d->greycstorationIface = 0;
+ }
+
+ d->greycstorationIface = new GreycstorationIface(
+ &image, d->settingsWidget->getSettings(),
+ GreycstorationIface::Resize,
+ d->wInput->value(),
+ d->hInput->value(),
+ 0, this);
+ }
+ else
+ {
+ // See B.K.O #152192: CImg resize() sound like bugous or unadapted
+ // to resize image without good quality.
+
+ image.resize(d->wInput->value(), d->hInput->value());
+ iface.putOriginalImage(i18n("Resize"), image.bits(),
+ image.width(), image.height());
+ d->parent->unsetCursor();
+ accept();
+ }
+}
+
+void ImageResize::customEvent(TQCustomEvent *event)
+{
+ if (!event) return;
+
+ GreycstorationIface::EventData *data = (GreycstorationIface::EventData*) event->data();
+
+ if (!data) return;
+
+ if (data->starting) // Computation in progress !
+ {
+ d->progressBar->setValue(data->progress);
+ }
+ else
+ {
+ if (data->success) // Computation Completed !
+ {
+ switch (d->currentRenderingMode)
+ {
+ case ImageResizePriv::FinalRendering:
+ {
+ DDebug() << "Final resizing completed..." << endl;
+
+ ImageIface iface(0, 0);
+ DImg resizedImage = d->greycstorationIface->getTargetImage();
+
+ iface.putOriginalImage(i18n("Resize"), resizedImage.bits(),
+ resizedImage.width(), resizedImage.height());
+ d->parent->unsetCursor();
+ accept();
+ break;
+ }
+ }
+ }
+ else // Computation Failed !
+ {
+ switch (d->currentRenderingMode)
+ {
+ case ImageResizePriv::FinalRendering:
+ break;
+ }
+ }
+ }
+
+ delete data;
+}
+
+void ImageResize::slotUser3()
+{
+ KURL loadBlowupFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Photograph Resizing Settings File to Load")) );
+ if( loadBlowupFile.isEmpty() )
+ return;
+
+ TQFile file(loadBlowupFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ if (!d->settingsWidget->loadSettings(file, TQString("# Photograph Resizing Configuration File")))
+ {
+ KMessageBox::error(this,
+ i18n("\"%1\" is not a Photograph Resizing settings text file.")
+ .arg(loadBlowupFile.fileName()));
+ file.close();
+ return;
+ }
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot load settings from the Photograph Resizing text file."));
+
+ file.close();
+}
+
+void ImageResize::slotUser2()
+{
+ KURL saveBlowupFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Photograph Resizing Settings File to Save")) );
+ if( saveBlowupFile.isEmpty() )
+ return;
+
+ TQFile file(saveBlowupFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ d->settingsWidget->saveSettings(file, TQString("# Photograph Resizing Configuration File"));
+ else
+ KMessageBox::error(this, i18n("Cannot save settings to the Photograph Resizing text file."));
+
+ file.close();
+}
+
+} // NameSpace Digikam
+
diff --git a/src/utilities/imageeditor/tools/imageresize.h b/src/utilities/imageeditor/tools/imageresize.h
new file mode 100644
index 00000000..3f8b1c23
--- /dev/null
+++ b/src/utilities/imageeditor/tools/imageresize.h
@@ -0,0 +1,82 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-04-07
+ * Description : a tool to resize an image
+ *
+ * Copyright (C) 2005-2009 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 IMAGE_RESIZE_H
+#define IMAGE_RESIZE_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class ImageResizePriv;
+
+class DIGIKAM_EXPORT ImageResize : public KDialogBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageResize(TQWidget* parent);
+ ~ImageResize();
+
+protected:
+
+ void closeEvent(TQCloseEvent *e);
+
+private:
+
+ void customEvent(TQCustomEvent *event);
+ void writeUserSettings();
+
+private slots:
+
+ void slotOk();
+ void slotCancel();
+ void slotDefault();
+ void slotUser2();
+ void slotUser3();
+ void processCImgURL(const TQString&);
+ void slotValuesChanged();
+ void readUserSettings();
+ void slotRestorationToggled(bool);
+
+private:
+
+ ImageResizePriv *d;
+};
+
+} // NameSpace Digikam
+
+#endif /* IMAGE_RESIZE_H */