summaryrefslogtreecommitdiffstats
path: root/src/libs/widgets/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/widgets/common')
-rw-r--r--src/libs/widgets/common/Makefile.am25
-rw-r--r--src/libs/widgets/common/colorgradientwidget.cpp161
-rw-r--r--src/libs/widgets/common/colorgradientwidget.h73
-rw-r--r--src/libs/widgets/common/curveswidget.cpp838
-rw-r--r--src/libs/widgets/common/curveswidget.h132
-rw-r--r--src/libs/widgets/common/dcursortracker.cpp109
-rw-r--r--src/libs/widgets/common/dcursortracker.h76
-rw-r--r--src/libs/widgets/common/dlogoaction.cpp96
-rw-r--r--src/libs/widgets/common/dlogoaction.h56
-rw-r--r--src/libs/widgets/common/dpopupmenu.cpp197
-rw-r--r--src/libs/widgets/common/dpopupmenu.h83
-rw-r--r--src/libs/widgets/common/filesaveoptionsbox.cpp182
-rw-r--r--src/libs/widgets/common/filesaveoptionsbox.h72
-rw-r--r--src/libs/widgets/common/histogramwidget.cpp1089
-rw-r--r--src/libs/widgets/common/histogramwidget.h177
-rw-r--r--src/libs/widgets/common/paniconwidget.cpp324
-rw-r--r--src/libs/widgets/common/paniconwidget.h120
-rw-r--r--src/libs/widgets/common/previewwidget.cpp640
-rw-r--r--src/libs/widgets/common/previewwidget.h131
-rw-r--r--src/libs/widgets/common/searchtextbar.cpp260
-rw-r--r--src/libs/widgets/common/searchtextbar.h111
-rw-r--r--src/libs/widgets/common/sidebar.cpp363
-rw-r--r--src/libs/widgets/common/sidebar.h178
-rw-r--r--src/libs/widgets/common/splashscreen.cpp160
-rw-r--r--src/libs/widgets/common/splashscreen.h74
-rw-r--r--src/libs/widgets/common/squeezedcombobox.cpp198
-rw-r--r--src/libs/widgets/common/squeezedcombobox.h164
-rw-r--r--src/libs/widgets/common/statusled.cpp84
-rw-r--r--src/libs/widgets/common/statusled.h72
-rw-r--r--src/libs/widgets/common/statusnavigatebar.cpp172
-rw-r--r--src/libs/widgets/common/statusnavigatebar.h80
-rw-r--r--src/libs/widgets/common/statusprogressbar.cpp171
-rw-r--r--src/libs/widgets/common/statusprogressbar.h87
-rw-r--r--src/libs/widgets/common/statuszoombar.cpp208
-rw-r--r--src/libs/widgets/common/statuszoombar.h100
35 files changed, 7063 insertions, 0 deletions
diff --git a/src/libs/widgets/common/Makefile.am b/src/libs/widgets/common/Makefile.am
new file mode 100644
index 00000000..287f60d8
--- /dev/null
+++ b/src/libs/widgets/common/Makefile.am
@@ -0,0 +1,25 @@
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libcommonwidgets.la
+
+libcommonwidgets_la_SOURCES = histogramwidget.cpp colorgradientwidget.cpp curveswidget.cpp dlogoaction.cpp \
+ sidebar.cpp squeezedcombobox.cpp filesaveoptionsbox.cpp dpopupmenu.cpp \
+ statuszoombar.cpp statusnavigatebar.cpp statusprogressbar.cpp searchtextbar.cpp \
+ dcursortracker.cpp paniconwidget.cpp previewwidget.cpp splashscreen.cpp statusled.cpp
+
+libcommonwidgets_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor
+
+INCLUDES = -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dimg/loaders \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+
+digikaminclude_HEADERS = histogramwidget.h colorgradientwidget.h curveswidget.h sidebar.h dlogoaction.h \
+ squeezedcombobox.h dpopupmenu.h statuszoombar.h statusnavigatebar.h searchtextbar.h \
+ statusprogressbar.h dcursortracker.h paniconwidget.h previewwidget.h statusled.h
+
+digikamincludedir = $(includedir)/digikam
diff --git a/src/libs/widgets/common/colorgradientwidget.cpp b/src/libs/widgets/common/colorgradientwidget.cpp
new file mode 100644
index 00000000..df4c96ca
--- /dev/null
+++ b/src/libs/widgets/common/colorgradientwidget.cpp
@@ -0,0 +1,161 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-28
+ * Description : a color gradient widget
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqpainter.h>
+#include <tqdrawutil.h>
+
+// KDE includes.
+
+#include <kimageeffect.h>
+
+// Local includes.
+
+#include "colorgradientwidget.h"
+#include "colorgradientwidget.moc"
+
+namespace Digikam
+{
+
+class ColorGradientWidgetPriv
+{
+
+public:
+
+ ColorGradientWidgetPriv(){}
+
+ int orientation;
+
+ TQColor color1;
+ TQColor color2;
+};
+
+ColorGradientWidget::ColorGradientWidget(int o, int size, TQWidget *parent)
+ : TQFrame(parent, 0, TQt::WDestructiveClose)
+{
+ d = new ColorGradientWidgetPriv;
+ d->orientation = o;
+
+ setFrameStyle(TQFrame::Box|TQFrame::Plain);
+ setLineWidth(1);
+
+ if ( d->orientation ==TQt::Horizontal )
+ setFixedHeight( size );
+ else
+ setFixedWidth( size );
+
+ d->color1.setRgb( 0, 0, 0 );
+ d->color2.setRgb( 255, 255, 255 );
+}
+
+ColorGradientWidget::~ColorGradientWidget()
+{
+ delete d;
+}
+
+void ColorGradientWidget::setColors( const TQColor &col1, const TQColor &col2 )
+{
+ d->color1 = col1;
+ d->color2 = col2;
+ update();
+}
+
+void ColorGradientWidget::drawContents(TQPainter *p)
+{
+ TQImage image(contentsRect().width(), contentsRect().height(), 32);
+
+ TQColor col, color1, color2;
+ float scale;
+
+ // Widget is disable : drawing grayed frame.
+ if ( !isEnabled() )
+ {
+ color1 = palette().disabled().foreground();
+ color2 = palette().disabled().background();
+ }
+ else
+ {
+ color1 = d->color1;
+ color2 = d->color2;
+ }
+
+ int redDiff = color2.red() - color1.red();
+ int greenDiff = color2.green() - color1.green();
+ int blueDiff = color2.blue() - color1.blue();
+
+ if ( d->orientation ==TQt::Vertical )
+ {
+ for ( int y = 0; y < image.height(); y++ )
+ {
+ scale = 1.0 * y / image.height();
+ col.setRgb( color1.red() + int(redDiff * scale),
+ color1.green() + int(greenDiff * scale),
+ color1.blue() + int(blueDiff * scale) );
+
+ unsigned int *p = (uint *) image.scanLine( y );
+
+ for ( int x = 0; x < image.width(); x++ )
+ *p++ = col.rgb();
+ }
+ }
+ else
+ {
+ unsigned int *p = (uint *) image.scanLine( 0 );
+
+ for ( int x = 0; x < image.width(); x++ )
+ {
+ scale = 1.0 * x / image.width();
+ col.setRgb( color1.red() + int(redDiff * scale),
+ color1.green() + int(greenDiff * scale),
+ color1.blue() + int(blueDiff * scale) );
+ *p++ = col.rgb();
+ }
+
+ for ( int y = 1; y < image.height(); y++ )
+ {
+ memcpy( image.scanLine( y ), image.scanLine( y - 1),
+ sizeof( unsigned int ) * image.width() );
+ }
+ }
+
+ const int psize = 256;
+ TQColor ditherPalette[psize];
+
+ for ( int s = 0; s < psize; s++ )
+ {
+ ditherPalette[s].setRgb( color1.red() + redDiff * s / psize,
+ color1.green() + greenDiff * s / psize,
+ color1.blue() + blueDiff * s / psize );
+ }
+
+ KImageEffect::dither(image, ditherPalette, psize);
+
+ TQPixmap pm;
+ pm.convertFromImage(image);
+ p->drawPixmap(contentsRect(), pm);
+}
+
+} // namespace Digikam
+
diff --git a/src/libs/widgets/common/colorgradientwidget.h b/src/libs/widgets/common/colorgradientwidget.h
new file mode 100644
index 00000000..aafc3df6
--- /dev/null
+++ b/src/libs/widgets/common/colorgradientwidget.h
@@ -0,0 +1,73 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-28
+ * Description : a color gradient widget
+ *
+ * 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 COLORGRADIENTWIDGET_H
+#define COLORGRADIENTWIDGET_H
+
+// KDE includes.
+
+#include <tqframe.h>
+#include <tqcolor.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class ColorGradientWidgetPriv;
+
+class DIGIKAM_EXPORT ColorGradientWidget : public TQFrame
+{
+TQ_OBJECT
+
+
+public:
+
+ enum Orientation
+ {
+ Horizontal=0,
+ Vertical
+ };
+
+public:
+
+ ColorGradientWidget( int o, int size, TQWidget *parent=0 );
+
+ ~ColorGradientWidget();
+
+ void setColors( const TQColor &col1, const TQColor &col2 );
+
+protected:
+
+ void drawContents(TQPainter *);
+
+private:
+
+ ColorGradientWidgetPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* COLORGRADIENTWIDGET_H */
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
diff --git a/src/libs/widgets/common/curveswidget.h b/src/libs/widgets/common/curveswidget.h
new file mode 100644
index 00000000..c9cfed4a
--- /dev/null
+++ b/src/libs/widgets/common/curveswidget.h
@@ -0,0 +1,132 @@
+/* ============================================================
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef CURVESWIDGET_H
+#define CURVESWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+
+// Local includes.
+
+#include "dcolor.h"
+#include "digikam_export.h"
+
+class TQCustomEvent;
+
+namespace Digikam
+{
+
+class ImageHistogram;
+class ImageCurves;
+class CurvesWidgetPriv;
+
+class DIGIKAM_EXPORT CurvesWidget : public TQWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ enum HistogramType
+ {
+ ValueHistogram = 0, // Luminosity.
+ RedChannelHistogram, // Red channel.
+ GreenChannelHistogram, // Green channel.
+ BlueChannelHistogram, // Blue channel.
+ AlphaChannelHistogram, // Alpha channel.
+ };
+
+ enum HistogramScale
+ {
+ LinScaleHistogram=0, // Linear scale.
+ LogScaleHistogram // Logarithmic scale.
+ };
+
+public:
+
+ CurvesWidget(int w, int h, TQWidget *parent, bool readOnly=false);
+
+ CurvesWidget(int w, int h, // Widget size.
+ uchar *i_data, uint i_w, uint i_h, // Full image info.
+ bool i_sixteenBits, // 8 or 16 bits image.
+ TQWidget *parent=0, // Parent widget instance.
+ bool readOnly=false); // If true : widget with full edition mode capabilities.
+ // If false : display curve data only without edition.
+
+ ~CurvesWidget();
+
+ void setup(int w, int h, bool readOnly);
+ void updateData(uchar *i_data, uint i_w, uint i_h, bool i_sixteenBits);
+
+ // Stop current histogram computations.
+ void stopHistogramComputation();
+
+ void setDataLoading();
+ void setLoadingFailed();
+
+ void reset();
+ void curveTypeChanged();
+ void setCurveGuide(const DColor& color);
+
+ ImageCurves* curves() const;
+
+public:
+
+ int m_channelType; // Channel type to draw.
+ int m_scaleType; // Scale to use for drawing.
+
+ ImageHistogram *m_imageHistogram;
+
+signals:
+
+ void signalMouseMoved( int x, int y );
+ void signalCurvesChanged();
+ void signalHistogramComputationDone();
+ void signalHistogramComputationFailed();
+
+protected slots:
+
+ void slotBlinkTimerDone();
+
+protected:
+
+ void paintEvent(TQPaintEvent*);
+ void mousePressEvent(TQMouseEvent*);
+ void mouseReleaseEvent(TQMouseEvent*);
+ void mouseMoveEvent(TQMouseEvent*);
+ void leaveEvent(TQEvent*);
+
+private:
+
+ void customEvent(TQCustomEvent *event);
+
+private:
+
+ CurvesWidgetPriv* d;
+};
+
+} // NameSpace Digikam
+
+#endif /* CURVESWIDGET_H */
diff --git a/src/libs/widgets/common/dcursortracker.cpp b/src/libs/widgets/common/dcursortracker.cpp
new file mode 100644
index 00000000..bb9490cb
--- /dev/null
+++ b/src/libs/widgets/common/dcursortracker.cpp
@@ -0,0 +1,109 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-23-03
+ * Description : a tool tip widget witch follow cursor movements
+ * Tool tip content is displayed without delay.
+ *
+ * Copyright (C) 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 <tqevent.h>
+#include <tqtooltip.h>
+
+// Local includes.
+
+#include "dcursortracker.h"
+
+namespace Digikam
+{
+
+DCursorTracker::DCursorTracker(const TQString& txt, TQWidget *parent)
+ : TQLabel(txt, 0, "", WX11BypassWM)
+{
+ parent->setMouseTracking(true);
+ parent->installEventFilter(this);
+ setEnable(true);
+}
+
+/**
+ * Overload to make sure the widget size is correct
+ */
+void DCursorTracker::setText(const TQString& txt)
+{
+ TQLabel::setText(txt);
+ adjustSize();
+}
+
+void DCursorTracker::setEnable(bool b)
+{
+ m_enable = b;
+}
+
+bool DCursorTracker::eventFilter(TQObject *object, TQEvent *e)
+{
+ TQWidget *widget = static_cast<TQWidget*>(object);
+
+ switch (e->type())
+ {
+ case TQEvent::MouseMove:
+ {
+ TQMouseEvent *event = static_cast<TQMouseEvent*>(e);
+ if (m_enable && (widget->rect().contains(event->pos()) ||
+ (event->stateAfter() & TQt::LeftButton)))
+ {
+ show();
+ TQPoint p = widget->mapToGlobal(TQPoint(widget->width()/2, 0));
+ move(p.x()-width()/2, p.y()-height());
+ }
+ else
+ {
+ hide();
+ }
+ break;
+ }
+
+ case TQEvent::MouseButtonRelease:
+ {
+ TQMouseEvent* event = static_cast<TQMouseEvent*>(e);
+ if ( !widget->rect().contains(event->pos()) )
+ {
+ hide();
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+
+DTipTracker::DTipTracker(const TQString& txt, TQWidget *parent)
+ : DCursorTracker(txt, parent)
+{
+ setPalette(TQToolTip::palette());
+ setFrameStyle(TQFrame::Plain | TQFrame::Box);
+ setLineWidth(1);
+ setAlignment(AlignAuto | AlignTop);
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/common/dcursortracker.h b/src/libs/widgets/common/dcursortracker.h
new file mode 100644
index 00000000..33d322e1
--- /dev/null
+++ b/src/libs/widgets/common/dcursortracker.h
@@ -0,0 +1,76 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-23-03
+ * Description : a tool tip widget witch follow cursor movements
+ * Tool tip content is displayed without delay.
+ *
+ * Copyright (C) 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 DCURSOR_TRACKER_H
+#define DCURSOR_TRACKER_H
+
+// TQt includes.
+
+#include <tqlabel.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+/**
+ * This class implements a decoration-less window which will follow the cursor
+ * when it's over a specified widget.
+ */
+class DIGIKAM_EXPORT DCursorTracker : public TQLabel
+{
+
+public:
+
+ DCursorTracker(const TQString& txt, TQWidget *parent);
+
+ void setText(const TQString& txt);
+ void setEnable(bool b);
+
+protected:
+
+ bool eventFilter(TQObject*, TQEvent*);
+
+private:
+
+ bool m_enable;
+};
+
+
+/**
+ * A specialized CursorTracker class, which looks like a tool tip.
+ */
+class DTipTracker : public DCursorTracker
+{
+
+public:
+
+ DTipTracker(const TQString& txt, TQWidget *parent);
+};
+
+} // namespace Digikam
+
+#endif /* DCURSOR_TRACKER_H */
diff --git a/src/libs/widgets/common/dlogoaction.cpp b/src/libs/widgets/common/dlogoaction.cpp
new file mode 100644
index 00000000..60cfd77f
--- /dev/null
+++ b/src/libs/widgets/common/dlogoaction.cpp
@@ -0,0 +1,96 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-27-08
+ * Description : an tool bar action object to display logo
+ *
+ * Copyright (C) 2007-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqtooltip.h>
+#include <tqpixmap.h>
+
+// KDE includes.
+
+#include <kurllabel.h>
+#include <tdetoolbar.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "dlogoaction.h"
+
+namespace Digikam
+{
+
+DLogoAction::DLogoAction(TQObject* parent, const char* name)
+ : TDEAction(parent, name)
+{
+ setText("digikam.org");
+ setIcon("digikam");
+}
+
+int DLogoAction::plug(TQWidget *widget, int index)
+{
+ if (kapp && !kapp->authorizeTDEAction(name()))
+ return -1;
+
+ if ( widget->inherits( "TDEToolBar" ) )
+ {
+ TDEToolBar *bar = (TDEToolBar *)widget;
+ int id = getToolButtonID();
+ KURLLabel *pixmapLogo = new KURLLabel(Digikam::webProjectUrl(), TQString(), bar);
+ pixmapLogo->setMargin(0);
+ pixmapLogo->setScaledContents(false);
+ pixmapLogo->setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum));
+ TQToolTip::add(pixmapLogo, i18n("Visit digiKam project website"));
+ TDEGlobal::dirs()->addResourceType("banner-digikam", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("banner-digikam", "banner-digikam.png");
+ pixmapLogo->setPixmap(TQPixmap( directory + "banner-digikam.png" ));
+ pixmapLogo->setFocusPolicy(TQWidget::NoFocus);
+
+ bar->insertWidget(id, pixmapLogo->width(), pixmapLogo);
+ bar->alignItemRight(id);
+
+ addContainer(bar, id);
+
+ connect(bar, TQ_SIGNAL(destroyed()),
+ this, TQ_SLOT(slotDestroyed()));
+
+ connect(pixmapLogo, TQ_SIGNAL(leftClickedURL(const TQString&)),
+ this, TQ_SLOT(slotProcessURL(const TQString&)));
+
+ return containerCount() - 1;
+ }
+
+ int containerId = TDEAction::plug( widget, index );
+
+ return containerId;
+}
+
+void DLogoAction::slotProcessURL(const TQString& url)
+{
+ TDEApplication::kApplication()->invokeBrowser(url);
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/common/dlogoaction.h b/src/libs/widgets/common/dlogoaction.h
new file mode 100644
index 00000000..11a0052d
--- /dev/null
+++ b/src/libs/widgets/common/dlogoaction.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-27-08
+ * Description : an tool bar action object to display logo
+ *
+ * Copyright (C) 2007-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef DLOGO_ACTION_H
+#define DLOGO_ACTION_H
+
+// KDE includes.
+
+#include <tdeaction.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT DLogoAction : public TDEAction
+{
+ TQ_OBJECT
+
+
+public:
+
+ DLogoAction(TQObject* parent, const char* name=0);
+
+ virtual int plug(TQWidget *widget, int index=-1);
+
+private slots:
+
+ void slotProcessURL(const TQString&);
+};
+
+} // namespace Digikam
+
+#endif /* DLOGO_ACTION_H */
diff --git a/src/libs/widgets/common/dpopupmenu.cpp b/src/libs/widgets/common/dpopupmenu.cpp
new file mode 100644
index 00000000..f41404ce
--- /dev/null
+++ b/src/libs/widgets/common/dpopupmenu.cpp
@@ -0,0 +1,197 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-11-11
+ * Description : a popup menu with a decorative graphic banner
+ * at the left border.
+ *
+ * Copyright (C) 1996-2000 the kicker authors.
+ * Copyright (C) 2005 Mark Kretschmann <markey@web.de>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqpainter.h>
+#include <tqpixmap.h>
+#include <tqstyle.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <kiconeffect.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <tdeaboutdata.h>
+
+// Local includes.
+
+#include "dpopupmenu.h"
+
+namespace Digikam
+{
+
+static TQImage s_dpopupmenu_sidePixmap;
+static TQColor s_dpopupmenu_sidePixmapColor;
+
+DPopupMenu::DPopupMenu(TQWidget* parent, const char* name)
+ : TDEPopupMenu(parent, name)
+{
+ // Must be initialized so that we know the size on first invocation
+ if ( s_dpopupmenu_sidePixmap.isNull() )
+ generateSidePixmap();
+}
+
+DPopupMenu::~DPopupMenu()
+{
+}
+
+void DPopupMenu::generateSidePixmap()
+{
+ const TQColor newColor = calcPixmapColor();
+
+ if ( newColor != s_dpopupmenu_sidePixmapColor )
+ {
+ s_dpopupmenu_sidePixmapColor = newColor;
+
+ if (TDEApplication::kApplication()->aboutData()->appName() == TQString("digikam"))
+ s_dpopupmenu_sidePixmap.load( locate( "data","digikam/data/menusidepixmap.png" ) );
+ else
+ s_dpopupmenu_sidePixmap.load( locate( "data","showfoto/menusidepixmap.png" ) );
+
+ TDEIconEffect::colorize(s_dpopupmenu_sidePixmap, newColor, 1.0);
+ }
+}
+
+int DPopupMenu::sidePixmapWidth() const
+{
+ return s_dpopupmenu_sidePixmap.width();
+}
+
+TQRect DPopupMenu::sideImageRect() const
+{
+ return TQStyle::visualRect(TQRect(frameWidth(), frameWidth(),
+ s_dpopupmenu_sidePixmap.width(),
+ height() - 2*frameWidth()),
+ this);
+}
+
+TQColor DPopupMenu::calcPixmapColor()
+{
+ TQColor color;
+ TQColor activeTitle = TQApplication::palette().active().background();
+ TQColor inactiveTitle = TQApplication::palette().inactive().background();
+
+ // figure out which color is most suitable for recoloring to
+ int h1, s1, v1, h2, s2, v2, h3, s3, v3;
+ activeTitle.hsv(&h1, &s1, &v1);
+ inactiveTitle.hsv(&h2, &s2, &v2);
+ TQApplication::palette().active().background().hsv(&h3, &s3, &v3);
+
+ if ( (kAbs(h1-h3)+kAbs(s1-s3)+kAbs(v1-v3) < kAbs(h2-h3)+kAbs(s2-s3)+kAbs(v2-v3)) &&
+ ((kAbs(h1-h3)+kAbs(s1-s3)+kAbs(v1-v3) < 32) || (s1 < 32)) && (s2 > s1))
+ color = inactiveTitle;
+ else
+ color = activeTitle;
+
+ // limit max/min brightness
+ int r, g, b;
+ color.rgb(&r, &g, &b);
+ int gray = tqGray(r, g, b);
+ if (gray > 180)
+ {
+ r = (r - (gray - 180) < 0 ? 0 : r - (gray - 180));
+ g = (g - (gray - 180) < 0 ? 0 : g - (gray - 180));
+ b = (b - (gray - 180) < 0 ? 0 : b - (gray - 180));
+ }
+ else if (gray < 76)
+ {
+ r = (r + (76 - gray) > 255 ? 255 : r + (76 - gray));
+ g = (g + (76 - gray) > 255 ? 255 : g + (76 - gray));
+ b = (b + (76 - gray) > 255 ? 255 : b + (76 - gray));
+ }
+ color.setRgb(r, g, b);
+
+ return color;
+}
+
+void DPopupMenu::setMinimumSize(const TQSize & s)
+{
+ TDEPopupMenu::setMinimumSize(s.width() + s_dpopupmenu_sidePixmap.width(), s.height());
+}
+
+void DPopupMenu::setMaximumSize(const TQSize & s)
+{
+ TDEPopupMenu::setMaximumSize(s.width() + s_dpopupmenu_sidePixmap.width(), s.height());
+}
+
+void DPopupMenu::setMinimumSize(int w, int h)
+{
+ TDEPopupMenu::setMinimumSize(w + s_dpopupmenu_sidePixmap.width(), h);
+}
+
+void DPopupMenu::setMaximumSize(int w, int h)
+{
+ TDEPopupMenu::setMaximumSize(w + s_dpopupmenu_sidePixmap.width(), h);
+}
+
+void DPopupMenu::resizeEvent(TQResizeEvent * e)
+{
+ TDEPopupMenu::resizeEvent(e);
+
+ setFrameRect(TQStyle::visualRect(TQRect(s_dpopupmenu_sidePixmap.width(), 0,
+ width() - s_dpopupmenu_sidePixmap.width(), height()),
+ this ) );
+}
+
+//Workaround TQt3.3.x sizing bug, by ensuring we're always wide enough.
+void DPopupMenu::resize(int width, int height)
+{
+ width = kMax(width, maximumSize().width());
+ TDEPopupMenu::resize(width, height);
+}
+
+void DPopupMenu::paintEvent(TQPaintEvent* e)
+{
+ generateSidePixmap();
+
+ TQPainter p( this );
+
+ TQRect r = sideImageRect();
+ r.setTop(r.bottom()-s_dpopupmenu_sidePixmap.height()+1);
+ if ( r.intersects( e->rect() ) )
+ {
+ TQRect drawRect = r.intersect(e->rect()).intersect(sideImageRect());
+ TQRect pixRect = drawRect;
+ pixRect.moveBy(-r.left(), -r.top());
+ p.drawImage(drawRect.topLeft(), s_dpopupmenu_sidePixmap, pixRect);
+ }
+
+ p.setClipRegion(e->region());
+
+ //NOTE: The order is important here. drawContents() must be called before drawPrimitive(),
+ // otherwise we get rendering glitches.
+
+ drawContents(&p);
+
+ style().drawPrimitive(TQStyle::PE_PanelPopup, &p,
+ TQRect(0, 0, width(), height()),
+ colorGroup(), TQStyle::Style_Default,
+ TQStyleOption( frameWidth(), 0));
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/common/dpopupmenu.h b/src/libs/widgets/common/dpopupmenu.h
new file mode 100644
index 00000000..f3576580
--- /dev/null
+++ b/src/libs/widgets/common/dpopupmenu.h
@@ -0,0 +1,83 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-11-11
+ * Description : a popup menu with a decorative graphic banner
+ * at the left border.
+ *
+ * Copyright (C) 1996-2000 the kicker authors.
+ * Copyright (C) 2005 Mark Kretschmann <markey@web.de>
+ * 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 DPOPUPMENU_H
+#define DPOPUPMENU_H
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqimage.h>
+#include <tqrect.h>
+
+// KDE includes.
+
+#include <tdepopupmenu.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+class TQSize;
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT DPopupMenu : public TDEPopupMenu
+{
+
+public:
+
+ DPopupMenu(TQWidget *parent=0, const char *name=0);
+ ~DPopupMenu();
+
+ int sidePixmapWidth() const;
+
+private:
+
+ /** Loads and prepares the sidebar image */
+ void generateSidePixmap();
+
+ /** Returns the available size for the image */
+ TQRect sideImageRect() const;
+
+ /** Calculates a color that matches the current colorscheme */
+ TQColor calcPixmapColor();
+
+ void setMinimumSize(const TQSize& s);
+ void setMaximumSize(const TQSize& s);
+ void setMinimumSize(int w, int h);
+ void setMaximumSize(int w, int h);
+
+ void resizeEvent(TQResizeEvent* e);
+ void resize(int width, int height);
+
+ void paintEvent(TQPaintEvent* e);
+};
+
+} // namespace Digikam
+
+#endif /*DPOPUPMENU_H*/
diff --git a/src/libs/widgets/common/filesaveoptionsbox.cpp b/src/libs/widgets/common/filesaveoptionsbox.cpp
new file mode 100644
index 00000000..26985fb5
--- /dev/null
+++ b/src/libs/widgets/common/filesaveoptionsbox.cpp
@@ -0,0 +1,182 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-08-02
+ * Description : a stack of widgets to set image file save
+ * options into image editor.
+ *
+ * Copyright (C) 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 <tqlayout.h>
+#include <tqlabel.h>
+#include <tqwidget.h>
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqcheckbox.h>
+
+// KDE includes.
+
+#include <kimageio.h>
+#include <tdelocale.h>
+#include <kdialog.h>
+#include <knuminput.h>
+#include <tdeconfig.h>
+#include <tdeapplication.h>
+#include <tdefiledialog.h>
+
+// Local includes.
+
+#include "jpegsettings.h"
+#include "pngsettings.h"
+#include "tiffsettings.h"
+#include "jp2ksettings.h"
+#include "filesaveoptionsbox.h"
+#include "filesaveoptionsbox.moc"
+
+namespace Digikam
+{
+
+class FileSaveOptionsBoxPriv
+{
+
+public:
+
+ FileSaveOptionsBoxPriv()
+ {
+ noneOptions = 0;
+ JPEGOptions = 0;
+ PNGOptions = 0;
+ TIFFOptions = 0;
+ JPEG2000Options = 0;
+ }
+
+ TQWidget *noneOptions;
+
+ TQGridLayout *noneGrid;
+
+ TQLabel *labelNone;
+
+ JPEGSettings *JPEGOptions;
+
+ PNGSettings *PNGOptions;
+
+ TIFFSettings *TIFFOptions;
+
+ JP2KSettings *JPEG2000Options;
+};
+
+FileSaveOptionsBox::FileSaveOptionsBox(TQWidget *parent)
+ : TQWidgetStack(parent, 0, TQt::WDestructiveClose)
+{
+ d = new FileSaveOptionsBoxPriv;
+
+ //-- NONE Settings ------------------------------------------------------
+
+ d->noneOptions = new TQWidget(this);
+ d->noneGrid = new TQGridLayout(d->noneOptions, 1, 1, KDialog::spacingHint());
+ d->labelNone = new TQLabel(i18n("No options available"), d->noneOptions);
+ d->noneGrid->addMultiCellWidget(d->labelNone, 0, 0, 0, 1);
+
+ //-- JPEG Settings ------------------------------------------------------
+
+ d->JPEGOptions = new JPEGSettings(this);
+
+ //-- PNG Settings -------------------------------------------------------
+
+ d->PNGOptions = new PNGSettings(this);
+
+ //-- TIFF Settings ------------------------------------------------------
+
+ d->TIFFOptions = new TIFFSettings(this);
+
+ //-- JPEG 2000 Settings -------------------------------------------------
+
+ d->JPEG2000Options = new JP2KSettings(this);
+
+ //-----------------------------------------------------------------------
+
+ addWidget(d->noneOptions, DImg::NONE);
+ addWidget(d->JPEGOptions, DImg::JPEG);
+ addWidget(d->PNGOptions, DImg::PNG);
+ addWidget(d->TIFFOptions, DImg::TIFF);
+ addWidget(d->JPEG2000Options, DImg::JP2K);
+
+ //-----------------------------------------------------------------------
+
+ readSettings();
+}
+
+FileSaveOptionsBox::~FileSaveOptionsBox()
+{
+ delete d;
+}
+
+void FileSaveOptionsBox::slotImageFileSelected(const TQString& file)
+{
+ TQString format = TQImageIO::imageFormat(file);
+ toggleFormatOptions(format);
+}
+
+void FileSaveOptionsBox::slotImageFileFormatChanged(const TQString& filter)
+{
+ TQString format = KImageIO::typeForMime(filter).upper();
+ toggleFormatOptions(format);
+}
+
+void FileSaveOptionsBox::toggleFormatOptions(const TQString& format)
+{
+ if (format == TQString("JPEG"))
+ raiseWidget(DImg::JPEG);
+ else if (format == TQString("PNG"))
+ raiseWidget(DImg::PNG);
+ else if (format == TQString("TIFF"))
+ raiseWidget(DImg::TIFF);
+ else if (format == TQString("JP2"))
+ raiseWidget(DImg::JP2K);
+ else
+ raiseWidget(DImg::NONE);
+}
+
+void FileSaveOptionsBox::applySettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("ImageViewer Settings");
+ config->writeEntry("JPEGCompression", d->JPEGOptions->getCompressionValue());
+ config->writeEntry("JPEGSubSampling", d->JPEGOptions->getSubSamplingValue());
+ config->writeEntry("PNGCompression", d->PNGOptions->getCompressionValue());
+ config->writeEntry("TIFFCompression", d->TIFFOptions->getCompression());
+ config->writeEntry("JPEG2000Compression", d->JPEG2000Options->getCompressionValue());
+ config->writeEntry("JPEG2000LossLess", d->JPEG2000Options->getLossLessCompression());
+ config->sync();
+}
+
+void FileSaveOptionsBox::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("ImageViewer Settings");
+ d->JPEGOptions->setCompressionValue( config->readNumEntry("JPEGCompression", 75) );
+ d->JPEGOptions->setSubSamplingValue( config->readNumEntry("JPEGSubSampling", 1) ); // Medium subsampling
+ d->PNGOptions->setCompressionValue( config->readNumEntry("PNGCompression", 9) );
+ d->TIFFOptions->setCompression(config->readBoolEntry("TIFFCompression", false));
+ d->JPEG2000Options->setCompressionValue( config->readNumEntry("JPEG2000Compression", 75) );
+ d->JPEG2000Options->setLossLessCompression( config->readBoolEntry("JPEG2000LossLess", true) );
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/common/filesaveoptionsbox.h b/src/libs/widgets/common/filesaveoptionsbox.h
new file mode 100644
index 00000000..9d9f84fc
--- /dev/null
+++ b/src/libs/widgets/common/filesaveoptionsbox.h
@@ -0,0 +1,72 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-08-02
+ * Description : a stack of widgets to set image file save
+ * options into image editor.
+ *
+ * Copyright (C) 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 FILESAVEOPTIONSBOX_H
+#define FILESAVEOPTIONSBOX_H
+
+// KDE includes.
+
+#include <tqwidgetstack.h>
+#include <tqstring.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class FileSaveOptionsBoxPriv;
+
+class DIGIKAM_EXPORT FileSaveOptionsBox : public TQWidgetStack
+{
+TQ_OBJECT
+
+
+public:
+
+ FileSaveOptionsBox(TQWidget *parent=0);
+ ~FileSaveOptionsBox();
+
+ void applySettings();
+
+public slots:
+
+ void slotImageFileFormatChanged(const TQString&);
+ void slotImageFileSelected(const TQString&);
+
+private:
+
+ void toggleFormatOptions(const TQString& format);
+ void readSettings();
+
+private:
+
+ FileSaveOptionsBoxPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* FILESAVEOPTIONSBOX_H */
diff --git a/src/libs/widgets/common/histogramwidget.cpp b/src/libs/widgets/common/histogramwidget.cpp
new file mode 100644
index 00000000..b3017201
--- /dev/null
+++ b/src/libs/widgets/common/histogramwidget.cpp
@@ -0,0 +1,1089 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-21
+ * Description : a widget to display an image histogram.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Some code parts are inspired from from gimp 2.0
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <tqpixmap.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqevent.h>
+#include <tqtimer.h>
+#include <tqcolor.h>
+#include <tqbrush.h>
+#include <tqrect.h>
+#include <tqfont.h>
+#include <tqfontmetrics.h>
+#include <tqtooltip.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imagehistogram.h"
+#include "histogramwidget.h"
+#include "histogramwidget.moc"
+
+namespace Digikam
+{
+
+class HistogramWidgetPriv
+{
+public:
+
+ enum RepaintType
+ {
+ HistogramNone = 0, // No current histogram values calculation.
+ HistogramDataLoading, // The image is being loaded
+ HistogramStarted, // Histogram values calculation started.
+ HistogramCompleted, // Histogram values calculation completed.
+ HistogramFailed // Histogram values calculation failed.
+ };
+
+ HistogramWidgetPriv()
+ {
+ blinkTimer = 0;
+ sixteenBits = false;
+ inSelected = false;
+ clearFlag = HistogramNone;
+ xmin = 0.0;
+ xmax = 0.0;
+ range = 255;
+ guideVisible = false;
+ inInitialRepaintWait = false;
+ pos = 0;
+ }
+
+ // Current selection information.
+ double xmin;
+ double xminOrg;
+ double xmax;
+ int range;
+ int clearFlag; // Clear drawing zone with message.
+ int pos; // Position of animation during loading/calculation.
+
+ bool sixteenBits;
+ bool guideVisible; // Display color guide.
+ bool statisticsVisible; // Display tooltip histogram statistics.
+ bool inSelected;
+ bool selectMode; // If true, a part of the histogram can be selected !
+ bool showProgress; // If true, a message will be displayed during histogram computation,
+ // else nothing (limit flicker effect in widget especially for small
+ // image/computation time).
+ bool inInitialRepaintWait;
+
+ TQTimer *blinkTimer;
+
+ DColor colorGuide;
+};
+
+// Constructor without image data (needed to use updateData() method after instance created).
+
+HistogramWidget::HistogramWidget(int w, int h,
+ TQWidget *parent, bool selectMode,
+ bool showProgress, bool statisticsVisible)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ d = new HistogramWidgetPriv;
+ setup(w, h, selectMode, showProgress, statisticsVisible);
+
+ m_imageHistogram = 0L;
+ m_selectionHistogram = 0L;
+}
+
+// Constructor without image selection.
+
+HistogramWidget::HistogramWidget(int w, int h,
+ uchar *i_data, uint i_w, uint i_h,
+ bool i_sixteenBits,
+ TQWidget *parent, bool selectMode,
+ bool showProgress, bool statisticsVisible)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ d = new HistogramWidgetPriv;
+ d->sixteenBits = i_sixteenBits;
+ setup(w, h, selectMode, showProgress, statisticsVisible);
+
+ m_imageHistogram = new ImageHistogram(i_data, i_w, i_h, i_sixteenBits, this);
+ m_selectionHistogram = 0L;
+}
+
+// Constructor with image selection.
+
+HistogramWidget::HistogramWidget(int w, int h,
+ uchar *i_data, uint i_w, uint i_h,
+ uchar *s_data, uint s_w, uint s_h,
+ bool i_sixteenBits,
+ TQWidget *parent, bool selectMode,
+ bool showProgress, bool statisticsVisible)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ d = new HistogramWidgetPriv;
+ d->sixteenBits = i_sixteenBits;
+ setup(w, h, selectMode, showProgress, statisticsVisible);
+
+ m_imageHistogram = new ImageHistogram(i_data, i_w, i_h, i_sixteenBits, this);
+ m_selectionHistogram = new ImageHistogram(s_data, s_w, s_h, i_sixteenBits, this);
+}
+
+HistogramWidget::~HistogramWidget()
+{
+ d->blinkTimer->stop();
+
+ if (m_imageHistogram)
+ delete m_imageHistogram;
+
+ if (m_selectionHistogram)
+ delete m_selectionHistogram;
+
+ delete d;
+}
+
+void HistogramWidget::setup(int w, int h, bool selectMode, bool showProgress, bool statisticsVisible)
+{
+ m_channelType = ValueHistogram;
+ m_scaleType = LogScaleHistogram;
+ m_colorType = RedColor;
+ m_renderingType = FullImageHistogram;
+ d->statisticsVisible = statisticsVisible;
+ d->selectMode = selectMode;
+ d->showProgress = showProgress;
+
+ setMouseTracking(true);
+ setMinimumSize(w, h);
+
+ d->blinkTimer = new TQTimer( this );
+
+ connect( d->blinkTimer, TQ_SIGNAL(timeout()),
+ this, TQ_SLOT(slotBlinkTimerDone()) );
+}
+
+void HistogramWidget::setHistogramGuideByColor(const DColor& color)
+{
+ d->guideVisible = true;
+ d->colorGuide = color;
+ repaint(false);
+}
+
+void HistogramWidget::reset()
+{
+ d->guideVisible = false;
+ repaint(false);
+}
+
+void HistogramWidget::customEvent(TQCustomEvent *event)
+{
+ if (!event) return;
+
+ ImageHistogram::EventData *ed = (ImageHistogram::EventData*) event->data();
+
+ if (!ed) return;
+
+ if (ed->histogram != m_imageHistogram && ed->histogram != m_selectionHistogram)
+ return;
+
+ if (ed->starting)
+ {
+ setCursor( KCursor::waitCursor() );
+ d->clearFlag = HistogramWidgetPriv::HistogramStarted;
+ if (!d->inInitialRepaintWait)
+ {
+ if (d->clearFlag != HistogramWidgetPriv::HistogramDataLoading)
+ {
+ // enter initial repaint wait, repaint only after waiting
+ // a short time so that very fast computation does not create flicker
+ d->inInitialRepaintWait = true;
+ d->blinkTimer->start( 100 );
+ }
+ else
+ {
+ // after the initial repaint, we can repaint immediately
+ repaint(false);
+ d->blinkTimer->start( 200 );
+ }
+ }
+ }
+ else
+ {
+ if (ed->success)
+ {
+ // Repaint histogram
+ d->clearFlag = HistogramWidgetPriv::HistogramCompleted;
+ d->blinkTimer->stop();
+ d->inInitialRepaintWait = false;
+ setCursor( KCursor::arrowCursor() );
+
+ // Send signals to refresh information if necessary.
+ // The signals may trigger multiple repaints, avoid this,
+ // we repaint once afterwards.
+ setUpdatesEnabled(false);
+
+ notifyValuesChanged();
+ emit signalHistogramComputationDone(d->sixteenBits);
+
+ setUpdatesEnabled(true);
+ repaint(false);
+ }
+ else
+ {
+ d->clearFlag = HistogramWidgetPriv::HistogramFailed;
+ d->blinkTimer->stop();
+ d->inInitialRepaintWait = false;
+ repaint(false);
+ setCursor( KCursor::arrowCursor() );
+ // Remove old histogram data from memory.
+ if (m_imageHistogram)
+ {
+ delete m_imageHistogram;
+ m_imageHistogram = 0;
+ }
+ if (m_selectionHistogram)
+ {
+ delete m_selectionHistogram;
+ m_selectionHistogram = 0;
+ }
+ emit signalHistogramComputationFailed();
+ }
+ }
+
+ delete ed;
+}
+
+void HistogramWidget::setDataLoading()
+{
+ if (d->clearFlag != HistogramWidgetPriv::HistogramDataLoading)
+ {
+ setCursor( KCursor::waitCursor() );
+ d->clearFlag = HistogramWidgetPriv::HistogramDataLoading;
+ // enter initial repaint wait, repaint only after waiting
+ // a short time so that very fast computation does not create flicker
+ d->inInitialRepaintWait = true;
+ d->pos = 0;
+ d->blinkTimer->start( 100 );
+ }
+}
+
+void HistogramWidget::setLoadingFailed()
+{
+ d->clearFlag = HistogramWidgetPriv::HistogramFailed;
+ d->pos = 0;
+ d->blinkTimer->stop();
+ d->inInitialRepaintWait = false;
+ repaint(false);
+ setCursor( KCursor::arrowCursor() );
+}
+
+void HistogramWidget::stopHistogramComputation()
+{
+ if (m_imageHistogram)
+ m_imageHistogram->stopCalcHistogramValues();
+
+ if (m_selectionHistogram)
+ m_selectionHistogram->stopCalcHistogramValues();
+
+ d->blinkTimer->stop();
+ d->pos = 0;
+}
+
+void HistogramWidget::updateData(uchar *i_data, uint i_w, uint i_h,
+ bool i_sixteenBits,
+ uchar *s_data, uint s_w, uint s_h,
+ bool showProgress)
+{
+ d->showProgress = showProgress;
+ d->sixteenBits = i_sixteenBits;
+
+ // We are deleting the histogram data, so we must not use it to draw any more.
+ d->clearFlag = HistogramWidgetPriv::HistogramNone;
+
+ // Do not using ImageHistogram::getHistogramSegment()
+ // method here because histogram hasn't yet been computed.
+ d->range = d->sixteenBits ? 65535 : 255;
+ emit signalMaximumValueChanged( d->range );
+
+
+ // Remove old histogram data from memory.
+ if (m_imageHistogram)
+ delete m_imageHistogram;
+
+ if (m_selectionHistogram)
+ delete m_selectionHistogram;
+
+ // Calc new histogram data
+ m_imageHistogram = new ImageHistogram(i_data, i_w, i_h, i_sixteenBits, this);
+
+ if (s_data && s_w && s_h)
+ m_selectionHistogram = new ImageHistogram(s_data, s_w, s_h, i_sixteenBits, this);
+ else
+ m_selectionHistogram = 0L;
+}
+
+void HistogramWidget::updateSelectionData(uchar *s_data, uint s_w, uint s_h,
+ bool i_sixteenBits,
+ bool showProgress)
+{
+ d->showProgress = showProgress;
+
+ // Remove old histogram data from memory.
+
+ if (m_selectionHistogram)
+ delete m_selectionHistogram;
+
+ // Calc new histogram data
+ m_selectionHistogram = new ImageHistogram(s_data, s_w, s_h, i_sixteenBits, this);
+}
+
+void HistogramWidget::slotBlinkTimerDone()
+{
+ d->inInitialRepaintWait = false;
+ repaint(false);
+ d->blinkTimer->start( 200 );
+}
+
+void HistogramWidget::paintEvent(TQPaintEvent*)
+{
+ // Widget is disabled, not initialized,
+ // or loading, but no message shall be drawn:
+ // Drawing grayed frame.
+ if ( !isEnabled() ||
+ d->clearFlag == HistogramWidgetPriv::HistogramNone ||
+ (!d->showProgress && (d->clearFlag == HistogramWidgetPriv::HistogramStarted ||
+ d->clearFlag == HistogramWidgetPriv::HistogramDataLoading))
+ )
+ {
+ TQPixmap pm(size());
+ TQPainter p1;
+ p1.begin(&pm, this);
+ p1.fillRect(0, 0, size().width(), size().height(), palette().disabled().background());
+ p1.setPen(TQPen(palette().active().foreground(), 1, TQt::SolidLine));
+ p1.drawRect(0, 0, width(), height());
+ p1.setPen(TQPen(palette().disabled().foreground(), 1, TQt::SolidLine));
+ p1.drawRect(0, 0, width(), height());
+ p1.end();
+ bitBlt(this, 0, 0, &pm);
+ return;
+ }
+ // Image data is loading or histogram is being computed:
+ // Draw message.
+ else if ( d->showProgress &&
+ (d->clearFlag == HistogramWidgetPriv::HistogramStarted ||
+ d->clearFlag == HistogramWidgetPriv::HistogramDataLoading)
+ )
+ {
+ // 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 == HistogramWidgetPriv::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;
+ }
+ // Histogram computation failed:
+ // Draw message.
+ else if (d->clearFlag == HistogramWidgetPriv::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;
+ }
+
+ int x, y;
+ int yr, yg, yb; // For all color channels.
+ int wWidth = width();
+ int wHeight = height();
+ double max;
+ class ImageHistogram *histogram;
+
+ if (m_renderingType == ImageSelectionHistogram && m_selectionHistogram)
+ histogram = m_selectionHistogram;
+ else
+ histogram = m_imageHistogram;
+
+ if (!histogram)
+ return;
+
+ x = 0; y = 0;
+ yr = 0; yg = 0; yb = 0;
+ max = 0.0;
+
+ switch(m_channelType)
+ {
+ case HistogramWidget::GreenChannelHistogram: // Green channel.
+ max = histogram->getMaximum(ImageHistogram::GreenChannel);
+ break;
+
+ case HistogramWidget::BlueChannelHistogram: // Blue channel.
+ max = histogram->getMaximum(ImageHistogram::BlueChannel);
+ break;
+
+ case HistogramWidget::RedChannelHistogram: // Red channel.
+ max = histogram->getMaximum(ImageHistogram::RedChannel);
+ break;
+
+ case HistogramWidget::AlphaChannelHistogram: // Alpha channel.
+ max = histogram->getMaximum(ImageHistogram::AlphaChannel);
+ break;
+
+ case HistogramWidget::ColorChannelsHistogram: // All color channels.
+ max = TQMAX (TQMAX (histogram->getMaximum(ImageHistogram::RedChannel),
+ histogram->getMaximum(ImageHistogram::GreenChannel)),
+ histogram->getMaximum(ImageHistogram::BlueChannel));
+ break;
+
+ case HistogramWidget::ValueHistogram: // Luminosity.
+ max = histogram->getMaximum(ImageHistogram::ValueChannel);
+ break;
+ }
+
+ switch (m_scaleType)
+ {
+ case HistogramWidget::LinScaleHistogram:
+ break;
+
+ case HistogramWidget::LogScaleHistogram:
+ if (max > 0.0)
+ max = log (max);
+ else
+ max = 1.0;
+ break;
+ }
+
+ // A TQPixmap is used to enable the double buffering.
+
+ TQPixmap pm(size());
+ TQPainter p1;
+ p1.begin(&pm, this);
+ p1.fillRect(0, 0, width(), height(), palette().active().background());
+
+ // Drawing selection or all histogram values.
+
+ for (x = 0 ; x < wWidth ; x++)
+ {
+ double value = 0.0;
+ double value_r = 0.0, value_g = 0.0, value_b = 0.0; // For all color channels.
+ int i, j;
+
+ i = (x * histogram->getHistogramSegment()) / wWidth;
+ j = ((x + 1) * histogram->getHistogramSegment()) / wWidth;
+
+ do
+ {
+ double v;
+ double vr, vg, vb; // For all color channels.
+
+ v = 0.0;
+ vr = 0.0; vg = 0.0; vb = 0.0;
+
+ switch(m_channelType)
+ {
+ case HistogramWidget::GreenChannelHistogram: // Green channel.
+ v = histogram->getValue(ImageHistogram::GreenChannel, i++);
+ break;
+
+ case HistogramWidget::BlueChannelHistogram: // Blue channel.
+ v = histogram->getValue(ImageHistogram::BlueChannel, i++);
+ break;
+
+ case HistogramWidget::RedChannelHistogram: // Red channel.
+ v = histogram->getValue(ImageHistogram::RedChannel, i++);
+ break;
+
+ case HistogramWidget::AlphaChannelHistogram: // Alpha channel.
+ v = histogram->getValue(ImageHistogram::AlphaChannel, i++);
+ break;
+
+ case HistogramWidget::ColorChannelsHistogram: // All color channels.
+ vr = histogram->getValue(ImageHistogram::RedChannel, i++);
+ vg = histogram->getValue(ImageHistogram::GreenChannel, i);
+ vb = histogram->getValue(ImageHistogram::BlueChannel, i);
+ break;
+
+ case HistogramWidget::ValueHistogram: // Luminosity.
+ v = histogram->getValue(ImageHistogram::ValueChannel, i++);
+ break;
+ }
+
+ if ( m_channelType != HistogramWidget::ColorChannelsHistogram )
+ {
+ if (v > value)
+ value = v;
+ }
+ else
+ {
+ if (vr > value_r)
+ value_r = vr;
+ if (vg > value_g)
+ value_g = vg;
+ if (vb > value_b)
+ value_b = vb;
+ }
+ }
+ while (i < j);
+
+ if ( m_channelType != HistogramWidget::ColorChannelsHistogram )
+ {
+ switch (m_scaleType)
+ {
+ case HistogramWidget::LinScaleHistogram:
+ y = (int) ((wHeight * value) / max);
+ break;
+
+ case HistogramWidget::LogScaleHistogram:
+ if (value <= 0.0) value = 1.0;
+ y = (int) ((wHeight * log (value)) / max);
+ break;
+
+ default:
+ y = 0;
+ break;
+ }
+ }
+ else
+ {
+ switch (m_scaleType)
+ {
+ case HistogramWidget::LinScaleHistogram:
+ yr = (int) ((wHeight * value_r) / max);
+ yg = (int) ((wHeight * value_g) / max);
+ yb = (int) ((wHeight * value_b) / max);
+ break;
+
+ case HistogramWidget::LogScaleHistogram:
+ if (value_r <= 0.0) value_r = 1.0;
+ if (value_g <= 0.0) value_g = 1.0;
+ if (value_b <= 0.0) value_b = 1.0;
+ yr = (int) ((wHeight * log (value_r)) / max);
+ yg = (int) ((wHeight * log (value_g)) / max);
+ yb = (int) ((wHeight * log (value_b)) / max);
+ break;
+
+ default:
+ yr = 0;
+ yg = 0;
+ yb = 0;
+ break;
+ }
+ }
+
+ // Drawing the histogram + selection or only the histogram.
+
+ if ( m_channelType != HistogramWidget::ColorChannelsHistogram )
+ {
+ if ( d->selectMode == true ) // Selection mode enable ?
+ {
+ if ( x >= (int)(d->xmin * wWidth) && x <= (int)(d->xmax * wWidth) )
+ {
+ p1.setPen(TQPen(palette().active().foreground(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, 0);
+ p1.setPen(TQPen(palette().active().background(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - y);
+ }
+ else
+ {
+ 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);
+
+ if ( x == wWidth/4 || x == wWidth/2 || x == 3*wWidth/4 )
+ {
+ p1.setPen(TQPen(palette().active().base(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, 0);
+ }
+ }
+ }
+ else
+ {
+ 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);
+
+ if ( x == wWidth/4 || x == wWidth/2 || x == 3*wWidth/4 )
+ {
+ p1.setPen(TQPen(palette().active().base(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, 0);
+ }
+ }
+ }
+ else
+ {
+ if ( d->selectMode == true ) // Histogram selection mode enable ?
+ {
+ if ( x >= (int)(d->xmin * wWidth) && x <= (int)(d->xmax * wWidth) )
+ {
+ p1.setPen(TQPen(palette().active().foreground(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, 0);
+ p1.setPen(TQPen(palette().active().background(), 1, TQt::SolidLine));
+
+ // Witch color must be used on the foreground with all colors channel mode?
+ switch (m_colorType)
+ {
+ case HistogramWidget::RedColor:
+ p1.drawLine(x, wHeight, x, wHeight - yr);
+ break;
+
+ case HistogramWidget::GreenColor:
+ p1.drawLine(x, wHeight, x, wHeight - yg);
+ break;
+
+ default:
+ p1.drawLine(x, wHeight, x, wHeight - yb);
+ break;
+ }
+ }
+ else
+ {
+ // Which color must be used on the foreground with all colors channel mode?
+ switch (m_colorType)
+ {
+ case HistogramWidget::RedColor:
+ p1.setPen(TQPen(TQt::green, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yg);
+ p1.setPen(TQPen(TQt::blue, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yb);
+ p1.setPen(TQPen(TQt::red, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yr);
+
+ p1.setPen(TQPen(palette().active().background(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight - TQMAX(TQMAX(yr, yg), yb), x, 0);
+ p1.setPen(TQPen(palette().active().foreground(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight - yg -1, x, wHeight - yg);
+ p1.drawLine(x, wHeight - yb -1, x, wHeight - yb);
+ p1.drawLine(x, wHeight - yr -1, x, wHeight - yr);
+
+ if ( x == wWidth/4 || x == wWidth/2 || x == 3*wWidth/4 )
+ {
+ p1.setPen(TQPen(palette().active().base(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, 0);
+ }
+
+ break;
+
+ case HistogramWidget::GreenColor:
+ p1.setPen(TQPen(TQt::blue, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yb);
+ p1.setPen(TQPen(TQt::red, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yr);
+ p1.setPen(TQPen(TQt::green, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yg);
+
+ p1.setPen(TQPen(palette().active().background(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight - TQMAX(TQMAX(yr, yg), yb), x, 0);
+ p1.setPen(TQPen(palette().active().foreground(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight - yb -1, x, wHeight - yb);
+ p1.drawLine(x, wHeight - yr -1, x, wHeight - yr);
+ p1.drawLine(x, wHeight - yg -1, x, wHeight - yg);
+
+ if ( x == wWidth/4 || x == wWidth/2 || x == 3*wWidth/4 )
+ {
+ p1.setPen(TQPen(palette().active().base(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, 0);
+ }
+
+ break;
+
+ default:
+ p1.setPen(TQPen(TQt::red, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yr);
+ p1.setPen(TQPen(TQt::green, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yg);
+ p1.setPen(TQPen(TQt::blue, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yb);
+
+ p1.setPen(TQPen(palette().active().background(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight - TQMAX(TQMAX(yr, yg), yb), x, 0);
+ p1.setPen(TQPen(palette().active().foreground(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight - yr -1, x, wHeight - yr);
+ p1.drawLine(x, wHeight - yg -1, x, wHeight - yg);
+ p1.drawLine(x, wHeight - yb -1, x, wHeight - yb);
+
+ if ( x == wWidth/4 || x == wWidth/2 || x == 3*wWidth/4 )
+ {
+ p1.setPen(TQPen(palette().active().base(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, 0);
+ }
+
+ break;
+ }
+ }
+ }
+ else
+ {
+ // Which color must be used on the foreground with all colors channel mode?
+ switch (m_colorType)
+ {
+ case HistogramWidget::RedColor:
+ p1.setPen(TQPen(TQt::green, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yg);
+ p1.setPen(TQPen(TQt::blue, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yb);
+ p1.setPen(TQPen(TQt::red, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yr);
+
+ p1.setPen(TQPen(palette().active().background(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight - TQMAX(TQMAX(yr, yg), yb), x, 0);
+ p1.setPen(TQPen(palette().active().foreground(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight - yg -1, x, wHeight - yg);
+ p1.drawLine(x, wHeight - yb -1, x, wHeight - yb);
+ p1.drawLine(x, wHeight - yr -1, x, wHeight - yr);
+
+ if ( x == wWidth/4 || x == wWidth/2 || x == 3*wWidth/4 )
+ {
+ p1.setPen(TQPen(palette().active().base(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, 0);
+ }
+
+ break;
+
+ case HistogramWidget::GreenColor:
+ p1.setPen(TQPen(TQt::blue, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yb);
+ p1.setPen(TQPen(TQt::red, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yr);
+ p1.setPen(TQPen(TQt::green, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yg);
+
+ p1.setPen(TQPen(palette().active().background(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight - TQMAX(TQMAX(yr, yg), yb), x, 0);
+ p1.setPen(TQPen(palette().active().foreground(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight - yb -1, x, wHeight - yb);
+ p1.drawLine(x, wHeight - yr -1, x, wHeight - yr);
+ p1.drawLine(x, wHeight - yg -1, x, wHeight - yg);
+
+ if ( x == wWidth/4 || x == wWidth/2 || x == 3*wWidth/4 )
+ {
+ p1.setPen(TQPen(palette().active().base(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, 0);
+ }
+
+ break;
+
+ default:
+ p1.setPen(TQPen(TQt::red, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yr);
+ p1.setPen(TQPen(TQt::green, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yg);
+ p1.setPen(TQPen(TQt::blue, 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, wHeight - yb);
+
+ p1.setPen(TQPen(palette().active().background(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight - TQMAX(TQMAX(yr, yg), yb), x, 0);
+ p1.setPen(TQPen(palette().active().foreground(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight - yr -1, x, wHeight - yr);
+ p1.drawLine(x, wHeight - yg -1, x, wHeight - yg);
+ p1.drawLine(x, wHeight - yb -1, x, wHeight - yb);
+
+ if ( x == wWidth/4 || x == wWidth/2 || x == 3*wWidth/4 )
+ {
+ p1.setPen(TQPen(palette().active().base(), 1, TQt::SolidLine));
+ p1.drawLine(x, wHeight, x, 0);
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ // Drawing color guide.
+
+ p1.setPen(TQPen(TQt::red, 1, TQt::DotLine));
+ int guidePos;
+
+ if (d->guideVisible)
+ {
+ switch(m_channelType)
+ {
+ case HistogramWidget::RedChannelHistogram:
+ guidePos = d->colorGuide.red();
+ break;
+
+ case HistogramWidget::GreenChannelHistogram:
+ guidePos = d->colorGuide.green();
+ break;
+
+ case HistogramWidget::BlueChannelHistogram:
+ guidePos = d->colorGuide.blue();
+ break;
+
+ case HistogramWidget::ValueHistogram:
+ guidePos = TQMAX(TQMAX(d->colorGuide.red(), d->colorGuide.green()), d->colorGuide.blue());
+ break;
+
+ case HistogramWidget::ColorChannelsHistogram:
+ {
+ switch(m_channelType)
+ {
+ case HistogramWidget::RedChannelHistogram:
+ guidePos = d->colorGuide.red();
+ break;
+
+ case HistogramWidget::GreenChannelHistogram:
+ guidePos = d->colorGuide.green();
+ break;
+
+ case HistogramWidget::BlueChannelHistogram:
+ guidePos = d->colorGuide.blue();
+ break;
+ }
+ }
+
+ default:
+ guidePos = d->colorGuide.alpha();
+ 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);
+ }
+ }
+ }
+
+ if (d->statisticsVisible)
+ {
+ TQString tipText, value;
+ TQString cellBeg("<tr><td><nobr><font size=-1>");
+ TQString cellMid("</font></nobr></td><td><nobr><font size=-1>");
+ TQString cellEnd("</font></nobr></td></tr>");
+ tipText = "<table cellspacing=0 cellpadding=0>";
+
+ tipText += cellBeg + i18n("Mean:") + cellMid;
+ double mean = histogram->getMean(m_channelType, 0, histogram->getHistogramSegment()-1);
+ tipText += value.setNum(mean, 'f', 1) + cellEnd;
+
+ tipText += cellBeg + i18n("Pixels:") + cellMid;
+ double pixels = histogram->getPixels();
+ tipText += value.setNum((float)pixels, 'f', 0) + cellEnd;
+
+ tipText += cellBeg + i18n("Std dev.:") + cellMid;
+ double stddev = histogram->getStdDev(m_channelType, 0, histogram->getHistogramSegment()-1);
+ tipText += value.setNum(stddev, 'f', 1) + cellEnd;
+
+ tipText += cellBeg + i18n("Count:") + cellMid;
+ double counts = histogram->getCount(m_channelType, 0, histogram->getHistogramSegment()-1);
+ tipText += value.setNum((float)counts, 'f', 0) + cellEnd;
+
+ tipText += cellBeg + i18n("Median:") + cellMid;
+ double median = histogram->getMedian(m_channelType, 0, histogram->getHistogramSegment()-1);
+ tipText += value.setNum(median, 'f', 1) + cellEnd;
+
+ tipText += cellBeg + i18n("Percent:") + cellMid;
+ double percentile = (pixels > 0 ? (100.0 * counts / pixels) : 0.0);
+ tipText += value.setNum(percentile, 'f', 1) + cellEnd;
+
+ tipText += "</table>";
+
+ TQToolTip::add( this, tipText);
+ }
+
+ p1.setPen(TQPen(palette().active().foreground(), 1, TQt::SolidLine));
+ p1.drawRect(0, 0, width(), height());
+ p1.end();
+ bitBlt(this, 0, 0, &pm);
+}
+
+void HistogramWidget::mousePressEvent(TQMouseEvent* e)
+{
+ if ( d->selectMode == true && d->clearFlag == HistogramWidgetPriv::HistogramCompleted )
+ {
+ if (!d->inSelected)
+ {
+ d->inSelected = true;
+ repaint(false);
+ }
+
+ d->xmin = ((double)e->pos().x()) / ((double)width());
+ d->xminOrg = d->xmin;
+ notifyValuesChanged();
+ //emit signalValuesChanged( (int)(d->xmin * d->range), );
+ d->xmax = 0.0;
+ }
+}
+
+void HistogramWidget::mouseReleaseEvent(TQMouseEvent*)
+{
+ if ( d->selectMode == true && d->clearFlag == HistogramWidgetPriv::HistogramCompleted )
+ {
+ d->inSelected = false;
+ // Only single click without mouse move? Remove selection.
+ if (d->xmax == 0.0)
+ {
+ d->xmin = 0.0;
+ //emit signalMinValueChanged( 0 );
+ //emit signalMaxValueChanged( d->range );
+ notifyValuesChanged();
+ repaint(false);
+ }
+ }
+}
+
+void HistogramWidget::mouseMoveEvent(TQMouseEvent *e)
+{
+ if ( d->selectMode == true && d->clearFlag == HistogramWidgetPriv::HistogramCompleted )
+ {
+ setCursor( KCursor::crossCursor() );
+
+ if (d->inSelected)
+ {
+ double max = ((double)e->pos().x()) / ((double)width());
+ //int max = (int)(e->pos().x()*((float)m_imageHistogram->getHistogramSegment()/(float)width()));
+
+ if (max < d->xminOrg)
+ {
+ d->xmax = d->xminOrg;
+ d->xmin = max;
+ //emit signalMinValueChanged( (int)(d->xmin * d->range) );
+ }
+ else
+ {
+ d->xmin = d->xminOrg;
+ d->xmax = max;
+ }
+
+ notifyValuesChanged();
+ //emit signalMaxValueChanged( d->xmax == 0.0 ? d->range : (int)(d->xmax * d->range) );
+
+ repaint(false);
+ }
+ }
+}
+
+void HistogramWidget::notifyValuesChanged()
+{
+ emit signalIntervalChanged( (int)(d->xmin * d->range), d->xmax == 0.0 ? d->range : (int)(d->xmax * d->range) );
+}
+
+void HistogramWidget::slotMinValueChanged( int min )
+{
+ if ( d->selectMode == true && d->clearFlag == HistogramWidgetPriv::HistogramCompleted )
+ {
+ if (min == 0 && d->xmax == 1.0)
+ {
+ // everything is selected means no selection
+ d->xmin = 0.0;
+ d->xmax = 0.0;
+ }
+ if (min >= 0 && min < d->range)
+ {
+ d->xmin = ((double)min)/d->range;
+ }
+ repaint(false);
+ }
+}
+
+void HistogramWidget::slotMaxValueChanged(int max)
+{
+ if ( d->selectMode == true && d->clearFlag == HistogramWidgetPriv::HistogramCompleted )
+ {
+ if (d->xmin == 0.0 && max == d->range)
+ {
+ // everything is selected means no selection
+ d->xmin = 0.0;
+ d->xmax = 0.0;
+ }
+ else if (max > 0 && max <= d->range)
+ {
+ d->xmax = ((double)max)/d->range;
+ }
+ repaint(false);
+ }
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/common/histogramwidget.h b/src/libs/widgets/common/histogramwidget.h
new file mode 100644
index 00000000..26157170
--- /dev/null
+++ b/src/libs/widgets/common/histogramwidget.h
@@ -0,0 +1,177 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-21
+ * Description : a widget to display an image histogram.
+ *
+ * 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 HISTOGRAMWIDGET_H
+#define HISTOGRAMWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+
+// Local includes.
+
+#include "dcolor.h"
+#include "digikam_export.h"
+
+class TQCustomEvent;
+
+namespace Digikam
+{
+
+class ImageHistogram;
+class HistogramWidgetPriv;
+
+class DIGIKAM_EXPORT HistogramWidget : public TQWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ enum HistogramType
+ {
+ ValueHistogram = 0, // Luminosity.
+ RedChannelHistogram, // Red channel.
+ GreenChannelHistogram, // Green channel.
+ BlueChannelHistogram, // Blue channel.
+ AlphaChannelHistogram, // Alpha channel.
+ ColorChannelsHistogram // All color channels.
+ };
+
+ enum HistogramScale
+ {
+ LinScaleHistogram=0, // Linear scale.
+ LogScaleHistogram // Logarithmic scale.
+ };
+
+ enum HistogramAllColorMode
+ {
+ RedColor=0, // Red color to foreground in All Colors Channel mode.
+ GreenColor, // Green color to foreground in All Colors Channel mode.
+ BlueColor // Blue color to foreground in All Colors Channel mode.
+ };
+
+ enum HistogramRenderingType
+ {
+ FullImageHistogram=0, // Full image histogram rendering.
+ ImageSelectionHistogram // Image selection histogram rendering.
+ };
+
+public:
+
+ /** Constructor without image data. Needed to use updateData() method after to create instance.*/
+ HistogramWidget(int w, int h, // Widget size.
+ TQWidget *parent=0, bool selectMode=true,
+ bool showProgress=true,
+ bool statisticsVisible=false);
+
+ /** Constructor with image data and without image selection data.*/
+ HistogramWidget(int w, int h, // Widget size.
+ uchar *i_data, uint i_w, uint i_h, // Full image info.
+ bool i_sixteenBits, // 8 or 16 bits image.
+ TQWidget *parent=0, bool selectMode=true,
+ bool showProgress=true,
+ bool statisticsVisible=false);
+
+ /** Constructor with image data and image selection data.*/
+ HistogramWidget(int w, int h, // Widget size.
+ uchar *i_data, uint i_w, uint i_h, // Full image info.
+ uchar *s_data, uint s_w, uint s_h, // Image selection info.
+ bool i_sixteenBits, // 8 or 16 bits image.
+ TQWidget *parent=0, bool selectMode=true,
+ bool showProgress=true,
+ bool statisticsVisible=false);
+
+ void setup(int w, int h, bool selectMode=true,
+ bool showProgress=true,
+ bool statisticsVisible=false);
+
+ ~HistogramWidget();
+
+ /** Stop current histogram computations.*/
+ void stopHistogramComputation(void);
+
+ /** Update full image histogram data methods.*/
+ void updateData(uchar *i_data, uint i_w, uint i_h,
+ bool i_sixteenBits, // 8 or 16 bits image.
+ uchar *s_data=0, uint s_w=0, uint s_h=0,
+ bool showProgress=true);
+
+ /** Update image selection histogram data methods.*/
+ void updateSelectionData(uchar *s_data, uint s_w, uint s_h,
+ bool i_sixteenBits, // 8 or 16 bits image.
+ bool showProgress=true);
+
+ void setDataLoading();
+ void setLoadingFailed();
+
+ void setHistogramGuideByColor(const DColor& color);
+
+ void reset();
+
+public:
+
+ int m_channelType; // Channel type to draw.
+ int m_scaleType; // Scale to use for drawing.
+ int m_colorType; // Color to use for drawing in All Colors Channel mode.
+ int m_renderingType; // Using full image or image selection for histogram rendering.
+
+ ImageHistogram *m_imageHistogram; // Full image.
+ ImageHistogram *m_selectionHistogram; // Image selection.
+
+signals:
+
+ void signalIntervalChanged(int min, int max);
+ void signalMaximumValueChanged(int);
+ void signalHistogramComputationDone(bool);
+ void signalHistogramComputationFailed();
+
+public slots:
+
+ void slotMinValueChanged(int min);
+ void slotMaxValueChanged(int max);
+
+protected slots:
+
+ void slotBlinkTimerDone();
+
+protected:
+
+ void paintEvent(TQPaintEvent*);
+ void mousePressEvent(TQMouseEvent*);
+ void mouseReleaseEvent(TQMouseEvent*);
+ void mouseMoveEvent(TQMouseEvent*);
+
+private :
+
+ void customEvent(TQCustomEvent*);
+ void notifyValuesChanged();
+
+private:
+
+ HistogramWidgetPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* HISTOGRAMWIDGET_H */
diff --git a/src/libs/widgets/common/paniconwidget.cpp b/src/libs/widgets/common/paniconwidget.cpp
new file mode 100644
index 00000000..d5549691
--- /dev/null
+++ b/src/libs/widgets/common/paniconwidget.cpp
@@ -0,0 +1,324 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-22
+ * Description : a generic widget to display a panel to choose
+ * a rectangular image area.
+ *
+ * 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 <cmath>
+
+// TQt includes.
+
+#include <tqpainter.h>
+#include <tqpixmap.h>
+#include <tqpen.h>
+#include <tqtimer.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "paniconwidget.h"
+#include "paniconwidget.moc"
+
+namespace Digikam
+{
+
+class PanIconWidgetPriv
+{
+
+public:
+
+ PanIconWidgetPriv()
+ {
+ moveSelection = false;
+ }
+
+ bool moveSelection;
+
+ int xpos;
+ int ypos;
+
+ TQRect regionSelection; // Original size image selection.
+
+ TQImage image;
+};
+
+PanIconWidget::PanIconWidget(TQWidget *parent, WFlags flags)
+ : TQWidget(parent, 0, flags)
+{
+ d = new PanIconWidgetPriv;
+ m_flicker = false;
+ m_timerID = 0;
+ m_pixmap = 0;
+ m_zoomFactor = 1.0;
+
+ setBackgroundMode(TQt::NoBackground);
+ setMouseTracking(true);
+}
+
+PanIconWidget::~PanIconWidget()
+{
+ if (m_timerID) killTimer(m_timerID);
+
+ if (m_pixmap) delete m_pixmap;
+
+ delete d;
+}
+
+void PanIconWidget::setImage(int previewWidth, int previewHeight, const TQImage& image)
+{
+ TQSize sz(image.width(), image.height());
+ sz.scale(previewWidth, previewHeight, TQSize::ScaleMin);
+ m_pixmap = new TQPixmap(previewWidth, previewHeight);
+ m_width = sz.width();
+ m_height = sz.height();
+ d->image = image.smoothScale(sz.width(), sz.height());
+ m_orgWidth = image.width();
+ m_orgHeight = image.height();
+ m_zoomedOrgWidth = image.width();
+ m_zoomedOrgHeight = image.height();
+ setFixedSize(m_width, m_height);
+
+ m_rect = TQRect(width()/2-m_width/2, height()/2-m_height/2, m_width, m_height);
+ updatePixmap();
+ m_timerID = startTimer(800);
+}
+
+void PanIconWidget::setImage(int previewWidth, int previewHeight, const DImg& image)
+{
+ DImg img(image);
+ setImage(previewWidth, previewHeight, img.copyTQImage());
+}
+
+void PanIconWidget::slotZoomFactorChanged(double factor)
+{
+ if (m_zoomFactor == factor) return;
+ m_zoomFactor = factor;
+ m_zoomedOrgWidth = (int)(m_orgWidth * factor);
+ m_zoomedOrgHeight = (int)(m_orgHeight * factor);
+ updatePixmap();
+ repaint(false);
+}
+
+void PanIconWidget::setRegionSelection(const TQRect& regionSelection)
+{
+ d->regionSelection = regionSelection;
+ m_localRegionSelection.setX( m_rect.x() + (int)((float)d->regionSelection.x() *
+ ((float)m_width / (float)m_zoomedOrgWidth)) );
+
+ m_localRegionSelection.setY( m_rect.y() + (int)((float)d->regionSelection.y() *
+ ((float)m_height / (float)m_zoomedOrgHeight)) );
+
+ m_localRegionSelection.setWidth( (int)((float)d->regionSelection.width() *
+ ((float)m_width / (float)m_zoomedOrgWidth)) );
+
+ m_localRegionSelection.setHeight( (int)((float)d->regionSelection.height() *
+ ((float)m_height / (float)m_zoomedOrgHeight)) );
+
+ updatePixmap();
+ repaint(false);
+}
+
+TQRect PanIconWidget::getRegionSelection()
+{
+ return (d->regionSelection);
+}
+
+void PanIconWidget::setCursorToLocalRegionSelectionCenter()
+{
+ TQCursor::setPos(mapToGlobal(m_localRegionSelection.center()));
+}
+
+void PanIconWidget::setCenterSelection()
+{
+ setRegionSelection(TQRect(
+ (int)(((float)m_zoomedOrgWidth / 2.0) - ((float)d->regionSelection.width() / 2.0)),
+ (int)(((float)m_zoomedOrgHeight / 2.0) - ((float)d->regionSelection.height() / 2.0)),
+ d->regionSelection.width(),
+ d->regionSelection.height()));
+}
+
+void PanIconWidget::regionSelectionMoved(bool targetDone)
+{
+ if (targetDone)
+ {
+ updatePixmap();
+ repaint(false);
+ }
+
+ int x = (int)lround( ((float)m_localRegionSelection.x() - (float)m_rect.x() ) *
+ ((float)m_zoomedOrgWidth / (float)m_width) );
+
+ int y = (int)lround( ((float)m_localRegionSelection.y() - (float)m_rect.y() ) *
+ ((float)m_zoomedOrgHeight / (float)m_height) );
+
+ int w = (int)lround( (float)m_localRegionSelection.width() *
+ ((float)m_zoomedOrgWidth / (float)m_width) );
+
+ int h = (int)lround( (float)m_localRegionSelection.height() *
+ ((float)m_zoomedOrgHeight / (float)m_height) );
+
+ d->regionSelection.setX(x);
+ d->regionSelection.setY(y);
+ d->regionSelection.setWidth(w);
+ d->regionSelection.setHeight(h);
+
+ emit signalSelectionMoved( d->regionSelection, targetDone );
+}
+
+void PanIconWidget::updatePixmap()
+{
+ // Drawing background and image.
+ m_pixmap->fill(colorGroup().background());
+ bitBlt(m_pixmap, m_rect.x(), m_rect.y(), &d->image, 0, 0);
+
+ TQPainter p(m_pixmap);
+
+ // Drawing selection border
+
+ if (m_flicker) p.setPen(TQPen(TQt::white, 1, TQt::SolidLine));
+ else p.setPen(TQPen(TQt::red, 1, TQt::SolidLine));
+
+ p.drawRect(m_localRegionSelection.x(),
+ m_localRegionSelection.y(),
+ m_localRegionSelection.width(),
+ m_localRegionSelection.height());
+
+ if (m_flicker) p.setPen(TQPen(TQt::red, 1, TQt::DotLine));
+ else p.setPen(TQPen(TQt::white, 1, TQt::DotLine));
+
+ p.drawRect(m_localRegionSelection.x(),
+ m_localRegionSelection.y(),
+ m_localRegionSelection.width(),
+ m_localRegionSelection.height());
+
+ p.end();
+}
+
+void PanIconWidget::paintEvent(TQPaintEvent*)
+{
+ bitBlt(this, 0, 0, m_pixmap);
+}
+
+void PanIconWidget::setMouseFocus()
+{
+ raise();
+ d->xpos = m_localRegionSelection.center().x();
+ d->ypos = m_localRegionSelection.center().y();
+ d->moveSelection = true;
+ setCursor( KCursor::sizeAllCursor() );
+ emit signalSelectionTakeFocus();
+}
+
+void PanIconWidget::hideEvent(TQHideEvent *e)
+{
+ TQWidget::hideEvent(e);
+
+ if ( d->moveSelection )
+ {
+ d->moveSelection = false;
+ setCursor( KCursor::arrowCursor() );
+ emit signalHiden();
+ }
+}
+
+void PanIconWidget::mousePressEvent ( TQMouseEvent * e )
+{
+ if ( (e->button() == TQt::LeftButton || e->button() == TQt::MidButton) &&
+ m_localRegionSelection.contains( e->x(), e->y() ) )
+ {
+ d->xpos = e->x();
+ d->ypos = e->y();
+ d->moveSelection = true;
+ setCursor( KCursor::sizeAllCursor() );
+ emit signalSelectionTakeFocus();
+ }
+}
+
+void PanIconWidget::mouseMoveEvent ( TQMouseEvent * e )
+{
+ if ( d->moveSelection &&
+ (e->state() == TQt::LeftButton || e->state() == TQt::MidButton) )
+ {
+ int newxpos = e->x();
+ int newypos = e->y();
+
+ m_localRegionSelection.moveBy (newxpos - d->xpos, newypos - d->ypos);
+
+ d->xpos = newxpos;
+ d->ypos = newypos;
+
+ // Perform normalization of selection area.
+
+ if (m_localRegionSelection.left() < m_rect.left())
+ m_localRegionSelection.moveLeft(m_rect.left());
+
+ if (m_localRegionSelection.top() < m_rect.top())
+ m_localRegionSelection.moveTop(m_rect.top());
+
+ if (m_localRegionSelection.right() > m_rect.right())
+ m_localRegionSelection.moveRight(m_rect.right());
+
+ if (m_localRegionSelection.bottom() > m_rect.bottom())
+ m_localRegionSelection.moveBottom(m_rect.bottom());
+
+ updatePixmap();
+ repaint(false);
+ regionSelectionMoved(false);
+ return;
+ }
+ else
+ {
+ if ( m_localRegionSelection.contains( e->x(), e->y() ) )
+ setCursor( KCursor::handCursor() );
+ else
+ setCursor( KCursor::arrowCursor() );
+ }
+}
+
+void PanIconWidget::mouseReleaseEvent ( TQMouseEvent * )
+{
+ if ( d->moveSelection )
+ {
+ d->moveSelection = false;
+ setCursor( KCursor::arrowCursor() );
+ regionSelectionMoved(true);
+ }
+}
+
+void PanIconWidget::timerEvent(TQTimerEvent * e)
+{
+ if (e->timerId() == m_timerID)
+ {
+ m_flicker = !m_flicker;
+ updatePixmap();
+ repaint(false);
+ }
+ else
+ TQWidget::timerEvent(e);
+}
+
+} // NameSpace Digikam
diff --git a/src/libs/widgets/common/paniconwidget.h b/src/libs/widgets/common/paniconwidget.h
new file mode 100644
index 00000000..40b0758e
--- /dev/null
+++ b/src/libs/widgets/common/paniconwidget.h
@@ -0,0 +1,120 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-22
+ * Description : a generic widget to display a panel to choose
+ * a rectangular image area.
+ *
+ * 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 PANICONWIDGET_H
+#define PANICONWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqrect.h>
+#include <tqimage.h>
+
+// Local includes.
+
+#include "dimg.h"
+
+namespace Digikam
+{
+
+class ImagePanIconWidget;
+class PanIconWidgetPriv;
+
+class PanIconWidget : public TQWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ PanIconWidget(TQWidget *parent=0, WFlags flags=TQt::WDestructiveClose);
+ ~PanIconWidget();
+
+ void setImage(int previewWidth, int previewHeight, const TQImage& image);
+ void setImage(int previewWidth, int previewHeight, const DImg& image);
+
+ void setRegionSelection(const TQRect& regionSelection);
+ TQRect getRegionSelection();
+ void setCenterSelection();
+
+ void setCursorToLocalRegionSelectionCenter();
+ void setMouseFocus();
+
+signals:
+
+ // Used with ImagePreview widget.
+ // Emit when selection have been moved with mouse. 'targetDone' booleen
+ // value is used for indicate if the mouse have been released.
+ void signalSelectionMoved(const TQRect& rect, bool targetDone );
+
+ void signalSelectionTakeFocus();
+
+ void signalHiden();
+
+public slots:
+
+ void slotZoomFactorChanged(double);
+
+protected:
+
+ void hideEvent(TQHideEvent*);
+ void paintEvent(TQPaintEvent*);
+ void mousePressEvent(TQMouseEvent*);
+ void mouseReleaseEvent(TQMouseEvent*);
+ void mouseMoveEvent(TQMouseEvent*);
+ void timerEvent(TQTimerEvent*);
+
+ /** Recalculate the target selection position and emit 'signalSelectionMoved'.*/
+ void regionSelectionMoved(bool targetDone);
+
+ virtual void updatePixmap();
+
+protected:
+
+ bool m_flicker;
+
+ int m_timerID;
+ int m_width;
+ int m_height;
+ int m_zoomedOrgWidth;
+ int m_zoomedOrgHeight;
+ int m_orgWidth;
+ int m_orgHeight;
+
+ double m_zoomFactor;
+
+ TQRect m_rect;
+ TQRect m_localRegionSelection; // Thumbnail size selection.
+
+ TQPixmap *m_pixmap;
+
+
+private:
+
+ PanIconWidgetPriv* d;
+};
+
+} // NameSpace Digikam
+
+#endif /* PANICONWIDGET_H */
diff --git a/src/libs/widgets/common/previewwidget.cpp b/src/libs/widgets/common/previewwidget.cpp
new file mode 100644
index 00000000..0fe5cb29
--- /dev/null
+++ b/src/libs/widgets/common/previewwidget.cpp
@@ -0,0 +1,640 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-06-13
+ * Description : a widget to display an image preview
+ *
+ * Copyright (C) 2006-2008 Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+
+// TQt includes.
+
+#include <tqstring.h>
+#include <tqcache.h>
+#include <tqpainter.h>
+#include <tqimage.h>
+#include <tqpixmap.h>
+#include <tqrect.h>
+#include <tqtimer.h>
+#include <tqguardedptr.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "previewwidget.h"
+#include "previewwidget.moc"
+
+namespace Digikam
+{
+
+class PreviewWidgetPriv
+{
+public:
+
+ PreviewWidgetPriv() :
+ tileSize(128), zoomMultiplier(1.2)
+ {
+ midButtonX = 0;
+ midButtonY = 0;
+ autoZoom = false;
+ fullScreen = false;
+ zoom = 1.0;
+ minZoom = 0.1;
+ maxZoom = 12.0;
+ zoomWidth = 0;
+ zoomHeight = 0;
+ tileTmpPix = new TQPixmap(tileSize, tileSize);
+
+ tileCache.setMaxCost((10*1024*1024)/(tileSize*tileSize*4));
+ tileCache.setAutoDelete(true);
+ }
+
+ bool autoZoom;
+ bool fullScreen;
+
+ const int tileSize;
+ int midButtonX;
+ int midButtonY;
+ int zoomWidth;
+ int zoomHeight;
+
+ double zoom;
+ double minZoom;
+ double maxZoom;
+ const double zoomMultiplier;
+
+ TQPoint centerZoomPoint;
+
+ TQRect pixmapRect;
+
+ TQCache<TQPixmap> tileCache;
+
+ TQPixmap* tileTmpPix;
+
+ TQColor bgColor;
+};
+
+PreviewWidget::PreviewWidget(TQWidget *parent)
+ : TQScrollView(parent, 0, TQt::WDestructiveClose)
+{
+ d = new PreviewWidgetPriv;
+ d->bgColor.setRgb(0, 0, 0);
+ m_movingInProgress = false;
+
+ viewport()->setBackgroundMode(TQt::NoBackground);
+ viewport()->setMouseTracking(false);
+
+ horizontalScrollBar()->setLineStep( 1 );
+ horizontalScrollBar()->setPageStep( 1 );
+ verticalScrollBar()->setLineStep( 1 );
+ verticalScrollBar()->setPageStep( 1 );
+
+ setFrameStyle(TQFrame::GroupBoxPanel|TQFrame::Plain);
+ setMargin(0);
+ setLineWidth(1);
+}
+
+PreviewWidget::~PreviewWidget()
+{
+ delete d->tileTmpPix;
+ delete d;
+}
+
+void PreviewWidget::setBackgroundColor(const TQColor& color)
+{
+ if (d->bgColor == color)
+ return;
+
+ d->bgColor = color;
+ viewport()->update();
+}
+
+void PreviewWidget::slotReset()
+{
+ d->tileCache.clear();
+ resetPreview();
+}
+
+TQRect PreviewWidget::previewRect()
+{
+ return d->pixmapRect;
+}
+
+int PreviewWidget::tileSize()
+{
+ return d->tileSize;
+}
+
+int PreviewWidget::zoomWidth()
+{
+ return d->zoomWidth;
+}
+
+int PreviewWidget::zoomHeight()
+{
+ return d->zoomHeight;
+}
+
+double PreviewWidget::zoomMax()
+{
+ return d->maxZoom;
+}
+
+double PreviewWidget::zoomMin()
+{
+ return d->minZoom;
+}
+
+void PreviewWidget::setZoomMax(double z)
+{
+ d->maxZoom = ceilf(z * 10000.0) / 10000.0;
+}
+
+void PreviewWidget::setZoomMin(double z)
+{
+ d->minZoom = floor(z * 10000.0) / 10000.0;
+}
+
+bool PreviewWidget::maxZoom()
+{
+ return (d->zoom >= d->maxZoom);
+}
+
+bool PreviewWidget::minZoom()
+{
+ return (d->zoom <= d->minZoom);
+}
+
+double PreviewWidget::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(ZoomInOrOut);
+ 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
+ {
+ for(it = snapValues.constEnd(); it != snapValues.constBegin(); --it)
+ {
+ double z = *it;
+ if ((d->zoom > z) && (zoom < z))
+ {
+ zoom = z;
+ break;
+ }
+ }
+ }
+
+ return zoom;
+}
+
+void PreviewWidget::slotIncreaseZoom()
+{
+ double zoom = d->zoom * d->zoomMultiplier;
+ zoom = snapZoom(zoom > zoomMax() ? zoomMax() : zoom);
+ setZoomFactor(zoom);
+}
+
+void PreviewWidget::slotDecreaseZoom()
+{
+ double zoom = d->zoom / d->zoomMultiplier;
+ zoom = snapZoom(zoom < zoomMin() ? zoomMin() : zoom);
+ setZoomFactor(zoom);
+}
+
+void PreviewWidget::setZoomFactorSnapped(double zoom)
+{
+ double fit = calcAutoZoomFactor(ZoomInOrOut);
+ if (fabs(zoom-1.0) < 0.05)
+ {
+ zoom = 1.0;
+ }
+ if (fabs(zoom-0.5) < 0.05)
+ {
+ zoom = 0.5;
+ }
+ if (fabs(zoom-fit) < 0.05)
+ {
+ zoom = fit;
+ }
+
+ setZoomFactor(zoom);
+}
+
+void PreviewWidget::setZoomFactor(double zoom)
+{
+ setZoomFactor(zoom, false);
+}
+
+void PreviewWidget::setZoomFactor(double zoom, bool centerView)
+{
+ // Zoom using center of canvas and given zoom factor.
+
+ double oldZoom = d->zoom;
+ double cpx, cpy;
+
+ if (d->centerZoomPoint.isNull())
+ {
+ // center on current center
+ // store old center pos
+ cpx = contentsX() + visibleWidth() / 2.0;
+ cpy = contentsY() + visibleHeight() / 2.0;
+
+ cpx = ( cpx / d->tileSize ) * floor(d->tileSize / d->zoom);
+ cpy = ( cpy / d->tileSize ) * floor(d->tileSize / d->zoom);
+ }
+ else
+ {
+ // keep mouse pointer position constant
+ // store old content pos
+ cpx = contentsX();
+ cpy = contentsY();
+ }
+
+ // To limit precision of zoom value and reduce error with check of max/min zoom.
+ d->zoom = floor(zoom * 10000.0) / 10000.0;
+ d->zoomWidth = (int)(previewWidth() * d->zoom);
+ d->zoomHeight = (int)(previewHeight() * d->zoom);
+
+ updateContentsSize();
+
+ // adapt step size to zoom factor. Overall, using a finer step size than scrollbar default.
+ int step = TQMAX(2, 2*lround(d->zoom));
+ horizontalScrollBar()->setLineStep( step );
+ horizontalScrollBar()->setPageStep( step * 10 );
+ verticalScrollBar()->setLineStep( step );
+ verticalScrollBar()->setPageStep( step * 10 );
+
+ viewport()->setUpdatesEnabled(false);
+ if (d->centerZoomPoint.isNull())
+ {
+ cpx = ( cpx * d->tileSize ) / floor(d->tileSize / d->zoom);
+ cpy = ( cpy * d->tileSize ) / floor(d->tileSize / d->zoom);
+
+ if (centerView)
+ {
+ cpx = d->zoomWidth/2.0;
+ cpy = d->zoomHeight/2.0;
+ }
+
+ center((int)cpx, (int)(cpy));
+ }
+ else
+ {
+ cpx = d->zoom * d->centerZoomPoint.x() / oldZoom - d->centerZoomPoint.x() + cpx;
+ cpy = d->zoom * d->centerZoomPoint.y() / oldZoom - d->centerZoomPoint.y() + cpy;
+
+ setContentsPos((int)cpx, (int)(cpy));
+ }
+ viewport()->setUpdatesEnabled(true);
+ viewport()->update();
+
+ zoomFactorChanged(d->zoom);
+}
+
+double PreviewWidget::zoomFactor()
+{
+ return d->zoom;
+}
+
+bool PreviewWidget::isFitToWindow()
+{
+ return d->autoZoom;
+}
+
+void PreviewWidget::fitToWindow()
+{
+ updateAutoZoom();
+ updateContentsSize();
+ zoomFactorChanged(d->zoom);
+ viewport()->update();
+}
+
+void PreviewWidget::toggleFitToWindow()
+{
+ d->autoZoom = !d->autoZoom;
+
+ if (d->autoZoom)
+ {
+ updateAutoZoom();
+ }
+ else
+ {
+ d->zoom = 1.0;
+ zoomFactorChanged(d->zoom);
+ }
+
+ updateContentsSize();
+ viewport()->update();
+}
+
+void PreviewWidget::toggleFitToWindowOr100()
+{
+ // If the current zoom is 100%, then fit to window.
+ if (d->zoom == 1.0)
+ {
+ fitToWindow();
+ }
+ else
+ {
+ setZoomFactor(1.0, true);
+ }
+}
+
+void PreviewWidget::updateAutoZoom(AutoZoomMode mode)
+{
+ d->zoom = calcAutoZoomFactor(mode);
+ d->zoomWidth = (int)(previewWidth() * d->zoom);
+ d->zoomHeight = (int)(previewHeight() * d->zoom);
+
+ zoomFactorChanged(d->zoom);
+}
+
+double PreviewWidget::calcAutoZoomFactor(AutoZoomMode mode)
+{
+ if (previewIsNull()) return d->zoom;
+
+ double srcWidth = previewWidth();
+ double srcHeight = previewHeight();
+ double dstWidth = contentsRect().width();
+ double dstHeight = contentsRect().height();
+
+ double zoom = TQMIN(dstWidth/srcWidth, dstHeight/srcHeight);
+ // limit precision as above
+ zoom = floor(zoom * 10000.0) / 10000.0;
+ if (mode == ZoomInOrOut)
+ // fit to available space, scale up or down
+ return zoom;
+ else
+ // ZoomInOnly: accept that an image is smaller than available space, dont scale up
+ return TQMIN(1.0, zoom);
+}
+
+void PreviewWidget::updateContentsSize()
+{
+ viewport()->setUpdatesEnabled(false);
+
+ if (visibleWidth() > d->zoomWidth || visibleHeight() > d->zoomHeight)
+ {
+ // Center the image
+ int centerx = contentsRect().width()/2;
+ int centery = contentsRect().height()/2;
+ int xoffset = int(centerx - d->zoomWidth/2);
+ int yoffset = int(centery - d->zoomHeight/2);
+ xoffset = TQMAX(xoffset, 0);
+ yoffset = TQMAX(yoffset, 0);
+
+ d->pixmapRect = TQRect(xoffset, yoffset, d->zoomWidth, d->zoomHeight);
+ }
+ else
+ {
+ d->pixmapRect = TQRect(0, 0, d->zoomWidth, d->zoomHeight);
+ }
+
+ d->tileCache.clear();
+ setContentsSize();
+ viewport()->setUpdatesEnabled(true);
+}
+
+void PreviewWidget::setContentsSize()
+{
+ resizeContents(d->zoomWidth, d->zoomHeight);
+}
+
+void PreviewWidget::resizeEvent(TQResizeEvent* e)
+{
+ if (!e) return;
+
+ TQScrollView::resizeEvent(e);
+
+ if (d->autoZoom)
+ updateAutoZoom();
+
+ updateContentsSize();
+
+ // 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.
+ zoomFactorChanged(d->zoom);
+}
+
+void PreviewWidget::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()));
+
+ bool antialias = (d->zoom <= 1.0) ? true : false;
+
+ TQRect o_cr(viewportToContents(er.topLeft()), viewportToContents(er.bottomRight()));
+ TQRect cr = o_cr;
+
+ TQRegion clipRegion(er);
+ cr = d->pixmapRect.intersect(cr);
+
+ if (!cr.isEmpty() && !previewIsNull())
+ {
+ 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);
+
+ 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;
+ }
+
+ pix->fill(d->bgColor);
+
+ sx = (int)floor((double)i / d->tileSize ) * step;
+ sy = (int)floor((double)j / d->tileSize ) * step;
+ sw = step;
+ sh = step;
+
+ paintPreview(pix, sx, sy, sw, sh);
+ }
+
+ 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());
+ }
+ }
+ }
+
+ TQPainter p(viewport());
+ p.setClipRegion(clipRegion);
+ p.fillRect(er, d->bgColor);
+ p.end();
+
+ viewportPaintExtraData();
+}
+
+void PreviewWidget::contentsMousePressEvent(TQMouseEvent *e)
+{
+ if (!e || e->button() == TQt::RightButton)
+ return;
+
+ m_movingInProgress = false;
+
+ if (e->button() == TQt::LeftButton)
+ {
+ emit signalLeftButtonClicked();
+ }
+ else if (e->button() == TQt::MidButton)
+ {
+ if (visibleWidth() < d->zoomWidth ||
+ visibleHeight() < d->zoomHeight)
+ {
+ m_movingInProgress = true;
+ d->midButtonX = e->x();
+ d->midButtonY = e->y();
+ viewport()->repaint(false);
+ viewport()->setCursor(TQt::SizeAllCursor);
+ }
+ return;
+ }
+
+ viewport()->setMouseTracking(false);
+}
+
+void PreviewWidget::contentsMouseMoveEvent(TQMouseEvent *e)
+{
+ if (!e) return;
+
+ if (e->state() & TQt::MidButton)
+ {
+ if (m_movingInProgress)
+ {
+ scrollBy(d->midButtonX - e->x(),
+ d->midButtonY - e->y());
+ emit signalContentsMovedEvent(false);
+ }
+ }
+}
+
+void PreviewWidget::contentsMouseReleaseEvent(TQMouseEvent *e)
+{
+ if (!e) return;
+
+ m_movingInProgress = false;
+
+ if (e->button() == TQt::MidButton)
+ {
+ emit signalContentsMovedEvent(true);
+ viewport()->unsetCursor();
+ viewport()->repaint(false);
+ }
+
+ if (e->button() == TQt::RightButton)
+ {
+ emit signalRightButtonClicked();
+ }
+}
+
+void PreviewWidget::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)
+ {
+ // When zooming with the mouse-wheel, the image center is kept fixed.
+ d->centerZoomPoint = e->pos();
+ if (e->delta() < 0 && !minZoom())
+ slotDecreaseZoom();
+ else if (e->delta() > 0 && !maxZoom())
+ slotIncreaseZoom();
+ d->centerZoomPoint = TQPoint();
+ return;
+ }
+
+ TQScrollView::contentsWheelEvent(e);
+}
+
+void PreviewWidget::zoomFactorChanged(double zoom)
+{
+ emit signalZoomFactorChanged(zoom);
+}
+
+} // NameSpace Digikam
diff --git a/src/libs/widgets/common/previewwidget.h b/src/libs/widgets/common/previewwidget.h
new file mode 100644
index 00000000..03369a42
--- /dev/null
+++ b/src/libs/widgets/common/previewwidget.h
@@ -0,0 +1,131 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-06-13
+ * Description : a widget to display an image preview
+ *
+ * Copyright (C) 2006-2007 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 PREVIEWWIDGET_H
+#define PREVIEWWIDGET_H
+
+// TQt includes.
+
+#include <tqscrollview.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+class TQPainter;
+class TQPixmap;
+class TQColor;
+
+namespace Digikam
+{
+
+class PreviewWidgetPriv;
+
+class DIGIKAM_EXPORT PreviewWidget : public TQScrollView
+{
+TQ_OBJECT
+
+
+public:
+
+ PreviewWidget(TQWidget *parent=0);
+ ~PreviewWidget();
+
+ void setZoomFactor(double z);
+ void setZoomFactor(double z, bool centerView);
+ void setZoomFactorSnapped(double z);
+
+ void setBackgroundColor(const TQColor& color);
+ void fitToWindow();
+ bool isFitToWindow();
+ void toggleFitToWindow();
+ void toggleFitToWindowOr100();
+
+ int zoomWidth();
+ int zoomHeight();
+ bool maxZoom();
+ bool minZoom();
+ double snapZoom(double zoom);
+
+ double zoomFactor();
+ double zoomMax();
+ double zoomMin();
+ void setZoomMax(double z);
+ void setZoomMin(double z);
+
+signals:
+
+ void signalRightButtonClicked();
+ void signalLeftButtonClicked();
+ void signalShowNextImage();
+ void signalShowPrevImage();
+ void signalZoomFactorChanged(double);
+ void signalContentsMovedEvent(bool);
+
+public slots:
+
+ void slotIncreaseZoom();
+ void slotDecreaseZoom();
+ void slotReset();
+
+protected:
+
+ bool m_movingInProgress;
+
+protected:
+
+ enum AutoZoomMode
+ {
+ ZoomInOrOut,
+ ZoomInOnly
+ };
+
+ double calcAutoZoomFactor(AutoZoomMode mode = ZoomInOrOut);
+ int tileSize();
+ void updateAutoZoom(AutoZoomMode mode = ZoomInOrOut);
+ void updateContentsSize();
+ TQRect previewRect();
+
+ virtual void resizeEvent(TQResizeEvent *);
+ virtual void viewportPaintEvent(TQPaintEvent *);
+ virtual void contentsMousePressEvent(TQMouseEvent *);
+ virtual void contentsMouseMoveEvent(TQMouseEvent *);
+ virtual void contentsMouseReleaseEvent(TQMouseEvent *);
+ virtual void contentsWheelEvent(TQWheelEvent *);
+ virtual void setContentsSize();
+ virtual void viewportPaintExtraData(){};
+ virtual int previewWidth()=0;
+ virtual int previewHeight()=0;
+ virtual bool previewIsNull()=0;
+ virtual void resetPreview()=0;
+ virtual void paintPreview(TQPixmap *pix, int sx, int sy, int sw, int sh)=0;
+ virtual void zoomFactorChanged(double zoom);
+
+private:
+
+ PreviewWidgetPriv* d;
+};
+
+} // NameSpace Digikam
+
+#endif /* PREVIEWWIDGET_H */
diff --git a/src/libs/widgets/common/searchtextbar.cpp b/src/libs/widgets/common/searchtextbar.cpp
new file mode 100644
index 00000000..1a81c03b
--- /dev/null
+++ b/src/libs/widgets/common/searchtextbar.cpp
@@ -0,0 +1,260 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-11-25
+ * Description : a bar used to search a string.
+ *
+ * Copyright (C) 2007-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqpalette.h>
+#include <tqpainter.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqtoolbutton.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <kiconloader.h>
+#include <kdialogbase.h>
+#include <tdeconfig.h>
+
+// Local includes.
+
+#include "searchtextbar.h"
+#include "searchtextbar.moc"
+
+namespace Digikam
+{
+
+class DLineEditPriv
+{
+public:
+
+ DLineEditPriv()
+ {
+ drawMsg = true;
+ }
+
+ bool drawMsg;
+
+ TQString message;
+};
+
+DLineEdit::DLineEdit(const TQString &msg, TQWidget *parent)
+ : KLineEdit(parent)
+{
+ d = new DLineEditPriv;
+ setMessage(msg);
+}
+
+DLineEdit::~DLineEdit()
+{
+ delete d;
+}
+
+TQString DLineEdit::message() const
+{
+ return d->message;
+}
+
+void DLineEdit::setMessage(const TQString &msg)
+{
+ d->message = msg;
+ repaint();
+}
+
+void DLineEdit::setText(const TQString &txt)
+{
+ d->drawMsg = txt.isEmpty();
+ repaint();
+ KLineEdit::setText(txt);
+}
+
+void DLineEdit::drawContents(TQPainter *p)
+{
+ KLineEdit::drawContents(p);
+
+ if (d->drawMsg && !hasFocus())
+ {
+ TQPen tmp = p->pen();
+ p->setPen(palette().color(TQPalette::Disabled, TQColorGroup::Text));
+ TQRect cr = contentsRect();
+
+ // Add two pixel margin on the left side
+ cr.rLeft() += 3;
+ p->drawText(cr, AlignAuto | AlignVCenter, d->message);
+ p->setPen( tmp );
+ }
+}
+
+void DLineEdit::dropEvent(TQDropEvent *e)
+{
+ d->drawMsg = false;
+ KLineEdit::dropEvent(e);
+}
+
+void DLineEdit::focusInEvent(TQFocusEvent *e)
+{
+ if (d->drawMsg)
+ {
+ d->drawMsg = false;
+ repaint();
+ }
+ TQLineEdit::focusInEvent(e);
+}
+
+void DLineEdit::focusOutEvent(TQFocusEvent *e)
+{
+ if (text().isEmpty())
+ {
+ d->drawMsg = true;
+ repaint();
+ }
+ TQLineEdit::focusOutEvent(e);
+}
+
+// ---------------------------------------------------------------------
+
+class SearchTextBarPriv
+{
+public:
+
+ SearchTextBarPriv()
+ {
+ textQueryCompletion = false;
+ searchEdit = 0;
+ clearButton = 0;
+ }
+
+ bool textQueryCompletion;
+
+ TQToolButton *clearButton;
+
+ DLineEdit *searchEdit;
+};
+
+SearchTextBar::SearchTextBar(TQWidget *parent, const char* name, const TQString &msg)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ d = new SearchTextBarPriv;
+ setFocusPolicy(TQWidget::NoFocus);
+ setName(name);
+
+ TQHBoxLayout *hlay = new TQHBoxLayout(this);
+
+ d->clearButton = new TQToolButton(this);
+ d->clearButton->setEnabled(false);
+ d->clearButton->setAutoRaise(true);
+ d->clearButton->setIconSet(kapp->iconLoader()->loadIcon("clear_left",
+ TDEIcon::Toolbar, TDEIcon::SizeSmall));
+
+ d->searchEdit = new DLineEdit(msg, this);
+ TDECompletion *kcom = new TDECompletion;
+ kcom->setOrder(TDECompletion::Sorted);
+ d->searchEdit->setCompletionObject(kcom, true);
+ d->searchEdit->setAutoDeleteCompletionObject(true);
+ d->searchEdit->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Minimum));
+
+ hlay->setSpacing(0);
+ hlay->setMargin(0);
+ hlay->addWidget(d->searchEdit);
+ hlay->addWidget(d->clearButton);
+
+ connect(d->clearButton, TQ_SIGNAL(clicked()),
+ d->searchEdit, TQ_SLOT(clear()));
+
+ connect(d->searchEdit, TQ_SIGNAL(textChanged(const TQString&)),
+ this, TQ_SLOT(slotTextChanged(const TQString&)));
+
+ TDEConfig *config = kapp->config();
+ config->setGroup(name + TQString(" Search Text Tool"));
+ d->searchEdit->setCompletionMode((TDEGlobalSettings::Completion)config->readNumEntry("AutoCompletionMode",
+ (int)TDEGlobalSettings::CompletionAuto));
+}
+
+SearchTextBar::~SearchTextBar()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup(name() + TQString(" Search Text Tool"));
+ config->writeEntry("AutoCompletionMode", (int)d->searchEdit->completionMode());
+ config->sync();
+
+ delete d;
+}
+
+void SearchTextBar::setEnableTextQueryCompletion(bool b)
+{
+ d->textQueryCompletion = b;
+}
+
+bool SearchTextBar::textQueryCompletion() const
+{
+ return d->textQueryCompletion;
+}
+
+void SearchTextBar::setText(const TQString& text)
+{
+ d->searchEdit->setText(text);
+}
+
+TQString SearchTextBar::text() const
+{
+ return d->searchEdit->text();
+}
+
+DLineEdit *SearchTextBar::lineEdit() const
+{
+ return d->searchEdit;
+}
+
+void SearchTextBar::slotTextChanged(const TQString& text)
+{
+ if (d->searchEdit->text().isEmpty())
+ d->searchEdit->unsetPalette();
+
+ d->clearButton->setEnabled(text.isEmpty() ? false : true);
+
+ emit signalTextChanged(text);
+}
+
+void SearchTextBar::slotSearchResult(bool match)
+{
+ if (d->searchEdit->text().isEmpty())
+ {
+ d->searchEdit->unsetPalette();
+ return;
+ }
+
+ TQPalette pal = d->searchEdit->palette();
+ pal.setColor(TQPalette::Active, TQColorGroup::Base,
+ match ? TQColor(200, 255, 200) :
+ TQColor(255, 200, 200));
+ pal.setColor(TQPalette::Active, TQColorGroup::Text, TQt::black);
+ d->searchEdit->setPalette(pal);
+
+ // If search result match the text query, we put the text
+ // in auto-completion history.
+ if (d->textQueryCompletion && match)
+ d->searchEdit->completionObject()->addItem(d->searchEdit->text());
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/common/searchtextbar.h b/src/libs/widgets/common/searchtextbar.h
new file mode 100644
index 00000000..04ef9947
--- /dev/null
+++ b/src/libs/widgets/common/searchtextbar.h
@@ -0,0 +1,111 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-11-25
+ * Description : a bar used to search a string.
+ *
+ * Copyright (C) 2007-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef SEARCH_TEXT_BAR_H
+#define SEARCH_TEXT_BAR_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <klineedit.h>
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DLineEditPriv;
+class SearchTextBarPriv;
+
+class DIGIKAM_EXPORT DLineEdit : public KLineEdit
+{
+ TQ_OBJECT
+
+
+public:
+
+ DLineEdit(const TQString &msg, TQWidget *parent);
+ ~DLineEdit();
+
+ void setMessage(const TQString &msg);
+ TQString message() const;
+
+ void setText(const TQString& txt);
+
+protected:
+
+ void drawContents(TQPainter *p);
+ void dropEvent(TQDropEvent *e);
+ void focusInEvent(TQFocusEvent *e);
+ void focusOutEvent(TQFocusEvent *e);
+
+private :
+
+ DLineEditPriv* d;
+};
+
+class DIGIKAM_EXPORT SearchTextBar : public TQWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ SearchTextBar(TQWidget *parent, const char* name, const TQString &msg=i18n("Search..."));
+ ~SearchTextBar();
+
+ void setText(const TQString& text);
+ TQString text() const;
+
+ void setEnableTextQueryCompletion(bool b);
+ bool textQueryCompletion() const;
+
+ DLineEdit *lineEdit() const;
+
+signals:
+
+ void signalTextChanged(const TQString&);
+
+public slots:
+
+ void slotSearchResult(bool);
+
+private slots:
+
+ void slotTextChanged(const TQString&);
+
+private :
+
+ SearchTextBarPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* SEARCH_TEXT_BAR_H */
diff --git a/src/libs/widgets/common/sidebar.cpp b/src/libs/widgets/common/sidebar.cpp
new file mode 100644
index 00000000..a1bcd752
--- /dev/null
+++ b/src/libs/widgets/common/sidebar.cpp
@@ -0,0 +1,363 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-22
+ * Description : a widget to manage sidebar in gui.
+ *
+ * Copyright (C) 2005-2006 by Joern Ahrens <joern.ahrens@kdemail.net>
+ * 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.
+ *
+ * ============================================================ */
+
+/** @file sidebar.cpp */
+
+// TQt includes.
+
+#include <tqsplitter.h>
+#include <tqwidgetstack.h>
+#include <tqdatastream.h>
+#include <tqtimer.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <tdeversion.h>
+#include <kiconloader.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "sidebar.h"
+#include "sidebar.moc"
+
+namespace Digikam
+{
+
+class SidebarPriv
+{
+public:
+
+ SidebarPriv()
+ {
+ minimizedDefault = false;
+ minimized = false;
+ isMinimized = false;
+
+ tabs = 0;
+ activeTab = -1;
+ minSize = 0;
+ maxSize = 0;
+ dragSwitchId = -1;
+
+ stack = 0;
+ splitter = 0;
+ dragSwitchTimer = 0;
+ }
+
+ bool minimizedDefault;
+ bool minimized;
+ bool isMinimized; // Backup of minimized status (used with Fullscreen)
+
+ int tabs;
+ int activeTab;
+ int minSize;
+ int maxSize;
+ int dragSwitchId;
+
+ TQWidgetStack *stack;
+ TQSplitter *splitter;
+ TQSize bigSize;
+ TQTimer *dragSwitchTimer;
+
+ Sidebar::Side side;
+};
+
+Sidebar::Sidebar(TQWidget *parent, const char *name, Side side, bool minimizedDefault)
+ : KMultiTabBar(KMultiTabBar::Vertical, parent, name)
+{
+ d = new SidebarPriv;
+ d->minimizedDefault = minimizedDefault;
+ d->side = side;
+ d->dragSwitchTimer = new TQTimer(this);
+
+ connect(d->dragSwitchTimer, TQ_SIGNAL(timeout()),
+ this, TQ_SLOT(slotDragSwitchTimer()));
+}
+
+Sidebar::~Sidebar()
+{
+ saveViewState();
+ delete d;
+}
+
+void Sidebar::updateMinimumWidth()
+{
+ int width = 0;
+ for (int i = 0; i < d->tabs; i++)
+ {
+ TQWidget *w = d->stack->widget(i);
+ if (w && w->width() > width)
+ width = w->width();
+ }
+ d->stack->setMinimumWidth(width);
+}
+
+void Sidebar::setSplitter(TQSplitter *sp)
+{
+#if KDE_IS_VERSION(3,3,0)
+ setStyle(KMultiTabBar::VSNET);
+#else
+ setStyle(KMultiTabBar::KDEV3);
+#endif
+
+ d->splitter = sp;
+ d->stack = new TQWidgetStack(d->splitter);
+
+ if(d->side == Left)
+ setPosition(KMultiTabBar::Left);
+ else
+ setPosition(KMultiTabBar::Right);
+}
+
+TQSplitter* Sidebar::splitter() const
+{
+ return d->splitter;
+}
+
+void Sidebar::loadViewState()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup(TQString("%1").arg(name()));
+
+ int tab = config->readNumEntry("ActiveTab", 0);
+ bool minimized = config->readBoolEntry("Minimized", d->minimizedDefault);
+
+ // validate
+ if(tab >= d->tabs || tab < 0)
+ tab = 0;
+
+ if (minimized)
+ {
+ d->activeTab = tab;
+ //setTab(d->activeTab, true);
+ d->stack->raiseWidget(d->activeTab);
+ emit signalChangedTab(d->stack->visibleWidget());
+ }
+ else
+ {
+ d->activeTab = -1;
+ }
+
+ clicked(tab);
+}
+
+void Sidebar::saveViewState()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup(TQString("%1").arg(name()));
+ config->writeEntry("ActiveTab", d->activeTab);
+ config->writeEntry("Minimized", d->minimized);
+ config->sync();
+}
+
+void Sidebar::backup()
+{
+ d->isMinimized = d->minimized;
+
+ if (!d->isMinimized)
+ shrink();
+
+ KMultiTabBar::hide();
+}
+
+void Sidebar::restore()
+{
+ if (!d->isMinimized)
+ expand();
+
+ KMultiTabBar::show();
+}
+
+void Sidebar::appendTab(TQWidget *w, const TQPixmap &pic, const TQString &title)
+{
+ w->reparent(d->stack, TQPoint(0, 0));
+ KMultiTabBar::appendTab(pic, d->tabs, title);
+ d->stack->addWidget(w, d->tabs);
+
+ tab(d->tabs)->setAcceptDrops(true);
+ tab(d->tabs)->installEventFilter(this);
+
+ connect(tab(d->tabs), TQ_SIGNAL(clicked(int)),
+ this, TQ_SLOT(clicked(int)));
+
+ d->tabs++;
+}
+
+void Sidebar::deleteTab(TQWidget *w)
+{
+ int tab = d->stack->id(w);
+ if(tab < 0)
+ return;
+
+ if(tab == d->activeTab)
+ d->activeTab = -1;
+
+ d->stack->removeWidget(d->stack->widget(tab));
+ removeTab(tab);
+ d->tabs--;
+ updateMinimumWidth();
+
+ //TODO show another widget
+}
+
+void Sidebar::clicked(int tab)
+{
+ if(tab >= d->tabs || tab < 0)
+ return;
+
+ if(tab == d->activeTab)
+ {
+ d->stack->isHidden() ? expand() : shrink();
+ }
+ else
+ {
+ if(d->activeTab >= 0)
+ setTab(d->activeTab, false);
+
+ d->activeTab = tab;
+ setTab(d->activeTab, true);
+ d->stack->raiseWidget(d->activeTab);
+
+ if(d->minimized)
+ expand();
+
+ emit signalChangedTab(d->stack->visibleWidget());
+ }
+}
+
+void Sidebar::setActiveTab(TQWidget *w)
+{
+ int tab = d->stack->id(w);
+ if(tab < 0)
+ return;
+
+ if(d->activeTab >= 0)
+ setTab(d->activeTab, false);
+
+ d->activeTab = tab;
+ setTab(d->activeTab, true);
+ d->stack->raiseWidget(d->activeTab);
+
+ if(d->minimized)
+ expand();
+
+ emit signalChangedTab(d->stack->visibleWidget());
+}
+
+TQWidget* Sidebar::getActiveTab()
+{
+ return d->stack->visibleWidget();
+}
+
+void Sidebar::shrink()
+{
+ d->minimized = true;
+ d->bigSize = size();
+ d->minSize = minimumWidth();
+ d->maxSize = maximumWidth();
+
+ d->stack->hide();
+
+ KMultiTabBarTab* tab = tabs()->first();
+ if (tab)
+ setFixedWidth(tab->width());
+ else
+ setFixedWidth(width());
+
+ emit signalViewChanged();
+}
+
+void Sidebar::expand()
+{
+ d->minimized = false;
+ d->stack->show();
+ resize(d->bigSize);
+ setMinimumWidth(d->minSize);
+ setMaximumWidth(d->maxSize);
+ emit signalViewChanged();
+}
+
+bool Sidebar::isExpanded()
+{
+ return !d->minimized;
+}
+
+bool Sidebar::eventFilter(TQObject *obj, TQEvent *ev)
+{
+ TQPtrList<KMultiTabBarTab>* pTabs = tabs();
+
+ for (TQPtrListIterator<KMultiTabBarTab> it(*pTabs); it.current(); ++it)
+ {
+ if ( obj == *it )
+ {
+ if ( ev->type() == TQEvent::DragEnter)
+ {
+ TQDragEnterEvent *e = static_cast<TQDragEnterEvent *>(ev);
+ enterEvent(e);
+ e->accept(true);
+ return false;
+ }
+ else if (ev->type() == TQEvent::DragMove)
+ {
+ if (!d->dragSwitchTimer->isActive())
+ {
+ d->dragSwitchTimer->start(800, true);
+ d->dragSwitchId = (*it)->id();
+ }
+ return false;
+ }
+ else if (ev->type() == TQEvent::DragLeave)
+ {
+ d->dragSwitchTimer->stop();
+ TQDragLeaveEvent *e = static_cast<TQDragLeaveEvent *>(ev);
+ leaveEvent(e);
+ return false;
+ }
+ else if (ev->type() == TQEvent::Drop)
+ {
+ d->dragSwitchTimer->stop();
+ TQDropEvent *e = static_cast<TQDropEvent *>(ev);
+ leaveEvent(e);
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ // Else, pass the event on to the parent class
+ return KMultiTabBar::eventFilter(obj, ev);
+}
+
+void Sidebar::slotDragSwitchTimer()
+{
+ clicked(d->dragSwitchId);
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/common/sidebar.h b/src/libs/widgets/common/sidebar.h
new file mode 100644
index 00000000..8d2dc519
--- /dev/null
+++ b/src/libs/widgets/common/sidebar.h
@@ -0,0 +1,178 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-22
+ * Description : a widget to manage sidebar in gui.
+ *
+ * Copyright (C) 2005-2006 by Joern Ahrens <joern.ahrens@kdemail.net>
+ * 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.
+ *
+ * ============================================================ */
+
+/** @file sidebar.h */
+
+#ifndef _SIDEBAR_H_
+#define _SIDEBAR_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+// KDE includes.
+
+#include <tdemultitabbar.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+class TQSplitter;
+
+namespace Digikam
+{
+
+class SidebarPriv;
+
+/**
+ * This class handles a sidebar view
+ */
+class DIGIKAM_EXPORT Sidebar : public KMultiTabBar
+{
+ TQ_OBJECT
+
+
+public:
+
+ /**
+ * The side where the bar should be visible
+ */
+ enum Side
+ {
+ Left,
+ Right
+ };
+
+ /**
+ * Creates a new sidebar
+ * @param parent sidebar's parent
+ * @param name the name of the widget is used to store its state to config
+ * @param side where the sidebar should be displayed. At the left or right border.
+ * @param minimizedDefault hide the sidebar when the program is started the first time?
+ */
+ Sidebar(TQWidget *parent, const char *name, Side side=Left, bool mimimizedDefault=false);
+ virtual ~Sidebar();
+
+ /**
+ * The width of the widget stack can be changed by a TQSplitter.
+ * @param sp sets the splitter, which should handle the width. The splitter normally
+ * is part of the main view.
+ */
+ void setSplitter(TQSplitter *sp);
+ void setSplitterSizePolicy(TQSizePolicy p);
+
+ TQSplitter* splitter() const;
+
+ /**
+ * Appends a new tab to the sidebar
+ * @param w widget which is activated by this tab
+ * @param pic icon which is shown in this tab
+ * @param title text which is shown it this tab
+ */
+ void appendTab(TQWidget *w, const TQPixmap &pic, const TQString &title);
+
+ /**
+ * Deletes a tab from the tabbar
+ */
+ void deleteTab(TQWidget *w);
+
+ /**
+ * Activates a tab
+ */
+ void setActiveTab(TQWidget *w);
+
+ /**
+ * Returns the currently activated tab, or 0 if no tab is active
+ */
+ TQWidget* getActiveTab();
+
+ /**
+ * Hides the sidebar (display only the activation buttons)
+ */
+ void shrink();
+
+ /**
+ * redisplays the whole sidebar
+ */
+ void expand();
+
+ /**
+ * load the last view state from disk
+ */
+ void loadViewState();
+
+ /**
+ * hide sidebar and backup minimized state.
+ */
+ void backup();
+
+ /**
+ * show sidebar and restore minimized state.
+ */
+ void restore();
+
+ /**
+ * return the visible status of current sidebar tab.
+ */
+ bool isExpanded();
+
+private:
+
+ /**
+ * save the view state to disk
+ */
+ void saveViewState();
+ bool eventFilter(TQObject *o, TQEvent *e);
+ void updateMinimumWidth();
+
+private slots:
+
+ /**
+ * Activates a tab
+ */
+ void clicked(int tab);
+
+ void slotDragSwitchTimer();
+
+signals:
+
+ /**
+ * is emitted, when another tab is activated
+ */
+ void signalChangedTab(TQWidget *w);
+
+ /**
+ * is emitted, when tab is shrink or expanded
+ */
+ void signalViewChanged();
+
+private:
+
+ SidebarPriv* d;
+};
+
+} // namespace Digikam
+
+#endif // _SIDEBAR_H_
diff --git a/src/libs/widgets/common/splashscreen.cpp b/src/libs/widgets/common/splashscreen.cpp
new file mode 100644
index 00000000..7a8cbba1
--- /dev/null
+++ b/src/libs/widgets/common/splashscreen.cpp
@@ -0,0 +1,160 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2003-02-10
+ * Description : a widget to display spash with progress bar
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * 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.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqtimer.h>
+#include <tqfont.h>
+#include <tqstring.h>
+#include <tqcolor.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kstandarddirs.h>
+#include <tdeglobalsettings.h>
+
+// Local includes.
+
+#include "splashscreen.h"
+#include "splashscreen.moc"
+
+namespace Digikam
+{
+
+class SplashScreenPriv
+{
+public:
+
+ SplashScreenPriv()
+ {
+ state = 0;
+ progressBarSize = 3;
+ state = 0;
+ color = TQt::black;
+ alignment = TQt::AlignLeft;
+ }
+
+ int state;
+ int progressBarSize;
+ int alignment;
+
+ TQString string;
+
+ TQColor color;
+};
+
+SplashScreen::SplashScreen(const TQString& splash, WFlags f)
+ : KSplashScreen(TQPixmap(locate("appdata", splash)), f)
+{
+ d = new SplashScreenPriv;
+
+ TQTimer *timer = new TQTimer(this);
+
+ connect(timer, TQ_SIGNAL(timeout()),
+ this, TQ_SLOT(animate()));
+
+ timer->start(150);
+}
+
+SplashScreen::~SplashScreen()
+{
+ delete d;
+}
+
+void SplashScreen::animate()
+{
+ d->state = ((d->state + 1) % (2*d->progressBarSize-1));
+ repaint();
+}
+
+void SplashScreen::setColor(const TQColor& color)
+{
+ d->color = color;
+}
+void SplashScreen::setAlignment(int alignment)
+{
+ d->alignment = alignment;
+}
+
+void SplashScreen::message(const TQString& message)
+{
+ d->string = message;
+ TQSplashScreen::message(d->string, d->alignment, d->color);
+ animate();
+}
+
+void SplashScreen::drawContents(TQPainter* painter)
+{
+ int position;
+ TQColor basecolor(155, 192, 231);
+
+ // Draw background circles
+ painter->setPen(NoPen);
+ painter->setBrush(TQColor(225, 234, 231));
+ painter->drawEllipse(21, 7, 9, 9);
+ painter->drawEllipse(32, 7, 9, 9);
+ painter->drawEllipse(43, 7, 9, 9);
+
+ // Draw animated circles, increments are chosen
+ // to get close to background's color
+ // (didn't work well with TQColor::light function)
+ for (int i=0; i < d->progressBarSize; i++)
+ {
+ position = (d->state+i)%(2*d->progressBarSize-1);
+ if (position < 3)
+ {
+ painter->setBrush(TQColor(basecolor.red() -18*i,
+ basecolor.green()-28*i,
+ basecolor.blue() -10*i));
+
+ painter->drawEllipse(21+position*11, 7, 9, 9);
+ }
+ }
+
+ painter->setPen(d->color);
+
+ TQFont fnt(TDEGlobalSettings::generalFont());
+ int fntSize = fnt.pointSize();
+ if (fntSize > 0)
+ {
+ fnt.setPointSize(fntSize-2);
+ }
+ else
+ {
+ fntSize = fnt.pixelSize();
+ fnt.setPixelSize(fntSize-2);
+ }
+ painter->setFont(fnt);
+
+ TQRect r = rect();
+ r.setRect( r.x() + 59, r.y() + 5, r.width() - 10, r.height() - 10 );
+
+ // Draw message at given position, limited to 43 chars
+ // If message is too long, string is truncated
+ if (d->string.length() > 40) {d->string.truncate(39); d->string += "...";}
+ painter->drawText(r, d->alignment, d->string);
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/common/splashscreen.h b/src/libs/widgets/common/splashscreen.h
new file mode 100644
index 00000000..d2d4cf45
--- /dev/null
+++ b/src/libs/widgets/common/splashscreen.h
@@ -0,0 +1,74 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2003-02-10
+ * Description : a widget to display spash with progress bar
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * 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 SPLASHSCREEN_H
+#define SPLASHSCREEN_H
+
+// TQt includes.
+
+#include <tqpainter.h>
+
+// KDE includes.
+
+#include <ksplashscreen.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class SplashScreenPriv;
+
+class DIGIKAM_EXPORT SplashScreen : public KSplashScreen
+{
+TQ_OBJECT
+
+
+public:
+
+ SplashScreen(const TQString& splash, WFlags f=0);
+ virtual ~SplashScreen();
+
+ void setAlignment(int alignment);
+ void setColor(const TQColor& color);
+
+protected:
+
+ void drawContents (TQPainter *);
+
+public slots:
+
+ void animate();
+ void message(const TQString &message);
+
+private:
+
+ SplashScreenPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* SPLASHSCREEN_H */
diff --git a/src/libs/widgets/common/squeezedcombobox.cpp b/src/libs/widgets/common/squeezedcombobox.cpp
new file mode 100644
index 00000000..b70da094
--- /dev/null
+++ b/src/libs/widgets/common/squeezedcombobox.cpp
@@ -0,0 +1,198 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-01
+ * Description : a combo box with a width not depending of text
+ * content size
+ *
+ * Copyright (C) 2005 by Tom Albers <tomalbers@kde.nl>
+ * 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.
+ *
+ * ============================================================ */
+
+/** @file squeezedcombobox.cpp */
+
+// TQt includes.
+
+#include <tqlistbox.h>
+#include <tqcombobox.h>
+#include <tqpair.h>
+#include <tqtimer.h>
+#include <tqvaluelist.h>
+#include <tqstyle.h>
+#include <tqapplication.h>
+#include <tqtooltip.h>
+#include <tqmap.h>
+
+// Local includes.
+
+#include "squeezedcombobox.h"
+#include "squeezedcombobox.moc"
+
+namespace Digikam
+{
+
+class SqueezedComboBoxPriv
+{
+public:
+
+ SqueezedComboBoxPriv()
+ {
+ timer = 0;
+ tooltip = 0;
+ }
+
+ TQMap<int, TQString> originalItems;
+
+ TQTimer *timer;
+
+ SqueezedComboBoxTip *tooltip;
+};
+
+SqueezedComboBox::SqueezedComboBox(TQWidget *parent, const char *name)
+ : TQComboBox(parent, name)
+{
+ d = new SqueezedComboBoxPriv;
+ d->timer = new TQTimer(this);
+
+ // See B.K.O #138747 : always for TQComboBox instance to use a TQListbox to
+ // render content independently of Widget style used.
+ setListBox(new TQListBox(this));
+
+ d->tooltip = new SqueezedComboBoxTip(listBox()->viewport(), this);
+ setMinimumWidth(100);
+
+ connect(d->timer, TQ_SIGNAL(timeout()),
+ this, TQ_SLOT(slotTimeOut()));
+
+ connect(this, TQ_SIGNAL(activated( int )),
+ this, TQ_SLOT(slotUpdateToolTip( int )));
+}
+
+SqueezedComboBox::~SqueezedComboBox()
+{
+ delete d->tooltip;
+ delete d->timer;
+ delete d;
+}
+
+TQSize SqueezedComboBox::sizeHint() const
+{
+ constPolish();
+ TQFontMetrics fm = fontMetrics();
+
+ int maxW = count() ? 18 : 7 * fm.width(TQChar('x')) + 18;
+ int maxH = TQMAX( fm.lineSpacing(), 14 ) + 2;
+
+ return style().sizeFromContents(TQStyle::CT_ComboBox, this,
+ TQSize(maxW, maxH)).expandedTo(TQApplication::globalStrut());
+}
+
+void SqueezedComboBox::insertSqueezedItem(const TQString& newItem, int index)
+{
+ d->originalItems[index] = newItem;
+ insertItem( squeezeText(newItem), index );
+
+ // if this is the first item, set the tooltip.
+ if (index == 0)
+ slotUpdateToolTip(0);
+}
+
+void SqueezedComboBox::insertSqueezedList(const TQStringList& newItems, int index)
+{
+ for(TQStringList::const_iterator it = newItems.begin() ; it != newItems.end() ; ++it)
+ {
+ insertSqueezedItem(*it, index);
+ index++;
+ }
+}
+
+void SqueezedComboBox::resizeEvent(TQResizeEvent *)
+{
+ d->timer->start(200, true);
+}
+
+void SqueezedComboBox::slotTimeOut()
+{
+ TQMapIterator<int,TQString> it;
+ for (it = d->originalItems.begin() ; it != d->originalItems.end();
+ ++it)
+ {
+ changeItem(squeezeText(it.data()), it.key());
+ }
+}
+
+TQString SqueezedComboBox::squeezeText(const TQString& original)
+{
+ // not the complete widgetSize is usable. Need to compensate for that.
+ int widgetSize = width()-30;
+ TQFontMetrics fm(fontMetrics());
+
+ // If we can fit the full text, return that.
+ if (fm.width(original) < widgetSize)
+ return(original);
+
+ // We need to squeeze.
+ TQString sqItem = original; // prevent empty return value;
+ widgetSize = widgetSize-fm.width("...");
+ for (uint i = 0 ; i != original.length(); ++i)
+ {
+ if ((int)fm.width(original.right(i)) > widgetSize)
+ {
+ sqItem = TQString(original.left(i) + "...");
+ break;
+ }
+ }
+ return sqItem;
+}
+
+void SqueezedComboBox::slotUpdateToolTip(int index)
+{
+ TQToolTip::remove(this);
+ TQToolTip::add(this, d->originalItems[index]);
+}
+
+TQString SqueezedComboBox::itemHighlighted()
+{
+ int curItem = listBox()->currentItem();
+ return d->originalItems[curItem];
+}
+
+// ------------------------------------------------------------------------
+
+SqueezedComboBoxTip::SqueezedComboBoxTip(TQWidget *parent, SqueezedComboBox *name)
+ : TQToolTip( parent )
+{
+ m_originalWidget = name;
+}
+
+void SqueezedComboBoxTip::maybeTip(const TQPoint &pos)
+{
+ TQListBox* listBox = m_originalWidget->listBox();
+ if (!listBox)
+ return;
+
+ TQListBoxItem* selectedItem = listBox->itemAt( pos );
+ if (selectedItem)
+ {
+ TQRect positionToolTip = listBox->itemRect(selectedItem);
+ TQString toolTipText = m_originalWidget->itemHighlighted();
+ if (!toolTipText.isNull())
+ tip(positionToolTip, toolTipText);
+ }
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/common/squeezedcombobox.h b/src/libs/widgets/common/squeezedcombobox.h
new file mode 100644
index 00000000..7baaeca1
--- /dev/null
+++ b/src/libs/widgets/common/squeezedcombobox.h
@@ -0,0 +1,164 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-01
+ * Description : a combo box with a width not depending of text
+ * content size
+ *
+ * Copyright (C) 2005 by Tom Albers <tomalbers@kde.nl>
+ * 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.
+ *
+ * ============================================================ */
+
+/** @file squeezedcombobox.h */
+
+#ifndef SQUEEZEDCOMBOBOX_H
+#define SQUEEZEDCOMBOBOX_H
+
+// TQt includes.
+
+#include <tqcombobox.h>
+#include <tqtooltip.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class SqueezedComboBoxPriv;
+
+/** @class SqueezedComboBox
+ *
+ * This widget is a TQComboBox, but then a little bit
+ * different. It only shows the right part of the items
+ * depending on de size of the widget. When it is not
+ * possible to show the complete item, it will be shortened
+ * and "..." will be prepended.
+ *
+ * @image html squeezedcombobox.png "This is how it looks"
+ * @author Tom Albers
+ */
+class DIGIKAM_EXPORT SqueezedComboBox : public TQComboBox
+{
+ TQ_OBJECT
+
+
+public:
+
+ /**
+ * Constructor
+ * @param parent parent widget
+ * @param name name to give to the widget
+ */
+ SqueezedComboBox(TQWidget *parent = 0, const char *name = 0 );
+
+ /**
+ * destructor
+ */
+ virtual ~SqueezedComboBox();
+
+ /**
+ * This inserts a item to the list. See TQComboBox::insertItem()
+ * for details. Please do not use TQComboBox::insertItem() to this
+ * widget, as that will fail.
+ * @param newItem the original (long version) of the item which needs
+ * to be added to the combobox
+ * @param index the position in the widget.
+ */
+ void insertSqueezedItem(const TQString& newItem, int index);
+
+ /**
+ * This inserts items to the list. See TQComboBox::insertStringList()
+ * for details. Please do not use TQComboBox::insertStringList() to this
+ * widget, as that will fail.
+ * @param newItems the originals (long version) of the items which needs
+ * to be added to the combobox
+ * @param index the position in the widget.
+ */
+ void insertSqueezedList(const TQStringList& newItems, int index);
+
+ /**
+ * This method returns the full text (not squeezed) of the currently
+ * highlighted item.
+ * @return full text of the highlighted item
+ */
+ TQString itemHighlighted();
+
+ /**
+ * Sets the sizeHint() of this widget.
+ */
+ virtual TQSize sizeHint() const;
+
+private slots:
+
+ void slotTimeOut();
+ void slotUpdateToolTip(int index);
+
+private:
+
+ void resizeEvent(TQResizeEvent *);
+ TQString squeezeText(const TQString& original);
+
+private:
+
+ SqueezedComboBoxPriv *d;
+};
+
+// ----------------------------------------------------------------
+
+/** @class SqueezedComboBoxTip
+ * This class shows a tooltip for a SqueezedComboBox
+ * the tooltip will contain the full text and helps
+ * the user find the correct entry. It is automatically
+ * activated when starting a SqueezedComboBox. This is
+ * inherited from TQToolTip
+ *
+ * @author Tom Albers
+ */
+class SqueezedComboBoxTip : public TQToolTip
+{
+
+public:
+ /**
+ * Constructor. An example call (as done in
+ * SqueezedComboBox::SqueezedComboBox):
+ * @code
+ * t = new SqueezedComboBoxTip( this->listBox()->viewport(), this );
+ * @endcode
+ *
+ * @param parent parent widget (viewport)
+ * @param name parent widget
+ */
+ SqueezedComboBoxTip(TQWidget *parent, SqueezedComboBox *name);
+
+protected:
+ /**
+ * Reimplemented version from TQToolTip which shows the
+ * tooltip when needed.
+ * @param pos the point where the mouse currently is
+ */
+ void maybeTip(const TQPoint& pos);
+
+private:
+
+ SqueezedComboBox *m_originalWidget;
+};
+
+} // namespace Digikam
+
+#endif // SQUEEZEDCOMBOBOX_H
diff --git a/src/libs/widgets/common/statusled.cpp b/src/libs/widgets/common/statusled.cpp
new file mode 100644
index 00000000..e0475057
--- /dev/null
+++ b/src/libs/widgets/common/statusled.cpp
@@ -0,0 +1,84 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-02-15
+ * Description : a led indicator.
+ *
+ * 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 <tqpixmap.h>
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <tdeglobalsettings.h>
+#include <kstandarddirs.h>
+
+// Local includes.
+
+#include "statusled.h"
+#include "statusled.moc"
+
+namespace Digikam
+{
+
+StatusLed::StatusLed(TQWidget *parent)
+ : TQLabel(parent)
+{
+ setLedColor(Gray);
+ setFocusPolicy(TQWidget::NoFocus);
+}
+
+StatusLed::~StatusLed()
+{
+}
+
+void StatusLed::setLedColor(LedColor color)
+{
+ m_color = color;
+
+ TQString file;
+ switch(m_color)
+ {
+ case Green:
+ file = TQString("indicator-green");
+ break;
+
+ case Red:
+ file = TQString("indicator-red");
+ break;
+
+ default:
+ file = TQString("indicator-gray");
+ break;
+ }
+
+ TDEGlobal::dirs()->addResourceType(file.ascii(), TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir(file.ascii(), file + TQString(".png"));
+ setPixmap(TQPixmap(directory + file + TQString(".png")));
+}
+
+StatusLed::LedColor StatusLed::ledColor() const
+{
+ return m_color;
+}
+
+} // namespace Digikam
+
diff --git a/src/libs/widgets/common/statusled.h b/src/libs/widgets/common/statusled.h
new file mode 100644
index 00000000..2fd94cb2
--- /dev/null
+++ b/src/libs/widgets/common/statusled.h
@@ -0,0 +1,72 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-02-15
+ * Description : a led indicator.
+ *
+ * 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 STATUS_LED_H
+#define STATUS_LED_H
+
+// TQt includes.
+
+#include <tqlabel.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class StatusNavigateBarPriv;
+
+class DIGIKAM_EXPORT StatusLed : public TQLabel
+{
+TQ_OBJECT
+
+
+public:
+
+ enum LedColor
+ {
+ Gray=0,
+ Green,
+ Red
+ };
+
+public:
+
+ StatusLed(TQWidget *parent=0);
+ ~StatusLed();
+
+ LedColor ledColor() const;
+
+public slots:
+
+ void setLedColor(LedColor color);
+
+private:
+
+ LedColor m_color;
+};
+
+} // namespace Digikam
+
+#endif /* STATUS_LED_H */
diff --git a/src/libs/widgets/common/statusnavigatebar.cpp b/src/libs/widgets/common/statusnavigatebar.cpp
new file mode 100644
index 00000000..0ebcaf84
--- /dev/null
+++ b/src/libs/widgets/common/statusnavigatebar.cpp
@@ -0,0 +1,172 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-01-30
+ * Description : a button bar to navigate between album items
+ * using status bar.
+ *
+ * Copyright (C) 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 <tqlayout.h>
+#include <tqtoolbutton.h>
+#include <tqtooltip.h>
+
+// KDE includes.
+
+#include <kiconloader.h>
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "statusnavigatebar.h"
+#include "statusnavigatebar.moc"
+
+namespace Digikam
+{
+
+class StatusNavigateBarPriv
+{
+public:
+
+ StatusNavigateBarPriv()
+ {
+ firstButton = 0;
+ prevButton = 0;
+ nextButton = 0;
+ lastButton = 0;
+ itemType = StatusNavigateBar::ItemCurrent;
+ }
+
+ int itemType;
+
+ TQToolButton *firstButton;
+ TQToolButton *prevButton;
+ TQToolButton *nextButton;
+ TQToolButton *lastButton;
+};
+
+StatusNavigateBar::StatusNavigateBar(TQWidget *parent)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ d = new StatusNavigateBarPriv;
+ setFocusPolicy(TQWidget::NoFocus);
+
+ TQHBoxLayout *lay = new TQHBoxLayout(this);
+
+ d->firstButton = new TQToolButton(this);
+ d->firstButton->setFocusPolicy(TQWidget::NoFocus);
+ d->firstButton->setAutoRaise(true);
+ d->firstButton->setIconSet(SmallIconSet("go-first"));
+ TQToolTip::add(d->firstButton, i18n("Go to the first item"));
+
+ d->prevButton = new TQToolButton(this);
+ d->prevButton->setFocusPolicy(TQWidget::NoFocus);
+ d->prevButton->setAutoRaise(true);
+ d->prevButton->setIconSet(SmallIconSet("back"));
+ TQToolTip::add(d->prevButton, i18n("Go to the previous item"));
+
+ d->nextButton = new TQToolButton(this);
+ d->nextButton->setFocusPolicy(TQWidget::NoFocus);
+ d->nextButton->setAutoRaise(true);
+ d->nextButton->setIconSet(SmallIconSet("forward"));
+ TQToolTip::add(d->nextButton, i18n("Go to the next item"));
+
+ d->lastButton = new TQToolButton(this);
+ d->lastButton->setFocusPolicy(TQWidget::NoFocus);
+ d->lastButton->setAutoRaise(true);
+ d->lastButton->setIconSet(SmallIconSet("go-last"));
+ TQToolTip::add(d->lastButton, i18n("Go to the last item"));
+
+ lay->addWidget(d->firstButton);
+ lay->addWidget(d->prevButton);
+ lay->addWidget(d->nextButton);
+ lay->addWidget(d->lastButton);
+
+ connect(d->firstButton, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalFirstItem()));
+
+ connect(d->prevButton, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalPrevItem()));
+
+ connect(d->nextButton, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalNextItem()));
+
+ connect(d->lastButton, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalLastItem()));
+}
+
+StatusNavigateBar::~StatusNavigateBar()
+{
+ delete d;
+}
+
+void StatusNavigateBar::setNavigateBarState(bool hasPrev, bool hasNext)
+{
+ if (hasPrev && hasNext)
+ setButtonsState(ItemCurrent);
+ else if (!hasPrev && hasNext)
+ setButtonsState(ItemFirst);
+ else if (hasPrev && !hasNext)
+ setButtonsState(ItemLast);
+ else
+ setButtonsState(NoNavigation);
+}
+
+void StatusNavigateBar::setButtonsState(int itemType)
+{
+ d->itemType = itemType;
+
+ if (d->itemType == ItemFirst)
+ {
+ d->firstButton->setEnabled(false);
+ d->prevButton->setEnabled(false);
+ d->nextButton->setEnabled(true);
+ d->lastButton->setEnabled(true);
+ }
+ else if (d->itemType == ItemLast)
+ {
+ d->firstButton->setEnabled(true);
+ d->prevButton->setEnabled(true);
+ d->nextButton->setEnabled(false);
+ d->lastButton->setEnabled(false);
+ }
+ else if (d->itemType == ItemCurrent)
+ {
+ d->firstButton->setEnabled(true);
+ d->prevButton->setEnabled(true);
+ d->nextButton->setEnabled(true);
+ d->lastButton->setEnabled(true);
+ }
+ else if (d->itemType == NoNavigation)
+ {
+ d->firstButton->setEnabled(false);
+ d->prevButton->setEnabled(false);
+ d->nextButton->setEnabled(false);
+ d->lastButton->setEnabled(false);
+ }
+}
+
+int StatusNavigateBar::getButtonsState()
+{
+ return (d->itemType);
+}
+
+} // namespace Digikam
+
diff --git a/src/libs/widgets/common/statusnavigatebar.h b/src/libs/widgets/common/statusnavigatebar.h
new file mode 100644
index 00000000..7972f740
--- /dev/null
+++ b/src/libs/widgets/common/statusnavigatebar.h
@@ -0,0 +1,80 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-01-30
+ * Description : a button bar to navigate between album items
+ * using status bar.
+ *
+ * Copyright (C) 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 STATUS_NAVIGATE_BAR_H
+#define STATUS_NAVIGATE_BAR_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqstring.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class StatusNavigateBarPriv;
+
+class DIGIKAM_EXPORT StatusNavigateBar : public TQWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ enum CurrentItemPosition
+ {
+ ItemCurrent=0,
+ ItemFirst,
+ ItemLast,
+ NoNavigation
+ };
+
+public:
+
+ StatusNavigateBar(TQWidget *parent=0);
+ ~StatusNavigateBar();
+
+ void setNavigateBarState(bool hasPrev, bool hasNext);
+ void setButtonsState(int itemType);
+ int getButtonsState();
+
+signals:
+
+ void signalFirstItem(void);
+ void signalPrevItem(void);
+ void signalNextItem(void);
+ void signalLastItem(void);
+
+private :
+
+ StatusNavigateBarPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* STATUS_NAVIGATE_BAR_H */
diff --git a/src/libs/widgets/common/statusprogressbar.cpp b/src/libs/widgets/common/statusprogressbar.cpp
new file mode 100644
index 00000000..215f81fe
--- /dev/null
+++ b/src/libs/widgets/common/statusprogressbar.cpp
@@ -0,0 +1,171 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-01-24
+ * Description : a progress bar used to display file access
+ * progress or a text in status bar.
+ *
+ * Copyright (C) 2007-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqwidget.h>
+#include <tqpushbutton.h>
+
+// KDE includes.
+
+#include <ksqueezedtextlabel.h>
+#include <kprogress.h>
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "statusprogressbar.h"
+#include "statusprogressbar.moc"
+
+namespace Digikam
+{
+
+class StatusProgressBarPriv
+{
+
+public:
+
+ enum WidgetStackEnum
+ {
+ TextLabel=0,
+ ProgressBar
+ };
+
+ StatusProgressBarPriv()
+ {
+ textLabel = 0;
+ progressBar = 0;
+ progressWidget = 0;
+ cancelButton = 0;
+ }
+
+
+ TQWidget *progressWidget;
+
+ TQPushButton *cancelButton;
+
+ KSqueezedTextLabel *textLabel;
+
+ KProgress *progressBar;
+};
+
+StatusProgressBar::StatusProgressBar(TQWidget *parent)
+ : TQWidgetStack(parent, 0, TQt::WDestructiveClose)
+{
+ d = new StatusProgressBarPriv;
+ setFocusPolicy(TQWidget::NoFocus);
+
+ d->textLabel = new KSqueezedTextLabel(this);
+ d->progressWidget = new TQWidget(this);
+ TQHBoxLayout *hBox = new TQHBoxLayout(d->progressWidget);
+ d->progressBar = new KProgress(d->progressWidget);
+ setProgressTotalSteps(100);
+ d->cancelButton = new TQPushButton(d->progressWidget);
+ d->cancelButton->setFocusPolicy(TQWidget::NoFocus);
+ d->cancelButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Minimum ) );
+ d->cancelButton->setPixmap(SmallIcon("cancel"));
+
+ // Parent widget will probably have the wait cursor set.
+ // Set arrow cursor to indicate the button can be clicked
+ d->cancelButton->setCursor(KCursor::arrowCursor());
+
+ hBox->addWidget(d->progressBar);
+ hBox->addWidget(d->cancelButton);
+
+ addWidget(d->textLabel, StatusProgressBarPriv::TextLabel);
+ addWidget(d->progressWidget, StatusProgressBarPriv::ProgressBar);
+
+ connect( d->cancelButton, TQ_SIGNAL( clicked() ),
+ this, TQ_SIGNAL( signalCancelButtonPressed() ) );
+
+ progressBarMode(TextMode);
+}
+
+StatusProgressBar::~StatusProgressBar()
+{
+ delete d;
+}
+
+void StatusProgressBar::setText(const TQString& text)
+{
+ d->textLabel->setText(text);
+}
+
+void StatusProgressBar::setAlignment(int a)
+{
+ d->textLabel->setAlignment(a);
+}
+
+int StatusProgressBar::progressValue()
+{
+ return d->progressBar->progress();
+}
+
+void StatusProgressBar::setProgressValue(int v)
+{
+ d->progressBar->setProgress(v);
+}
+
+void StatusProgressBar::setProgressTotalSteps(int v)
+{
+ d->progressBar->setTotalSteps(v);
+}
+
+int StatusProgressBar::progressTotalSteps()
+{
+ return d->progressBar->totalSteps();
+}
+
+void StatusProgressBar::setProgressText(const TQString& text)
+{
+ d->progressBar->setFormat( text + TQString ("%p%") );
+ d->progressBar->update();
+}
+
+void StatusProgressBar::progressBarMode(int mode, const TQString& text)
+{
+ if ( mode == TextMode)
+ {
+ raiseWidget(StatusProgressBarPriv::TextLabel);
+ setProgressValue(0);
+ setText( text );
+ }
+ else if ( mode == ProgressBarMode )
+ {
+ d->cancelButton->hide();
+ raiseWidget(StatusProgressBarPriv::ProgressBar);
+ setProgressText( text );
+ }
+ else // CancelProgressBarMode
+ {
+ d->cancelButton->show();
+ raiseWidget(StatusProgressBarPriv::ProgressBar);
+ setProgressText( text );
+ }
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/common/statusprogressbar.h b/src/libs/widgets/common/statusprogressbar.h
new file mode 100644
index 00000000..e227a6de
--- /dev/null
+++ b/src/libs/widgets/common/statusprogressbar.h
@@ -0,0 +1,87 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-01-24
+ * Description : a progress bar used to display file access
+ * progress or a text in status bar.
+ *
+ * Copyright (C) 2007-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef STATUSPROGRESSBAR_H
+#define STATUSPROGRESSBAR_H
+
+// KDE includes.
+
+#include <tqwidgetstack.h>
+#include <tqstring.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class StatusProgressBarPriv;
+
+class DIGIKAM_EXPORT StatusProgressBar : public TQWidgetStack
+{
+TQ_OBJECT
+
+
+public:
+
+ enum StatusProgressBarMode
+ {
+ TextMode=0,
+ ProgressBarMode,
+ CancelProgressBarMode
+ };
+
+public:
+
+ StatusProgressBar(TQWidget *parent=0);
+ ~StatusProgressBar();
+
+ void setAlignment(int a);
+
+ void progressBarMode(int mode, const TQString& text=TQString());
+
+ int progressValue();
+
+ int progressTotalSteps();
+ void setProgressTotalSteps(int v);
+
+public slots:
+
+ void setText(const TQString& text);
+ void setProgressValue(int v);
+ void setProgressText(const TQString& text);
+
+signals:
+
+ void signalCancelButtonPressed();
+
+private:
+
+ StatusProgressBarPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* STATUSPROGRESSBAR_H */
diff --git a/src/libs/widgets/common/statuszoombar.cpp b/src/libs/widgets/common/statuszoombar.cpp
new file mode 100644
index 00000000..44302481
--- /dev/null
+++ b/src/libs/widgets/common/statuszoombar.cpp
@@ -0,0 +1,208 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-04-15
+ * Description : a zoom bar used in status bar.
+ *
+ * Copyright (C) 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 <tqtoolbutton.h>
+#include <tqtimer.h>
+#include <tqslider.h>
+#include <tqtooltip.h>
+#include <tqevent.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kiconloader.h>
+
+// Local includes.
+
+#include "thumbnailsize.h"
+#include "dcursortracker.h"
+#include "statuszoombar.h"
+#include "statuszoombar.moc"
+
+namespace Digikam
+{
+
+TQSliderReverseWheel::TQSliderReverseWheel(TQWidget *parent)
+ : TQSlider(parent)
+{
+ // empty, we just need to re-implement wheelEvent to reverse the wheel
+}
+
+TQSliderReverseWheel::~TQSliderReverseWheel()
+{
+}
+
+void TQSliderReverseWheel::wheelEvent(TQWheelEvent * e)
+{
+ if ( e->orientation() != orientation() && !rect().contains(e->pos()) )
+ return;
+
+ static float offset = 0;
+ static TQSlider* offset_owner = 0;
+ if (offset_owner != this){
+ offset_owner = this;
+ offset = 0;
+ }
+ // note: different sign in front of e->delta vs. original implementation
+ offset += e->delta()*TQMAX(pageStep(),lineStep())/120;
+ if (TQABS(offset)<1)
+ return;
+ setValue( value() + int(offset) );
+ offset -= int(offset);
+ e->accept();
+}
+
+// ----------------------------------------------------------------------
+
+class StatusZoomBarPriv
+{
+
+public:
+
+ StatusZoomBarPriv()
+ {
+ zoomTracker = 0;
+ zoomMinusButton = 0;
+ zoomPlusButton = 0;
+ zoomSlider = 0;
+ zoomTimer = 0;
+ }
+
+ TQToolButton *zoomPlusButton;
+ TQToolButton *zoomMinusButton;
+
+ TQTimer *zoomTimer;
+
+ TQSlider *zoomSlider;
+
+ DTipTracker *zoomTracker;
+};
+
+StatusZoomBar::StatusZoomBar(TQWidget *parent)
+ : TQHBox(parent, 0, TQt::WDestructiveClose)
+{
+ d = new StatusZoomBarPriv;
+ setFocusPolicy(TQWidget::NoFocus);
+
+ d->zoomMinusButton = new TQToolButton(this);
+ d->zoomMinusButton->setAutoRaise(true);
+ d->zoomMinusButton->setFocusPolicy(TQWidget::NoFocus);
+ d->zoomMinusButton->setIconSet(SmallIconSet("zoom-out"));
+ TQToolTip::add(d->zoomMinusButton, i18n("Zoom Out"));
+
+ d->zoomSlider = new TQSliderReverseWheel(this);
+ d->zoomSlider->setMinValue(ThumbnailSize::Small);
+ d->zoomSlider->setMaxValue(ThumbnailSize::Huge);
+ d->zoomSlider->setPageStep(ThumbnailSize::Step);
+ d->zoomSlider->setValue(ThumbnailSize::Medium);
+ d->zoomSlider->setOrientation(TQt::Horizontal);
+ d->zoomSlider->setLineStep(ThumbnailSize::Step);
+ d->zoomSlider->setMaximumHeight(fontMetrics().height()+2);
+ d->zoomSlider->setFixedWidth(120);
+ d->zoomSlider->setFocusPolicy(TQWidget::NoFocus);
+
+ d->zoomPlusButton = new TQToolButton(this);
+ d->zoomPlusButton->setAutoRaise(true);
+ d->zoomPlusButton->setIconSet(SmallIconSet("zoom-in"));
+ d->zoomPlusButton->setFocusPolicy(TQWidget::NoFocus);
+ TQToolTip::add(d->zoomPlusButton, i18n("Zoom In"));
+
+ d->zoomTracker = new DTipTracker("", d->zoomSlider);
+
+ // -------------------------------------------------------------
+
+ connect(d->zoomMinusButton, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalZoomMinusClicked()));
+
+ connect(d->zoomPlusButton, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalZoomPlusClicked()));
+
+ connect(d->zoomSlider, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SIGNAL(signalZoomSliderChanged(int)));
+
+ connect(d->zoomSlider, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotZoomSliderChanged(int)));
+
+ connect(d->zoomSlider, TQ_SIGNAL(sliderReleased()),
+ this, TQ_SLOT(slotZoomSliderReleased()));
+}
+
+StatusZoomBar::~StatusZoomBar()
+{
+ if (d->zoomTimer)
+ delete d->zoomTimer;
+
+ delete d->zoomTracker;
+ delete d;
+}
+
+void StatusZoomBar::slotZoomSliderChanged(int)
+{
+ if (d->zoomTimer)
+ {
+ d->zoomTimer->stop();
+ delete d->zoomTimer;
+ }
+
+ d->zoomTimer = new TQTimer( this );
+ connect(d->zoomTimer, TQ_SIGNAL(timeout()),
+ this, TQ_SLOT(slotDelayedZoomSliderChanged()) );
+ d->zoomTimer->start(300, true);
+}
+
+void StatusZoomBar::slotDelayedZoomSliderChanged()
+{
+ emit signalDelayedZoomSliderChanged(d->zoomSlider->value());
+}
+
+void StatusZoomBar::slotZoomSliderReleased()
+{
+ emit signalZoomSliderReleased(d->zoomSlider->value());
+}
+
+void StatusZoomBar::setZoomSliderValue(int v)
+{
+ d->zoomSlider->blockSignals(true);
+ d->zoomSlider->setValue(v);
+ d->zoomSlider->blockSignals(false);
+}
+
+void StatusZoomBar::setZoomTrackerText(const TQString& text)
+{
+ d->zoomTracker->setText(text);
+}
+
+void StatusZoomBar::setEnableZoomPlus(bool e)
+{
+ d->zoomPlusButton->setEnabled(e);
+}
+
+void StatusZoomBar::setEnableZoomMinus(bool e)
+{
+ d->zoomMinusButton->setEnabled(e);
+}
+
+} // namespace Digikam
+
diff --git a/src/libs/widgets/common/statuszoombar.h b/src/libs/widgets/common/statuszoombar.h
new file mode 100644
index 00000000..adf69416
--- /dev/null
+++ b/src/libs/widgets/common/statuszoombar.h
@@ -0,0 +1,100 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-04-15
+ * Description : a zoom bar used in status bar.
+ *
+ * Copyright (C) 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 STATUSSTATUSBAR_H
+#define STATUSSTATUSBAR_H
+
+// TQt includes.
+
+#include <tqslider.h>
+#include <tqevent.h>
+
+// KDE includes.
+
+#include <tqhbox.h>
+#include <tqstring.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class StatusZoomBarPriv;
+
+
+class DIGIKAM_EXPORT TQSliderReverseWheel : public TQSlider
+{
+
+public:
+
+ TQSliderReverseWheel(TQWidget *parent=0);
+ ~TQSliderReverseWheel();
+
+private:
+
+ void wheelEvent(TQWheelEvent *e);
+};
+
+// ----------------------------------------------------------------------
+
+class DIGIKAM_EXPORT StatusZoomBar : public TQHBox
+{
+
+TQ_OBJECT
+
+
+public:
+
+ StatusZoomBar( TQWidget *parent=0 );
+ ~StatusZoomBar();
+
+ void setEnableZoomPlus(bool e);
+ void setEnableZoomMinus(bool e);
+
+ void setZoomSliderValue(int v);
+ void setZoomTrackerText(const TQString& text);
+
+signals:
+
+ void signalZoomPlusClicked();
+ void signalZoomMinusClicked();
+ void signalZoomSliderChanged(int);
+ void signalDelayedZoomSliderChanged(int);
+ void signalZoomSliderReleased(int);
+
+private slots:
+
+ void slotZoomSliderChanged(int);
+ void slotDelayedZoomSliderChanged();
+ void slotZoomSliderReleased();
+
+private:
+
+ StatusZoomBarPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* STATUSSTATUSBAR_H */