summaryrefslogtreecommitdiffstats
path: root/src/libs/widgets/common/curveswidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/widgets/common/curveswidget.cpp')
-rw-r--r--src/libs/widgets/common/curveswidget.cpp838
1 files changed, 838 insertions, 0 deletions
diff --git a/src/libs/widgets/common/curveswidget.cpp b/src/libs/widgets/common/curveswidget.cpp
new file mode 100644
index 00000000..281aecc9
--- /dev/null
+++ b/src/libs/widgets/common/curveswidget.cpp
@@ -0,0 +1,838 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-01
+ * Description : a widget to draw histogram curves
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+#define CLAMP(x,l,u) ((x)<(l)?(l):((x)>(u)?(u):(x)))
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// TQt includes.
+
+#include <tqpixmap.h>
+#include <tqpainter.h>
+#include <tqpoint.h>
+#include <tqpen.h>
+#include <tqevent.h>
+#include <tqtimer.h>
+#include <tqrect.h>
+#include <tqcolor.h>
+#include <tqfont.h>
+#include <tqfontmetrics.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <tdelocale.h>
+
+// Digikam includes.
+
+#include "ddebug.h"
+#include "imagehistogram.h"
+#include "imagecurves.h"
+
+// Local includes.
+
+#include "curveswidget.h"
+#include "curveswidget.moc"
+
+namespace Digikam
+{
+
+class CurvesWidgetPriv
+{
+public:
+
+ enum RepaintType
+ {
+ HistogramDataLoading = 0, // Image Data loading in progress.
+ HistogramNone, // No current histogram values calculation.
+ HistogramStarted, // Histogram values calculation started.
+ HistogramCompleted, // Histogram values calculation completed.
+ HistogramFailed // Histogram values calculation failed.
+ };
+
+ CurvesWidgetPriv()
+ {
+ blinkTimer = 0;
+ curves = 0;
+ grabPoint = -1;
+ last = 0;
+ guideVisible = false;
+ xMouseOver = -1;
+ yMouseOver = -1;
+ clearFlag = HistogramNone;
+ pos = 0;
+ }
+
+ int clearFlag; // Clear drawing zone with message.
+ int leftMost;
+ int rightMost;
+ int grabPoint;
+ int last;
+ int xMouseOver;
+ int yMouseOver;
+ int pos; // Position of animation during loading/calculation.
+
+ bool sixteenBits;
+ bool readOnlyMode;
+ bool guideVisible;
+
+ DColor colorGuide;
+
+ TQTimer *blinkTimer;
+
+ ImageCurves *curves; // Curves data instance.
+
+};
+
+CurvesWidget::CurvesWidget(int w, int h, TQWidget *parent, bool readOnly)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ d = new CurvesWidgetPriv;
+
+ setup(w, h, readOnly);
+}
+
+CurvesWidget::CurvesWidget(int w, int h,
+ uchar *i_data, uint i_w, uint i_h, bool i_sixteenBits,
+ TQWidget *parent, bool readOnly)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ d = new CurvesWidgetPriv;
+
+ setup(w, h, readOnly);
+ updateData(i_data, i_w, i_h, i_sixteenBits);
+}
+
+CurvesWidget::~CurvesWidget()
+{
+ d->blinkTimer->stop();
+
+ if (m_imageHistogram)
+ delete m_imageHistogram;
+
+ if (d->curves)
+ delete d->curves;
+
+ delete d;
+}
+
+void CurvesWidget::setup(int w, int h, bool readOnly)
+{
+ d->readOnlyMode = readOnly;
+ d->curves = new ImageCurves(true);
+ m_channelType = ValueHistogram;
+ m_scaleType = LogScaleHistogram;
+ m_imageHistogram = 0;
+
+ setMouseTracking(true);
+ setPaletteBackgroundColor(colorGroup().background());
+ setMinimumSize(w, h);
+
+ d->blinkTimer = new TQTimer( this );
+
+ connect(d->blinkTimer, TQ_SIGNAL(timeout()),
+ this, TQ_SLOT(slotBlinkTimerDone()));
+}
+
+void CurvesWidget::updateData(uchar *i_data, uint i_w, uint i_h, bool i_sixteenBits)
+{
+ stopHistogramComputation();
+
+ d->sixteenBits = i_sixteenBits;
+
+ // Remove old histogram data from memory.
+ if (m_imageHistogram)
+ delete m_imageHistogram;
+
+ // Calc new histogram data
+ m_imageHistogram = new ImageHistogram(i_data, i_w, i_h, i_sixteenBits, this);
+
+ if (d->curves)
+ delete d->curves;
+
+ d->curves = new ImageCurves(i_sixteenBits);
+ reset();
+}
+
+void CurvesWidget::reset()
+{
+ if (d->curves)
+ d->curves->curvesReset();
+
+ d->grabPoint = -1;
+ d->guideVisible = false;
+ repaint(false);
+}
+
+ImageCurves* CurvesWidget::curves() const
+{
+ return d->curves;
+}
+
+void CurvesWidget::setDataLoading()
+{
+ if (d->clearFlag != CurvesWidgetPriv::HistogramDataLoading)
+ {
+ setCursor(KCursor::waitCursor());
+ d->clearFlag = CurvesWidgetPriv::HistogramDataLoading;
+ d->pos = 0;
+ d->blinkTimer->start(100);
+ }
+}
+
+void CurvesWidget::setLoadingFailed()
+{
+ d->clearFlag = CurvesWidgetPriv::HistogramFailed;
+ d->pos = 0;
+ d->blinkTimer->stop();
+ repaint(false);
+ setCursor(KCursor::arrowCursor());
+}
+
+void CurvesWidget::setCurveGuide(const DColor& color)
+{
+ d->guideVisible = true;
+ d->colorGuide = color;
+ repaint(false);
+}
+
+void CurvesWidget::curveTypeChanged()
+{
+ switch (d->curves->getCurveType(m_channelType))
+ {
+ case ImageCurves::CURVE_SMOOTH:
+
+ // pick representative points from the curve and make them control points
+
+ for (int i = 0; i <= 8; i++)
+ {
+ int index = CLAMP(i * m_imageHistogram->getHistogramSegment()/8,
+ 0, m_imageHistogram->getHistogramSegment()-1);
+
+ d->curves->setCurvePoint( m_channelType,
+ i * 2, TQPoint(index,
+ d->curves->getCurveValue(m_channelType,
+ index)) );
+ }
+
+ d->curves->curvesCalculateCurve(m_channelType);
+ break;
+
+ case ImageCurves::CURVE_FREE:
+ break;
+ }
+
+ repaint(false);
+ emit signalCurvesChanged();
+}
+
+void CurvesWidget::customEvent(TQCustomEvent *event)
+{
+ if (!event) return;
+
+ ImageHistogram::EventData *ed = (ImageHistogram::EventData*) event->data();
+
+ if (!ed) return;
+
+ if (ed->starting)
+ {
+ setCursor(KCursor::waitCursor());
+ d->clearFlag = CurvesWidgetPriv::HistogramStarted;
+ d->blinkTimer->start(200);
+ repaint(false);
+ }
+ else
+ {
+ if (ed->success)
+ {
+ // Repaint histogram
+ d->clearFlag = CurvesWidgetPriv::HistogramCompleted;
+ d->blinkTimer->stop();
+ repaint(false);
+ setCursor(KCursor::arrowCursor());
+ }
+ else
+ {
+ d->clearFlag = CurvesWidgetPriv::HistogramFailed;
+ d->blinkTimer->stop();
+ repaint(false);
+ setCursor(KCursor::arrowCursor());
+ emit signalHistogramComputationFailed();
+ }
+ }
+
+ delete ed;
+}
+
+void CurvesWidget::stopHistogramComputation()
+{
+ if (m_imageHistogram)
+ m_imageHistogram->stopCalcHistogramValues();
+
+ d->blinkTimer->stop();
+ d->pos = 0;
+}
+
+void CurvesWidget::slotBlinkTimerDone()
+{
+ repaint(false);
+ d->blinkTimer->start(200);
+}
+
+void CurvesWidget::paintEvent(TQPaintEvent*)
+{
+ if (d->clearFlag == CurvesWidgetPriv::HistogramDataLoading ||
+ d->clearFlag == CurvesWidgetPriv::HistogramStarted)
+ {
+ // In first, we draw an animation.
+
+ int asize = 24;
+ TQPixmap anim(asize, asize);
+ TQPainter p2;
+ p2.begin(&anim, this);
+ p2.fillRect(0, 0, asize, asize, palette().active().background());
+ p2.translate(asize/2, asize/2);
+
+ d->pos = (d->pos + 10) % 360;
+ p2.setPen(TQPen(palette().active().text()));
+ p2.rotate(d->pos);
+ for ( int i=0 ; i<12 ; i++ )
+ {
+ p2.drawLine(asize/2-5, 0, asize/2-2, 0);
+ p2.rotate(30);
+ }
+ p2.end();
+
+ // ... and we render busy text.
+
+ TQPixmap pm(size());
+ TQPainter p1;
+ p1.begin(&pm, this);
+ p1.fillRect(0, 0, width(), height(), palette().active().background());
+ p1.setPen(TQPen(palette().active().foreground(), 1, TQt::SolidLine));
+ p1.drawRect(0, 0, width(), height());
+ p1.drawPixmap(width()/2 - asize /2, asize, anim);
+ p1.setPen(TQPen(palette().active().text()));
+
+ if (d->clearFlag == CurvesWidgetPriv::HistogramDataLoading)
+ p1.drawText(0, 0, width(), height(), TQt::AlignCenter,
+ i18n("Loading image..."));
+ else
+ p1.drawText(0, 0, width(), height(), TQt::AlignCenter,
+ i18n("Histogram calculation..."));
+
+ p1.end();
+ bitBlt(this, 0, 0, &pm);
+ return;
+ }
+
+ if (d->clearFlag == CurvesWidgetPriv::HistogramFailed)
+ {
+ TQPixmap pm(size());
+ TQPainter p1;
+ p1.begin(&pm, this);
+ p1.fillRect(0, 0, width(), height(), palette().active().background());
+ p1.setPen(TQPen(palette().active().foreground(), 1, TQt::SolidLine));
+ p1.drawRect(0, 0, width(), height());
+ p1.setPen(TQPen(palette().active().text()));
+ p1.drawText(0, 0, width(), height(), TQt::AlignCenter,
+ i18n("Histogram\ncalculation\nfailed."));
+ p1.end();
+ bitBlt(this, 0, 0, &pm);
+ return;
+ }
+
+ if (!m_imageHistogram) return;
+
+ int x, y;
+ int wWidth = width();
+ int wHeight = height();
+ double max;
+ class ImageHistogram *histogram = m_imageHistogram;
+
+ x = 0;
+ y = 0;
+ max = 0.0;
+
+ switch(m_channelType)
+ {
+ case CurvesWidget::GreenChannelHistogram: // Green channel.
+ max = histogram->getMaximum(ImageHistogram::GreenChannel);
+ break;
+
+ case CurvesWidget::BlueChannelHistogram: // Blue channel.
+ max = histogram->getMaximum(ImageHistogram::BlueChannel);
+ break;
+
+ case CurvesWidget::RedChannelHistogram: // Red channel.
+ max = histogram->getMaximum(ImageHistogram::RedChannel);
+ break;
+
+ case CurvesWidget::AlphaChannelHistogram: // Alpha channel.
+ max = histogram->getMaximum(ImageHistogram::AlphaChannel);
+ break;
+
+ case CurvesWidget::ValueHistogram: // Luminosity.
+ max = histogram->getMaximum(ImageHistogram::ValueChannel);
+ break;
+ }
+
+ switch (m_scaleType)
+ {
+ case CurvesWidget::LinScaleHistogram:
+ break;
+
+ case CurvesWidget::LogScaleHistogram:
+ if (max > 0.0)
+ max = log (max);
+ else
+ max = 1.0;
+ break;
+ }
+
+ // Drawing selection or all histogram values.
+ // A TQPixmap is used for enable the double buffering.
+
+ TQPixmap pm(size());
+ TQPainter p1;
+ p1.begin(&pm, this);
+
+ int curvePrevVal = 0;
+
+ for (x = 0 ; x < wWidth ; x++)
+ {
+ double value = 0.0;
+ int i, j;
+ int curveVal;
+
+ i = (x * histogram->getHistogramSegment()) / wWidth;
+ j = ((x + 1) * histogram->getHistogramSegment()) / wWidth;
+
+ curveVal = d->curves->getCurveValue(m_channelType, i);
+
+ do
+ {
+ double v = 0.0;
+
+ switch(m_channelType)
+ {
+ case CurvesWidget::RedChannelHistogram: // Red channel.
+ v = histogram->getValue(ImageHistogram::RedChannel, i++);
+ break;
+
+ case CurvesWidget::GreenChannelHistogram: // Green channel.
+ v = histogram->getValue(ImageHistogram::GreenChannel, i++);
+ break;
+
+ case CurvesWidget::BlueChannelHistogram: // Blue channel.
+ v = histogram->getValue(ImageHistogram::BlueChannel, i++);
+ break;
+
+ case CurvesWidget::AlphaChannelHistogram: // Alpha channel.
+ v = histogram->getValue(ImageHistogram::AlphaChannel, i++);
+ break;
+
+ case CurvesWidget::ValueHistogram: // Luminosity.
+ v = histogram->getValue(ImageHistogram::ValueChannel, i++);
+ break;
+ }
+
+ if (v > value)
+ value = v;
+ }
+ while (i < j);
+
+ switch (m_scaleType)
+ {
+ case CurvesWidget::LinScaleHistogram:
+ y = (int) ((wHeight * value) / max);
+ break;
+
+ case CurvesWidget::LogScaleHistogram:
+ if (value <= 0.0) value = 1.0;
+ y = (int) ((wHeight * log (value)) / max);
+ break;
+
+ default:
+ y = 0;
+ break;
+ }
+
+ // Drawing histogram
+
+ p1.setPen(TQPen(palette().active().foreground(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - y);
+ p1.setPen(TQPen(palette().active().background(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight - y, x, 0);
+
+ // Drawing curves.
+
+ p1.setPen(TQPen(palette().active().link(), 2, TQt::SolidLine));
+ p1.drawLine(x - 1, wHeight - ((curvePrevVal * wHeight) / histogram->getHistogramSegment()),
+ x, wHeight - ((curveVal * wHeight) / histogram->getHistogramSegment()));
+
+ curvePrevVal = curveVal;
+ }
+
+ // Drawing curves points.
+
+ if (!d->readOnlyMode && d->curves->getCurveType(m_channelType) == ImageCurves::CURVE_SMOOTH)
+ {
+ p1.setPen(TQPen(TQt::red, 3, TQt::SolidLine));
+
+ for (int p = 0 ; p < 17 ; p++)
+ {
+ TQPoint curvePoint = d->curves->getCurvePoint(m_channelType, p);
+
+ if (curvePoint.x() >= 0)
+ {
+ p1.drawEllipse( ((curvePoint.x() * wWidth) / histogram->getHistogramSegment()) - 2,
+ wHeight - 2 - ((curvePoint.y() * wHeight) / histogram->getHistogramSegment()),
+ 4, 4 );
+ }
+ }
+ }
+
+ // Drawing black/middle/highlight tone grid separators.
+
+ p1.setPen(TQPen(palette().active().base(), 1, TQt::SolidLine));
+ p1.drawLine(wWidth/4, 0, wWidth/4, wHeight);
+ p1.drawLine(wWidth/2, 0, wWidth/2, wHeight);
+ p1.drawLine(3*wWidth/4, 0, 3*wWidth/4, wHeight);
+ p1.drawLine(0, wHeight/4, wWidth, wHeight/4);
+ p1.drawLine(0, wHeight/2, wWidth, wHeight/2);
+ p1.drawLine(0, 3*wHeight/4, wWidth, 3*wHeight/4);
+
+ // Drawing X,Y point position dragged by mouse over widget.
+
+ p1.setPen(TQPen(TQt::red, 1, TQt::DotLine));
+
+ if (d->xMouseOver != -1 && d->yMouseOver != -1)
+ {
+ TQString string = i18n("x:%1\ny:%2").arg(d->xMouseOver).arg(d->yMouseOver);
+ TQFontMetrics fontMt(string);
+ TQRect rect = fontMt.boundingRect(0, 0, wWidth, wHeight, 0, string);
+ rect.moveRight(wWidth);
+ rect.moveBottom(wHeight);
+ p1.drawText(rect, TQt::AlignLeft||TQt::AlignTop, string);
+ }
+
+ // Drawing color guide.
+
+ int guidePos;
+
+ if (d->guideVisible)
+ {
+ switch(m_channelType)
+ {
+ case CurvesWidget::RedChannelHistogram:
+ guidePos = d->colorGuide.red();
+ break;
+
+ case CurvesWidget::GreenChannelHistogram:
+ guidePos = d->colorGuide.green();
+ break;
+
+ case CurvesWidget::BlueChannelHistogram:
+ guidePos = d->colorGuide.blue();
+ break;
+
+ case CurvesWidget::ValueHistogram:
+ guidePos = TQMAX(TQMAX(d->colorGuide.red(), d->colorGuide.green()), d->colorGuide.blue());
+ break;
+
+ default: // Alpha.
+ guidePos = -1;
+ break;
+ }
+
+ if (guidePos != -1)
+ {
+ int xGuide = (guidePos * wWidth) / histogram->getHistogramSegment();
+ p1.drawLine(xGuide, 0, xGuide, wHeight);
+
+ TQString string = i18n("x:%1").arg(guidePos);
+ TQFontMetrics fontMt( string );
+ TQRect rect = fontMt.boundingRect(0, 0, wWidth, wHeight, 0, string);
+ p1.setPen(TQPen(TQt::red, 1, TQt::SolidLine));
+ rect.moveTop(1);
+
+ if (xGuide < wWidth/2)
+ {
+ rect.moveLeft(xGuide);
+ p1.fillRect(rect, TQBrush(TQColor(250, 250, 255)));
+ p1.drawRect(rect);
+ rect.moveLeft(xGuide+3);
+ p1.drawText(rect, TQt::AlignLeft, string);
+ }
+ else
+ {
+ rect.moveRight(xGuide);
+ p1.fillRect(rect, TQBrush(TQColor(250, 250, 255)));
+ p1.drawRect(rect);
+ rect.moveRight(xGuide-3);
+ p1.drawText(rect, TQt::AlignRight, string);
+ }
+ }
+ }
+
+ // Drawing frame.
+
+ p1.setPen(TQPen(palette().active().foreground(), 1, TQt::SolidLine));
+ p1.drawRect(0, 0, width(), height());
+
+ p1.end();
+ bitBlt(this, 0, 0, &pm);
+}
+
+void CurvesWidget::mousePressEvent(TQMouseEvent *e)
+{
+ if (d->readOnlyMode || !m_imageHistogram) return;
+
+ int i;
+ int closest_point;
+ int distance;
+
+ if (e->button() != TQt::LeftButton || d->clearFlag == CurvesWidgetPriv::HistogramStarted)
+ return;
+
+ int x = CLAMP((int)(e->pos().x() *
+ ((float)(m_imageHistogram->getHistogramSegment()-1) / (float)width())),
+ 0, m_imageHistogram->getHistogramSegment()-1 );
+ int y = CLAMP((int)(e->pos().y() *
+ ((float)(m_imageHistogram->getHistogramSegment()-1) / (float)height())),
+ 0, m_imageHistogram->getHistogramSegment()-1 );
+
+ distance = 65536;
+
+ for (i = 0, closest_point = 0 ; i < 17 ; i++)
+ {
+ int xcurvepoint = d->curves->getCurvePointX(m_channelType, i);
+
+ if (xcurvepoint != -1)
+ {
+ if (abs (x - xcurvepoint) < distance)
+ {
+ distance = abs (x - xcurvepoint);
+ closest_point = i;
+ }
+ }
+ }
+
+ int delta = m_imageHistogram->getHistogramSegment()/16;
+ if (distance > 8)
+ closest_point = (x + delta/2) / delta;
+
+ setCursor(KCursor::crossCursor());
+
+ switch(d->curves->getCurveType(m_channelType))
+ {
+ case ImageCurves::CURVE_SMOOTH:
+ {
+ // Determine the leftmost and rightmost points.
+
+ d->leftMost = -1;
+
+ for (i = closest_point - 1 ; i >= 0 ; i--)
+ {
+ if (d->curves->getCurvePointX(m_channelType, i) != -1)
+ {
+ d->leftMost = d->curves->getCurvePointX(m_channelType, i);
+ break;
+ }
+ }
+
+ d->rightMost = m_imageHistogram->getHistogramSegment();
+
+ for (i = closest_point + 1 ; i < 17 ; i++)
+ {
+ if (d->curves->getCurvePointX(m_channelType, i) != -1)
+ {
+ d->rightMost = d->curves->getCurvePointX(m_channelType, i);
+ break;
+ }
+ }
+
+ d->grabPoint = closest_point;
+ d->curves->setCurvePoint(m_channelType, d->grabPoint,
+ TQPoint(x, m_imageHistogram->getHistogramSegment() - y));
+
+ break;
+ }
+
+ case ImageCurves::CURVE_FREE:
+ {
+
+ d->curves->setCurveValue(m_channelType, x, m_imageHistogram->getHistogramSegment() - y);
+ d->grabPoint = x;
+ d->last = y;
+ break;
+ }
+ }
+
+ d->curves->curvesCalculateCurve(m_channelType);
+ repaint(false);
+}
+
+void CurvesWidget::mouseReleaseEvent(TQMouseEvent *e)
+{
+ if (d->readOnlyMode || !m_imageHistogram) return;
+
+ if (e->button() != TQt::LeftButton || d->clearFlag == CurvesWidgetPriv::HistogramStarted)
+ return;
+
+ setCursor(KCursor::arrowCursor());
+ d->grabPoint = -1;
+ d->curves->curvesCalculateCurve(m_channelType);
+ repaint(false);
+ emit signalCurvesChanged();
+}
+
+void CurvesWidget::mouseMoveEvent(TQMouseEvent *e)
+{
+ if (d->readOnlyMode || !m_imageHistogram) return;
+
+ int i;
+ int closest_point;
+ int x1, x2, y1, y2;
+ int distance;
+
+ if (d->clearFlag == CurvesWidgetPriv::HistogramStarted)
+ return;
+
+ int x = CLAMP( (int)(e->pos().x()*((float)(m_imageHistogram->getHistogramSegment()-1)/(float)width())),
+ 0, m_imageHistogram->getHistogramSegment()-1 );
+ int y = CLAMP( (int)(e->pos().y()*((float)(m_imageHistogram->getHistogramSegment()-1)/(float)height())),
+ 0, m_imageHistogram->getHistogramSegment()-1 );
+
+ distance = 65536;
+
+ for (i = 0, closest_point = 0 ; i < 17 ; i++)
+ {
+ if (d->curves->getCurvePointX(m_channelType, i) != -1)
+ {
+ if (abs (x - d->curves->getCurvePointX(m_channelType, i)) < distance)
+ {
+ distance = abs (x - d->curves->getCurvePointX(m_channelType, i));
+ closest_point = i;
+ }
+ }
+ }
+
+ int delta = m_imageHistogram->getHistogramSegment()/16;
+ if (distance > 8)
+ closest_point = (x + delta/2) / delta;
+
+ switch ( d->curves->getCurveType(m_channelType) )
+ {
+ case ImageCurves::CURVE_SMOOTH:
+ {
+ if (d->grabPoint == -1) // If no point is grabbed...
+ {
+ if ( d->curves->getCurvePointX(m_channelType, closest_point) != -1 )
+ setCursor(KCursor::arrowCursor());
+ else
+ setCursor(KCursor::crossCursor());
+ }
+ else // Else, drag the grabbed point
+ {
+ setCursor(KCursor::crossCursor());
+
+ d->curves->setCurvePointX(m_channelType, d->grabPoint, -1);
+
+ if (x > d->leftMost && x < d->rightMost)
+ {
+ closest_point = (x + delta/2) / delta;
+
+ if (d->curves->getCurvePointX(m_channelType, closest_point) == -1)
+ d->grabPoint = closest_point;
+
+ d->curves->setCurvePoint(m_channelType, d->grabPoint,
+ TQPoint(x, m_imageHistogram->getHistogramSegment()-1 - y));
+ }
+
+ d->curves->curvesCalculateCurve(m_channelType);
+ emit signalCurvesChanged();
+ }
+
+ break;
+ }
+
+ case ImageCurves::CURVE_FREE:
+ {
+ if (d->grabPoint != -1)
+ {
+ if (d->grabPoint > x)
+ {
+ x1 = x;
+ x2 = d->grabPoint;
+ y1 = y;
+ y2 = d->last;
+ }
+ else
+ {
+ x1 = d->grabPoint;
+ x2 = x;
+ y1 = d->last;
+ y2 = y;
+ }
+
+ if (x2 != x1)
+ {
+ for (i = x1 ; i <= x2 ; i++)
+ d->curves->setCurveValue(m_channelType, i,
+ m_imageHistogram->getHistogramSegment()-1 - (y1 + ((y2 - y1) * (i - x1)) / (x2 - x1)));
+ }
+ else
+ {
+ d->curves->setCurveValue(m_channelType, x, m_imageHistogram->getHistogramSegment()-1 - y);
+ }
+
+ d->grabPoint = x;
+ d->last = y;
+ }
+
+ emit signalCurvesChanged();
+
+ break;
+ }
+ }
+
+ d->xMouseOver = x;
+ d->yMouseOver = m_imageHistogram->getHistogramSegment()-1 - y;
+ emit signalMouseMoved(d->xMouseOver, d->yMouseOver);
+ repaint(false);
+}
+
+void CurvesWidget::leaveEvent(TQEvent*)
+{
+ d->xMouseOver = -1;
+ d->yMouseOver = -1;
+ emit signalMouseMoved(d->xMouseOver, d->yMouseOver);
+ repaint(false);
+}
+
+} // NameSpace Digikam