summaryrefslogtreecommitdiffstats
path: root/src/libs/widgets
diff options
context:
space:
mode:
authorMichele Calgaro <[email protected]>2024-11-22 18:41:30 +0900
committerMichele Calgaro <[email protected]>2024-11-22 20:55:03 +0900
commit5bed6e4a4c916a97f8fe4d1b07f7eecf4d733b90 (patch)
treef89cc49efc9ca1d0e1579ecb079ee7e7088ff8c8 /src/libs/widgets
parent0bfbf616d9c1fd7abb1bd02732389ab35e5f8771 (diff)
downloaddigikam-5bed6e4a4c916a97f8fe4d1b07f7eecf4d733b90.tar.gz
digikam-5bed6e4a4c916a97f8fe4d1b07f7eecf4d733b90.zip
Rename 'digikam' folder to 'src'
Signed-off-by: Michele Calgaro <[email protected]> (cherry picked from commit ee0d99607c14cb63d3ebdb3a970b508949fa8219)
Diffstat (limited to 'src/libs/widgets')
-rw-r--r--src/libs/widgets/Makefile.am12
-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
-rw-r--r--src/libs/widgets/iccprofiles/Makefile.am23
-rw-r--r--src/libs/widgets/iccprofiles/cietonguewidget.cpp816
-rw-r--r--src/libs/widgets/iccprofiles/cietonguewidget.h115
-rw-r--r--src/libs/widgets/iccprofiles/iccpreviewwidget.cpp83
-rw-r--r--src/libs/widgets/iccprofiles/iccpreviewwidget.h71
-rw-r--r--src/libs/widgets/iccprofiles/iccprofilewidget.cpp448
-rw-r--r--src/libs/widgets/iccprofiles/iccprofilewidget.h79
-rw-r--r--src/libs/widgets/imageplugins/Makefile.am22
-rw-r--r--src/libs/widgets/imageplugins/imageguidewidget.cpp625
-rw-r--r--src/libs/widgets/imageplugins/imageguidewidget.h132
-rw-r--r--src/libs/widgets/imageplugins/imagepanelwidget.cpp335
-rw-r--r--src/libs/widgets/imageplugins/imagepanelwidget.h117
-rw-r--r--src/libs/widgets/imageplugins/imagepaniconwidget.cpp198
-rw-r--r--src/libs/widgets/imageplugins/imagepaniconwidget.h68
-rw-r--r--src/libs/widgets/imageplugins/imagepannelwidget.cpp477
-rw-r--r--src/libs/widgets/imageplugins/imagepannelwidget.h123
-rw-r--r--src/libs/widgets/imageplugins/imageregionwidget.cpp473
-rw-r--r--src/libs/widgets/imageplugins/imageregionwidget.h115
-rw-r--r--src/libs/widgets/imageplugins/imagewidget.cpp347
-rw-r--r--src/libs/widgets/imageplugins/imagewidget.h106
-rw-r--r--src/libs/widgets/imageplugins/listboxpreviewitem.cpp62
-rw-r--r--src/libs/widgets/imageplugins/listboxpreviewitem.h80
-rw-r--r--src/libs/widgets/metadata/Makefile.am17
-rw-r--r--src/libs/widgets/metadata/exifwidget.cpp185
-rw-r--r--src/libs/widgets/metadata/exifwidget.h73
-rw-r--r--src/libs/widgets/metadata/gpswidget.cpp340
-rw-r--r--src/libs/widgets/metadata/gpswidget.h95
-rw-r--r--src/libs/widgets/metadata/iptcwidget.cpp167
-rw-r--r--src/libs/widgets/metadata/iptcwidget.h69
-rw-r--r--src/libs/widgets/metadata/makernotewidget.cpp210
-rw-r--r--src/libs/widgets/metadata/makernotewidget.h70
-rw-r--r--src/libs/widgets/metadata/mdkeylistviewitem.cpp94
-rw-r--r--src/libs/widgets/metadata/mdkeylistviewitem.h63
-rw-r--r--src/libs/widgets/metadata/metadatalistview.cpp283
-rw-r--r--src/libs/widgets/metadata/metadatalistview.h85
-rw-r--r--src/libs/widgets/metadata/metadatalistviewitem.cpp75
-rw-r--r--src/libs/widgets/metadata/metadatalistviewitem.h59
-rw-r--r--src/libs/widgets/metadata/metadatawidget.cpp454
-rw-r--r--src/libs/widgets/metadata/metadatawidget.h120
-rw-r--r--src/libs/widgets/metadata/worldmapwidget.cpp211
-rw-r--r--src/libs/widgets/metadata/worldmapwidget.h73
77 files changed, 14733 insertions, 0 deletions
diff --git a/src/libs/widgets/Makefile.am b/src/libs/widgets/Makefile.am
new file mode 100644
index 00000000..699a4438
--- /dev/null
+++ b/src/libs/widgets/Makefile.am
@@ -0,0 +1,12 @@
+SUBDIRS = metadata imageplugins common iccprofiles
+
+noinst_LTLIBRARIES = libwidgets.la
+
+libwidgets_la_SOURCES =
+
+libwidgets_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor
+
+libwidgets_la_LIBADD = $(top_builddir)/src/libs/widgets/metadata/libmetadatawidgets.la \
+ $(top_builddir)/src/libs/widgets/iccprofiles/libiccprofileswidgets.la \
+ $(top_builddir)/src/libs/widgets/imageplugins/libimagepluginswidgets.la \
+ $(top_builddir)/src/libs/widgets/common/libcommonwidgets.la
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 <[email protected]>
+ * 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 <[email protected]>
+ * 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 <[email protected]>
+ * 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 <[email protected]>
+ * 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 <[email protected]>
+ * 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 <[email protected]>
+ * 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 <[email protected]>
+ * 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 <[email protected]>
+ * 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 */
diff --git a/src/libs/widgets/iccprofiles/Makefile.am b/src/libs/widgets/iccprofiles/Makefile.am
new file mode 100644
index 00000000..8888d326
--- /dev/null
+++ b/src/libs/widgets/iccprofiles/Makefile.am
@@ -0,0 +1,23 @@
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libiccprofileswidgets.la
+
+libiccprofileswidgets_la_SOURCES = iccprofilewidget.cpp cietonguewidget.cpp iccpreviewwidget.cpp
+
+libiccprofileswidgets_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor
+
+libiccprofileswidgets_la_LIBADD = $(top_builddir)/src/libs/lprof/liblprof.la
+
+INCLUDES = -I$(top_srcdir)/src/libs/widgets/metadata \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/lprof \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(LIBKEXIV2_CFLAGS) \
+ $(all_includes)
+
+digikaminclude_HEADERS = cietonguewidget.h iccprofilewidget.h iccpreviewwidget.h
+
+digikamincludedir = $(includedir)/digikam
diff --git a/src/libs/widgets/iccprofiles/cietonguewidget.cpp b/src/libs/widgets/iccprofiles/cietonguewidget.cpp
new file mode 100644
index 00000000..2ec738b3
--- /dev/null
+++ b/src/libs/widgets/iccprofiles/cietonguewidget.cpp
@@ -0,0 +1,816 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-10
+ * Description : a widget to display CIE tongue from
+ * an ICC profile.
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Any source code are inspired from lprof project and
+ * Copyright (C) 1998-2001 Marti Maria
+ *
+ * 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 <tqimage.h>
+#include <tqpainter.h>
+#include <tqpixmap.h>
+#include <tqfile.h>
+#include <tqtimer.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "lcmsprf.h"
+#include "cietonguewidget.h"
+#include "cietonguewidget.moc"
+
+namespace Digikam
+{
+
+ // The following table gives the CIE colour matching functions
+ // \bar{x}(\lambda), \bar{y}(\lambda), and \bar{z}(\lambda), for
+ // wavelengths \lambda at 5 nanometre increments from 380 nm through
+ // 780 nm. This table is used in conjunction with Planck's law for
+ // the energy spectrum of a black body at a given temperature to plot
+ // the black body curve on the CIE chart.
+
+ // The following table gives the spectral chromaticity co-ordinates
+ // x(\lambda) and y(\lambda) for wavelengths in 5 nanometre increments
+ // from 380 nm through 780 nm. These co-ordinates represent the
+ // position in the CIE x-y space of pure spectral colours of the given
+ // wavelength, and thus define the outline of the CIE "tongue"
+ // diagram.
+
+ static const double spectral_chromaticity[81][3] =
+ {
+ { 0.1741, 0.0050 }, // 380 nm
+ { 0.1740, 0.0050 },
+ { 0.1738, 0.0049 },
+ { 0.1736, 0.0049 },
+ { 0.1733, 0.0048 },
+ { 0.1730, 0.0048 },
+ { 0.1726, 0.0048 },
+ { 0.1721, 0.0048 },
+ { 0.1714, 0.0051 },
+ { 0.1703, 0.0058 },
+ { 0.1689, 0.0069 },
+ { 0.1669, 0.0086 },
+ { 0.1644, 0.0109 },
+ { 0.1611, 0.0138 },
+ { 0.1566, 0.0177 },
+ { 0.1510, 0.0227 },
+ { 0.1440, 0.0297 },
+ { 0.1355, 0.0399 },
+ { 0.1241, 0.0578 },
+ { 0.1096, 0.0868 },
+ { 0.0913, 0.1327 },
+ { 0.0687, 0.2007 },
+ { 0.0454, 0.2950 },
+ { 0.0235, 0.4127 },
+ { 0.0082, 0.5384 },
+ { 0.0039, 0.6548 },
+ { 0.0139, 0.7502 },
+ { 0.0389, 0.8120 },
+ { 0.0743, 0.8338 },
+ { 0.1142, 0.8262 },
+ { 0.1547, 0.8059 },
+ { 0.1929, 0.7816 },
+ { 0.2296, 0.7543 },
+ { 0.2658, 0.7243 },
+ { 0.3016, 0.6923 },
+ { 0.3373, 0.6589 },
+ { 0.3731, 0.6245 },
+ { 0.4087, 0.5896 },
+ { 0.4441, 0.5547 },
+ { 0.4788, 0.5202 },
+ { 0.5125, 0.4866 },
+ { 0.5448, 0.4544 },
+ { 0.5752, 0.4242 },
+ { 0.6029, 0.3965 },
+ { 0.6270, 0.3725 },
+ { 0.6482, 0.3514 },
+ { 0.6658, 0.3340 },
+ { 0.6801, 0.3197 },
+ { 0.6915, 0.3083 },
+ { 0.7006, 0.2993 },
+ { 0.7079, 0.2920 },
+ { 0.7140, 0.2859 },
+ { 0.7190, 0.2809 },
+ { 0.7230, 0.2770 },
+ { 0.7260, 0.2740 },
+ { 0.7283, 0.2717 },
+ { 0.7300, 0.2700 },
+ { 0.7311, 0.2689 },
+ { 0.7320, 0.2680 },
+ { 0.7327, 0.2673 },
+ { 0.7334, 0.2666 },
+ { 0.7340, 0.2660 },
+ { 0.7344, 0.2656 },
+ { 0.7346, 0.2654 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 } // 780 nm
+ };
+
+class CIETongueWidgetPriv
+{
+public:
+
+ CIETongueWidgetPriv()
+ {
+ hMonitorProfile = 0;
+ hXYZProfile = 0;
+ hXFORM = 0;
+
+ Measurement.Patches = 0;
+ Measurement.Allowed = 0;
+ blinkTimer = 0;
+ pos = 0;
+
+ profileDataAvailable = true;
+ loadingImageMode = false;
+ loadingImageSucess = false;
+ }
+
+ bool profileDataAvailable;
+ bool loadingImageMode;
+ bool loadingImageSucess;
+
+ double gridside;
+
+ int xBias;
+ int yBias;
+ int pxcols;
+ int pxrows;
+ int pos; // Position of animation during loading/calculation.
+
+ TQPainter painter;
+ TQPixmap pixmap;
+ TQTimer *blinkTimer;
+
+ cmsHPROFILE hMonitorProfile;
+ cmsHPROFILE hXYZProfile;
+ cmsHTRANSFORM hXFORM;
+ cmsCIExyYTRIPLE Primaries;
+ cmsCIEXYZ MediaWhite;
+
+ MEASUREMENT Measurement;
+};
+
+CIETongueWidget::CIETongueWidget(int w, int h, TQWidget *parent, cmsHPROFILE hMonitor)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ d = new CIETongueWidgetPriv;
+ d->blinkTimer = new TQTimer( this );
+ setMinimumSize(w, h);
+ cmsErrorAction(LCMS_ERROR_SHOW);
+
+ if (hMonitor)
+ d->hMonitorProfile = hMonitor;
+ else
+ d->hMonitorProfile = cmsCreate_sRGBProfile();
+
+ d->hXYZProfile = cmsCreateXYZProfile();
+ d->hXFORM = cmsCreateTransform(d->hXYZProfile, TYPE_XYZ_16,
+ d->hMonitorProfile, TYPE_RGB_8,
+ INTENT_PERCEPTUAL, 0);
+
+ connect(d->blinkTimer, TQ_SIGNAL(timeout()),
+ this, TQ_SLOT(slotBlinkTimerDone()));
+}
+
+CIETongueWidget::~CIETongueWidget()
+{
+ if (d->Measurement.Patches)
+ free(d->Measurement.Patches);
+
+ if (d->Measurement.Allowed)
+ free(d->Measurement.Allowed);
+
+ cmsDeleteTransform(d->hXFORM);
+ cmsCloseProfile(d->hXYZProfile);
+ cmsCloseProfile(d->hMonitorProfile);
+ delete d;
+}
+
+int CIETongueWidget::grids(double val) const
+{
+ return (int) floor(val * d->gridside + 0.5);
+}
+
+bool CIETongueWidget::setProfileData(const TQByteArray &profileData)
+{
+ if (!profileData.isEmpty())
+ {
+ cmsHPROFILE hProfile = cmsOpenProfileFromMem(const_cast<char*>(profileData.data()),
+ (DWORD)profileData.size());
+
+ if (!hProfile)
+ {
+ d->profileDataAvailable = false;
+ d->loadingImageSucess = false;
+ }
+ else
+ {
+ setProfile(hProfile);
+ cmsCloseProfile(hProfile);
+ d->profileDataAvailable = true;
+ d->loadingImageSucess = true;
+ }
+ }
+ else
+ {
+ d->profileDataAvailable = false;
+ d->loadingImageSucess = false;
+ }
+
+ d->loadingImageMode = false;
+
+ d->blinkTimer->stop();
+ repaint(false);
+ return (d->profileDataAvailable);
+}
+
+bool CIETongueWidget::setProfileFromFile(const KURL& file)
+{
+ if (!file.isEmpty() && file.isValid())
+ {
+ cmsHPROFILE hProfile = cmsOpenProfileFromFile(TQFile::encodeName(file.path()), "r");
+
+ if (!hProfile)
+ {
+ d->profileDataAvailable = false;
+ d->loadingImageSucess = false;
+ }
+ else
+ {
+ setProfile(hProfile);
+ cmsCloseProfile(hProfile);
+ d->profileDataAvailable = true;
+ d->loadingImageSucess = true;
+ }
+ }
+ else
+ {
+ d->profileDataAvailable = false;
+ d->loadingImageSucess = false;
+ }
+
+ d->blinkTimer->stop();
+ repaint(false);
+ return (d->profileDataAvailable);
+}
+
+void CIETongueWidget::setProfile(cmsHPROFILE hProfile)
+{
+ // Get the white point.
+
+ ZeroMemory(&(d->MediaWhite), sizeof(cmsCIEXYZ));
+ cmsTakeMediaWhitePoint(&(d->MediaWhite), hProfile);
+ cmsCIExyY White;
+ cmsXYZ2xyY(&White, &(d->MediaWhite));
+
+ // Get the colorant matrix.
+
+ ZeroMemory(&(d->Primaries), sizeof(cmsCIExyYTRIPLE));
+
+ if (cmsIsTag(hProfile, icSigRedColorantTag) &&
+ cmsIsTag(hProfile, icSigGreenColorantTag) &&
+ cmsIsTag(hProfile, icSigBlueColorantTag))
+ {
+ MAT3 Mat;
+
+ if (cmsReadICCMatrixRGB2XYZ(&Mat, hProfile))
+ {
+ // Undo chromatic adaptation
+ if (cmsAdaptMatrixFromD50(&Mat, &White))
+ {
+ cmsCIEXYZ tmp;
+
+ tmp.X = Mat.v[0].n[0];
+ tmp.Y = Mat.v[1].n[0];
+ tmp.Z = Mat.v[2].n[0];
+
+ // ScaleToWhite(&MediaWhite, &tmp);
+ cmsXYZ2xyY(&(d->Primaries.Red), &tmp);
+
+ tmp.X = Mat.v[0].n[1];
+ tmp.Y = Mat.v[1].n[1];
+ tmp.Z = Mat.v[2].n[1];
+ // ScaleToWhite(&MediaWhite, &tmp);
+ cmsXYZ2xyY(&(d->Primaries.Green), &tmp);
+
+ tmp.X = Mat.v[0].n[2];
+ tmp.Y = Mat.v[1].n[2];
+ tmp.Z = Mat.v[2].n[2];
+ // ScaleToWhite(&MediaWhite, &tmp);
+ cmsXYZ2xyY(&(d->Primaries.Blue), &tmp);
+ }
+ }
+ }
+
+ // Get target data stored in profile
+
+ ZeroMemory(&(d->Measurement), sizeof(MEASUREMENT));
+ char* CharTarget;
+ size_t CharTargetSize;
+
+ if (cmsTakeCharTargetData(hProfile, &CharTarget, &CharTargetSize))
+ {
+ LCMSHANDLE hSheet = cmsxIT8LoadFromMem(CharTarget, CharTargetSize);
+ if (hSheet != NULL)
+ {
+ cmsxPCollLoadFromSheet(&(d->Measurement), hSheet);
+ cmsxIT8Free(hSheet);
+ cmsxPCollValidatePatches(&(d->Measurement), PATCH_HAS_XYZ|PATCH_HAS_RGB);
+ }
+ }
+}
+
+void CIETongueWidget::mapPoint(int& icx, int& icy, LPcmsCIExyY xyY)
+{
+ icx = (int) floor((xyY->x * (d->pxcols - 1)) + .5);
+ icy = (int) floor(((d->pxrows - 1) - xyY->y * (d->pxrows - 1)) + .5);
+}
+
+void CIETongueWidget::biasedLine(int x1, int y1, int x2, int y2)
+{
+ d->painter.drawLine(x1 + d->xBias, y1, x2 + d->xBias, y2);
+}
+
+void CIETongueWidget::biasedText(int x, int y, TQString Txt)
+{
+ d->painter.drawText(TQPoint(d->xBias + x, y), Txt);
+}
+
+TQRgb CIETongueWidget::colorByCoord(double x, double y)
+{
+ // Get xyz components scaled from coordinates
+
+ double cx = ((double) x) / (d->pxcols - 1);
+ double cy = 1.0 - ((double) y) / (d->pxrows - 1);
+ double cz = 1.0 - cx - cy;
+
+ // Project xyz to XYZ space. Note that in this
+ // particular case we are substituting XYZ with xyz
+
+ cmsCIEXYZ XYZ = { cx , cy , cz };
+
+ WORD XYZW[3];
+ BYTE RGB[3];
+
+ cmsFloat2XYZEncoded(XYZW, &XYZ);
+ cmsDoTransform(d->hXFORM, XYZW, RGB, 1);
+
+ return tqRgb(RGB[0], RGB[1], RGB[2]);
+}
+
+void CIETongueWidget::outlineTongue()
+{
+ int lx = 0, ly = 0;
+ int fx=0, fy=0;
+
+ for (int x = 380; x <= 700; x += 5)
+ {
+ int ix = (x - 380) / 5;
+
+ cmsCIExyY p = {spectral_chromaticity[ix][0],
+ spectral_chromaticity[ix][1], 1};
+
+ int icx, icy;
+ mapPoint(icx, icy, &p);
+
+ if (x > 380)
+ {
+ biasedLine(lx, ly, icx, icy);
+ }
+ else
+ {
+ fx = icx;
+ fy = icy;
+ }
+
+ lx = icx;
+ ly = icy;
+ }
+
+ biasedLine(lx, ly, fx, fy);
+}
+
+void CIETongueWidget::fillTongue()
+{
+
+ TQImage Img = d->pixmap.convertToImage();
+
+ int x;
+
+ for (int y = 0; y < d->pxrows; y++)
+ {
+ int xe = 0;
+
+ // Find horizontal extents of tongue on this line.
+
+ for (x = 0; x < d->pxcols; x++)
+ {
+ if ((TQColor) Img.pixel(x + d->xBias, y) != TQt::black)
+ {
+ for (xe = d->pxcols - 1; xe >= x; xe--)
+ {
+ if ((TQColor) Img.pixel(xe + d->xBias, y) != TQt::black)
+ {
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+
+ if (x < d->pxcols)
+ {
+ for ( ; x <= xe; x++)
+ {
+ TQRgb Color = colorByCoord(x, y);
+ Img.setPixel(x + d->xBias, y, Color);
+ }
+ }
+ }
+
+ d->pixmap.convertFromImage(Img, TQPixmap::AvoidDither );
+}
+
+void CIETongueWidget::drawTongueAxis()
+{
+ TQFont font;
+ font.setPointSize(6);
+ d->painter.setFont(font);
+
+ d->painter.setPen(tqRgb(255, 255, 255));
+
+ biasedLine(0, 0, 0, d->pxrows - 1);
+ biasedLine(0, d->pxrows-1, d->pxcols-1, d->pxrows - 1);
+
+ for (int y = 1; y <= 9; y += 1)
+ {
+ TQString s;
+ int xstart = (y * (d->pxcols - 1)) / 10;
+ int ystart = (y * (d->pxrows - 1)) / 10;
+
+ s.sprintf("0.%d", y);
+ biasedLine(xstart, d->pxrows - grids(1), xstart, d->pxrows - grids(4));
+ biasedText(xstart - grids(11), d->pxrows + grids(15), s);
+
+ s.sprintf("0.%d", 10 - y);
+ biasedLine(0, ystart, grids(3), ystart);
+ biasedText(grids(-25), ystart + grids(5), s);
+ }
+}
+
+void CIETongueWidget::drawTongueGrid()
+{
+ d->painter.setPen(tqRgb(80, 80, 80));
+
+ for (int y = 1; y <= 9; y += 1)
+ {
+ int xstart = (y * (d->pxcols - 1)) / 10;
+ int ystart = (y * (d->pxrows - 1)) / 10;
+
+ biasedLine(xstart, grids(4), xstart, d->pxrows - grids(4) - 1);
+ biasedLine(grids(7), ystart, d->pxcols-1-grids(7), ystart);
+ }
+}
+
+void CIETongueWidget::drawLabels()
+{
+ TQFont font;
+ font.setPointSize(5);
+ d->painter.setFont(font);
+
+ for (int x = 450; x <= 650; x += (x > 470 && x < 600) ? 5 : 10)
+ {
+ TQString wl;
+ int bx = 0, by = 0, tx, ty;
+
+ if (x < 520)
+ {
+ bx = grids(-22);
+ by = grids(2);
+ }
+ else if (x < 535)
+ {
+ bx = grids(-8);
+ by = grids(-6);
+ }
+ else
+ {
+ bx = grids(4);
+ }
+
+ int ix = (x - 380) / 5;
+
+ cmsCIExyY p = {spectral_chromaticity[ix][0],
+ spectral_chromaticity[ix][1], 1};
+
+ int icx, icy;
+ mapPoint(icx, icy, &p);
+
+ tx = icx + ((x < 520) ? grids(-2) : ((x >= 535) ? grids(2) : 0));
+ ty = icy + ((x < 520) ? 0 : ((x >= 535) ? grids(-1) : grids(-2)));
+
+ d->painter.setPen(tqRgb(255, 255, 255));
+ biasedLine(icx, icy, tx, ty);
+
+ TQRgb Color = colorByCoord(icx, icy);
+ d->painter.setPen(Color);
+
+ wl.sprintf("%d", x);
+ biasedText(icx+bx, icy+by, wl);
+ }
+}
+
+void CIETongueWidget::drawSmallElipse(LPcmsCIExyY xyY, BYTE r, BYTE g, BYTE b, int sz)
+{
+ int icx, icy;
+
+ mapPoint(icx, icy, xyY);
+ d->painter.setPen(tqRgb(r, g, b));
+ d->painter.drawEllipse(icx + d->xBias- sz/2, icy-sz/2, sz, sz);
+}
+
+void CIETongueWidget::drawPatches()
+{
+ for (int i=0; i < d->Measurement.nPatches; i++)
+ {
+ LPPATCH p = d->Measurement.Patches + i;
+
+ if (d->Measurement.Allowed[i])
+ {
+ LPcmsCIEXYZ XYZ = &p ->XYZ;
+ cmsCIExyY xyY;
+ cmsXYZ2xyY(&xyY, XYZ);
+
+ drawSmallElipse(&xyY, 0, 0, 0, 4);
+
+ if (p->dwFlags & PATCH_HAS_XYZ_PROOF)
+ {
+ if (p->XYZ.Y < 0.03)
+ continue;
+
+ if (p->XYZProof.Y < 0.03)
+ continue;
+
+ cmsCIExyY Pt;
+ cmsXYZ2xyY(&Pt, &p->XYZProof);
+ int icx1, icx2, icy1, icy2;
+
+ mapPoint(icx1, icy1, &xyY);
+ mapPoint(icx2, icy2, &Pt);
+
+ if (icx2 < 5 || icy2 < 5 || icx1 < 5 || icy1 < 5)
+ continue;
+
+ d->painter.setPen(tqRgb(255, 255, 0));
+ biasedLine(icx1, icy1, icx2, icy2);
+ }
+ }
+ }
+}
+
+void CIETongueWidget::drawColorantTriangle()
+{
+ drawSmallElipse(&(d->Primaries.Red), 255, 128, 128, 6);
+ drawSmallElipse(&(d->Primaries.Green), 128, 255, 128, 6);
+ drawSmallElipse(&(d->Primaries.Blue), 128, 128, 255, 6);
+
+ int x1, y1, x2, y2, x3, y3;
+
+ mapPoint(x1, y1, &(d->Primaries.Red));
+ mapPoint(x2, y2, &(d->Primaries.Green));
+ mapPoint(x3, y3, &(d->Primaries.Blue));
+
+ d->painter.setPen(tqRgb(255, 255, 255));
+
+ biasedLine(x1, y1, x2, y2);
+ biasedLine(x2, y2, x3, y3);
+ biasedLine(x3, y3, x1, y1);
+}
+
+void CIETongueWidget::sweep_sRGB()
+{
+ int r, g, b;
+ cmsHPROFILE hXYZ, hsRGB;
+
+ hXYZ = cmsCreateXYZProfile();
+ hsRGB = cmsCreate_sRGBProfile();
+
+ cmsHTRANSFORM xform = cmsCreateTransform(hsRGB, TYPE_RGB_16, hXYZ, TYPE_XYZ_16,
+ INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOTPRECALC);
+ WORD RGB[3], XYZ[3];
+ cmsCIEXYZ xyz, MediaWhite;
+ cmsCIExyY xyY, WhitePt;
+ int x1, y1;
+
+ cmsTakeMediaWhitePoint(&MediaWhite, hsRGB);
+ cmsXYZ2xyY(&WhitePt, &MediaWhite);
+
+ for (r=0; r < 65536; r += 1024)
+ {
+ for (g=0; g < 65536; g += 1024)
+ {
+ for (b=0; b < 65536; b += 1024)
+ {
+ RGB[0] = r; RGB[1] = g; RGB[2] = b;
+ cmsDoTransform(xform, RGB, XYZ, 1);
+ cmsXYZEncoded2Float(&xyz, XYZ);
+ cmsXYZ2xyY(&xyY, &xyz);
+ mapPoint(x1, y1, &xyY);
+ d->painter.drawPoint(x1 + d->xBias, y1);
+ }
+ }
+ }
+
+ cmsDeleteTransform(xform);
+ cmsCloseProfile(hXYZ);
+ cmsCloseProfile(hsRGB);
+}
+
+void CIETongueWidget::drawWhitePoint()
+{
+ cmsCIExyY Whitem_pntxyY;
+ cmsXYZ2xyY(&Whitem_pntxyY, &(d->MediaWhite));
+ drawSmallElipse(&Whitem_pntxyY, 255, 255, 255, 8);
+}
+
+void CIETongueWidget::loadingStarted()
+{
+ d->pos = 0;
+ d->loadingImageMode = true;
+ d->loadingImageSucess = false;
+ repaint(false);
+ d->blinkTimer->start(200);
+}
+
+void CIETongueWidget::loadingFailed()
+{
+ d->blinkTimer->stop();
+ d->pos = 0;
+ d->loadingImageMode = false;
+ d->loadingImageSucess = false;
+ repaint(false);
+}
+
+void CIETongueWidget::paintEvent(TQPaintEvent*)
+{
+ d->pixmap = TQPixmap(size());
+ d->pixmap.setOptimization(TQPixmap::BestOptim);
+
+ // Widget is disable : drawing grayed frame.
+
+ if ( !isEnabled() )
+ {
+ d->painter.begin(&d->pixmap);
+ d->painter.fillRect(0, 0, size().width(), size().height(), palette().disabled().background());
+ d->painter.setPen(TQPen(palette().disabled().foreground(), 1, TQt::SolidLine));
+ d->painter.drawRect(0, 0, width(), height());
+ d->painter.end();
+ bitBlt(this, 0, 0, &d->pixmap);
+ return;
+ }
+
+ // Loading image mode.
+
+ if (d->loadingImageMode && !d->loadingImageSucess)
+ {
+ // 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.
+
+ d->painter.begin(&d->pixmap);
+ d->painter.fillRect(0, 0, size().width(), size().height(), palette().active().background());
+ d->painter.drawPixmap(width()/2 - asize /2, asize, anim);
+ d->painter.setPen(TQPen(palette().active().text(), 1, TQt::SolidLine));
+ d->painter.drawRect(0, 0, width(), height());
+ d->painter.drawText(0, 0, size().width(), size().height(), TQt::AlignCenter,
+ i18n("Loading image..."));
+
+ d->painter.end();
+ bitBlt(this, 0, 0, &d->pixmap);
+ return;
+ }
+
+ // No profile data to show.
+
+ if (!d->profileDataAvailable || (!d->loadingImageMode && !d->loadingImageSucess))
+ {
+ d->painter.begin(&d->pixmap);
+ d->painter.fillRect(0, 0, size().width(), size().height(), palette().active().background());
+ d->painter.setPen(TQPen(palette().active().text(), 1, TQt::SolidLine));
+ d->painter.drawRect(0, 0, width(), height());
+ d->painter.drawText(0, 0, size().width(), size().height(), TQt::AlignCenter,
+ i18n("No profile available..."));
+
+ d->painter.end();
+ bitBlt(this, 0, 0, &d->pixmap);
+ return;
+ }
+
+ // Draw the CIE tongue curve.
+
+ d->pixmap.fill(TQt::black);
+ d->painter.begin(&d->pixmap);
+
+ int pixcols = d->pixmap.width();
+ int pixrows = d->pixmap.height();
+
+ d->gridside = (TQMIN(pixcols, pixrows)) / 512.0;
+ d->xBias = grids(32);
+ d->yBias = grids(20);
+ d->pxcols = pixcols - d->xBias;
+ d->pxrows = pixrows - d->yBias;
+
+ d->painter.setBackgroundColor(tqRgb(0, 0, 0));
+ d->painter.setPen(tqRgb(255, 255, 255));
+
+ outlineTongue();
+ fillTongue();
+
+ drawTongueAxis();
+ drawLabels();
+ drawTongueGrid();
+
+ if (d->MediaWhite.Y > 0.0)
+ drawWhitePoint();
+
+ if (d->Primaries.Red.Y != 0.0)
+ drawColorantTriangle();
+
+ if (d->Measurement.Patches && d->Measurement.Allowed)
+ drawPatches();
+
+ d->painter.end();
+
+ bitBlt(this, 0, 0, &d->pixmap);
+}
+
+void CIETongueWidget::slotBlinkTimerDone()
+{
+ repaint(false);
+ d->blinkTimer->start( 200 );
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/iccprofiles/cietonguewidget.h b/src/libs/widgets/iccprofiles/cietonguewidget.h
new file mode 100644
index 00000000..9fc8503d
--- /dev/null
+++ b/src/libs/widgets/iccprofiles/cietonguewidget.h
@@ -0,0 +1,115 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-10
+ * Description : a widget to display CIE tongue from
+ * an ICC profile.
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Any source code are inspired from lprof project and
+ * Copyright (C) 1998-2001 Marti Maria
+ *
+ * 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 CIETONGUEWIDGET_H
+#define CIETONGUEWIDGET_H
+
+#include <config.h>
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqcolor.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// lcms includes.
+
+#include LCMS_HEADER
+#if LCMS_VERSION < 114
+#define cmsTakeCopyright(profile) "Unknown"
+#endif // LCMS_VERSION < 114
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class CIETongueWidgetPriv;
+
+class DIGIKAM_EXPORT CIETongueWidget : public TQWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ CIETongueWidget(int w, int h, TQWidget *parent=0, cmsHPROFILE hMonitor=0);
+ ~CIETongueWidget();
+
+ bool setProfileData(const TQByteArray& profileData=TQByteArray());
+ bool setProfileFromFile(const KURL& file=KURL());
+
+ void loadingStarted();
+ void loadingFailed();
+
+protected:
+
+ int grids(double val) const;
+
+ void outlineTongue();
+ void fillTongue();
+ void drawTongueAxis();
+ void drawTongueGrid();
+ void drawLabels();
+
+ TQRgb colorByCoord(double x, double y);
+ void drawSmallElipse(LPcmsCIExyY xyY, BYTE r, BYTE g, BYTE b, int sz);
+
+ void paintEvent( TQPaintEvent * );
+
+private:
+
+ void drawColorantTriangle();
+ void drawWhitePoint();
+ void drawPatches();
+
+ void mapPoint(int& icx, int& icy, LPcmsCIExyY xyY);
+ void biasedLine(int x1, int y1, int x2, int y2);
+ void biasedText(int x, int y, TQString Txt);
+
+ void sweep_sRGB();
+
+ void setProfile(cmsHPROFILE hProfile);
+
+private slots:
+
+ void slotBlinkTimerDone();
+
+private :
+
+ CIETongueWidgetPriv* d;
+
+};
+
+} // namespace Digikam
+
+#endif /* CIETONGUEWIDGET_H */
diff --git a/src/libs/widgets/iccprofiles/iccpreviewwidget.cpp b/src/libs/widgets/iccprofiles/iccpreviewwidget.cpp
new file mode 100644
index 00000000..3398b37f
--- /dev/null
+++ b/src/libs/widgets/iccprofiles/iccpreviewwidget.cpp
@@ -0,0 +1,83 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-12
+ * Description : a widget to display ICC profiles descriptions
+ * in file dialog preview.
+ *
+ * Copyright (C) 2006-2007 by Francisco J. Cruz <[email protected]>
+ *
+ * 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 <tqfileinfo.h>
+#include <tqlayout.h>
+#include <tqvgroupbox.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "iccprofilewidget.h"
+#include "iccpreviewwidget.h"
+#include "iccpreviewwidget.moc"
+
+namespace Digikam
+{
+
+ICCPreviewWidget::ICCPreviewWidget(TQWidget *parent)
+ : KPreviewWidgetBase( parent )
+{
+ TQVBoxLayout *layout = new TQVBoxLayout( this );
+ TQVGroupBox *box = new TQVGroupBox( this );
+ box->setInsideMargin(0);
+ box->setFrameStyle(TQFrame::NoFrame|TQFrame::Plain);
+ m_iccProfileWidget = new ICCProfileWidget(box);
+ layout->addWidget( box );
+}
+
+ICCPreviewWidget::~ICCPreviewWidget()
+{
+}
+
+void ICCPreviewWidget::showPreview( const KURL &url)
+{
+ clearPreview();
+ TQFileInfo fInfo(url.path());
+
+ if ( url.isLocalFile() && fInfo.isFile() && fInfo.isReadable() )
+ {
+ DDebug() << url << " is a readble local file" << endl;
+ m_iccProfileWidget->loadFromURL(url);
+ }
+ else
+ {
+ DDebug() << url << " is not a readable local file" << endl;
+ }
+}
+
+void ICCPreviewWidget::clearPreview()
+{
+ m_iccProfileWidget->loadFromURL(KURL());
+}
+
+} // namespace Digikam
+
+
diff --git a/src/libs/widgets/iccprofiles/iccpreviewwidget.h b/src/libs/widgets/iccprofiles/iccpreviewwidget.h
new file mode 100644
index 00000000..89b1f4b5
--- /dev/null
+++ b/src/libs/widgets/iccprofiles/iccpreviewwidget.h
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-12
+ * Description : a widget to display ICC profiles descriptions
+ * in file dialog preview.
+ *
+ * Copyright (C) 2006-2007 by Francisco J. Cruz <[email protected]>
+ *
+ * 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 ICCPREVIEWWIDGET_H
+#define ICCPREVIEWWIDGET_H
+
+// KDE includes.
+
+#include <kpreviewwidgetbase.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+class KURL;
+
+namespace Digikam
+{
+
+class ICCProfileWidget;
+
+class DIGIKAM_EXPORT ICCPreviewWidget : public KPreviewWidgetBase
+{
+
+TQ_OBJECT
+
+
+public:
+
+ ICCPreviewWidget(TQWidget *parent);
+ ~ICCPreviewWidget();
+
+public slots:
+
+ virtual void showPreview(const KURL &url);
+
+protected:
+
+ virtual void clearPreview();
+ virtual void virtual_hook(int, void*){};
+
+private :
+
+ ICCProfileWidget *m_iccProfileWidget;
+
+};
+
+} // namespace Digikam
+
+#endif /* ICCPREVIEWWIDGET_H */
diff --git a/src/libs/widgets/iccprofiles/iccprofilewidget.cpp b/src/libs/widgets/iccprofiles/iccprofilewidget.cpp
new file mode 100644
index 00000000..2e5152f7
--- /dev/null
+++ b/src/libs/widgets/iccprofiles/iccprofilewidget.cpp
@@ -0,0 +1,448 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-06-23
+ * Description : a tab widget to display ICC profile infos
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+#include <config.h>
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqwhatsthis.h>
+#include <tqlabel.h>
+#include <tqmap.h>
+#include <tqhbox.h>
+#include <tqfile.h>
+#include <tqcombobox.h>
+#include <tqgroupbox.h>
+#include <tqmap.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+#include <tdelocale.h>
+#include <tdeapplication.h>
+
+// Lcms includes.
+
+#include LCMS_HEADER
+#if LCMS_VERSION < 114
+#define cmsTakeCopyright(profile) "Unknown"
+#endif // LCMS_VERSION < 114
+
+// Local includes.
+
+#include "ddebug.h"
+#include "metadatalistview.h"
+#include "cietonguewidget.h"
+#include "iccprofilewidget.h"
+#include "iccprofilewidget.moc"
+
+namespace Digikam
+{
+
+static const char* ICCHumanList[] =
+{
+ "ColorSpace",
+ "Copyright",
+ "DeviceClass",
+ "Name",
+ "Description",
+ "RenderingIntent",
+ "-1"
+};
+
+// This entry list is only require for compatibility with MetadataWidget implementation.
+static const char* ICCEntryList[] =
+{
+ "Header",
+ "-1"
+};
+
+class ICCTagInfo
+{
+
+public:
+
+ ICCTagInfo(){}
+
+ ICCTagInfo(const TQString& title, const TQString& description)
+ : m_title(title), m_description(description){}
+
+ TQString title() const { return m_title; }
+ TQString description() const { return m_description; }
+
+private:
+
+ TQString m_title;
+ TQString m_description;
+};
+
+typedef TQMap<TQString, ICCTagInfo> ICCTagInfoMap;
+
+class ICCProfileWidgetPriv
+{
+
+public:
+
+ ICCProfileWidgetPriv()
+ {
+ cieTongue = 0;
+ }
+
+ TQStringList tagsfilter;
+ TQStringList keysFilter;
+
+ CIETongueWidget *cieTongue;
+
+ ICCTagInfoMap iccTagsDescription;
+};
+
+
+ICCProfileWidget::ICCProfileWidget(TQWidget* parent, const char* name, int w, int h)
+ : MetadataWidget(parent, name)
+{
+ cmsErrorAction(LCMS_ERROR_SHOW);
+
+ d = new ICCProfileWidgetPriv;
+
+ // Set the translated ICC tags titles/descriptions list
+ d->iccTagsDescription["Icc.Header.Name"] = ICCTagInfo(i18n("Name"),
+ i18n("The ICC profile product name"));
+ d->iccTagsDescription["Icc.Header.Description"] = ICCTagInfo(i18n("Description"),
+ i18n("The ICC profile product description"));
+ d->iccTagsDescription["Icc.Header.Information"] = ICCTagInfo(i18n("Information"),
+ i18n("Additional ICC profile information"));
+ d->iccTagsDescription["Icc.Header.Manufacturer"] = ICCTagInfo(i18n("Manufacturer"),
+ i18n("Raw information about the ICC profile manufacturer"));
+ d->iccTagsDescription["Icc.Header.Model"] = ICCTagInfo(i18n("Model"),
+ i18n("Raw information about the ICC profile model"));
+ d->iccTagsDescription["Icc.Header.Copyright"] = ICCTagInfo(i18n("Copyright"),
+ i18n("Raw information about the ICC profile copyright"));
+ d->iccTagsDescription["Icc.Header.ProfileID"] = ICCTagInfo(i18n("Profile ID"),
+ i18n("The ICC profile ID number"));
+ d->iccTagsDescription["Icc.Header.ColorSpace"] = ICCTagInfo(i18n("Color Space"),
+ i18n("The color space used by the ICC profile"));
+ d->iccTagsDescription["Icc.Header.ConnectionSpace"] = ICCTagInfo(i18n("Connection Space"),
+ i18n("The connection space used by the ICC profile"));
+ d->iccTagsDescription["Icc.Header.DeviceClass"] = ICCTagInfo(i18n("Device Class"),
+ i18n("The ICC profile device class"));
+ d->iccTagsDescription["Icc.Header.RenderingIntent"] = ICCTagInfo(i18n("Rendering Intent"),
+ i18n("The ICC profile rendering intent"));
+ d->iccTagsDescription["Icc.Header.ProfileVersion"] = ICCTagInfo(i18n("Profile Version"),
+ i18n("The ICC version used to record the profile"));
+ d->iccTagsDescription["Icc.Header.CMMFlags"] = ICCTagInfo(i18n("CMM Flags"),
+ i18n("The ICC profile color management flags"));
+
+ // Set the list of keys and tags filters.
+ for (int i=0 ; TQString(ICCEntryList[i]) != TQString("-1") ; i++)
+ d->keysFilter << ICCEntryList[i];
+
+ for (int i=0 ; TQString(ICCHumanList[i]) != TQString("-1") ; i++)
+ d->tagsfilter << ICCHumanList[i];
+
+ // Add CIE tongue graph to the widget area
+
+ d->cieTongue = new CIETongueWidget(w, h, this);
+ TQWhatsThis::add( d->cieTongue, i18n("<p>This area contains a CIE or chromaticity diagram. "
+ "A CIE diagram is a representation of all the colors "
+ "that a person with normal vision can see. This is represented "
+ "by the colored sail-shaped area. In addition you will see a "
+ "triangle that is superimposed on the diagram outlined in white. "
+ "This triangle represents the outer boundaries of the color space "
+ "of the device that is characterized by the inspected profile. "
+ "This is called the device gamut.<p>"
+ "In addition there are black dots and yellow lines on the diagram. "
+ "Each black dot represents one of the measurement points that were "
+ "used to create this profile. The yellow line represents the "
+ "amount that each point is corrected by the profile, and the "
+ "direction of this correction."));
+
+ setUserAreaWidget(d->cieTongue);
+ decodeMetadata();
+}
+
+ICCProfileWidget::~ICCProfileWidget()
+{
+ delete d;
+}
+
+void ICCProfileWidget::setDataLoading()
+{
+ d->cieTongue->loadingStarted();
+}
+
+void ICCProfileWidget::setLoadingFailed()
+{
+ d->cieTongue->loadingFailed();
+}
+
+TQString ICCProfileWidget::getMetadataTitle()
+{
+ return i18n("ICC Color Profile Information");
+}
+
+bool ICCProfileWidget::loadFromURL(const KURL& url)
+{
+ setFileName(url.path());
+
+ if (url.isEmpty())
+ {
+ setMetadata();
+ d->cieTongue->setProfileData();
+ return false;
+ }
+ else
+ {
+ TQFile file(url.path());
+ if ( !file.open(IO_ReadOnly) )
+ {
+ setMetadata();
+ d->cieTongue->setProfileData();
+ return false;
+ }
+
+ TQByteArray iccData(file.size());
+ TQDataStream stream( &file );
+ stream.readRawBytes(iccData.data(), iccData.size());
+ file.close();
+
+ if (iccData.isEmpty())
+ {
+ setMetadata();
+ d->cieTongue->setProfileData();
+ return false;
+ }
+ else
+ {
+ setMetadata(iccData);
+ d->cieTongue->setProfileData(iccData);
+ }
+ }
+
+ return true;
+}
+
+bool ICCProfileWidget::decodeMetadata()
+{
+ TQByteArray iccData = getMetadata();
+ if (iccData.isNull())
+ return false;
+
+ d->cieTongue->setProfileData(iccData);
+
+ cmsHPROFILE hProfile = cmsOpenProfileFromMem(iccData.data(), (DWORD)iccData.size());
+
+ if (!hProfile)
+ {
+ DDebug() << "Cannot parse ICC profile tags using LCMS" << endl;
+ return false;
+ }
+
+ DMetadata::MetaDataMap metaDataMap;
+
+ if ( !TQString(cmsTakeProductName(hProfile)).isEmpty() )
+ metaDataMap.insert("Icc.Header.Name", TQString(cmsTakeProductName(hProfile)).replace("\n", " "));
+
+ if ( !TQString(cmsTakeProductDesc(hProfile)).isEmpty() )
+ metaDataMap.insert("Icc.Header.Description", TQString(cmsTakeProductDesc(hProfile)).replace("\n", " "));
+
+ if ( !TQString(cmsTakeProductInfo(hProfile)).isEmpty() )
+ metaDataMap.insert("Icc.Header.Information", TQString(cmsTakeProductInfo(hProfile)).replace("\n", " "));
+
+ if ( !TQString(cmsTakeManufacturer(hProfile)).isEmpty() )
+ metaDataMap.insert("Icc.Header.Manufacturer", TQString(cmsTakeManufacturer(hProfile)).replace("\n", " "));
+
+ if ( !TQString(cmsTakeModel(hProfile)).isEmpty() )
+ metaDataMap.insert("Icc.Header.Model", TQString(cmsTakeModel(hProfile)).replace("\n", " "));
+
+ if ( !TQString(cmsTakeCopyright(hProfile)).isEmpty() )
+ metaDataMap.insert("Icc.Header.Copyright", TQString(cmsTakeCopyright(hProfile)).replace("\n", " "));
+
+ metaDataMap.insert("Icc.Header.ProfileID", TQString::number((uint)*cmsTakeProfileID(hProfile)));
+ metaDataMap.insert("Icc.Header.ProfileVersion", TQString::number((uint)cmsGetProfileICCversion(hProfile)));
+ metaDataMap.insert("Icc.Header.CMMFlags", TQString::number((uint)cmsTakeHeaderFlags(hProfile)));
+
+ TQString colorSpace;
+ switch (cmsGetColorSpace(hProfile))
+ {
+ case icSigLabData:
+ colorSpace = i18n("Lab");
+ break;
+ case icSigLuvData:
+ colorSpace = i18n("Luv");
+ break;
+ case icSigRgbData:
+ colorSpace = i18n("RGB");
+ break;
+ case icSigGrayData:
+ colorSpace = i18n("GRAY");
+ break;
+ case icSigHsvData:
+ colorSpace = i18n("HSV");
+ break;
+ case icSigHlsData:
+ colorSpace = i18n("HLS");
+ break;
+ case icSigCmykData:
+ colorSpace = i18n("CMYK");
+ break;
+ case icSigCmyData:
+ colorSpace= i18n("CMY");
+ break;
+ default:
+ colorSpace = i18n("Unknown");
+ break;
+ }
+ metaDataMap.insert("Icc.Header.ColorSpace", colorSpace);
+
+ TQString connectionSpace;
+ switch (cmsGetPCS(hProfile))
+ {
+ case icSigLabData:
+ connectionSpace = i18n("Lab");
+ break;
+ case icSigLuvData:
+ connectionSpace = i18n("Luv");
+ break;
+ case icSigRgbData:
+ connectionSpace = i18n("RGB");
+ break;
+ case icSigGrayData:
+ connectionSpace = i18n("GRAY");
+ break;
+ case icSigHsvData:
+ connectionSpace = i18n("HSV");
+ break;
+ case icSigHlsData:
+ connectionSpace = i18n("HLS");
+ break;
+ case icSigCmykData:
+ connectionSpace = i18n("CMYK");
+ break;
+ case icSigCmyData:
+ connectionSpace= i18n("CMY");
+ break;
+ default:
+ connectionSpace = i18n("Unknown");
+ break;
+ }
+ metaDataMap.insert("Icc.Header.ConnectionSpace", connectionSpace);
+
+ TQString device;
+ switch ((int)cmsGetDeviceClass(hProfile))
+ {
+ case icSigInputClass:
+ device = i18n("Input device");
+ break;
+ case icSigDisplayClass:
+ device = i18n("Display device");
+ break;
+ case icSigOutputClass:
+ device = i18n("Output device");
+ break;
+ case icSigColorSpaceClass:
+ device = i18n("Color space");
+ break;
+ case icSigLinkClass:
+ device = i18n("Link device");
+ break;
+ case icSigAbstractClass:
+ device = i18n("Abstract");
+ break;
+ case icSigNamedColorClass:
+ device = i18n("Named color");
+ break;
+ default:
+ device = i18n("Unknown");
+ break;
+ }
+ metaDataMap.insert("Icc.Header.DeviceClass", device);
+
+ TQString intent;
+ switch (cmsTakeRenderingIntent(hProfile))
+ {
+ case 0:
+ intent = i18n("Perceptual");
+ break;
+ case 1:
+ intent = i18n("Relative Colorimetric");
+ break;
+ case 2:
+ intent = i18n("Saturation");
+ break;
+ case 3:
+ intent = i18n("Absolute Colorimetric");
+ break;
+ default:
+ intent = i18n("Unknown");
+ break;
+ }
+ metaDataMap.insert("Icc.Header.RenderingIntent", intent);
+
+ cmsCloseProfile(hProfile);
+
+ // Update all metadata contents.
+ setMetadataMap(metaDataMap);
+ return true;
+}
+
+void ICCProfileWidget::buildView()
+{
+ if (getMode() == SIMPLE)
+ {
+ setIfdList(getMetadataMap(), d->keysFilter, d->tagsfilter);
+ }
+ else
+ {
+ setIfdList(getMetadataMap(), d->keysFilter, TQStringList());
+ }
+
+ MetadataWidget::buildView();
+}
+
+TQString ICCProfileWidget::getTagTitle(const TQString& key)
+{
+ ICCTagInfoMap::Iterator it = d->iccTagsDescription.find(key);
+ if (it != d->iccTagsDescription.end())
+ return(it.data().title());
+
+ return key.section('.', 2, 2);
+}
+
+void ICCProfileWidget::slotSaveMetadataToFile()
+{
+ KURL url = saveMetadataToFile(i18n("ICC color profile File to Save"),
+ TQString("*.icc *.icm|"+i18n("ICC Files (*.icc; *.icm)")));
+ storeMetadataToFile(url);
+}
+
+TQString ICCProfileWidget::getTagDescription(const TQString& key)
+{
+ ICCTagInfoMap::Iterator it = d->iccTagsDescription.find(key);
+ if (it != d->iccTagsDescription.end())
+ return(it.data().description());
+
+ return key.section('.', 2, 2);
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/iccprofiles/iccprofilewidget.h b/src/libs/widgets/iccprofiles/iccprofilewidget.h
new file mode 100644
index 00000000..d753f30e
--- /dev/null
+++ b/src/libs/widgets/iccprofiles/iccprofilewidget.h
@@ -0,0 +1,79 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-06-23
+ * Description : a tab widget to display ICC profile infos
+ *
+ * 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 ICCPROFILEWIDGET_H
+#define ICCPROFILEWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqstring.h>
+
+// Local includes.
+
+#include "metadatawidget.h"
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class ICCProfileWidgetPriv;
+
+class DIGIKAM_EXPORT ICCProfileWidget : public MetadataWidget
+{
+ TQ_OBJECT
+
+
+public:
+
+ ICCProfileWidget(TQWidget* parent, const char* name=0, int w=256, int h=256);
+ ~ICCProfileWidget();
+
+ bool loadFromURL(const KURL& url);
+
+ TQString getTagDescription(const TQString& key);
+ TQString getTagTitle(const TQString& key);
+
+ TQString getMetadataTitle();
+
+ void setLoadingFailed();
+ void setDataLoading();
+
+protected slots:
+
+ virtual void slotSaveMetadataToFile();
+
+private:
+
+ bool decodeMetadata();
+ void buildView();
+
+private:
+
+ ICCProfileWidgetPriv *d;
+
+};
+
+} // namespace Digikam
+
+#endif /* ICCPROFILEWIDGET_H */
diff --git a/src/libs/widgets/imageplugins/Makefile.am b/src/libs/widgets/imageplugins/Makefile.am
new file mode 100644
index 00000000..d223cb05
--- /dev/null
+++ b/src/libs/widgets/imageplugins/Makefile.am
@@ -0,0 +1,22 @@
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libimagepluginswidgets.la
+
+libimagepluginswidgets_la_SOURCES = imageregionwidget.cpp imagepaniconwidget.cpp imageguidewidget.cpp \
+ imagewidget.cpp listboxpreviewitem.cpp imagepanelwidget.cpp
+
+libimagepluginswidgets_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikaminclude_HEADERS = imageregionwidget.h imagepaniconwidget.h \
+ imagepanelwidget.h imageguidewidget.h \
+ listboxpreviewitem.h imagewidget.h
+
+digikamincludedir = $(includedir)/digikam
diff --git a/src/libs/widgets/imageplugins/imageguidewidget.cpp b/src/libs/widgets/imageplugins/imageguidewidget.cpp
new file mode 100644
index 00000000..4ed7f254
--- /dev/null
+++ b/src/libs/widgets/imageplugins/imageguidewidget.cpp
@@ -0,0 +1,625 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-11-16
+ * Description : a widget to display an image with guides
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqregion.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqpixmap.h>
+#include <tqtooltip.h>
+#include <tqtimer.h>
+#include <tqrect.h>
+#include <tqbrush.h>
+#include <tqfont.h>
+#include <tqfontmetrics.h>
+
+// KDE includes.
+
+#include <kstandarddirs.h>
+#include <kcursor.h>
+#include <tdeglobal.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imageguidewidget.h"
+#include "imageguidewidget.moc"
+
+namespace Digikam
+{
+
+class ImageGuideWidgetPriv
+{
+public:
+
+ ImageGuideWidgetPriv()
+ {
+ pixmap = 0;
+ iface = 0;
+ flicker = 0;
+ timerID = 0;
+ focus = false;
+ onMouseMovePreviewToggled = true;
+ renderingPreviewMode = ImageGuideWidget::NoPreviewMode;
+ underExposureIndicator = false;
+ overExposureIndicator = false;
+ }
+
+ bool sixteenBit;
+ bool focus;
+ bool spotVisible;
+ bool onMouseMovePreviewToggled;
+ bool underExposureIndicator;
+ bool overExposureIndicator;
+
+ int width;
+ int height;
+ int timerID;
+ int guideMode;
+ int guideSize;
+ int flicker;
+ int renderingPreviewMode;
+
+ // Current spot position in preview coordinates.
+ TQPoint spot;
+
+ TQRect rect;
+
+ TQColor guideColor;
+
+ TQPixmap *pixmap;
+
+ ImageIface *iface;
+
+ DImg preview;
+};
+
+ImageGuideWidget::ImageGuideWidget(int w, int h, TQWidget *parent,
+ bool spotVisible, int guideMode,
+ const TQColor& guideColor, int guideSize,
+ bool blink, bool useImageSelection)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ d = new ImageGuideWidgetPriv;
+ d->spotVisible = spotVisible;
+ d->guideMode = guideMode;
+ d->guideColor = guideColor;
+ d->guideSize = guideSize;
+
+ setBackgroundMode(TQt::NoBackground);
+ setMinimumSize(w, h);
+ setMouseTracking(true);
+
+ d->iface = new ImageIface(w, h);
+ d->iface->setPreviewType(useImageSelection);
+ uchar *data = d->iface->getPreviewImage();
+ d->width = d->iface->previewWidth();
+ d->height = d->iface->previewHeight();
+ bool sixteenBit = d->iface->previewSixteenBit();
+ bool hasAlpha = d->iface->previewHasAlpha();
+ d->preview = DImg(d->width, d->height, sixteenBit, hasAlpha, data);
+ d->preview.setICCProfil( d->iface->getOriginalImg()->getICCProfil() );
+
+ delete [] data;
+
+ d->pixmap = new TQPixmap(w, h);
+ d->rect = TQRect(w/2-d->width/2, h/2-d->height/2, d->width, d->height);
+
+ resetSpotPosition();
+ setSpotVisible(d->spotVisible, blink);
+}
+
+ImageGuideWidget::~ImageGuideWidget()
+{
+ delete d->iface;
+
+ if (d->timerID)
+ killTimer(d->timerID);
+
+ if (d->pixmap)
+ delete d->pixmap;
+
+ delete d;
+}
+
+ImageIface* ImageGuideWidget::imageIface()
+{
+ return d->iface;
+}
+
+void ImageGuideWidget::slotToggleUnderExposure(bool u)
+{
+ d->underExposureIndicator = u;
+ updatePreview();
+}
+
+void ImageGuideWidget::slotToggleOverExposure(bool o)
+{
+ d->overExposureIndicator = o;
+ updatePreview();
+}
+
+void ImageGuideWidget::resetSpotPosition()
+{
+ d->spot.setX( d->width / 2 );
+ d->spot.setY( d->height / 2 );
+ updatePreview();
+}
+
+void ImageGuideWidget::slotChangeRenderingPreviewMode(int mode)
+{
+ d->renderingPreviewMode = mode;
+ updatePreview();
+}
+
+int ImageGuideWidget::getRenderingPreviewMode()
+{
+ return (d->renderingPreviewMode);
+}
+
+TQPoint ImageGuideWidget::getSpotPosition()
+{
+ return (TQPoint( (int)((float)d->spot.x() * (float)d->iface->originalWidth() / (float)d->width),
+ (int)((float)d->spot.y() * (float)d->iface->originalHeight() / (float)d->height)));
+}
+
+DColor ImageGuideWidget::getSpotColor(int getColorFrom)
+{
+ if (getColorFrom == OriginalImage) // Get point color from full original image
+ return (d->iface->getColorInfoFromOriginalImage(getSpotPosition()));
+ else if (getColorFrom == PreviewImage) // Get point color from full preview image
+ return (d->iface->getColorInfoFromPreviewImage(d->spot));
+
+ // In other cases, get point color from preview target image
+ return (d->iface->getColorInfoFromTargetPreviewImage(d->spot));
+}
+
+void ImageGuideWidget::setSpotVisible(bool spotVisible, bool blink)
+{
+ d->spotVisible = spotVisible;
+
+ if (blink)
+ {
+ if (d->spotVisible)
+ d->timerID = startTimer(800);
+ else
+ {
+ killTimer(d->timerID);
+ d->timerID = 0;
+ }
+ }
+
+ updatePreview();
+}
+
+void ImageGuideWidget::slotChangeGuideColor(const TQColor &color)
+{
+ d->guideColor = color;
+ updatePreview();
+}
+
+void ImageGuideWidget::slotChangeGuideSize(int size)
+{
+ d->guideSize = size;
+ updatePreview();
+}
+
+void ImageGuideWidget::updatePixmap()
+{
+ TQPainter p(d->pixmap);
+ TQString text;
+ TQRect textRect, fontRect;
+ TQFontMetrics fontMt = p.fontMetrics();
+ p.setPen(TQPen(TQt::red, 1)) ;
+
+ d->pixmap->fill(colorGroup().background());
+
+ if (d->renderingPreviewMode == PreviewOriginalImage ||
+ (d->renderingPreviewMode == PreviewToggleOnMouseOver && d->onMouseMovePreviewToggled == false ))
+ {
+ p.drawPixmap(d->rect, d->iface->convertToPixmap(d->preview));
+
+ text = i18n("Original");
+ fontRect = fontMt.boundingRect(0, 0, d->rect.width(), d->rect.height(), 0, text);
+ textRect.setTopLeft(TQPoint(d->rect.x() + 20, d->rect.y() + 20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2 ) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+ }
+ else if (d->renderingPreviewMode == PreviewTargetImage || d->renderingPreviewMode == NoPreviewMode ||
+ (d->renderingPreviewMode == PreviewToggleOnMouseOver && d->onMouseMovePreviewToggled == true ))
+ {
+ d->iface->paint(d->pixmap, d->rect.x(), d->rect.y(),
+ d->rect.width(), d->rect.height(),
+ d->underExposureIndicator, d->overExposureIndicator);
+
+ if (d->renderingPreviewMode == PreviewTargetImage ||
+ d->renderingPreviewMode == PreviewToggleOnMouseOver)
+ {
+ text = i18n("Target");
+ fontRect = fontMt.boundingRect(0, 0, d->rect.width(), d->rect.height(), 0, text);
+ textRect.setTopLeft(TQPoint(d->rect.x() + 20, d->rect.y() + 20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2 ) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+ }
+ }
+ else if (d->renderingPreviewMode == PreviewBothImagesVert ||
+ d->renderingPreviewMode == PreviewBothImagesVertCont)
+ {
+ if (d->renderingPreviewMode == PreviewBothImagesVert)
+ {
+ // Drawing the original image.
+ p.drawPixmap(d->rect, d->iface->convertToPixmap(d->preview));
+
+ // Drawing the target image under the original.
+ d->iface->paint(d->pixmap,
+ d->rect.x()+d->rect.width()/2,
+ d->rect.y(),
+ d->rect.width()/2,
+ d->rect.height(),
+ d->underExposureIndicator,
+ d->overExposureIndicator);
+ }
+ else
+ {
+ // Drawing the target image.
+ d->iface->paint(d->pixmap,
+ d->rect.x(),
+ d->rect.y(),
+ d->rect.width(),
+ d->rect.height(),
+ d->underExposureIndicator,
+ d->overExposureIndicator);
+
+ // Drawing the original image under the target.
+ p.drawPixmap(d->rect.x(), d->rect.y(), d->iface->convertToPixmap(d->preview),
+ 0, 0, d->rect.width()/2, d->rect.height());
+ }
+
+ // Drawing the information and others stuff.
+ p.fillRect(d->rect.right(), 0, width(), height(), colorGroup().background());
+
+ p.setPen(TQPen(TQt::white, 2, TQt::SolidLine));
+ p.drawLine(d->rect.x()+d->rect.width()/2-1,
+ d->rect.y(),
+ d->rect.x()+d->rect.width()/2-1,
+ d->rect.y()+d->rect.height());
+ p.setPen(TQPen(TQt::red, 2, TQt::DotLine));
+ p.drawLine(d->rect.x()+d->rect.width()/2-1,
+ d->rect.y(),
+ d->rect.x()+d->rect.width()/2-1,
+ d->rect.y()+d->rect.height());
+
+ p.setPen(TQPen(TQt::red, 1)) ;
+
+ text = i18n("Target");
+ fontRect = fontMt.boundingRect(0, 0, d->rect.width(), d->rect.height(), 0, text);
+ textRect.setTopLeft(TQPoint(d->rect.x() + d->rect.width()/2 + 20,
+ d->rect.y() + 20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+
+ text = i18n("Original");
+ fontRect = fontMt.boundingRect(0, 0, d->rect.width(), d->rect.height(), 0, text);
+ textRect.setTopLeft(TQPoint(d->rect.x() + 20, d->rect.y() + 20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2 ) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+ }
+ else if (d->renderingPreviewMode == PreviewBothImagesHorz ||
+ d->renderingPreviewMode == PreviewBothImagesHorzCont)
+ {
+ if (d->renderingPreviewMode == PreviewBothImagesHorz)
+ {
+ // Drawing the original image.
+ p.drawPixmap(d->rect, d->iface->convertToPixmap(d->preview));
+
+ // Drawing the target image under the original.
+ d->iface->paint(d->pixmap,
+ d->rect.x(),
+ d->rect.y()+d->rect.height()/2,
+ d->rect.width(),
+ d->rect.height()/2,
+ d->underExposureIndicator,
+ d->overExposureIndicator);
+ }
+ else
+ {
+ // Drawing the target image.
+ d->iface->paint(d->pixmap,
+ d->rect.x(),
+ d->rect.y(),
+ d->rect.width(),
+ d->rect.height(),
+ d->underExposureIndicator,
+ d->overExposureIndicator);
+
+ // Drawing the original image under the target.
+ p.drawPixmap(d->rect.x(), d->rect.y(), d->iface->convertToPixmap(d->preview),
+ 0, 0, d->rect.width(), d->rect.height()/2);
+ }
+
+ p.fillRect(0, d->rect.bottom(), width(), height(), colorGroup().background());
+
+ p.setPen(TQPen(TQt::white, 2, TQt::SolidLine));
+ p.drawLine(d->rect.x(),
+ d->rect.y()+d->rect.height()/2-1,
+ d->rect.x()+d->rect.width(),
+ d->rect.y()+d->rect.height()/2-1);
+ p.setPen(TQPen(TQt::red, 2, TQt::DotLine));
+ p.drawLine(d->rect.x(),
+ d->rect.y()+d->rect.height()/2-1,
+ d->rect.x()+d->rect.width(),
+ d->rect.y()+d->rect.height()/2-1);
+
+ p.setPen(TQPen(TQt::red, 1)) ;
+
+ text = i18n("Target");
+ fontRect = fontMt.boundingRect(0, 0, d->rect.width(), d->rect.height(), 0, text);
+ textRect.setTopLeft(TQPoint(d->rect.x() + 20,
+ d->rect.y() + d->rect.height()/2 + 20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+
+ text = i18n("Original");
+ fontRect = fontMt.boundingRect(0, 0, d->rect.width(), d->rect.height(), 0, text);
+ textRect.setTopLeft(TQPoint(d->rect.x() + 20, d->rect.y() + 20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2 ) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+ }
+
+ if (d->spotVisible)
+ {
+ // Adapt spot from image coordinate to widget coordinate.
+ int xspot = d->spot.x() + d->rect.x();
+ int yspot = d->spot.y() + d->rect.y();
+
+ switch (d->guideMode)
+ {
+ case HVGuideMode:
+ {
+ p.setPen(TQPen(TQt::white, d->guideSize, TQt::SolidLine));
+ p.drawLine(xspot, d->rect.top() + d->flicker, xspot, d->rect.bottom() - d->flicker);
+ p.drawLine(d->rect.left() + d->flicker, yspot, d->rect.right() - d->flicker, yspot);
+ p.setPen(TQPen(d->guideColor, d->guideSize, TQt::DotLine));
+ p.drawLine(xspot, d->rect.top() + d->flicker, xspot, d->rect.bottom() - d->flicker);
+ p.drawLine(d->rect.left() + d->flicker, yspot, d->rect.right() - d->flicker, yspot);
+ break;
+ }
+
+ case PickColorMode:
+ {
+ p.setPen(TQPen(d->guideColor, 1, TQt::SolidLine));
+ p.drawLine(xspot-10, yspot-10, xspot+10, yspot+10);
+ p.drawLine(xspot+10, yspot-10, xspot-10, yspot+10);
+ p.setPen(TQPen(d->guideColor, 3, TQt::SolidLine));
+ p.drawEllipse( xspot-5, yspot-5, 11, 11 );
+
+ if (d->flicker%2 != 0)
+ {
+ p.setPen(TQPen(TQt::white, 1, TQt::SolidLine));
+ p.drawEllipse( xspot-5, yspot-5, 11, 11 );
+ }
+
+ break;
+ }
+ }
+ }
+
+ p.end();
+}
+
+void ImageGuideWidget::paintEvent(TQPaintEvent*)
+{
+ bitBlt(this, 0, 0, d->pixmap);
+}
+
+void ImageGuideWidget::updatePreview()
+{
+ updatePixmap();
+ repaint(false);
+}
+
+void ImageGuideWidget::timerEvent(TQTimerEvent* e)
+{
+ if (e->timerId() == d->timerID)
+ {
+ if (d->flicker == 5) d->flicker=0;
+ else d->flicker++;
+ updatePreview();
+ }
+ else
+ TQWidget::timerEvent(e);
+}
+
+void ImageGuideWidget::resizeEvent(TQResizeEvent* e)
+{
+ blockSignals(true);
+ delete d->pixmap;
+ int w = e->size().width();
+ int h = e->size().height();
+ int old_w = d->width;
+ int old_h = d->height;
+
+ uchar *data = d->iface->setPreviewImageSize(w, h);
+ d->width = d->iface->previewWidth();
+ d->height = d->iface->previewHeight();
+ bool sixteenBit = d->iface->previewSixteenBit();
+ bool hasAlpha = d->iface->previewHasAlpha();
+ d->preview = DImg(d->width, d->height, sixteenBit, hasAlpha, data);
+ d->preview.setICCProfil( d->iface->getOriginalImg()->getICCProfil() );
+
+ delete [] data;
+
+ d->pixmap = new TQPixmap(w, h);
+ d->rect = TQRect(w/2-d->width/2, h/2-d->height/2, d->width, d->height);
+
+ d->spot.setX((int)((float)d->spot.x() * ( (float)d->width / (float)old_w)));
+ d->spot.setY((int)((float)d->spot.y() * ( (float)d->height / (float)old_h)));
+ updatePixmap();
+ blockSignals(false);
+ emit signalResized();
+}
+
+void ImageGuideWidget::mousePressEvent(TQMouseEvent* e)
+{
+ if ( !d->focus && e->button() == TQt::LeftButton &&
+ d->rect.contains( e->x(), e->y() ) && d->spotVisible )
+ {
+ d->focus = true;
+ d->spot.setX(e->x()-d->rect.x());
+ d->spot.setY(e->y()-d->rect.y());
+ updatePreview();
+ }
+}
+
+void ImageGuideWidget::mouseReleaseEvent(TQMouseEvent* e)
+{
+ if ( d->rect.contains( e->x(), e->y() ) && d->focus && d->spotVisible)
+ {
+ d->focus = false;
+ updatePreview();
+ d->spot.setX(e->x()-d->rect.x());
+ d->spot.setY(e->y()-d->rect.y());
+
+ DColor color;
+ TQPoint point = getSpotPosition();
+
+ if (d->renderingPreviewMode == PreviewOriginalImage)
+ {
+ color = getSpotColor(OriginalImage);
+ emit spotPositionChangedFromOriginal( color, d->spot );
+ }
+ else if (d->renderingPreviewMode == PreviewTargetImage || d->renderingPreviewMode == NoPreviewMode)
+ {
+ color = getSpotColor(TargetPreviewImage);
+ emit spotPositionChangedFromTarget( color, d->spot );
+ }
+ else if (d->renderingPreviewMode == PreviewBothImagesVert)
+ {
+ if (d->spot.x() > d->rect.width()/2)
+ {
+ color = getSpotColor(TargetPreviewImage);
+ emit spotPositionChangedFromTarget(color, TQPoint(d->spot.x() - d->rect.width()/2,
+ d->spot.y()));
+ }
+ else
+ {
+ color = getSpotColor(OriginalImage);
+ emit spotPositionChangedFromOriginal( color, d->spot );
+ }
+ }
+ else if (d->renderingPreviewMode == PreviewBothImagesVertCont)
+ {
+ if (d->spot.x() > d->rect.width()/2)
+ {
+ color = getSpotColor(TargetPreviewImage);
+ emit spotPositionChangedFromTarget( color, d->spot);
+ }
+ else
+ {
+ color = getSpotColor(OriginalImage);
+ emit spotPositionChangedFromOriginal( color, d->spot );
+ }
+ }
+ else if (d->renderingPreviewMode == PreviewBothImagesHorz)
+ {
+ if (d->spot.y() > d->rect.height()/2)
+ {
+ color = getSpotColor(TargetPreviewImage);
+ emit spotPositionChangedFromTarget(color, TQPoint(d->spot.x(),
+ d->spot.y() - d->rect.height()/2 ));
+ }
+ else
+ {
+ color = getSpotColor(OriginalImage);
+ emit spotPositionChangedFromOriginal( color, d->spot );
+ }
+ }
+ else if (d->renderingPreviewMode == PreviewBothImagesHorzCont)
+ {
+ if (d->spot.y() > d->rect.height()/2)
+ {
+ color = getSpotColor(TargetPreviewImage);
+ emit spotPositionChangedFromTarget( color, d->spot);
+ }
+ else
+ {
+ color = getSpotColor(OriginalImage);
+ emit spotPositionChangedFromOriginal( color, d->spot );
+ }
+ }
+ }
+}
+
+void ImageGuideWidget::mouseMoveEvent(TQMouseEvent* e)
+{
+ if ( d->rect.contains( e->x(), e->y() ) && !d->focus && d->spotVisible )
+ {
+ setCursor( KCursor::crossCursor() );
+ }
+ else if ( d->rect.contains( e->x(), e->y() ) && d->focus && d->spotVisible )
+ {
+ d->spot.setX(e->x()-d->rect.x());
+ d->spot.setY(e->y()-d->rect.y());
+ }
+ else
+ {
+ unsetCursor();
+ }
+}
+
+void ImageGuideWidget::enterEvent(TQEvent*)
+{
+ if ( !d->focus && d->renderingPreviewMode == PreviewToggleOnMouseOver )
+ {
+ d->onMouseMovePreviewToggled = false;
+ updatePixmap();
+ repaint(false);
+ }
+}
+
+void ImageGuideWidget::leaveEvent(TQEvent*)
+{
+ if ( !d->focus && d->renderingPreviewMode == PreviewToggleOnMouseOver )
+ {
+ d->onMouseMovePreviewToggled = true;
+ updatePixmap();
+ repaint(false);
+ }
+}
+
+} // NameSpace Digikam
diff --git a/src/libs/widgets/imageplugins/imageguidewidget.h b/src/libs/widgets/imageplugins/imageguidewidget.h
new file mode 100644
index 00000000..48d6d246
--- /dev/null
+++ b/src/libs/widgets/imageplugins/imageguidewidget.h
@@ -0,0 +1,132 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-20
+ * Description : a widget to display an image with guides
+ *
+ * Copyright (C) 2004-2008 Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEGUIDEWIDGET_H
+#define IMAGEGUIDEWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqpoint.h>
+#include <tqcolor.h>
+
+// Local includes.
+
+#include "dcolor.h"
+#include "digikam_export.h"
+
+class TQPixmap;
+
+namespace Digikam
+{
+
+class DColor;
+class ImageIface;
+class ImageGuideWidgetPriv;
+
+class DIGIKAM_EXPORT ImageGuideWidget : public TQWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ enum GuideToolMode
+ {
+ HVGuideMode=0,
+ PickColorMode
+ };
+
+ enum RenderingPreviewMode
+ {
+ PreviewOriginalImage=0, // Original image only.
+ PreviewBothImagesHorz, // Horizontal with original and target duplicated.
+ PreviewBothImagesVert, // Vertical with original and target duplicated.
+ PreviewBothImagesHorzCont, // Horizontal with original and target in contiguous.
+ PreviewBothImagesVertCont, // Vertical with original and target in contiguous.
+ PreviewTargetImage, // Target image only.
+ PreviewToggleOnMouseOver, // Original image if mouse is over image area, else target image.
+ NoPreviewMode // Target image only without information displayed.
+ };
+
+ enum ColorPointSrc
+ {
+ OriginalImage=0,
+ PreviewImage,
+ TargetPreviewImage
+ };
+
+public:
+
+ ImageGuideWidget(int w, int h, TQWidget *parent=0,
+ bool spotVisible=true, int guideMode=HVGuideMode,
+ const TQColor& guideColor=TQt::red, int guideSize=1,
+ bool blink=false, bool useImageSelection=false);
+ ~ImageGuideWidget();
+
+ ImageIface* imageIface();
+
+ TQPoint getSpotPosition();
+ DColor getSpotColor(int getColorFrom);
+ void setSpotVisible(bool spotVisible, bool blink=false);
+ int getRenderingPreviewMode();
+ void resetSpotPosition();
+ void updatePreview();
+
+public slots:
+
+ void slotChangeGuideColor(const TQColor &color);
+ void slotChangeGuideSize(int size);
+ void slotChangeRenderingPreviewMode(int mode);
+ void slotToggleUnderExposure(bool);
+ void slotToggleOverExposure(bool);
+
+signals:
+
+ void spotPositionChangedFromOriginal(const Digikam::DColor &color, const TQPoint &position);
+ void spotPositionChangedFromTarget(const Digikam::DColor &color, const TQPoint &position);
+ void signalResized();
+
+protected:
+
+ void paintEvent(TQPaintEvent*);
+ void resizeEvent(TQResizeEvent*);
+ void timerEvent(TQTimerEvent*);
+ void mousePressEvent(TQMouseEvent*);
+ void mouseReleaseEvent(TQMouseEvent*);
+ void mouseMoveEvent(TQMouseEvent*);
+ void enterEvent(TQEvent*);
+ void leaveEvent(TQEvent*);
+
+private:
+
+ void updatePixmap();
+
+private:
+
+ ImageGuideWidgetPriv *d;
+};
+
+} // NameSpace Digikam
+
+#endif /* IMAGEGUIDEWIDGET_H */
diff --git a/src/libs/widgets/imageplugins/imagepanelwidget.cpp b/src/libs/widgets/imageplugins/imagepanelwidget.cpp
new file mode 100644
index 00000000..4551e09e
--- /dev/null
+++ b/src/libs/widgets/imageplugins/imagepanelwidget.cpp
@@ -0,0 +1,335 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-07-01
+ * Description : a widget to draw a control panel image tool.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqframe.h>
+#include <tqvgroupbox.h>
+#include <tqlabel.h>
+#include <tqpixmap.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqtimer.h>
+#include <tqhbuttongroup.h>
+#include <tqpushbutton.h>
+#include <tqlayout.h>
+#include <tqpixmap.h>
+
+// KDE includes.
+
+#include <kdialog.h>
+#include <tdelocale.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+#include <kiconloader.h>
+#include <tdeconfig.h>
+#include <kstandarddirs.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "thumbnailsize.h"
+#include "imageregionwidget.h"
+#include "imagepaniconwidget.h"
+#include "imagepanelwidget.h"
+#include "imagepanelwidget.moc"
+
+namespace Digikam
+{
+
+class ImagePanelWidgetPriv
+{
+public:
+
+ ImagePanelWidgetPriv()
+ {
+ imagePanIconWidget = 0;
+ imageRegionWidget = 0;
+ separateView = 0;
+ }
+
+ TQString settingsSection;
+
+ TQHButtonGroup *separateView;
+
+ ImagePanIconWidget *imagePanIconWidget;
+
+ ImageRegionWidget *imageRegionWidget;
+};
+
+ImagePanelWidget::ImagePanelWidget(uint w, uint h, const TQString& settingsSection,
+ ImagePanIconWidget *pan, TQWidget *parent, int separateViewMode)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ d = new ImagePanelWidgetPriv;
+ d->settingsSection = settingsSection;
+ d->imagePanIconWidget = pan;
+ TQGridLayout *grid = new TQGridLayout(this, 2, 3);
+
+ // -------------------------------------------------------------
+
+ TQFrame *preview = new TQFrame(this);
+ TQVBoxLayout* l1 = new TQVBoxLayout(preview, 5, 0);
+ d->imageRegionWidget = new ImageRegionWidget(w, h, preview, false);
+ d->imageRegionWidget->setFrameStyle(TQFrame::NoFrame);
+ preview->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+ TQWhatsThis::add( d->imageRegionWidget, i18n("<p>Here you can see the original clip image "
+ "which will be used for the preview computation."
+ "<p>Click and drag the mouse cursor in the "
+ "image to change the clip focus."));
+ l1->addWidget(d->imageRegionWidget, 0);
+
+ // -------------------------------------------------------------
+
+ TQString directory;
+ d->separateView = new TQHButtonGroup(this);
+ d->separateView->setExclusive(true);
+ d->separateView->setInsideMargin( 0 );
+ d->separateView->setFrameShape(TQFrame::NoFrame);
+
+ if (separateViewMode == SeparateViewDuplicate ||
+ separateViewMode == SeparateViewAll)
+ {
+ TQPushButton *duplicateHorButton = new TQPushButton( d->separateView );
+ d->separateView->insert(duplicateHorButton, ImageRegionWidget::SeparateViewDuplicateHorz);
+ TDEGlobal::dirs()->addResourceType("duplicatebothhorz", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("duplicatebothhorz", "duplicatebothhorz.png");
+ duplicateHorButton->setPixmap( TQPixmap( directory + "duplicatebothhorz.png" ) );
+ duplicateHorButton->setToggleButton(true);
+ TQWhatsThis::add( duplicateHorButton, i18n("<p>If you enable this option, you will separate the preview area "
+ "horizontally, displaying the original and target image "
+ "at the same time. The target is duplicated from the original "
+ "below the red dashed line." ) );
+
+ TQPushButton *duplicateVerButton = new TQPushButton( d->separateView );
+ d->separateView->insert(duplicateVerButton, ImageRegionWidget::SeparateViewDuplicateVert);
+ TDEGlobal::dirs()->addResourceType("duplicatebothvert", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("duplicatebothvert", "duplicatebothvert.png");
+ duplicateVerButton->setPixmap( TQPixmap( directory + "duplicatebothvert.png" ) );
+ duplicateVerButton->setToggleButton(true);
+ TQWhatsThis::add( duplicateVerButton, i18n("<p>If you enable this option, you will separate the preview area "
+ "vertically, displaying the original and target image "
+ "at the same time. The target is duplicated from the original to "
+ "the right of the red dashed line." ) );
+ }
+
+ if (separateViewMode == SeparateViewNormal ||
+ separateViewMode == SeparateViewAll)
+ {
+ TQPushButton *separateHorButton = new TQPushButton( d->separateView );
+ d->separateView->insert(separateHorButton, ImageRegionWidget::SeparateViewHorizontal);
+ TDEGlobal::dirs()->addResourceType("bothhorz", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("bothhorz", "bothhorz.png");
+ separateHorButton->setPixmap( TQPixmap( directory + "bothhorz.png" ) );
+ separateHorButton->setToggleButton(true);
+ TQWhatsThis::add( separateHorButton, i18n( "<p>If you enable this option, you will separate the preview area "
+ "horizontally, displaying the original and target image "
+ "at the same time. The original is above the "
+ "red dashed line, the target below it." ) );
+
+ TQPushButton *separateVerButton = new TQPushButton( d->separateView );
+ d->separateView->insert(separateVerButton, ImageRegionWidget::SeparateViewVertical);
+ TDEGlobal::dirs()->addResourceType("bothvert", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("bothvert", "bothvert.png");
+ separateVerButton->setPixmap( TQPixmap( directory + "bothvert.png" ) );
+ separateVerButton->setToggleButton(true);
+ TQWhatsThis::add( separateVerButton, i18n( "<p>If you enable this option, you will separate the preview area "
+ "vertically, displaying the original and target image "
+ "at the same time. The original is to the left of the "
+ "red dashed line, the target to the right of it." ) );
+ }
+
+ TQPushButton *noSeparateButton = new TQPushButton( d->separateView );
+ d->separateView->insert(noSeparateButton, ImageRegionWidget::SeparateViewNone);
+ TDEGlobal::dirs()->addResourceType("target", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("target", "target.png");
+ noSeparateButton->setPixmap( TQPixmap( directory + "target.png" ) );
+ noSeparateButton->setToggleButton(true);
+ TQWhatsThis::add( noSeparateButton, i18n( "<p>If you enable this option, the preview area will not "
+ "be separated." ) );
+
+ // -------------------------------------------------------------
+
+ grid->addMultiCellWidget(preview, 0, 1, 0, 3);
+ grid->addMultiCellWidget(d->separateView, 2, 2, 3, 3);
+ grid->setRowStretch(1, 10);
+ grid->setColStretch(1, 10);
+ grid->setMargin(0);
+ grid->setSpacing(KDialog::spacingHint());
+
+ // -------------------------------------------------------------
+
+ TQTimer::singleShot(0, this, TQ_SLOT(slotInitGui()));
+
+ // -------------------------------------------------------------
+
+ connect(d->imageRegionWidget, TQ_SIGNAL(signalContentsMovedEvent(bool)),
+ this, TQ_SLOT(slotOriginalImageRegionChanged(bool)));
+
+ connect(d->imagePanIconWidget, TQ_SIGNAL(signalSelectionMoved(const TQRect&, bool)),
+ this, TQ_SLOT(slotSetImageRegionPosition(const TQRect&, bool)));
+
+ connect(d->imagePanIconWidget, TQ_SIGNAL(signalSelectionTakeFocus()),
+ this, TQ_SLOT(slotPanIconTakeFocus()));
+
+ connect(d->separateView, TQ_SIGNAL(released(int)),
+ d->imagePanIconWidget, TQ_SLOT(slotSeparateViewToggled(int)));
+
+ connect(d->separateView, TQ_SIGNAL(released(int)),
+ d->imageRegionWidget, TQ_SLOT(slotSeparateViewToggled(int)));
+}
+
+ImagePanelWidget::~ImagePanelWidget()
+{
+ writeSettings();
+ delete d;
+}
+
+ImageRegionWidget *ImagePanelWidget::previewWidget() const
+{
+ return d->imageRegionWidget;
+}
+
+void ImagePanelWidget::readSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup(d->settingsSection);
+ int mode = config->readNumEntry("Separate View", ImageRegionWidget::SeparateViewDuplicateVert);
+ mode = TQMAX(ImageRegionWidget::SeparateViewHorizontal, mode);
+ mode = TQMIN(ImageRegionWidget::SeparateViewDuplicateHorz, mode);
+
+ d->imageRegionWidget->blockSignals(true);
+ d->imagePanIconWidget->blockSignals(true);
+ d->separateView->blockSignals(true);
+ d->imageRegionWidget->slotSeparateViewToggled( mode );
+ d->imagePanIconWidget->slotSeparateViewToggled( mode );
+ d->separateView->setButton( mode );
+ d->imageRegionWidget->blockSignals(false);
+ d->imagePanIconWidget->blockSignals(false);
+ d->separateView->blockSignals(false);
+}
+
+void ImagePanelWidget::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup(d->settingsSection);
+ config->writeEntry( "Separate View", d->separateView->selectedId() );
+ config->sync();
+}
+
+void ImagePanelWidget::slotOriginalImageRegionChanged(bool target)
+{
+ d->imagePanIconWidget->slotZoomFactorChanged(d->imageRegionWidget->zoomFactor());
+ TQRect rect = getOriginalImageRegion();
+ d->imagePanIconWidget->setRegionSelection(rect);
+ updateSelectionInfo(rect);
+
+ if (target)
+ {
+ d->imageRegionWidget->backupPixmapRegion();
+ emit signalOriginalClipFocusChanged();
+ }
+}
+
+void ImagePanelWidget::slotZoomSliderChanged(int size)
+{
+ double h = (double)ThumbnailSize::Huge;
+ double s = (double)ThumbnailSize::Small;
+ double zmin = d->imageRegionWidget->zoomMin();
+ double zmax = d->imageRegionWidget->zoomMax();
+ double b = (zmin-(zmax*s/h))/(1-s/h);
+ double a = (zmax-b)/h;
+ double z = a*size+b;
+
+ d->imageRegionWidget->setZoomFactorSnapped(z);
+}
+
+void ImagePanelWidget::resizeEvent(TQResizeEvent *)
+{
+ emit signalResized();
+}
+
+void ImagePanelWidget::slotInitGui()
+{
+ readSettings();
+ setCenterImageRegionPosition();
+ slotOriginalImageRegionChanged(true);
+}
+
+void ImagePanelWidget::setPanIconHighLightPoints(const TQPointArray& pt)
+{
+ d->imageRegionWidget->setHighLightPoints(pt);
+ d->imagePanIconWidget->setHighLightPoints(pt);
+}
+
+void ImagePanelWidget::slotPanIconTakeFocus()
+{
+ d->imageRegionWidget->restorePixmapRegion();
+}
+
+void ImagePanelWidget::setEnable(bool b)
+{
+ d->imageRegionWidget->setEnabled(b);
+ d->separateView->setEnabled(b);
+}
+
+TQRect ImagePanelWidget::getOriginalImageRegion()
+{
+ return ( d->imageRegionWidget->getImageRegion() );
+}
+
+TQRect ImagePanelWidget::getOriginalImageRegionToRender()
+{
+ return ( d->imageRegionWidget->getImageRegionToRender() );
+}
+
+DImg ImagePanelWidget::getOriginalRegionImage()
+{
+ return ( d->imageRegionWidget->getImageRegionImage() );
+}
+
+void ImagePanelWidget::setPreviewImage(DImg img)
+{
+ d->imageRegionWidget->updatePreviewImage(&img);
+ d->imageRegionWidget->repaintContents(false);
+}
+
+void ImagePanelWidget::setCenterImageRegionPosition()
+{
+ d->imageRegionWidget->setCenterContentsPosition();
+}
+
+void ImagePanelWidget::slotSetImageRegionPosition(const TQRect& rect, bool targetDone)
+{
+ d->imageRegionWidget->setContentsPosition(rect.x(), rect.y(), targetDone);
+}
+
+void ImagePanelWidget::updateSelectionInfo(const TQRect& rect)
+{
+ TQToolTip::add( d->imagePanIconWidget,
+ i18n("<nobr>(%1,%2)(%3x%4)</nobr>")
+ .arg(rect.left()).arg(rect.top())
+ .arg(rect.width()).arg(rect.height()));
+}
+
+} // NameSpace Digikam
diff --git a/src/libs/widgets/imageplugins/imagepanelwidget.h b/src/libs/widgets/imageplugins/imagepanelwidget.h
new file mode 100644
index 00000000..32179da9
--- /dev/null
+++ b/src/libs/widgets/imageplugins/imagepanelwidget.h
@@ -0,0 +1,117 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-07-01
+ * Description : a widget to draw a control panel image tool.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPANELWIDGET_H
+#define IMAGEPANELWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqimage.h>
+#include <tqrect.h>
+#include <tqstring.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "digikam_export.h"
+
+class KProgress;
+
+namespace Digikam
+{
+
+class ImagePanelWidgetPriv;
+class ImageRegionWidget;
+class ImagePanIconWidget;
+
+class DIGIKAM_EXPORT ImagePanelWidget : public TQWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ enum SeparateViewOptions
+ {
+ SeparateViewNormal=0,
+ SeparateViewDuplicate,
+ SeparateViewAll
+ };
+
+public:
+
+ ImagePanelWidget(uint w, uint h, const TQString& settingsSection, ImagePanIconWidget *pan,
+ TQWidget *parent=0, int separateViewMode=SeparateViewAll);
+ ~ImagePanelWidget();
+
+ TQRect getOriginalImageRegion();
+ TQRect getOriginalImageRegionToRender();
+ DImg getOriginalRegionImage();
+ void setPreviewImage(DImg img);
+ void setCenterImageRegionPosition();
+
+ void setEnable(bool b);
+
+ void setPanIconHighLightPoints(const TQPointArray& pt);
+
+ void writeSettings();
+
+ ImageRegionWidget *previewWidget() const;
+
+signals:
+
+ void signalOriginalClipFocusChanged();
+ void signalResized();
+
+public slots:
+
+ // Set the top/Left conner clip position.
+ void slotSetImageRegionPosition(const TQRect& rect, bool targetDone);
+
+ // Slot used when the original image clip focus is changed by the user.
+ void slotOriginalImageRegionChanged(bool target);
+
+protected:
+
+ void resizeEvent(TQResizeEvent *e);
+
+private slots:
+
+ void slotPanIconTakeFocus();
+ void slotInitGui();
+ void slotZoomSliderChanged(int);
+
+private:
+
+ void updateSelectionInfo(const TQRect& rect);
+ void readSettings();
+
+private:
+
+ ImagePanelWidgetPriv* d;
+};
+
+} // NameSpace Digikam
+
+#endif /* IMAGEPANNELWIDGET_H */
diff --git a/src/libs/widgets/imageplugins/imagepaniconwidget.cpp b/src/libs/widgets/imageplugins/imagepaniconwidget.cpp
new file mode 100644
index 00000000..38564228
--- /dev/null
+++ b/src/libs/widgets/imageplugins/imagepaniconwidget.cpp
@@ -0,0 +1,198 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-22
+ * Description : a 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>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imageregionwidget.h"
+#include "imagepaniconwidget.h"
+#include "imagepaniconwidget.moc"
+
+namespace Digikam
+{
+
+class ImagePanIconWidgetPriv
+{
+public:
+
+ ImagePanIconWidgetPriv()
+ {
+ iface = 0;
+ data = 0;
+ separateView = ImageRegionWidget::SeparateViewNone;
+ }
+
+ uchar *data;
+
+ int separateView;
+
+ TQPointArray hightlightPoints;
+
+ ImageIface *iface;
+};
+
+ImagePanIconWidget::ImagePanIconWidget(int w, int h, TQWidget *parent, WFlags flags)
+ : PanIconWidget(parent, flags)
+{
+ d = new ImagePanIconWidgetPriv;
+
+ d->iface = new ImageIface(w, h);
+ d->data = d->iface->getPreviewImage();
+ m_width = d->iface->previewWidth();
+ m_height = d->iface->previewHeight();
+ m_orgWidth = d->iface->originalWidth();
+ m_orgHeight = d->iface->originalHeight();
+ m_zoomedOrgWidth = d->iface->originalWidth();
+ m_zoomedOrgHeight = d->iface->originalHeight();
+ m_pixmap = new TQPixmap(w, h);
+
+ 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);
+}
+
+ImagePanIconWidget::~ImagePanIconWidget()
+{
+ delete d->iface;
+ delete [] d->data;
+ delete d;
+}
+
+void ImagePanIconWidget::setHighLightPoints(const TQPointArray& pointsList)
+{
+ d->hightlightPoints = pointsList;
+ updatePixmap();
+ repaint(false);
+}
+
+void ImagePanIconWidget::updatePixmap()
+{
+ // Drawing background and image.
+ m_pixmap->fill(colorGroup().background());
+ d->iface->paint(m_pixmap, m_rect.x(), m_rect.y(), m_rect.width(), m_rect.height());
+
+ TQPainter p(m_pixmap);
+
+ // Drawing HighLighted points.
+
+ if (!d->hightlightPoints.isEmpty())
+ {
+ TQPoint pt;
+
+ for (int i = 0 ; i < d->hightlightPoints.count() ; i++)
+ {
+ pt = d->hightlightPoints.point(i);
+ pt.setX((int)(pt.x() * (float)(m_width) / (float)d->iface->originalWidth()));
+ pt.setY((int)(pt.y() * (float)(m_height) / (float)d->iface->originalHeight()));
+ p.setPen(TQPen(TQt::black, 1, TQt::SolidLine));
+ p.drawLine(pt.x(), pt.y()-1, pt.x(), pt.y()+1);
+ p.drawLine(pt.x()-1, pt.y(), pt.x()+1, pt.y());
+ p.setPen(TQPen(TQt::white, 1, TQt::SolidLine));
+ p.drawPoint(pt.x()-1, pt.y()-1);
+ p.drawPoint(pt.x()+1, pt.y()+1);
+ p.drawPoint(pt.x()-1, pt.y()+1);
+ p.drawPoint(pt.x()+1, pt.y()-1);
+ }
+ }
+
+ // 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());
+
+ if (d->separateView == ImageRegionWidget::SeparateViewVertical)
+ {
+ if (m_flicker) p.setPen(TQPen(TQt::white, 1, TQt::SolidLine));
+ else p.setPen(TQPen(TQt::red, 1, TQt::SolidLine));
+
+ p.drawLine(m_localRegionSelection.topLeft().x() + m_localRegionSelection.width()/2,
+ m_localRegionSelection.topLeft().y(),
+ m_localRegionSelection.bottomLeft().x() + m_localRegionSelection.width()/2,
+ m_localRegionSelection.bottomLeft().y());
+
+ if (m_flicker) p.setPen(TQPen(TQt::red, 1, TQt::DotLine));
+ else p.setPen(TQPen(TQt::white, 1, TQt::DotLine));
+
+ p.drawLine(m_localRegionSelection.topLeft().x() + m_localRegionSelection.width()/2,
+ m_localRegionSelection.topLeft().y() + 1,
+ m_localRegionSelection.bottomLeft().x() + m_localRegionSelection.width()/2,
+ m_localRegionSelection.bottomLeft().y() - 1);
+ }
+ else if (d->separateView == ImageRegionWidget::SeparateViewHorizontal)
+ {
+ if (m_flicker) p.setPen(TQPen(TQt::white, 1, TQt::SolidLine));
+ else p.setPen(TQPen(TQt::red, 1, TQt::SolidLine));
+
+ p.drawLine(m_localRegionSelection.topLeft().x(),
+ m_localRegionSelection.topLeft().y() + m_localRegionSelection.height()/2,
+ m_localRegionSelection.topRight().x(),
+ m_localRegionSelection.topRight().y() + m_localRegionSelection.height()/2);
+
+ if (m_flicker) p.setPen(TQPen(TQt::red, 1, TQt::DotLine));
+ else p.setPen(TQPen(TQt::white, 1, TQt::DotLine));
+
+ p.drawLine(m_localRegionSelection.topLeft().x() + 1,
+ m_localRegionSelection.topLeft().y() + m_localRegionSelection.height()/2,
+ m_localRegionSelection.topRight().x() - 1,
+ m_localRegionSelection.topRight().y() + m_localRegionSelection.height()/2);
+ }
+
+ p.end();
+}
+
+void ImagePanIconWidget::slotSeparateViewToggled(int t)
+{
+ d->separateView = t;
+ updatePixmap();
+ repaint(false);
+}
+
+} // NameSpace Digikam
diff --git a/src/libs/widgets/imageplugins/imagepaniconwidget.h b/src/libs/widgets/imageplugins/imagepaniconwidget.h
new file mode 100644
index 00000000..e7d6ffb7
--- /dev/null
+++ b/src/libs/widgets/imageplugins/imagepaniconwidget.h
@@ -0,0 +1,68 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-22
+ * Description : a 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 IMAGEPANICONWIDGET_H
+#define IMAGEPANICONWIDGET_H
+
+// TQt includes.
+
+#include <tqpointarray.h>
+
+// Local includes.
+
+#include "paniconwidget.h"
+
+namespace Digikam
+{
+
+class ImagePanIconWidgetPriv;
+
+class ImagePanIconWidget : public PanIconWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ ImagePanIconWidget(int width, int height, TQWidget *parent=0, WFlags flags=TQt::WDestructiveClose);
+ ~ImagePanIconWidget();
+
+ void setHighLightPoints(const TQPointArray& pointsList);
+
+public slots:
+
+ void slotSeparateViewToggled(int t);
+
+private:
+
+ void updatePixmap();
+
+private:
+
+ ImagePanIconWidgetPriv *d;
+};
+
+} // NameSpace Digikam
+
+#endif /* IMAGEPANICONWIDGET_H */
diff --git a/src/libs/widgets/imageplugins/imagepannelwidget.cpp b/src/libs/widgets/imageplugins/imagepannelwidget.cpp
new file mode 100644
index 00000000..cebf0f3c
--- /dev/null
+++ b/src/libs/widgets/imageplugins/imagepannelwidget.cpp
@@ -0,0 +1,477 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-07-01
+ * Description : a widget to draw a control pannel image tool.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqframe.h>
+#include <tqvgroupbox.h>
+#include <tqlabel.h>
+#include <tqpixmap.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqtimer.h>
+#include <tqhbuttongroup.h>
+#include <tqpushbutton.h>
+#include <tqlayout.h>
+#include <tqpixmap.h>
+
+// KDE includes.
+
+#include <kdialog.h>
+#include <tdelocale.h>
+#include <kcursor.h>
+#include <kprogress.h>
+#include <tdeapplication.h>
+#include <kiconloader.h>
+#include <tdeconfig.h>
+#include <kstandarddirs.h>
+#include <kseparator.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "sidebar.h"
+#include "statuszoombar.h"
+#include "thumbnailsize.h"
+#include "imageregionwidget.h"
+#include "imagepaniconwidget.h"
+#include "imagepannelwidget.h"
+#include "imagepannelwidget.moc"
+
+namespace Digikam
+{
+
+class ImagePannelWidgetPriv
+{
+public:
+
+ ImagePannelWidgetPriv()
+ {
+ imageRegionWidget = 0;
+ imagePanIconWidget = 0;
+ mainLayout = 0;
+ separateView = 0;
+ progressBar = 0;
+ settingsSideBar = 0;
+ splitter = 0;
+ settingsLayout = 0;
+ settings = 0;
+ previewWidget = 0;
+ zoomBar = 0;
+ }
+
+ TQGridLayout *mainLayout;
+
+ TQHButtonGroup *separateView;
+
+ TQString settingsSection;
+
+ TQWidget *settings;
+ TQWidget *previewWidget;
+
+ TQVBoxLayout *settingsLayout;
+
+ TQSplitter *splitter;
+
+ KProgress *progressBar;
+
+ ImageRegionWidget *imageRegionWidget;
+ ImagePanIconWidget *imagePanIconWidget;
+
+ Sidebar *settingsSideBar;
+
+ StatusZoomBar *zoomBar;
+};
+
+ImagePannelWidget::ImagePannelWidget(uint w, uint h, const TQString& settingsSection,
+ TQWidget *parent, int separateViewMode)
+ : TQHBox(parent, 0, TQt::WDestructiveClose)
+{
+ d = new ImagePannelWidgetPriv;
+ d->settingsSection = settingsSection;
+ d->splitter = new TQSplitter(this);
+ d->previewWidget = new TQWidget(d->splitter);
+ d->mainLayout = new TQGridLayout( d->previewWidget, 2, 3, 0, KDialog::spacingHint());
+
+ d->splitter->setFrameStyle( TQFrame::NoFrame );
+ d->splitter->setFrameShadow( TQFrame::Plain );
+ d->splitter->setFrameShape( TQFrame::NoFrame );
+ d->splitter->setOpaqueResize(false);
+
+ // -------------------------------------------------------------
+
+ TQFrame *preview = new TQFrame(d->previewWidget);
+ TQVBoxLayout* l1 = new TQVBoxLayout(preview, 5, 0);
+ d->imageRegionWidget = new ImageRegionWidget(w, h, preview, false);
+ d->imageRegionWidget->setFrameStyle(TQFrame::NoFrame);
+ preview->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+ TQWhatsThis::add( d->imageRegionWidget, i18n("<p>Here you can see the original clip image "
+ "which will be used for the preview computation."
+ "<p>Click and drag the mouse cursor in the "
+ "image to change the clip focus."));
+ l1->addWidget(d->imageRegionWidget, 0);
+
+ TQSizePolicy rightSzPolicy(TQSizePolicy::Preferred, TQSizePolicy::Expanding, 2, 1);
+ d->previewWidget->setSizePolicy(rightSzPolicy);
+
+ // -------------------------------------------------------------
+
+ d->zoomBar = new StatusZoomBar(d->previewWidget);
+ TQWhatsThis::add( d->zoomBar, i18n("<p>Here set the zoom factor of the preview area.") );
+
+ // -------------------------------------------------------------
+
+ TQString directory;
+ d->separateView = new TQHButtonGroup(d->previewWidget);
+ d->separateView->setExclusive(true);
+ d->separateView->setInsideMargin( 0 );
+ d->separateView->setFrameShape(TQFrame::NoFrame);
+
+ if (separateViewMode == SeparateViewDuplicate ||
+ separateViewMode == SeparateViewAll)
+ {
+ TQPushButton *duplicateHorButton = new TQPushButton( d->separateView );
+ d->separateView->insert(duplicateHorButton, ImageRegionWidget::SeparateViewDuplicateHorz);
+ TDEGlobal::dirs()->addResourceType("duplicatebothhorz", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("duplicatebothhorz", "duplicatebothhorz.png");
+ duplicateHorButton->setPixmap( TQPixmap( directory + "duplicatebothhorz.png" ) );
+ duplicateHorButton->setToggleButton(true);
+ TQWhatsThis::add( duplicateHorButton, i18n("<p>If you enable this option, you will separate the preview area "
+ "horizontally, displaying the original and target image "
+ "at the same time. The target is duplicated from the original "
+ "below the red dashed line." ) );
+
+ TQPushButton *duplicateVerButton = new TQPushButton( d->separateView );
+ d->separateView->insert(duplicateVerButton, ImageRegionWidget::SeparateViewDuplicateVert);
+ TDEGlobal::dirs()->addResourceType("duplicatebothvert", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("duplicatebothvert", "duplicatebothvert.png");
+ duplicateVerButton->setPixmap( TQPixmap( directory + "duplicatebothvert.png" ) );
+ duplicateVerButton->setToggleButton(true);
+ TQWhatsThis::add( duplicateVerButton, i18n("<p>If you enable this option, you will separate the preview area "
+ "vertically, displaying the original and target image "
+ "at the same time. The target is duplicated from the original to "
+ "the right of the red dashed line." ) );
+ }
+
+ if (separateViewMode == SeparateViewNormal ||
+ separateViewMode == SeparateViewAll)
+ {
+ TQPushButton *separateHorButton = new TQPushButton( d->separateView );
+ d->separateView->insert(separateHorButton, ImageRegionWidget::SeparateViewHorizontal);
+ TDEGlobal::dirs()->addResourceType("bothhorz", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("bothhorz", "bothhorz.png");
+ separateHorButton->setPixmap( TQPixmap( directory + "bothhorz.png" ) );
+ separateHorButton->setToggleButton(true);
+ TQWhatsThis::add( separateHorButton, i18n( "<p>If you enable this option, you will separate the preview area "
+ "horizontally, displaying the original and target image "
+ "at the same time. The original is above the "
+ "red dashed line, the target below it." ) );
+
+ TQPushButton *separateVerButton = new TQPushButton( d->separateView );
+ d->separateView->insert(separateVerButton, ImageRegionWidget::SeparateViewVertical);
+ TDEGlobal::dirs()->addResourceType("bothvert", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("bothvert", "bothvert.png");
+ separateVerButton->setPixmap( TQPixmap( directory + "bothvert.png" ) );
+ separateVerButton->setToggleButton(true);
+ TQWhatsThis::add( separateVerButton, i18n( "<p>If you enable this option, you will separate the preview area "
+ "vertically, displaying the original and target image "
+ "at the same time. The original is to the left of the "
+ "red dashed line, the target to the right of it." ) );
+ }
+
+ TQPushButton *noSeparateButton = new TQPushButton( d->separateView );
+ d->separateView->insert(noSeparateButton, ImageRegionWidget::SeparateViewNone);
+ TDEGlobal::dirs()->addResourceType("target", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("target", "target.png");
+ noSeparateButton->setPixmap( TQPixmap( directory + "target.png" ) );
+ noSeparateButton->setToggleButton(true);
+ TQWhatsThis::add( noSeparateButton, i18n( "<p>If you enable this option, the preview area will not "
+ "be separated." ) );
+
+ // -------------------------------------------------------------
+
+ d->progressBar = new KProgress(100, d->previewWidget);
+ TQWhatsThis::add(d->progressBar ,i18n("<p>This is the percentage of the task which has been completed up to this point."));
+ d->progressBar->setProgress(0);
+ d->progressBar->setMaximumHeight( fontMetrics().height() );
+
+ // -------------------------------------------------------------
+
+ d->mainLayout->addMultiCellWidget(preview, 0, 1, 0, 3);
+ d->mainLayout->addMultiCellWidget(d->zoomBar, 2, 2, 0, 0);
+ d->mainLayout->addMultiCellWidget(d->progressBar, 2, 2, 2, 2);
+ d->mainLayout->addMultiCellWidget(d->separateView, 2, 2, 3, 3);
+
+ d->mainLayout->setRowStretch(1, 10);
+ d->mainLayout->setColStretch(1, 10);
+
+ // -------------------------------------------------------------
+
+ TQString sbName(d->settingsSection + TQString(" Image Plugin Sidebar"));
+ d->settingsSideBar = new Sidebar(this, sbName.ascii(), Sidebar::Right);
+ d->settingsSideBar->setSplitter(d->splitter);
+
+ d->settings = new TQWidget(d->settingsSideBar);
+ d->settingsLayout = new TQVBoxLayout(d->settings);
+
+ TQFrame *frame3 = new TQFrame(d->settings);
+ frame3->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+ TQVBoxLayout* l3 = new TQVBoxLayout(frame3, 5, 0);
+ d->imagePanIconWidget = new ImagePanIconWidget(360, 240, frame3);
+ TQWhatsThis::add( d->imagePanIconWidget, i18n("<p>Here you can see the original image panel "
+ "which can help you to select the clip preview."
+ "<p>Click and drag the mouse cursor in the "
+ "red rectangle to change the clip focus."));
+ l3->addWidget(d->imagePanIconWidget, 0, TQt::AlignCenter);
+
+ d->settingsLayout->addWidget(frame3, 0, TQt::AlignHCenter);
+ d->settingsLayout->addSpacing(KDialog::spacingHint());
+
+ d->settingsSideBar->appendTab(d->settings, SmallIcon("configure"), i18n("Settings"));
+ d->settingsSideBar->loadViewState();
+
+ // -------------------------------------------------------------
+
+ setProgressVisible(false);
+ TQTimer::singleShot(0, this, TQ_SLOT(slotInitGui()));
+
+ // -------------------------------------------------------------
+
+ connect(d->imageRegionWidget, TQ_SIGNAL(signalContentsMovedEvent(bool)),
+ this, TQ_SLOT(slotOriginalImageRegionChanged(bool)));
+
+ connect(d->imagePanIconWidget, TQ_SIGNAL(signalSelectionMoved(const TQRect&, bool)),
+ this, TQ_SLOT(slotSetImageRegionPosition(const TQRect&, bool)));
+
+ connect(d->imagePanIconWidget, TQ_SIGNAL(signalSelectionTakeFocus()),
+ this, TQ_SLOT(slotPanIconTakeFocus()));
+
+ connect(d->separateView, TQ_SIGNAL(released(int)),
+ d->imageRegionWidget, TQ_SLOT(slotSeparateViewToggled(int)));
+
+ connect(d->separateView, TQ_SIGNAL(released(int)),
+ d->imagePanIconWidget, TQ_SLOT(slotSeparateViewToggled(int)));
+
+ connect(d->zoomBar, TQ_SIGNAL(signalZoomMinusClicked()),
+ d->imageRegionWidget, TQ_SLOT(slotDecreaseZoom()));
+
+ connect(d->zoomBar, TQ_SIGNAL(signalZoomPlusClicked()),
+ d->imageRegionWidget, TQ_SLOT(slotIncreaseZoom()));
+
+ connect(d->zoomBar, TQ_SIGNAL(signalZoomSliderReleased(int)),
+ this, TQ_SLOT(slotZoomSliderChanged(int)));
+}
+
+ImagePannelWidget::~ImagePannelWidget()
+{
+ writeSettings();
+ delete d->settingsSideBar;
+ delete d;
+}
+
+void ImagePannelWidget::readSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup(d->settingsSection);
+ int mode = config->readNumEntry("Separate View", ImageRegionWidget::SeparateViewDuplicateVert);
+ mode = TQMAX(ImageRegionWidget::SeparateViewHorizontal, mode);
+ mode = TQMIN(ImageRegionWidget::SeparateViewDuplicateHorz, mode);
+
+ d->imageRegionWidget->blockSignals(true);
+ d->imagePanIconWidget->blockSignals(true);
+ d->separateView->blockSignals(true);
+ d->imageRegionWidget->slotSeparateViewToggled( mode );
+ d->imagePanIconWidget->slotSeparateViewToggled( mode );
+ d->separateView->setButton( mode );
+ d->imageRegionWidget->blockSignals(false);
+ d->imagePanIconWidget->blockSignals(false);
+ d->separateView->blockSignals(false);
+}
+
+void ImagePannelWidget::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup(d->settingsSection);
+ config->writeEntry( "Separate View", d->separateView->selectedId() );
+ config->sync();
+}
+
+void ImagePannelWidget::slotOriginalImageRegionChanged(bool target)
+{
+ slotZoomFactorChanged(d->imageRegionWidget->zoomFactor());
+ TQRect rect = getOriginalImageRegion();
+ d->imagePanIconWidget->setRegionSelection(rect);
+ updateSelectionInfo(rect);
+
+ if (target)
+ {
+ d->imageRegionWidget->backupPixmapRegion();
+ emit signalOriginalClipFocusChanged();
+ }
+}
+
+void ImagePannelWidget::slotZoomFactorChanged(double zoom)
+{
+ double h = (double)ThumbnailSize::Huge;
+ double s = (double)ThumbnailSize::Small;
+ double zmin = d->imageRegionWidget->zoomMin();
+ double zmax = d->imageRegionWidget->zoomMax();
+ double b = (zmin-(zmax*s/h))/(1-s/h);
+ double a = (zmax-b)/h;
+ int size = (int)((zoom - b) /a);
+
+ d->zoomBar->setZoomSliderValue(size);
+ d->zoomBar->setZoomTrackerText(i18n("zoom: %1%").arg((int)(zoom*100.0)));
+
+ d->zoomBar->setEnableZoomPlus(true);
+ d->zoomBar->setEnableZoomMinus(true);
+
+ if (d->imageRegionWidget->maxZoom())
+ d->zoomBar->setEnableZoomPlus(false);
+
+ if (d->imageRegionWidget->minZoom())
+ d->zoomBar->setEnableZoomMinus(false);
+
+ d->imagePanIconWidget->slotZoomFactorChanged(zoom);
+}
+
+void ImagePannelWidget::slotZoomSliderChanged(int size)
+{
+ double h = (double)ThumbnailSize::Huge;
+ double s = (double)ThumbnailSize::Small;
+ double zmin = d->imageRegionWidget->zoomMin();
+ double zmax = d->imageRegionWidget->zoomMax();
+ double b = (zmin-(zmax*s/h))/(1-s/h);
+ double a = (zmax-b)/h;
+ double z = a*size+b;
+
+ d->imageRegionWidget->setZoomFactorSnapped(z);
+}
+
+KProgress *ImagePannelWidget::progressBar()
+{
+ return d->progressBar;
+}
+
+void ImagePannelWidget::resizeEvent(TQResizeEvent *)
+{
+ emit signalResized();
+}
+
+void ImagePannelWidget::slotInitGui()
+{
+ readSettings();
+ setCenterImageRegionPosition();
+ slotOriginalImageRegionChanged(true);
+}
+
+void ImagePannelWidget::setPanIconHighLightPoints(const TQPointArray& pt)
+{
+ d->imageRegionWidget->setHighLightPoints(pt);
+ d->imagePanIconWidget->setHighLightPoints(pt);
+}
+
+void ImagePannelWidget::slotPanIconTakeFocus()
+{
+ d->imageRegionWidget->restorePixmapRegion();
+}
+
+void ImagePannelWidget::setUserAreaWidget(TQWidget *w)
+{
+ w->reparent( d->settings, TQPoint(0, 0) );
+ d->settingsLayout->addSpacing(KDialog::spacingHint());
+ d->settingsLayout->addWidget(w);
+ d->settingsLayout->addStretch();
+}
+
+void ImagePannelWidget::setEnable(bool b)
+{
+ d->imageRegionWidget->setEnabled(b);
+ d->imagePanIconWidget->setEnabled(b);
+ d->separateView->setEnabled(b);
+ d->zoomBar->setEnabled(b);
+}
+
+void ImagePannelWidget::setProgress(int val)
+{
+ d->progressBar->setValue(val);
+}
+
+void ImagePannelWidget::setProgressVisible(bool b)
+{
+ if (b) d->progressBar->show();
+ else d->progressBar->hide();
+}
+
+void ImagePannelWidget::setProgressWhatsThis(const TQString& desc)
+{
+ TQWhatsThis::add( d->progressBar, desc);
+}
+
+void ImagePannelWidget::setPreviewImageWaitCursor(bool enable)
+{
+ if ( enable )
+ d->imageRegionWidget->setCursor( KCursor::waitCursor() );
+ else
+ d->imageRegionWidget->unsetCursor();
+}
+
+TQRect ImagePannelWidget::getOriginalImageRegion()
+{
+ return ( d->imageRegionWidget->getImageRegion() );
+}
+
+TQRect ImagePannelWidget::getOriginalImageRegionToRender()
+{
+ return ( d->imageRegionWidget->getImageRegionToRender() );
+}
+
+DImg ImagePannelWidget::getOriginalRegionImage()
+{
+ return ( d->imageRegionWidget->getImageRegionImage() );
+}
+
+void ImagePannelWidget::setPreviewImage(DImg img)
+{
+ d->imageRegionWidget->updatePreviewImage(&img);
+}
+
+void ImagePannelWidget::setCenterImageRegionPosition()
+{
+ d->imageRegionWidget->setCenterContentsPosition();
+}
+
+void ImagePannelWidget::slotSetImageRegionPosition(const TQRect& rect, bool targetDone)
+{
+ d->imageRegionWidget->setContentsPosition(rect.x(), rect.y(), targetDone);
+}
+
+void ImagePannelWidget::updateSelectionInfo(const TQRect& rect)
+{
+ TQToolTip::add( d->imagePanIconWidget,
+ i18n("<nobr>(%1,%2)(%3x%4)</nobr>")
+ .arg(rect.left()).arg(rect.top())
+ .arg(rect.width()).arg(rect.height()));
+}
+
+} // NameSpace Digikam
diff --git a/src/libs/widgets/imageplugins/imagepannelwidget.h b/src/libs/widgets/imageplugins/imagepannelwidget.h
new file mode 100644
index 00000000..a3429887
--- /dev/null
+++ b/src/libs/widgets/imageplugins/imagepannelwidget.h
@@ -0,0 +1,123 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-07-01
+ * Description : a widget to draw a control pannel image tool.
+ *
+ * Copyright (C) 2005-2008 Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPANNELWIDGET_H
+#define IMAGEPANNELWIDGET_H
+
+// TQt includes.
+
+#include <tqhbox.h>
+#include <tqimage.h>
+#include <tqrect.h>
+#include <tqstring.h>
+
+// Local includes
+
+#include "dimg.h"
+#include "digikam_export.h"
+
+class KProgress;
+
+namespace Digikam
+{
+
+class ImagePannelWidgetPriv;
+class ImageRegionWidget;
+
+class DIGIKAM_EXPORT ImagePannelWidget : public TQHBox
+{
+TQ_OBJECT
+
+
+public:
+
+ enum SeparateViewOptions
+ {
+ SeparateViewNormal=0,
+ SeparateViewDuplicate,
+ SeparateViewAll
+ };
+
+public:
+
+ ImagePannelWidget(uint w, uint h, const TQString& settingsSection, TQWidget *parent=0,
+ int separateViewMode=SeparateViewAll);
+ ~ImagePannelWidget();
+
+ TQRect getOriginalImageRegion();
+ TQRect getOriginalImageRegionToRender();
+ DImg getOriginalRegionImage();
+ void setPreviewImage(DImg img);
+ void setPreviewImageWaitCursor(bool enable);
+ void setCenterImageRegionPosition();
+
+ void setEnable(bool b);
+
+ void setProgress(int val);
+ void setProgressVisible(bool b);
+ void setProgressWhatsThis(const TQString& desc);
+
+ void setUserAreaWidget(TQWidget *w);
+
+ void setPanIconHighLightPoints(const TQPointArray& pt);
+
+ KProgress *progressBar();
+
+signals:
+
+ void signalOriginalClipFocusChanged();
+ void signalResized();
+
+public slots:
+
+ // Set the top/Left conner clip position.
+ void slotSetImageRegionPosition(const TQRect& rect, bool targetDone);
+
+ // Slot used when the original image clip focus is changed by the user.
+ void slotOriginalImageRegionChanged(bool target);
+
+protected:
+
+ void resizeEvent(TQResizeEvent *e);
+
+private slots:
+
+ void slotPanIconTakeFocus();
+ void slotInitGui();
+ void slotZoomSliderChanged(int);
+ void slotZoomFactorChanged(double);
+
+private:
+
+ void updateSelectionInfo(const TQRect& rect);
+ void readSettings();
+ void writeSettings();
+
+private:
+
+ ImagePannelWidgetPriv* d;
+};
+
+} // NameSpace Digikam
+
+#endif /* IMAGEPANNELWIDGET_H */
diff --git a/src/libs/widgets/imageplugins/imageregionwidget.cpp b/src/libs/widgets/imageplugins/imageregionwidget.cpp
new file mode 100644
index 00000000..c1392cc2
--- /dev/null
+++ b/src/libs/widgets/imageplugins/imageregionwidget.cpp
@@ -0,0 +1,473 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-17
+ * Description : a widget to draw an image clip region.
+ *
+ * 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 <tqtimer.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqimage.h>
+#include <tqbrush.h>
+#include <tqfont.h>
+#include <tqfontmetrics.h>
+#include <tqpointarray.h>
+
+// KDE includes.
+
+#include <kstandarddirs.h>
+#include <kcursor.h>
+#include <tdeglobal.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imageregionwidget.h"
+#include "imageregionwidget.moc"
+
+namespace Digikam
+{
+
+class ImageRegionWidgetPriv
+{
+
+public:
+
+ ImageRegionWidgetPriv()
+ {
+ iface = 0;
+ separateView = ImageRegionWidget::SeparateViewVertical;
+ }
+
+ int separateView;
+ int xpos;
+ int ypos;
+
+ TQPixmap pixmapRegion; // Pixmap of current region to render.
+
+ TQPointArray hightlightPoints;
+
+ DImg image; // Entire content image to render pixmap.
+
+ ImageIface *iface;
+};
+
+ImageRegionWidget::ImageRegionWidget(int wp, int hp, TQWidget *parent, bool scrollBar)
+ : PreviewWidget(parent)
+{
+ d = new ImageRegionWidgetPriv;
+ d->iface = new ImageIface(0, 0);
+ d->image = d->iface->getOriginalImg()->copy();
+
+ setMinimumSize(wp, hp);
+ setBackgroundColor(colorGroup().background());
+
+ if( !scrollBar )
+ {
+ setVScrollBarMode( TQScrollView::AlwaysOff );
+ setHScrollBarMode( TQScrollView::AlwaysOff );
+ }
+
+ connect(this, TQ_SIGNAL(signalZoomFactorChanged(double)),
+ this, TQ_SLOT(slotZoomFactorChanged()));
+}
+
+ImageRegionWidget::~ImageRegionWidget()
+{
+ if (d->iface) delete d->iface;
+ delete d;
+}
+
+void ImageRegionWidget::resizeEvent(TQResizeEvent* e)
+{
+ if (!e) return;
+
+ TQScrollView::resizeEvent(e);
+
+ // NOTE: We will always adapt the min. zoom factor to the visible size of canvas
+
+ double srcWidth = previewWidth();
+ double srcHeight = previewHeight();
+ double dstWidth = contentsRect().width();
+ double dstHeight = contentsRect().height();
+ double zoom = TQMAX(dstWidth/srcWidth, dstHeight/srcHeight);
+
+ setZoomMin(zoom);
+ setZoomMax(zoom*12.0);
+ setZoomFactor(zoom);
+}
+
+int ImageRegionWidget::previewWidth()
+{
+ return d->image.width();
+}
+
+int ImageRegionWidget::previewHeight()
+{
+ return d->image.height();
+}
+
+bool ImageRegionWidget::previewIsNull()
+{
+ return d->image.isNull();
+}
+
+void ImageRegionWidget::resetPreview()
+{
+ d->image.reset();
+}
+
+void ImageRegionWidget::paintPreview(TQPixmap *pix, int sx, int sy, int sw, int sh)
+{
+ DImg img = d->image.smoothScaleSection(sx, sy, sw, sh, tileSize(), tileSize());
+ TQPixmap pix2 = d->iface->convertToPixmap(img);
+ bitBlt(pix, 0, 0, &pix2, 0, 0);
+}
+
+void ImageRegionWidget::setHighLightPoints(const TQPointArray& pointsList)
+{
+ d->hightlightPoints = pointsList;
+ repaintContents(false);
+}
+
+void ImageRegionWidget::slotZoomFactorChanged()
+{
+ emit signalContentsMovedEvent(true);
+}
+
+void ImageRegionWidget::slotSeparateViewToggled(int mode)
+{
+ d->separateView = mode;
+ updateContentsSize();
+ slotZoomFactorChanged();
+}
+
+TQRect ImageRegionWidget::getImageRegion()
+{
+ TQRect region;
+
+ switch (d->separateView)
+ {
+ case SeparateViewVertical:
+ case SeparateViewHorizontal:
+ case SeparateViewNone:
+ region = TQRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
+ break;
+ case SeparateViewDuplicateVert:
+ region = TQRect(contentsX(), contentsY(), visibleWidth()/2, visibleHeight());
+ break;
+ case SeparateViewDuplicateHorz:
+ region = TQRect(contentsX(), contentsY(), visibleWidth(), visibleHeight()/2);
+ break;
+ }
+
+ return region;
+}
+
+void ImageRegionWidget::viewportPaintExtraData()
+{
+ if (!m_movingInProgress && !d->pixmapRegion.isNull())
+ {
+ TQPainter p(viewport());
+ TQRect region = getLocalTargetImageRegion();
+ TQRect rt(contentsToViewport(region.topLeft()), contentsToViewport(region.bottomRight()));
+
+ region = getLocalImageRegionToRender();
+ TQRect ro(contentsToViewport(region.topLeft()), contentsToViewport(region.bottomRight()));
+
+ bitBlt(viewport(), rt.x(), rt.y(), &d->pixmapRegion, 0, 0, rt.width(), rt.height());
+
+ // Drawing separate view.
+
+ switch (d->separateView)
+ {
+ case SeparateViewVertical:
+ case SeparateViewDuplicateVert:
+ {
+ p.setPen(TQPen(TQt::white, 2, TQt::SolidLine));
+ p.drawLine(rt.topLeft().x(), rt.topLeft().y(),
+ rt.bottomLeft().x(), rt.bottomLeft().y());
+ p.setPen(TQPen(TQt::red, 2, TQt::DotLine));
+ p.drawLine(rt.topLeft().x(), rt.topLeft().y()+1,
+ rt.bottomLeft().x(), rt.bottomLeft().y()-1);
+
+ p.setPen(TQPen(TQt::red, 1)) ;
+ TQFontMetrics fontMt = p.fontMetrics();
+
+ TQString text(i18n("Target"));
+ TQRect textRect;
+ TQRect fontRect = fontMt.boundingRect(0, 0, contentsWidth(), contentsHeight(), 0, text);
+ textRect.setTopLeft(TQPoint(rt.topLeft().x()+20, rt.topLeft().y()+20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+
+ text = i18n("Original");
+ fontRect = fontMt.boundingRect(0, 0, contentsWidth(), contentsHeight(), 0, text);
+
+ if (d->separateView == SeparateViewVertical)
+ ro.moveBy(-ro.width(), 0);
+
+ textRect.setTopLeft(TQPoint(ro.topLeft().x()+20, ro.topLeft().y()+20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2 ) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+ break;
+ }
+ case SeparateViewHorizontal:
+ case SeparateViewDuplicateHorz:
+ {
+ p.setPen(TQPen(TQt::white, 2, TQt::SolidLine));
+ p.drawLine(rt.topLeft().x()+1, rt.topLeft().y(),
+ rt.topRight().x()-1, rt.topRight().y());
+ p.setPen(TQPen(TQt::red, 2, TQt::DotLine));
+ p.drawLine(rt.topLeft().x(), rt.topLeft().y(),
+ rt.topRight().x(), rt.topRight().y());
+
+ p.setPen(TQPen(TQt::red, 1)) ;
+ TQFontMetrics fontMt = p.fontMetrics();
+
+ TQString text(i18n("Target"));
+ TQRect textRect;
+ TQRect fontRect = fontMt.boundingRect(0, 0, contentsWidth(), contentsHeight(), 0, text);
+ textRect.setTopLeft(TQPoint(rt.topLeft().x()+20, rt.topLeft().y()+20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+
+ text = i18n("Original");
+ fontRect = fontMt.boundingRect(0, 0, contentsWidth(), contentsHeight(), 0, text);
+
+ if (d->separateView == SeparateViewHorizontal)
+ ro.moveBy(0, -ro.height());
+
+ textRect.setTopLeft(TQPoint(ro.topLeft().x()+20, ro.topLeft().y()+20));
+ textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2 ) );
+ p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) );
+ p.drawRect(textRect);
+ p.drawText(textRect, TQt::AlignCenter, text);
+ break;
+ }
+ }
+
+ // Drawing HighLighted points.
+
+ if (!d->hightlightPoints.isEmpty())
+ {
+ TQPoint pt;
+ TQRect hpArea;
+
+ for (int i = 0 ; i < d->hightlightPoints.count() ; i++)
+ {
+ pt = d->hightlightPoints.point(i);
+
+ if ( getImageRegionToRender().contains(pt) )
+ {
+ int x = (int)(((double)pt.x() * tileSize()) / floor(tileSize() / zoomFactor()));
+ int y = (int)(((double)pt.y() * tileSize()) / floor(tileSize() / zoomFactor()));
+
+ TQPoint hp(contentsToViewport(TQPoint(x, y)));
+ hpArea.setSize(TQSize((int)(16*zoomFactor()), (int)(16*zoomFactor())));
+ hpArea.moveCenter(hp);
+
+ p.setPen(TQPen(TQt::white, 2, TQt::SolidLine));
+ p.drawLine(hp.x(), hpArea.y(),
+ hp.x(), hp.y()-(int)(3*zoomFactor()));
+ p.drawLine(hp.x(), hp.y()+(int)(3*zoomFactor()),
+ hp.x(), hpArea.bottom());
+ p.drawLine(hpArea.x(), hp.y(),
+ hp.x()-(int)(3*zoomFactor()), hp.y());
+ p.drawLine(hp.x()+(int)(3*zoomFactor()), hp.y(),
+ hpArea.right(), hp.y());
+
+ p.setPen(TQPen(TQt::red, 2, TQt::DotLine));
+ p.drawLine(hp.x(), hpArea.y(),
+ hp.x(), hp.y()-(int)(3*zoomFactor()));
+ p.drawLine(hp.x(), hp.y()+(int)(3*zoomFactor()),
+ hp.x(), hpArea.bottom());
+ p.drawLine(hpArea.x(), hp.y(),
+ hp.x()-(int)(3*zoomFactor()), hp.y());
+ p.drawLine(hp.x()+(int)(3*zoomFactor()), hp.y(),
+ hpArea.right(), hp.y());
+ }
+ }
+ }
+ p.end();
+ }
+}
+
+void ImageRegionWidget::setCenterContentsPosition()
+{
+ center(contentsWidth()/2, contentsHeight()/2);
+ slotZoomFactorChanged();
+}
+
+void ImageRegionWidget::setContentsPosition(int x, int y, bool targetDone)
+{
+ if( targetDone )
+ m_movingInProgress = false;
+
+ setContentsPos(x, y);
+
+ if( targetDone )
+ slotZoomFactorChanged();
+}
+
+void ImageRegionWidget::backupPixmapRegion()
+{
+ d->pixmapRegion = TQPixmap();
+}
+
+void ImageRegionWidget::restorePixmapRegion()
+{
+ m_movingInProgress = true;
+ viewport()->repaint(false);
+}
+
+void ImageRegionWidget::updatePreviewImage(DImg *img)
+{
+ DImg image = img->copy();
+ TQRect r = getLocalImageRegionToRender();
+ image.resize(r.width(), r.height());
+
+ // Because image plugins are tool witch only work on image data, the DImg container
+ // do not contain metadata from original image. About Color Managed View, we need to
+ // restore the embedded ICC color profile.
+ image.setICCProfil(d->image.getICCProfil());
+ d->pixmapRegion = d->iface->convertToPixmap(image);
+}
+
+DImg ImageRegionWidget::getImageRegionImage()
+{
+ return (d->image.copy(getImageRegionToRender()));
+}
+
+TQRect ImageRegionWidget::getImageRegionToRender()
+{
+ TQRect r = getLocalImageRegionToRender();
+
+ int x = (int)(((double)r.x() / tileSize()) * floor(tileSize() / zoomFactor()));
+ int y = (int)(((double)r.y() / tileSize()) * floor(tileSize() / zoomFactor()));
+ int w = (int)(((double)r.width() / tileSize()) * floor(tileSize() / zoomFactor()));
+ int h = (int)(((double)r.height() / tileSize()) * floor(tileSize() / zoomFactor()));
+
+ TQRect rect(x, y, w, h);
+ return (rect);
+}
+
+TQRect ImageRegionWidget::getLocalImageRegionToRender()
+{
+ TQRect region;
+
+ if (d->separateView == SeparateViewVertical)
+ {
+ region = TQRect((int)ceilf(contentsX()+visibleWidth()/2.0), contentsY(),
+ (int)ceilf(visibleWidth()/2.0), visibleHeight());
+ }
+ else if (d->separateView == SeparateViewHorizontal)
+ {
+ region = TQRect(contentsX(), (int)ceilf(contentsY()+visibleHeight()/2.0),
+ visibleWidth(), (int)ceilf(visibleHeight()/2.0));
+ }
+ else if (d->separateView == SeparateViewDuplicateVert)
+ {
+ region = TQRect(contentsX(), contentsY(),
+ (int)ceilf(visibleWidth()/2.0), visibleHeight());
+ }
+ else if (d->separateView == SeparateViewDuplicateHorz)
+ {
+ region = TQRect(contentsX(), contentsY(),
+ visibleWidth(), (int)ceilf(visibleHeight()/2.0));
+ }
+ else
+ {
+ region = TQRect(contentsX(), contentsY(),
+ visibleWidth(), visibleHeight());
+ }
+
+ return (region);
+}
+
+TQRect ImageRegionWidget::getLocalTargetImageRegion()
+{
+ TQRect region = getLocalImageRegionToRender();
+
+ if (d->separateView == SeparateViewDuplicateVert)
+ region.moveBy(region.width(), 0);
+ else if (d->separateView == SeparateViewDuplicateHorz)
+ region.moveBy(0, region.height());
+
+ return region;
+}
+
+void ImageRegionWidget::setContentsSize()
+{
+ switch (d->separateView)
+ {
+ case SeparateViewVertical:
+ case SeparateViewHorizontal:
+ case SeparateViewNone:
+ {
+ PreviewWidget::setContentsSize();
+ break;
+ }
+ case SeparateViewDuplicateVert:
+ {
+ resizeContents(zoomWidth()+visibleWidth()/2, zoomHeight());
+ break;
+ }
+ case SeparateViewDuplicateHorz:
+ {
+ resizeContents(zoomWidth(), zoomHeight()+visibleHeight()/2);
+ break;
+ }
+ default:
+ DWarning() << "Unknown separation view specified" << endl;
+ }
+}
+
+void ImageRegionWidget::contentsWheelEvent(TQWheelEvent *e)
+{
+ e->accept();
+
+ if (e->state() & TQt::ControlButton)
+ {
+ if (e->delta() < 0 && !maxZoom())
+ slotIncreaseZoom();
+ else if (e->delta() > 0 && !minZoom())
+ slotDecreaseZoom();
+ return;
+ }
+}
+
+} // NameSpace Digikam
diff --git a/src/libs/widgets/imageplugins/imageregionwidget.h b/src/libs/widgets/imageplugins/imageregionwidget.h
new file mode 100644
index 00000000..8555703d
--- /dev/null
+++ b/src/libs/widgets/imageplugins/imageregionwidget.h
@@ -0,0 +1,115 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-17
+ * Description : a widget to draw an image clip region.
+ *
+ * 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 IMAGEREGIONWIDGET_H
+#define IMAGEREGIONWIDGET_H
+
+// TQt includes.
+
+#include <tqrect.h>
+
+// Local includes.
+
+#include "previewwidget.h"
+#include "dimg.h"
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class ImageRegionWidgetPriv;
+
+class DIGIKAM_EXPORT ImageRegionWidget : public PreviewWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ enum SeparateViewMode
+ {
+ SeparateViewHorizontal=0,
+ SeparateViewVertical,
+ SeparateViewNone,
+ SeparateViewDuplicateVert,
+ SeparateViewDuplicateHorz
+ };
+
+public:
+
+ ImageRegionWidget(int wp, int hp, TQWidget *parent=0, bool scrollBar=true);
+ ~ImageRegionWidget();
+
+ void setContentsPosition(int x, int y, bool targetDone);
+ void setCenterContentsPosition();
+
+ /** To get image region including original or/and target area depending of separate view mode.
+ The region is given using not scaled image unit.*/
+ TQRect getImageRegion();
+
+ /** To get target image region area to render */
+ TQRect getImageRegionToRender();
+
+ /** To get target image region image to use for render operations */
+ DImg getImageRegionImage();
+
+ void updatePreviewImage(DImg *img);
+
+ void backupPixmapRegion();
+ void restorePixmapRegion();
+
+ void setHighLightPoints(const TQPointArray& pointsList);
+ void drawSeparateView();
+
+public slots:
+
+ void slotSeparateViewToggled(int mode);
+
+private slots:
+
+ void slotZoomFactorChanged();
+
+private:
+
+ void updatePixmap(DImg& img);
+ TQRect getLocalTargetImageRegion();
+ TQRect getLocalImageRegionToRender();
+ void viewportPaintExtraData();
+ int previewWidth();
+ int previewHeight();
+ bool previewIsNull();
+ void resetPreview();
+ void setContentsSize();
+ void resizeEvent(TQResizeEvent *);
+ void contentsWheelEvent(TQWheelEvent *);
+
+ inline void paintPreview(TQPixmap *pix, int sx, int sy, int sw, int sh);
+
+private:
+
+ ImageRegionWidgetPriv* d;
+};
+
+} // NameSpace Digikam
+
+#endif /* IMAGEREGIONWIDGET_H */
diff --git a/src/libs/widgets/imageplugins/imagewidget.cpp b/src/libs/widgets/imageplugins/imagewidget.cpp
new file mode 100644
index 00000000..ab73bbf7
--- /dev/null
+++ b/src/libs/widgets/imageplugins/imagewidget.cpp
@@ -0,0 +1,347 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-01
+ * Description : a widget to display an image preview with some
+ * modes to compare effect results.
+ *
+ * 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 <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqhbuttongroup.h>
+#include <tqpushbutton.h>
+
+// KDE includes.
+
+#include <ksqueezedtextlabel.h>
+#include <kdialog.h>
+#include <tdeapplication.h>
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <tdeconfig.h>
+#include <kstandarddirs.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imagewidget.h"
+#include "imagewidget.moc"
+
+namespace Digikam
+{
+
+class ImageWidgetPriv
+{
+public:
+
+ ImageWidgetPriv()
+ {
+ spotInfoLabel = 0;
+ previewButtons = 0;
+ underExposureButton = 0;
+ overExposureButton = 0;
+ previewWidget = 0;
+ }
+
+ TQString settingsSection;
+
+ TQHButtonGroup *previewButtons;
+
+ TQPushButton *underExposureButton;
+ TQPushButton *overExposureButton;
+
+ KSqueezedTextLabel *spotInfoLabel;
+
+ ImageGuideWidget *previewWidget;
+};
+
+ImageWidget::ImageWidget(const TQString& settingsSection, TQWidget *parent,
+ const TQString& previewWhatsThis, bool prevModeOptions,
+ int guideMode, bool guideVisible, bool useImageSelection)
+ : TQWidget(parent)
+{
+ d = new ImageWidgetPriv;
+ d->settingsSection = settingsSection;
+
+ // -------------------------------------------------------------
+
+ TQGridLayout* grid = new TQGridLayout(this, 2, 3);
+
+ d->spotInfoLabel = new KSqueezedTextLabel(this);
+ d->spotInfoLabel->setAlignment(TQt::AlignRight);
+
+ // -------------------------------------------------------------
+
+ d->previewButtons = new TQHButtonGroup(this);
+ d->previewButtons->setExclusive(true);
+ d->previewButtons->setInsideMargin(0);
+ d->previewButtons->setFrameShape(TQFrame::NoFrame);
+
+ TQPushButton *previewOriginalButton = new TQPushButton( d->previewButtons );
+ d->previewButtons->insert(previewOriginalButton, ImageGuideWidget::PreviewOriginalImage);
+ TDEGlobal::dirs()->addResourceType("original", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("original", "original.png");
+ previewOriginalButton->setPixmap( TQPixmap( directory + "original.png" ) );
+ previewOriginalButton->setToggleButton(true);
+ TQWhatsThis::add( previewOriginalButton, i18n( "<p>If you enable this option, you will see "
+ "the original image." ) );
+
+ TQPushButton *previewBothButtonVert = new TQPushButton( d->previewButtons );
+ d->previewButtons->insert(previewBothButtonVert, ImageGuideWidget::PreviewBothImagesVertCont);
+ TDEGlobal::dirs()->addResourceType("bothvert", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("bothvert", "bothvert.png");
+ previewBothButtonVert->setPixmap( TQPixmap( directory + "bothvert.png" ) );
+ previewBothButtonVert->setToggleButton(true);
+ TQWhatsThis::add( previewBothButtonVert, i18n( "<p>If you enable this option, the preview area will "
+ "split vertically. "
+ "A contiguous area of the image will be shown, "
+ "with one half from the original image, "
+ "the other half from the target image.") );
+
+ TQPushButton *previewBothButtonHorz = new TQPushButton( d->previewButtons );
+ d->previewButtons->insert(previewBothButtonHorz, ImageGuideWidget::PreviewBothImagesHorzCont);
+ TDEGlobal::dirs()->addResourceType("bothhorz", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("bothhorz", "bothhorz.png");
+ previewBothButtonHorz->setPixmap( TQPixmap( directory + "bothhorz.png" ) );
+ previewBothButtonHorz->setToggleButton(true);
+ TQWhatsThis::add( previewBothButtonHorz, i18n( "<p>If you enable this option, the preview area will "
+ "split horizontally. "
+ "A contiguous area of the image will be shown, "
+ "with one half from the original image, "
+ "the other half from the target image.") );
+
+ TQPushButton *previewDuplicateBothButtonVert = new TQPushButton( d->previewButtons );
+ d->previewButtons->insert(previewDuplicateBothButtonVert, ImageGuideWidget::PreviewBothImagesVert);
+ TDEGlobal::dirs()->addResourceType("duplicatebothvert", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("duplicatebothvert", "duplicatebothvert.png");
+ previewDuplicateBothButtonVert->setPixmap( TQPixmap( directory + "duplicatebothvert.png" ) );
+ previewDuplicateBothButtonVert->setToggleButton(true);
+ TQWhatsThis::add( previewDuplicateBothButtonVert, i18n( "<p>If you enable this option, the preview area will "
+ "split vertically. "
+ "The same part of the original and the target image "
+ "will be shown side by side.") );
+
+ TQPushButton *previewDupplicateBothButtonHorz = new TQPushButton( d->previewButtons );
+ d->previewButtons->insert(previewDupplicateBothButtonHorz, ImageGuideWidget::PreviewBothImagesHorz);
+ TDEGlobal::dirs()->addResourceType("duplicatebothhorz", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("duplicatebothhorz", "duplicatebothhorz.png");
+ previewDupplicateBothButtonHorz->setPixmap( TQPixmap( directory + "duplicatebothhorz.png" ) );
+ previewDupplicateBothButtonHorz->setToggleButton(true);
+ TQWhatsThis::add( previewDupplicateBothButtonHorz, i18n( "<p>If you enable this option, the preview area will "
+ "split horizontally. "
+ "The same part of the original and the target image "
+ "will be shown side by side.") );
+
+ TQPushButton *previewtargetButton = new TQPushButton( d->previewButtons );
+ d->previewButtons->insert(previewtargetButton, ImageGuideWidget::PreviewTargetImage);
+ TDEGlobal::dirs()->addResourceType("target", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("target", "target.png");
+ previewtargetButton->setPixmap( TQPixmap( directory + "target.png" ) );
+ previewtargetButton->setToggleButton(true);
+ TQWhatsThis::add( previewtargetButton, i18n( "<p>If you enable this option, you will see "
+ "the target image." ) );
+
+ TQPushButton *previewToggleMouseOverButton = new TQPushButton( d->previewButtons );
+ d->previewButtons->insert(previewToggleMouseOverButton, ImageGuideWidget::PreviewToggleOnMouseOver);
+ TDEGlobal::dirs()->addResourceType("togglemouseover", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("togglemouseover", "togglemouseover.png");
+ previewToggleMouseOverButton->setPixmap( TQPixmap( directory + "togglemouseover.png" ) );
+ previewToggleMouseOverButton->setToggleButton(true);
+ TQWhatsThis::add( previewToggleMouseOverButton, i18n( "<p>If you enable this option, you will see "
+ "the original image when the mouse is over image area, "
+ "else the target image." ) );
+
+ // -------------------------------------------------------------
+
+ TQHButtonGroup *exposureButtons = new TQHButtonGroup(this);
+ exposureButtons->setInsideMargin(0);
+ exposureButtons->setFrameShape(TQFrame::NoFrame);
+
+ d->underExposureButton = new TQPushButton(exposureButtons);
+ exposureButtons->insert(d->underExposureButton, UnderExposure);
+ d->underExposureButton->setPixmap(SmallIcon("underexposure"));
+ d->underExposureButton->setToggleButton(true);
+ TQWhatsThis::add(d->underExposureButton, i18n("<p>Set this option to display black "
+ "overlaid on the preview. This will help you to avoid "
+ "under-exposing the image." ) );
+
+ d->overExposureButton = new TQPushButton(exposureButtons);
+ exposureButtons->insert(d->overExposureButton, OverExposure);
+ d->overExposureButton->setPixmap(SmallIcon("overexposure"));
+ d->overExposureButton->setToggleButton(true);
+ TQWhatsThis::add(d->overExposureButton, i18n("<p>Set this option on display white "
+ "overlaid on the preview. This will help you to avoid "
+ "over-exposing the image." ) );
+
+ // -------------------------------------------------------------
+
+ TQFrame *frame = new TQFrame(this);
+ frame->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+ TQVBoxLayout* l = new TQVBoxLayout(frame, 5, 0);
+ d->previewWidget = new ImageGuideWidget(480, 320, frame, guideVisible,
+ guideMode, TQt::red, 1, false,
+ useImageSelection);
+ TQWhatsThis::add( d->previewWidget, previewWhatsThis);
+ l->addWidget(d->previewWidget, 0);
+
+ // -------------------------------------------------------------
+
+ grid->addMultiCellWidget(d->previewButtons, 1, 1, 0, 0);
+ grid->addMultiCellWidget(d->spotInfoLabel, 1, 1, 1, 1);
+ grid->addMultiCellWidget(exposureButtons, 1, 1, 2, 2);
+ grid->addMultiCellWidget(frame, 3, 3, 0, 2);
+ grid->setColSpacing(1, KDialog::spacingHint());
+ grid->setRowSpacing(0, KDialog::spacingHint());
+ grid->setRowSpacing(2, KDialog::spacingHint());
+ grid->setRowStretch(3, 10);
+ grid->setColStretch(1, 10);
+
+ // -------------------------------------------------------------
+
+ connect(d->previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SIGNAL(signalResized()));
+
+ connect(d->previewWidget, TQ_SIGNAL(spotPositionChangedFromOriginal( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SIGNAL(spotPositionChangedFromOriginal( const Digikam::DColor &, const TQPoint & )));
+
+ connect(d->previewWidget, TQ_SIGNAL(spotPositionChangedFromOriginal( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotUpdateSpotInfo( const Digikam::DColor &, const TQPoint & )));
+
+ connect(d->previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )));
+
+ connect(d->previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotUpdateSpotInfo( const Digikam::DColor &, const TQPoint & )));
+
+ connect(d->previewButtons, TQ_SIGNAL(released(int)),
+ d->previewWidget, TQ_SLOT(slotChangeRenderingPreviewMode(int)));
+
+ connect(d->underExposureButton, TQ_SIGNAL(toggled(bool)),
+ d->previewWidget, TQ_SLOT(slotToggleUnderExposure(bool)));
+
+ connect(d->overExposureButton, TQ_SIGNAL(toggled(bool)),
+ d->previewWidget, TQ_SLOT(slotToggleOverExposure(bool)));
+
+ // -------------------------------------------------------------
+
+ if (prevModeOptions)
+ readSettings();
+ else
+ {
+ setRenderingPreviewMode(ImageGuideWidget::NoPreviewMode);
+ d->spotInfoLabel->hide();
+ d->previewButtons->hide();
+ exposureButtons->hide();
+ }
+}
+
+ImageWidget::~ImageWidget()
+{
+ writeSettings();
+ delete d;
+}
+
+ImageIface* ImageWidget::imageIface()
+{
+ return d->previewWidget->imageIface();
+}
+
+void ImageWidget::updatePreview()
+{
+ d->previewWidget->updatePreview();
+}
+
+void ImageWidget::slotChangeGuideColor(const TQColor &color)
+{
+ d->previewWidget->slotChangeGuideColor(color);
+}
+
+void ImageWidget::slotChangeGuideSize(int size)
+{
+ d->previewWidget->slotChangeGuideSize(size);
+}
+
+void ImageWidget::resetSpotPosition()
+{
+ d->previewWidget->resetSpotPosition();
+}
+
+TQPoint ImageWidget::getSpotPosition()
+{
+ return ( d->previewWidget->getSpotPosition() );
+}
+
+DColor ImageWidget::getSpotColor(int getColorFrom)
+{
+ return ( d->previewWidget->getSpotColor(getColorFrom) );
+}
+
+void ImageWidget::setSpotVisible(bool spotVisible, bool blink)
+{
+ d->previewWidget->setSpotVisible(spotVisible, blink);
+}
+
+int ImageWidget::getRenderingPreviewMode()
+{
+ return ( d->previewWidget->getRenderingPreviewMode() );
+}
+
+void ImageWidget::setRenderingPreviewMode(int mode)
+{
+ d->previewButtons->setButton(mode);
+ d->previewWidget->slotChangeRenderingPreviewMode(mode);
+}
+
+void ImageWidget::slotUpdateSpotInfo(const Digikam::DColor &col, const TQPoint &point)
+{
+ DColor color = col;
+ d->spotInfoLabel->setText(i18n("(%1,%2) RGBA:%3,%4,%5,%6")
+ .arg(point.x()).arg(point.y())
+ .arg(color.red()).arg(color.green())
+ .arg(color.blue()).arg(color.alpha()) );
+}
+
+void ImageWidget::readSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup(d->settingsSection);
+
+ d->underExposureButton->setOn(config->readBoolEntry("Under Exposure Indicator", false));
+ d->overExposureButton->setOn(config->readBoolEntry("Over Exposure Indicator", false));
+
+ int mode = config->readNumEntry("Separate View", ImageGuideWidget::PreviewBothImagesVertCont);
+ mode = TQMAX(ImageGuideWidget::PreviewOriginalImage, mode);
+ mode = TQMIN(ImageGuideWidget::NoPreviewMode, mode);
+ setRenderingPreviewMode(mode);
+}
+
+void ImageWidget::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup(d->settingsSection);
+ config->writeEntry("Separate View", getRenderingPreviewMode());
+ config->writeEntry("Under Exposure Indicator", d->underExposureButton->isOn());
+ config->writeEntry("Over Exposure Indicator", d->overExposureButton->isOn());
+ config->sync();
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/imageplugins/imagewidget.h b/src/libs/widgets/imageplugins/imagewidget.h
new file mode 100644
index 00000000..ebdf92e9
--- /dev/null
+++ b/src/libs/widgets/imageplugins/imagewidget.h
@@ -0,0 +1,106 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-01
+ * Description : a widget to display an image preview with some
+ * modes to compare effect results.
+ *
+ * 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 IMAGEWIDGET_H
+#define IMAGEWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqpoint.h>
+#include <tqcolor.h>
+#include <tqstring.h>
+
+// Local includes.
+
+#include "dcolor.h"
+#include "imageguidewidget.h"
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class ImageIface;
+class ImageWidgetPriv;
+
+class DIGIKAM_EXPORT ImageWidget : public TQWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ enum ExposureIndicator
+ {
+ UnderExposure=0,
+ OverExposure
+ };
+
+public:
+
+ ImageWidget(const TQString& settingsSection, TQWidget *parent=0,
+ const TQString& previewWhatsThis=TQString(), bool prevModeOptions=true,
+ int guideMode=ImageGuideWidget::PickColorMode,
+ bool guideVisible=true, bool useImageSelection=false);
+ ~ImageWidget();
+
+ ImageIface* imageIface();
+
+ TQPoint getSpotPosition();
+ DColor getSpotColor(int getColorFrom);
+ void setSpotVisible(bool spotVisible, bool blink=false);
+ int getRenderingPreviewMode();
+ void resetSpotPosition();
+ void updatePreview();
+ void writeSettings();
+
+ void setRenderingPreviewMode(int mode);
+
+public slots:
+
+ void slotChangeGuideColor(const TQColor &color);
+ void slotChangeGuideSize(int size);
+
+signals:
+
+ void spotPositionChangedFromOriginal( const Digikam::DColor &color, const TQPoint &position );
+ void spotPositionChangedFromTarget( const Digikam::DColor &color, const TQPoint &position );
+ void signalResized();
+
+private slots:
+
+ void slotUpdateSpotInfo(const Digikam::DColor &col, const TQPoint &point);
+
+private:
+
+ void readSettings();
+
+private:
+
+ ImageWidgetPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* IMAGEWIDGET_H */
diff --git a/src/libs/widgets/imageplugins/listboxpreviewitem.cpp b/src/libs/widgets/imageplugins/listboxpreviewitem.cpp
new file mode 100644
index 00000000..8ba63a61
--- /dev/null
+++ b/src/libs/widgets/imageplugins/listboxpreviewitem.cpp
@@ -0,0 +1,62 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-10-05
+ * Description : a TQListBoxItem which can display an image preview
+ * as a thumbnail and a customized qwhatsthis class
+ * for listbox items
+ *
+ * Copyright (C) 2006-2007 by Guillaume Laurent <[email protected]>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Local includes.
+
+#include "listboxpreviewitem.h"
+
+namespace Digikam
+{
+
+int ListBoxPreviewItem::height(const TQListBox *lb) const
+{
+ int height = TQListBoxPixmap::height(lb);
+ return TQMAX(height, pixmap()->height() + 5);
+}
+
+int ListBoxPreviewItem::width(const TQListBox *lb) const
+{
+ int width = TQListBoxPixmap::width(lb);
+ return TQMAX(width, pixmap()->width() + 5);
+}
+
+// -------------------------------------------------------------------
+
+TQString ListBoxWhatsThis::text(const TQPoint &p)
+{
+ TQListBoxItem* item = m_listBox->itemAt(p);
+
+ if (item != 0)
+ return m_itemWhatsThisMap[item];
+
+ return TQString();
+}
+
+void ListBoxWhatsThis::add(TQListBoxItem* item, const TQString& text)
+{
+ m_itemWhatsThisMap[item] = text;
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/imageplugins/listboxpreviewitem.h b/src/libs/widgets/imageplugins/listboxpreviewitem.h
new file mode 100644
index 00000000..50b769c6
--- /dev/null
+++ b/src/libs/widgets/imageplugins/listboxpreviewitem.h
@@ -0,0 +1,80 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-10-05
+ * Description : a TQListBoxItem which can display an image preview
+ * as a thumbnail and a customized qwhatsthis class
+ * for listbox items
+ *
+ * Copyright (C) 2006-2007 by Guillaume Laurent <[email protected]>
+ *
+ * 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 LISTBOXPREVIEWITEM_H
+#define LISTBOXPREVIEWITEM_H
+
+// TQt includes.
+
+#include <tqmap.h>
+#include <tqlistbox.h>
+#include <tqwhatsthis.h>
+#include <tqpixmap.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT ListBoxPreviewItem : public TQListBoxPixmap
+{
+
+public:
+
+ ListBoxPreviewItem(TQListBox *listbox, const TQPixmap &pix, const TQString &text)
+ : TQListBoxPixmap(listbox, pix, text) {};
+
+ ListBoxPreviewItem(const TQPixmap &pix, const TQString &text)
+ : TQListBoxPixmap(pix, text) {};
+
+ virtual int height ( const TQListBox * lb ) const;
+ virtual int width ( const TQListBox * lb ) const;
+};
+
+/**
+ * A qwhatthis class which can be pointed to a specific item
+ * in a TQListBox rather than the TQListBox itself
+ *
+ */
+class DIGIKAM_EXPORT ListBoxWhatsThis : public TQWhatsThis
+{
+
+public:
+
+ ListBoxWhatsThis(TQListBox* w) : TQWhatsThis(w), m_listBox(w) {}
+ virtual TQString text (const TQPoint &);
+ void add(TQListBoxItem*, const TQString& text);
+
+protected:
+
+ TQMap<TQListBoxItem*, TQString> m_itemWhatsThisMap;
+ TQListBox *m_listBox;
+};
+
+} // namespace Digikam
+
+#endif // LISTBOXPREVIEWITEM_H
diff --git a/src/libs/widgets/metadata/Makefile.am b/src/libs/widgets/metadata/Makefile.am
new file mode 100644
index 00000000..4fe62356
--- /dev/null
+++ b/src/libs/widgets/metadata/Makefile.am
@@ -0,0 +1,17 @@
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libmetadatawidgets.la
+
+libmetadatawidgets_la_SOURCES = metadatalistview.cpp metadatalistviewitem.cpp metadatawidget.cpp \
+ iptcwidget.cpp exifwidget.cpp mdkeylistviewitem.cpp \
+ makernotewidget.cpp gpswidget.cpp worldmapwidget.cpp
+
+libmetadatawidgets_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor
+
+INCLUDES = -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/themeengine \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKEXIV2_CFLAGS) $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
diff --git a/src/libs/widgets/metadata/exifwidget.cpp b/src/libs/widgets/metadata/exifwidget.cpp
new file mode 100644
index 00000000..7761c250
--- /dev/null
+++ b/src/libs/widgets/metadata/exifwidget.cpp
@@ -0,0 +1,185 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-20
+ * Description : a widget to display Standard Exif metadata
+ *
+ * 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 <tqmap.h>
+#include <tqfile.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dmetadata.h"
+#include "metadatalistview.h"
+#include "exifwidget.h"
+#include "exifwidget.moc"
+
+namespace Digikam
+{
+
+static const char* ExifHumanList[] =
+{
+ "Make",
+ "Model",
+ "DateTime",
+ "ImageDescription",
+ "Copyright",
+ "ShutterSpeedValue",
+ "ApertureValue",
+ "ExposureProgram",
+ "ExposureMode",
+ "ExposureBiasValue",
+ "ExposureTime",
+ "WhiteBalance",
+ "ISOSpeedRatings",
+ "FocalLength",
+ "SubjectDistance",
+ "MeteringMode",
+ "Contrast",
+ "Saturation",
+ "Sharpness",
+ "LightSource",
+ "Flash",
+ "FNumber",
+ "-1"
+};
+
+// Standard Exif Entry list from to less important to the most important for photograph.
+// This will not including GPS information because they are displayed on another tab.
+static const char* StandardExifEntryList[] =
+{
+ "Iop",
+ "Thumbnail",
+ "SubImage1",
+ "SubImage2",
+ "Image",
+ "Photo",
+ "-1"
+};
+
+ExifWidget::ExifWidget(TQWidget* parent, const char* name)
+ : MetadataWidget(parent, name)
+{
+ view()->setSortColumn(-1);
+
+ for (int i=0 ; TQString(StandardExifEntryList[i]) != TQString("-1") ; i++)
+ m_keysFilter << StandardExifEntryList[i];
+
+ for (int i=0 ; TQString(ExifHumanList[i]) != TQString("-1") ; i++)
+ m_tagsfilter << ExifHumanList[i];
+}
+
+ExifWidget::~ExifWidget()
+{
+}
+
+TQString ExifWidget::getMetadataTitle()
+{
+ return i18n("Standard EXIF Tags");
+}
+
+bool ExifWidget::loadFromURL(const KURL& url)
+{
+ setFileName(url.path());
+
+ if (url.isEmpty())
+ {
+ setMetadata();
+ return false;
+ }
+ else
+ {
+ DMetadata metadata(url.path());
+ TQByteArray exifData = metadata.getExif();
+
+ if (exifData.isEmpty())
+ {
+ setMetadata();
+ return false;
+ }
+ else
+ setMetadata(exifData);
+ }
+
+ return true;
+}
+
+bool ExifWidget::decodeMetadata()
+{
+ DMetadata metaData;
+ if (!metaData.setExif(getMetadata()))
+ return false;
+
+ // Update all metadata contents.
+ setMetadataMap(metaData.getExifTagsDataList(m_keysFilter));
+ return true;
+}
+
+void ExifWidget::buildView()
+{
+ if (getMode() == SIMPLE)
+ {
+ setIfdList(getMetadataMap(), m_keysFilter, m_tagsfilter);
+ }
+ else
+ {
+ setIfdList(getMetadataMap(), m_keysFilter, TQStringList());
+ }
+
+ MetadataWidget::buildView();
+}
+
+TQString ExifWidget::getTagTitle(const TQString& key)
+{
+ DMetadata meta;
+ TQString title = meta.getExifTagTitle(key.ascii());
+
+ if (title.isEmpty())
+ return key.section('.', -1);
+
+ return title;
+}
+
+TQString ExifWidget::getTagDescription(const TQString& key)
+{
+ DMetadata meta;
+ TQString desc = meta.getExifTagDescription(key.ascii());
+
+ if (desc.isEmpty())
+ return i18n("No description available");
+
+ return desc;
+}
+
+void ExifWidget::slotSaveMetadataToFile()
+{
+ KURL url = saveMetadataToFile(i18n("EXIF File to Save"),
+ TQString("*.exif|"+i18n("EXIF binary Files (*.exif)")));
+ storeMetadataToFile(url);
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/metadata/exifwidget.h b/src/libs/widgets/metadata/exifwidget.h
new file mode 100644
index 00000000..ba66d085
--- /dev/null
+++ b/src/libs/widgets/metadata/exifwidget.h
@@ -0,0 +1,73 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-20
+ * Description : a widget to display Standard Exif metadata
+ *
+ * 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 EXIFWIDGET_H
+#define EXIFWIDGET_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// Local includes.
+
+#include "metadatawidget.h"
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT ExifWidget : public MetadataWidget
+{
+ TQ_OBJECT
+
+
+public:
+
+ ExifWidget(TQWidget* parent, const char* name=0);
+ ~ExifWidget();
+
+ bool loadFromURL(const KURL& url);
+
+ TQString getTagDescription(const TQString& key);
+ TQString getTagTitle(const TQString& key);
+
+ TQString getMetadataTitle();
+
+protected slots:
+
+ virtual void slotSaveMetadataToFile();
+
+private:
+
+ bool decodeMetadata();
+ void buildView();
+
+private:
+
+ TQStringList m_tagsfilter;
+ TQStringList m_keysFilter;
+};
+
+} // namespace Digikam
+
+#endif /* EXIFWIDGET_H */
diff --git a/src/libs/widgets/metadata/gpswidget.cpp b/src/libs/widgets/metadata/gpswidget.cpp
new file mode 100644
index 00000000..033423e9
--- /dev/null
+++ b/src/libs/widgets/metadata/gpswidget.cpp
@@ -0,0 +1,340 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-22
+ * Description : a tab widget to display GPS info
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+/*
+Any good explainations about GPS (in French) can be found at this url :
+http://www.gpspassion.com/forumsen/topic.asp?TOPIC_ID=16593
+*/
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqmap.h>
+#include <tqhbox.h>
+#include <tqfile.h>
+#include <tqcombobox.h>
+#include <tqgroupbox.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+#include <tdelocale.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dmetadata.h"
+#include "metadatalistview.h"
+#include "worldmapwidget.h"
+#include "gpswidget.h"
+#include "gpswidget.moc"
+
+namespace Digikam
+{
+
+static const char* ExifGPSHumanList[] =
+{
+ "GPSLatitude",
+ "GPSLongitude",
+ "GPSAltitude",
+ "-1"
+};
+
+// Standard Exif Entry list from to less important to the most important for photograph.
+static const char* StandardExifGPSEntryList[] =
+{
+ "GPSInfo",
+ "-1"
+};
+
+class GPSWidgetPriv
+{
+
+public:
+
+ GPSWidgetPriv()
+ {
+ detailsButton = 0;
+ detailsCombo = 0;
+ map = 0;
+ }
+
+ TQStringList tagsfilter;
+ TQStringList keysFilter;
+
+ TQPushButton *detailsButton;
+
+ TQComboBox *detailsCombo;
+
+ WorldMapWidget *map;
+};
+
+GPSWidget::GPSWidget(TQWidget* parent, const char* name)
+ : MetadataWidget(parent, name)
+{
+ d = new GPSWidgetPriv;
+
+ for (int i=0 ; TQString(StandardExifGPSEntryList[i]) != TQString("-1") ; i++)
+ d->keysFilter << StandardExifGPSEntryList[i];
+
+ for (int i=0 ; TQString(ExifGPSHumanList[i]) != TQString("-1") ; i++)
+ d->tagsfilter << ExifGPSHumanList[i];
+
+ // --------------------------------------------------------
+
+ TQWidget *gpsInfo = new TQWidget(this);
+ TQGridLayout *layout = new TQGridLayout(gpsInfo, 3, 2);
+ d->map = new WorldMapWidget(256, 256, gpsInfo);
+
+ // --------------------------------------------------------
+
+ TQGroupBox* box2 = new TQGroupBox( 0, TQt::Vertical, gpsInfo );
+ box2->setInsideMargin(0);
+ box2->setInsideSpacing(0);
+ box2->setFrameStyle( TQFrame::NoFrame );
+ TQGridLayout* box2Layout = new TQGridLayout( box2->layout(), 0, 2, KDialog::spacingHint() );
+
+ d->detailsCombo = new TQComboBox( false, box2 );
+ d->detailsButton = new TQPushButton(i18n("More Info..."), box2);
+ d->detailsCombo->insertItem(TQString("MapQuest"), MapQuest);
+ d->detailsCombo->insertItem(TQString("Google Maps"), GoogleMaps);
+ d->detailsCombo->insertItem(TQString("MSN Maps"), MsnMaps);
+ d->detailsCombo->insertItem(TQString("MultiMap"), MultiMap);
+
+ box2Layout->addMultiCellWidget( d->detailsCombo, 0, 0, 0, 0 );
+ box2Layout->addMultiCellWidget( d->detailsButton, 0, 0, 1, 1 );
+ box2Layout->setColStretch(2, 10);
+
+ // --------------------------------------------------------
+
+ layout->addMultiCellWidget(d->map, 0, 0, 0, 2);
+ layout->addMultiCell(new TQSpacerItem(KDialog::spacingHint(), KDialog::spacingHint(),
+ TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding), 1, 1, 0, 2);
+ layout->addMultiCellWidget(box2, 2, 2, 0, 0);
+ layout->setColStretch(2, 10);
+ layout->setRowStretch(3, 10);
+
+ // --------------------------------------------------------
+
+ connect(d->detailsButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotGPSDetails()));
+
+ setUserAreaWidget(gpsInfo);
+ decodeMetadata();
+}
+
+GPSWidget::~GPSWidget()
+{
+ delete d;
+}
+
+int GPSWidget::getWebGPSLocator()
+{
+ return ( d->detailsCombo->currentItem() );
+}
+
+void GPSWidget::setWebGPSLocator(int locator)
+{
+ d->detailsCombo->setCurrentItem(locator);
+}
+
+void GPSWidget::slotGPSDetails()
+{
+ TQString val, url;
+
+ switch( getWebGPSLocator() )
+ {
+ case MapQuest:
+ {
+ url.append("http://www.mapquest.com/maps/map.adp?searchtype=address"
+ "&formtype=address&latlongtype=decimal");
+ url.append("&latitude=");
+ url.append(val.setNum(d->map->getLatitude(), 'g', 12));
+ url.append("&longitude=");
+ url.append(val.setNum(d->map->getLongitude(), 'g', 12));
+ break;
+ }
+
+ case GoogleMaps:
+ {
+ url.append("http://maps.google.com/?q=");
+ url.append(val.setNum(d->map->getLatitude(), 'g', 12));
+ url.append(",");
+ url.append(val.setNum(d->map->getLongitude(), 'g', 12));
+ url.append("&spn=0.05,0.05&t=h&om=1&hl=en");
+ break;
+ }
+
+ case MsnMaps:
+ {
+ url.append("http://maps.msn.com/map.aspx?");
+ url.append("&lats1=");
+ url.append(val.setNum(d->map->getLatitude(), 'g', 12));
+ url.append("&lons1=");
+ url.append(val.setNum(d->map->getLongitude(), 'g', 12));
+ url.append("&name=HERE");
+ url.append("&alts1=7");
+ break;
+ }
+
+ case MultiMap:
+ {
+ url.append("http://www.multimap.com/map/browse.cgi?");
+ url.append("lat=");
+ url.append(val.setNum(d->map->getLatitude(), 'g', 12));
+ url.append("&lon=");
+ url.append(val.setNum(d->map->getLongitude(), 'g', 12));
+ url.append("&scale=10000");
+ url.append("&icon=x");
+ break;
+ }
+ }
+
+ TDEApplication::kApplication()->invokeBrowser(url);
+}
+
+TQString GPSWidget::getMetadataTitle()
+{
+ return i18n("Global Positioning System Information");
+}
+
+bool GPSWidget::loadFromURL(const KURL& url)
+{
+ setFileName(url.path());
+
+ if (url.isEmpty())
+ {
+ setMetadata();
+ return false;
+ }
+ else
+ {
+ DMetadata metadata(url.path());
+ TQByteArray exifData = metadata.getExif();
+
+ if (exifData.isEmpty())
+ {
+ setMetadata();
+ return false;
+ }
+ else
+ setMetadata(exifData);
+ }
+
+ return true;
+}
+
+bool GPSWidget::decodeMetadata()
+{
+ DMetadata metaData;
+ if (!metaData.setExif(getMetadata()))
+ {
+ setMetadataEmpty();
+ return false;
+ }
+
+ // Update all metadata contents.
+ setMetadataMap(metaData.getExifTagsDataList(d->keysFilter));
+
+ bool ret = decodeGPSPosition();
+ if (!ret)
+ {
+ setMetadataEmpty();
+ return false;
+ }
+
+ d->map->setEnabled(true);
+ d->detailsButton->setEnabled(true);
+ d->detailsCombo->setEnabled(true);
+ return true;
+}
+
+void GPSWidget::setMetadataEmpty()
+{
+ MetadataWidget::setMetadataEmpty();
+ d->map->setEnabled(false);
+ d->detailsButton->setEnabled(false);
+ d->detailsCombo->setEnabled(false);
+}
+
+void GPSWidget::buildView()
+{
+ if (getMode() == SIMPLE)
+ {
+ setIfdList(getMetadataMap(), d->keysFilter, d->tagsfilter);
+ }
+ else
+ {
+ setIfdList(getMetadataMap(), d->keysFilter, TQStringList());
+ }
+
+ MetadataWidget::buildView();
+}
+
+TQString GPSWidget::getTagTitle(const TQString& key)
+{
+ DMetadata meta;
+ TQString title = meta.getExifTagTitle(key.ascii());
+
+ if (title.isEmpty())
+ return key.section('.', -1);
+
+ return title;
+}
+
+TQString GPSWidget::getTagDescription(const TQString& key)
+{
+ DMetadata meta;
+ TQString desc = meta.getExifTagDescription(key.ascii());
+
+ if (desc.isEmpty())
+ return i18n("No description available");
+
+ return desc;
+}
+
+bool GPSWidget::decodeGPSPosition()
+{
+ double latitude=0.0, longitude=0.0, altitude=0.0;
+
+ DMetadata meta;
+ meta.setExif(getMetadata());
+
+ if (meta.getGPSInfo(altitude, latitude, longitude))
+ d->map->setGPSPosition(latitude, longitude);
+ else
+ return false;
+
+ return true;
+}
+
+void GPSWidget::slotSaveMetadataToFile()
+{
+ KURL url = saveMetadataToFile(i18n("EXIF File to Save"),
+ TQString("*.exif|"+i18n("EXIF binary Files (*.exif)")));
+ storeMetadataToFile(url);
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/metadata/gpswidget.h b/src/libs/widgets/metadata/gpswidget.h
new file mode 100644
index 00000000..fd787d67
--- /dev/null
+++ b/src/libs/widgets/metadata/gpswidget.h
@@ -0,0 +1,95 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-22
+ * Description : a tab widget to display GPS info
+ *
+ * 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 GPSWIDGET_H
+#define GPSWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqstring.h>
+
+// Local includes.
+
+#include "metadatawidget.h"
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class GPSWidgetPriv;
+class WorldMapWidget;
+
+class DIGIKAM_EXPORT GPSWidget : public MetadataWidget
+{
+ TQ_OBJECT
+
+
+public:
+
+ enum WebGPSLocator
+ {
+ MapQuest = 0,
+ GoogleMaps,
+ MsnMaps,
+ MultiMap
+ };
+
+public:
+
+ GPSWidget(TQWidget* parent, const char* name=0);
+ ~GPSWidget();
+
+ bool loadFromURL(const KURL& url);
+
+ TQString getTagDescription(const TQString& key);
+ TQString getTagTitle(const TQString& key);
+
+ TQString getMetadataTitle();
+
+ int getWebGPSLocator();
+ void setWebGPSLocator(int locator);
+
+protected slots:
+
+ virtual void slotSaveMetadataToFile();
+
+private slots:
+
+ void slotGPSDetails();
+
+private:
+
+ bool decodeMetadata();
+ void buildView();
+ bool decodeGPSPosition();
+ virtual void setMetadataEmpty();
+
+private:
+
+ GPSWidgetPriv *d;
+};
+
+} // namespace Digikam
+
+#endif /* GPSWIDGET_H */
diff --git a/src/libs/widgets/metadata/iptcwidget.cpp b/src/libs/widgets/metadata/iptcwidget.cpp
new file mode 100644
index 00000000..b0bcb009
--- /dev/null
+++ b/src/libs/widgets/metadata/iptcwidget.cpp
@@ -0,0 +1,167 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-20
+ * Description : A widget to display IPTC metadata
+ *
+ * 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 <tqmap.h>
+#include <tqfile.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dmetadata.h"
+#include "iptcwidget.h"
+#include "iptcwidget.moc"
+
+namespace Digikam
+{
+
+static const char* IptcHumanList[] =
+{
+ "Caption",
+ "City",
+ "Contact",
+ "Copyright",
+ "Credit",
+ "DateCreated",
+ "Headline",
+ "Keywords",
+ "ProvinceState",
+ "Source",
+ "Urgency",
+ "Writer",
+ "-1"
+};
+
+static const char* StandardIptcEntryList[] =
+{
+ "Envelope",
+ "Application2",
+ "-1"
+};
+
+IptcWidget::IptcWidget(TQWidget* parent, const char* name)
+ : MetadataWidget(parent, name)
+{
+ for (int i=0 ; TQString(StandardIptcEntryList[i]) != TQString("-1") ; i++)
+ m_keysFilter << StandardIptcEntryList[i];
+
+ for (int i=0 ; TQString(IptcHumanList[i]) != TQString("-1") ; i++)
+ m_tagsfilter << IptcHumanList[i];
+}
+
+IptcWidget::~IptcWidget()
+{
+}
+
+TQString IptcWidget::getMetadataTitle()
+{
+ return i18n("IPTC Records");
+}
+
+bool IptcWidget::loadFromURL(const KURL& url)
+{
+ setFileName(url.filename());
+
+ if (url.isEmpty())
+ {
+ setMetadata();
+ return false;
+ }
+ else
+ {
+ DMetadata metadata(url.path());
+ TQByteArray iptcData = metadata.getIptc();
+
+ if (iptcData.isEmpty())
+ {
+ setMetadata();
+ return false;
+ }
+ else
+ setMetadata(iptcData);
+ }
+
+ return true;
+}
+
+bool IptcWidget::decodeMetadata()
+{
+ DMetadata metaData;
+ if (!metaData.setIptc(getMetadata()))
+ return false;
+
+ // Update all metadata contents.
+ setMetadataMap(metaData.getIptcTagsDataList(m_keysFilter));
+ return true;
+}
+
+void IptcWidget::buildView()
+{
+ if (getMode() == SIMPLE)
+ {
+ setIfdList(getMetadataMap(), m_tagsfilter);
+ }
+ else
+ {
+ setIfdList(getMetadataMap());
+ }
+
+ MetadataWidget::buildView();
+}
+
+TQString IptcWidget::getTagTitle(const TQString& key)
+{
+ DMetadata meta;
+ TQString title = meta.getIptcTagTitle(key.ascii());
+
+ if (title.isEmpty())
+ return key.section('.', -1);
+
+ return title;
+}
+
+TQString IptcWidget::getTagDescription(const TQString& key)
+{
+ DMetadata meta;
+ TQString desc = meta.getIptcTagDescription(key.ascii());
+
+ if (desc.isEmpty())
+ return i18n("No description available");
+
+ return desc;
+}
+
+void IptcWidget::slotSaveMetadataToFile()
+{
+ KURL url = saveMetadataToFile(i18n("IPTC File to Save"),
+ TQString("*.iptc|"+i18n("IPTC binary Files (*.iptc)")));
+ storeMetadataToFile(url);
+}
+
+} // namespace Digikam
+
diff --git a/src/libs/widgets/metadata/iptcwidget.h b/src/libs/widgets/metadata/iptcwidget.h
new file mode 100644
index 00000000..58f1449e
--- /dev/null
+++ b/src/libs/widgets/metadata/iptcwidget.h
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-20
+ * Description : A widget to display IPTC metadata
+ *
+ * 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 IPTCWIDGET_H
+#define IPTCWIDGET_H
+
+// Local includes.
+
+#include "metadatawidget.h"
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT IptcWidget : public MetadataWidget
+{
+ TQ_OBJECT
+
+
+public:
+
+ IptcWidget(TQWidget* parent, const char* name=0);
+ ~IptcWidget();
+
+ bool loadFromURL(const KURL& url);
+
+ TQString getTagDescription(const TQString& key);
+ TQString getTagTitle(const TQString& key);
+
+ TQString getMetadataTitle();
+
+protected slots:
+
+ virtual void slotSaveMetadataToFile();
+
+private:
+
+ bool decodeMetadata();
+ void buildView();
+
+private:
+
+ TQStringList m_tagsfilter;
+ TQStringList m_keysFilter;
+};
+
+} // namespace Digikam
+
+#endif /* IPTCWIDGET_H */
diff --git a/src/libs/widgets/metadata/makernotewidget.cpp b/src/libs/widgets/metadata/makernotewidget.cpp
new file mode 100644
index 00000000..ddd1fe3c
--- /dev/null
+++ b/src/libs/widgets/metadata/makernotewidget.cpp
@@ -0,0 +1,210 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-20
+ * Description : a widget to display non standard Exif metadata
+ * used by camera makers
+ *
+ * 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 <tqmap.h>
+#include <tqfile.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dmetadata.h"
+#include "makernotewidget.h"
+#include "makernotewidget.moc"
+
+namespace Digikam
+{
+
+// This list mix differents tags name used by camera makers.
+static const char* MakerNoteHumanList[] =
+{
+ "AFFocusPos",
+ "AFMode",
+ "AFPoint",
+ "AutofocusMode",
+ "ColorMode",
+ "ColorTemperature",
+ "Contrast",
+ "DigitalZoom",
+ "ExposureMode",
+ "ExposureProgram",
+ "ExposureCompensation",
+ "ExposureManualBias",
+ "Flash",
+ "FlashBias",
+ "FlashMode",
+ "FlashType",
+ "FlashDevice",
+ "FNumber",
+ "Focus"
+ "FocusDistance",
+ "FocusMode",
+ "FocusSetting",
+ "FocusType",
+ "Hue",
+ "HueAdjustment",
+ "ImageStabilizer",
+ "ImageStabilization",
+ "InternalFlash",
+ "ISOSelection",
+ "ISOSpeed",
+ "Lens",
+ "LensType",
+ "LensRange",
+ "Macro",
+ "MacroFocus",
+ "MeteringMode",
+ "NoiseReduction",
+ "OwnerName",
+ "Quality",
+ "Tone",
+ "ToneComp",
+ "Saturation",
+ "Sharpness",
+ "ShootingMode",
+ "ShutterSpeedValue",
+ "SpotMode",
+ "SubjectDistance",
+ "WhiteBalance",
+ "WhiteBalanceBias",
+ "-1"
+};
+
+static const char* ExifEntryListToIgnore[] =
+{
+ "GPSInfo",
+ "Iop",
+ "Thumbnail",
+ "SubImage1",
+ "SubImage2",
+ "Image",
+ "Photo",
+ "-1"
+};
+
+MakerNoteWidget::MakerNoteWidget(TQWidget* parent, const char* name)
+ : MetadataWidget(parent, name)
+{
+ for (int i=0 ; TQString(ExifEntryListToIgnore[i]) != TQString("-1") ; i++)
+ m_keysFilter << ExifEntryListToIgnore[i];
+
+ for (int i=0 ; TQString(MakerNoteHumanList[i]) != TQString("-1") ; i++)
+ m_tagsfilter << MakerNoteHumanList[i];
+}
+
+MakerNoteWidget::~MakerNoteWidget()
+{
+}
+
+TQString MakerNoteWidget::getMetadataTitle()
+{
+ return i18n("MakerNote EXIF Tags");
+}
+
+bool MakerNoteWidget::loadFromURL(const KURL& url)
+{
+ setFileName(url.path());
+
+ if (url.isEmpty())
+ {
+ setMetadata();
+ return false;
+ }
+ else
+ {
+ DMetadata metadata(url.path());
+ TQByteArray exifData = metadata.getExif();
+
+ if (exifData.isEmpty())
+ {
+ setMetadata();
+ return false;
+ }
+ else
+ setMetadata(exifData);
+ }
+
+ return true;
+}
+
+bool MakerNoteWidget::decodeMetadata()
+{
+ DMetadata metaData;
+ if (!metaData.setExif(getMetadata()))
+ return false;
+
+ // Update all metadata contents.
+ setMetadataMap(metaData.getExifTagsDataList(m_keysFilter, true));
+ return true;
+}
+
+void MakerNoteWidget::buildView()
+{
+ if (getMode() == SIMPLE)
+ {
+ setIfdList(getMetadataMap(), m_tagsfilter);
+ }
+ else
+ {
+ setIfdList(getMetadataMap());
+ }
+
+ MetadataWidget::buildView();
+}
+
+TQString MakerNoteWidget::getTagTitle(const TQString& key)
+{
+ DMetadata meta;
+ TQString title = meta.getExifTagTitle(key.ascii());
+
+ if (title.isEmpty())
+ return key.section('.', -1);
+
+ return title;
+}
+
+TQString MakerNoteWidget::getTagDescription(const TQString& key)
+{
+ DMetadata meta;
+ TQString desc = meta.getExifTagDescription(key.ascii());
+
+ if (desc.isEmpty())
+ return i18n("No description available");
+
+ return desc;
+}
+
+void MakerNoteWidget::slotSaveMetadataToFile()
+{
+ KURL url = saveMetadataToFile(i18n("EXIF File to Save"),
+ TQString("*.exif|"+i18n("EXIF binary Files (*.exif)")));
+ storeMetadataToFile(url);
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/metadata/makernotewidget.h b/src/libs/widgets/metadata/makernotewidget.h
new file mode 100644
index 00000000..f6549591
--- /dev/null
+++ b/src/libs/widgets/metadata/makernotewidget.h
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-20
+ * Description : a widget to display non standard Exif metadata
+ * used by camera makers
+ *
+ * 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 MARKERNOTEWIDGET_H
+#define MARKERNOTEWIDGET_H
+
+// Local includes.
+
+#include "metadatawidget.h"
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT MakerNoteWidget : public MetadataWidget
+{
+ TQ_OBJECT
+
+
+public:
+
+ MakerNoteWidget(TQWidget* parent, const char* name=0);
+ ~MakerNoteWidget();
+
+ bool loadFromURL(const KURL& url);
+
+ TQString getTagDescription(const TQString& key);
+ TQString getTagTitle(const TQString& key);
+
+ TQString getMetadataTitle();
+
+protected slots:
+
+ virtual void slotSaveMetadataToFile();
+
+private:
+
+ bool decodeMetadata();
+ void buildView();
+
+private:
+
+ TQStringList m_tagsfilter;
+ TQStringList m_keysFilter;
+};
+
+} // namespace Digikam
+
+#endif /* MARKERNOTEWIDGET_H */
diff --git a/src/libs/widgets/metadata/mdkeylistviewitem.cpp b/src/libs/widgets/metadata/mdkeylistviewitem.cpp
new file mode 100644
index 00000000..27963eaf
--- /dev/null
+++ b/src/libs/widgets/metadata/mdkeylistviewitem.cpp
@@ -0,0 +1,94 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-21
+ * Description : a generic list view item widget to
+ * display metadata key like a title
+ *
+ * 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 <tqpalette.h>
+#include <tqfont.h>
+#include <tqpainter.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "themeengine.h"
+#include "ddebug.h"
+#include "mdkeylistviewitem.h"
+
+namespace Digikam
+{
+
+MdKeyListViewItem::MdKeyListViewItem(TQListView *parent, const TQString& key)
+ : TQListViewItem(parent)
+{
+ m_decryptedKey = key;
+
+ // Standard Exif key descriptions.
+ if (key == "Iop") m_decryptedKey = i18n("Interoperability");
+ else if (key == "Image") m_decryptedKey = i18n("Image Information");
+ else if (key == "Photo") m_decryptedKey = i18n("Photograph Information");
+ else if (key == "GPSInfo") m_decryptedKey = i18n("Global Positioning System");
+ else if (key == "Thumbnail") m_decryptedKey = i18n("Embedded Thumbnail");
+
+ // Standard IPTC key descriptions.
+ else if (key == "Envelope") m_decryptedKey = i18n("IIM Envelope");
+ else if (key == "Application2") m_decryptedKey = i18n("IIM Application 2");
+
+ setOpen(true);
+ setSelected(false);
+ setSelectable(false);
+}
+
+MdKeyListViewItem::~MdKeyListViewItem()
+{
+}
+
+TQString MdKeyListViewItem::getMdKey()
+{
+ return m_decryptedKey;
+}
+
+void MdKeyListViewItem::paintCell(TQPainter* p, const TQColorGroup&,
+ int column, int, int)
+{
+ p->save();
+ TQFont fn(p->font());
+ fn.setBold(true);
+ fn.setItalic(false);
+ p->setFont(fn);
+ p->setPen(ThemeEngine::instance()->textSelColor());
+ int width = listView()->contentsWidth();
+ TQRect rect(0, 0, width, fn.weight());
+
+ if (column == 1)
+ rect.moveLeft(-width/2);
+
+ p->fillRect(rect, ThemeEngine::instance()->thumbSelColor());
+ p->drawText(rect, TQt::AlignHCenter, m_decryptedKey);
+ p->restore();
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/metadata/mdkeylistviewitem.h b/src/libs/widgets/metadata/mdkeylistviewitem.h
new file mode 100644
index 00000000..aeaf7e4c
--- /dev/null
+++ b/src/libs/widgets/metadata/mdkeylistviewitem.h
@@ -0,0 +1,63 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-21
+ * Description : a generic list view item widget to
+ * display metadata key like a title
+ *
+ * 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 MDKEYLISTVIEWITEM_H
+#define MDKEYLISTVIEWITEM_H
+
+// TQt includes.
+
+#include <tqstring.h>
+#include <tqlistview.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+class TQPainter;
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT MdKeyListViewItem : public TQListViewItem
+{
+
+public:
+
+ MdKeyListViewItem(TQListView *parent, const TQString& key);
+ ~MdKeyListViewItem();
+
+ TQString getMdKey();
+
+protected:
+
+ void paintCell(TQPainter*, const TQColorGroup &, int, int, int);
+
+private:
+
+ TQString m_decryptedKey;
+};
+
+} // namespace Digikam
+
+#endif /* MDKEYLISTVIEWITEM_H */
diff --git a/src/libs/widgets/metadata/metadatalistview.cpp b/src/libs/widgets/metadata/metadatalistview.cpp
new file mode 100644
index 00000000..612eed1e
--- /dev/null
+++ b/src/libs/widgets/metadata/metadatalistview.cpp
@@ -0,0 +1,283 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-21
+ * Description : a generic list view widget to
+ * display metadata
+ *
+ * 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 <tqtimer.h>
+#include <tqptrlist.h>
+#include <tqpalette.h>
+#include <tqheader.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "mdkeylistviewitem.h"
+#include "metadatalistviewitem.h"
+#include "metadatalistview.h"
+#include "metadatalistview.moc"
+
+namespace Digikam
+{
+
+MetadataListView::MetadataListView(TQWidget* parent)
+ : TQListView(parent)
+{
+ header()->hide();
+ addColumn("Name"); // No need i18n here.
+ addColumn("Value"); // No need i18n here.
+ setItemMargin(0);
+ setAllColumnsShowFocus(true);
+ setResizeMode(TQListView::AllColumns);
+ // Vertical scroll bar is always disable to give more
+ // free space to metadata content
+ setVScrollBarMode(TQScrollView::AlwaysOff);
+
+ m_parent = dynamic_cast<MetadataWidget *>(parent);
+
+ connect(this, TQ_SIGNAL(selectionChanged(TQListViewItem*)),
+ this, TQ_SLOT(slotSelectionChanged(TQListViewItem*)));
+}
+
+MetadataListView::~MetadataListView()
+{
+}
+
+TQString MetadataListView::getCurrentItemKey()
+{
+ if (currentItem())
+ {
+ if (currentItem()->isSelectable())
+ {
+ MetadataListViewItem *item = static_cast<MetadataListViewItem *>(currentItem());
+ return item->getKey();
+ }
+ }
+
+ return TQString();
+}
+
+void MetadataListView::setCurrentItemByKey(TQString itemKey)
+{
+ if (itemKey.isNull())
+ return;
+
+ TQListViewItemIterator it(this);
+ while ( it.current() )
+ {
+ if ( it.current()->isSelectable() )
+ {
+ MetadataListViewItem *item = dynamic_cast<MetadataListViewItem *>(it.current());
+
+ if (item->getKey() == itemKey)
+ {
+ setSelected(item, true);
+ ensureItemVisible(item);
+ m_selectedItemKey = itemKey;
+ return;
+ }
+ }
+
+ ++it;
+ }
+}
+
+void MetadataListView::slotSelectionChanged(TQListViewItem *item)
+{
+ if (!item)
+ return;
+
+ MetadataListViewItem* viewItem = static_cast<MetadataListViewItem *>(item);
+ m_selectedItemKey = viewItem->getKey();
+ TQString tagValue = viewItem->getValue().simplifyWhiteSpace();
+ TQString tagTitle = m_parent->getTagTitle(m_selectedItemKey);
+ TQString tagDesc = m_parent->getTagDescription(m_selectedItemKey);
+ if (tagValue.length() > 128)
+ {
+ tagValue.truncate(128);
+ tagValue.append("...");
+ }
+
+ TQWhatsThis::add(this, i18n("<b>Title: </b><p>%1<p>"
+ "<b>Value: </b><p>%2<p>"
+ "<b>Description: </b><p>%3")
+ .arg(tagTitle)
+ .arg(tagValue)
+ .arg(tagDesc));
+}
+
+void MetadataListView::setIfdList(const DMetadata::MetaDataMap& ifds, const TQStringList& tagsfilter)
+{
+ clear();
+
+ uint subItems = 0;
+ TQString ifDItemName;
+ MdKeyListViewItem *parentifDItem = 0;
+
+ for (DMetadata::MetaDataMap::const_iterator it = ifds.begin(); it != ifds.end(); ++it)
+ {
+ // We checking if we have changed of ifDName
+ TQString currentIfDName = it.key().section('.', 1, 1);
+
+ if ( currentIfDName != ifDItemName )
+ {
+ ifDItemName = currentIfDName;
+
+ // Check if the current IfD have any items. If no remove it before to toggle to the next IfD.
+ if ( subItems == 0 && parentifDItem)
+ delete parentifDItem;
+
+ parentifDItem = new MdKeyListViewItem(this, currentIfDName);
+ subItems = 0;
+ }
+
+ // We ignore all unknown tags if necessary.
+ if (!it.key().section('.', 2, 2).startsWith("0x"))
+ {
+ if (!tagsfilter.isEmpty())
+ {
+ // We using the filter to make a more user friendly output (Simple Mode)
+
+ if (tagsfilter.contains(it.key().section('.', 2, 2)))
+ {
+ TQString tagTitle = m_parent->getTagTitle(it.key());
+ new MetadataListViewItem(parentifDItem, it.key(), tagTitle, it.data());
+ subItems++;
+ }
+ }
+ else
+ {
+ // We don't filter the output (Complete Mode)
+
+ TQString tagTitle = m_parent->getTagTitle(it.key());
+ new MetadataListViewItem(parentifDItem, it.key(), tagTitle, it.data());
+ subItems++;
+ }
+ }
+ }
+
+ // To check if the last IfD have any items...
+ if ( subItems == 0 && parentifDItem)
+ delete parentifDItem;
+
+ setCurrentItemByKey(m_selectedItemKey);
+ TQTimer::singleShot( 0, this, TQ_SLOT( triggerUpdate() ) );
+}
+
+void MetadataListView::setIfdList(const DMetadata::MetaDataMap& ifds, const TQStringList& keysFilter,
+ const TQStringList& tagsFilter)
+{
+ clear();
+
+ uint subItems = 0;
+ MdKeyListViewItem *parentifDItem = 0;
+
+ for (TQStringList::const_iterator itKeysFilter = keysFilter.begin();
+ itKeysFilter != keysFilter.end();
+ ++itKeysFilter)
+ {
+ subItems = 0;
+ parentifDItem = new MdKeyListViewItem(this, *itKeysFilter);
+
+ DMetadata::MetaDataMap::const_iterator it = ifds.end();
+
+ while(1)
+ {
+ if ( *itKeysFilter == it.key().section('.', 1, 1) )
+ {
+ // We ignore all unknown tags if necessary.
+ if (!it.key().section('.', 2, 2).startsWith("0x"))
+ {
+ if (!tagsFilter.isEmpty())
+ {
+ // We using the filter to make a more user friendly output (Simple Mode)
+
+ if (tagsFilter.contains(it.key().section('.', 2, 2)))
+ {
+ TQString tagTitle = m_parent->getTagTitle(it.key());
+ new MetadataListViewItem(parentifDItem, it.key(), tagTitle, it.data());
+ subItems++;
+ }
+ }
+ else
+ {
+ // We don't filter the output (Complete Mode)
+
+ TQString tagTitle = m_parent->getTagTitle(it.key());
+ new MetadataListViewItem(parentifDItem, it.key(), tagTitle, it.data());
+ subItems++;
+ }
+ }
+ }
+
+ if (it == ifds.begin()) break;
+ --it;
+ }
+
+ // We checking if the last IfD have any items. If no, we remove it.
+ if ( subItems == 0 && parentifDItem)
+ delete parentifDItem;
+ }
+
+ setCurrentItemByKey(m_selectedItemKey);
+ TQTimer::singleShot( 0, this, TQ_SLOT( triggerUpdate() ) );
+}
+
+void MetadataListView::viewportResizeEvent(TQResizeEvent* e)
+{
+ TQListView::viewportResizeEvent(e);
+ TQTimer::singleShot( 0, this, TQ_SLOT( triggerUpdate() ) );
+}
+
+void MetadataListView::slotSearchTextChanged(const TQString& filter)
+{
+ bool query = false;
+ TQString search = filter.lower();
+
+ TQListViewItemIterator it(this);
+ for ( ; it.current(); ++it )
+ {
+ MetadataListViewItem *item = dynamic_cast<MetadataListViewItem*>(it.current());
+ if (item)
+ {
+ if (item->text(0).lower().contains(search) ||
+ item->text(1).lower().contains(search))
+ {
+ query = true;
+ item->setVisible(true);
+ }
+ else
+ {
+ item->setVisible(false);
+ }
+ }
+ }
+
+ emit signalTextFilterMatch(query);
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/metadata/metadatalistview.h b/src/libs/widgets/metadata/metadatalistview.h
new file mode 100644
index 00000000..aefe6498
--- /dev/null
+++ b/src/libs/widgets/metadata/metadatalistview.h
@@ -0,0 +1,85 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-21
+ * Description : a generic list view widget to
+ * display metadata
+ *
+ * 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 METADATALISTVIEW_H
+#define METADATALISTVIEW_H
+
+// TQt includes.
+
+#include <tqstring.h>
+#include <tqptrlist.h>
+#include <tqmap.h>
+#include <tqlistview.h>
+
+// Local includes.
+
+#include "metadatawidget.h"
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT MetadataListView : public TQListView
+{
+ TQ_OBJECT
+
+
+public:
+
+ MetadataListView(TQWidget* parent);
+ ~MetadataListView();
+
+ TQString getCurrentItemKey();
+ void setCurrentItemByKey(TQString itemKey);
+
+ void setIfdList(const DMetadata::MetaDataMap& ifds, const TQStringList& tagsfilter);
+ void setIfdList(const DMetadata::MetaDataMap& ifds, const TQStringList& keysFilter,
+ const TQStringList& tagsFilter);
+
+signals:
+
+ void signalTextFilterMatch(bool);
+
+public slots:
+
+ void slotSearchTextChanged(const TQString&);
+
+protected:
+
+ void viewportResizeEvent(TQResizeEvent*);
+
+private slots:
+
+ void slotSelectionChanged(TQListViewItem *item);
+
+private:
+
+ TQString m_selectedItemKey;
+
+ MetadataWidget *m_parent;
+};
+
+} // namespace Digikam
+
+#endif // METADATALISTVIEW_H
diff --git a/src/libs/widgets/metadata/metadatalistviewitem.cpp b/src/libs/widgets/metadata/metadatalistviewitem.cpp
new file mode 100644
index 00000000..f18056b5
--- /dev/null
+++ b/src/libs/widgets/metadata/metadatalistviewitem.cpp
@@ -0,0 +1,75 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-21
+ * Description : a generic list view item widget to
+ * display metadata
+ *
+ * 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 <tqpalette.h>
+#include <tqfont.h>
+#include <tqpainter.h>
+
+// Local includes.
+
+#include "metadatalistviewitem.h"
+
+namespace Digikam
+{
+
+MetadataListViewItem::MetadataListViewItem(TQListViewItem *parent, const TQString& key,
+ const TQString& title, const TQString& value)
+ : TQListViewItem(parent)
+{
+ m_key = key;
+
+ setSelectable(true);
+ setText(0, title);
+
+ TQString tagVal = value.simplifyWhiteSpace();
+ if (tagVal.length() > 128)
+ {
+ tagVal.truncate(128);
+ tagVal.append("...");
+ }
+ setText(1, tagVal);
+}
+
+MetadataListViewItem::~MetadataListViewItem()
+{
+}
+
+TQString MetadataListViewItem::getKey()
+{
+ return m_key;
+}
+
+TQString MetadataListViewItem::getTitle()
+{
+ return text(0);
+}
+
+TQString MetadataListViewItem::getValue()
+{
+ return text(1);
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/metadata/metadatalistviewitem.h b/src/libs/widgets/metadata/metadatalistviewitem.h
new file mode 100644
index 00000000..4a860d5b
--- /dev/null
+++ b/src/libs/widgets/metadata/metadatalistviewitem.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-21
+ * Description : a generic list view item widget to
+ * display metadata
+ *
+ * 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 METADATALISTVIEWITEM_H
+#define METADATALISTVIEWITEM_H
+
+// TQt includes.
+
+#include <tqstring.h>
+#include <tqlistview.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT MetadataListViewItem : public TQListViewItem
+{
+public:
+
+ MetadataListViewItem(TQListViewItem *parent, const TQString& key,
+ const TQString& title, const TQString& value);
+ ~MetadataListViewItem();
+
+ TQString getKey();
+ TQString getTitle();
+ TQString getValue();
+
+private:
+
+ TQString m_key;
+};
+
+} // namespace Digikam
+
+#endif /* METADATALISTVIEWITEM_H */
diff --git a/src/libs/widgets/metadata/metadatawidget.cpp b/src/libs/widgets/metadata/metadatawidget.cpp
new file mode 100644
index 00000000..d0bd5b19
--- /dev/null
+++ b/src/libs/widgets/metadata/metadatawidget.cpp
@@ -0,0 +1,454 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-22
+ * Description : a generic widget to display metadata
+ *
+ * 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 <tqlayout.h>
+#include <tqmap.h>
+#include <tqfile.h>
+#include <tqmime.h>
+#include <tqheader.h>
+#include <tqwhatsthis.h>
+#include <tqpainter.h>
+#include <tqhbuttongroup.h>
+#include <tqpushbutton.h>
+#include <tqlabel.h>
+#include <tqdragobject.h>
+#include <tqclipboard.h>
+#include <tqsimplerichtext.h>
+#include <tqpaintdevicemetrics.h>
+#include <tqstylesheet.h>
+#include <tqlistview.h>
+#include <tqtooltip.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+#include <tdelocale.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <kprinter.h>
+#include <tdeglobal.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "metadatalistview.h"
+#include "mdkeylistviewitem.h"
+#include "searchtextbar.h"
+#include "metadatawidget.h"
+#include "metadatawidget.moc"
+
+namespace Digikam
+{
+
+class MetadataWidgetPriv
+{
+
+public:
+
+ MetadataWidgetPriv()
+ {
+ toolButtons = 0;
+ levelButtons = 0;
+ view = 0;
+ mainLayout = 0;
+ searchBar = 0;
+ }
+
+ TQGridLayout *mainLayout;
+
+ TQHButtonGroup *toolButtons;
+ TQHButtonGroup *levelButtons;
+
+ TQByteArray metadata;
+
+ TQString fileName;
+
+ MetadataListView *view;
+
+ SearchTextBar *searchBar;
+
+ DMetadata::MetaDataMap metaDataMap;
+};
+
+MetadataWidget::MetadataWidget(TQWidget* parent, const char* name)
+ : TQWidget(parent, name)
+{
+ d = new MetadataWidgetPriv;
+
+ d->mainLayout = new TQGridLayout(this, 3, 4, KDialog::spacingHint(), KDialog::spacingHint());
+ TDEIconLoader *iconLoader = TDEApplication::kApplication()->iconLoader();
+
+ d->levelButtons = new TQHButtonGroup(this);
+ d->levelButtons->setInsideMargin( 0 );
+ d->levelButtons->setExclusive(true);
+ d->levelButtons->setFrameShape(TQFrame::NoFrame);
+
+ TQPushButton *simpleLevel = new TQPushButton( d->levelButtons );
+ simpleLevel->setPixmap( iconLoader->loadIcon( "text-vnd.tde.ascii", (TDEIcon::Group)TDEIcon::Toolbar ) );
+ simpleLevel->setToggleButton(true);
+ TQWhatsThis::add( simpleLevel, i18n( "Switch the tags view to a simple human-readable list" ) );
+ TQToolTip::add( simpleLevel, i18n( "Simple list" ));
+ d->levelButtons->insert(simpleLevel, SIMPLE);
+
+ TQPushButton *fullLevel = new TQPushButton( d->levelButtons );
+ fullLevel->setPixmap( iconLoader->loadIcon( "text-x-generic", (TDEIcon::Group)TDEIcon::Toolbar ) );
+ fullLevel->setToggleButton(true);
+ TQWhatsThis::add( fullLevel, i18n( "Switch the tags view to a full list" ) );
+ TQToolTip::add( fullLevel, i18n( "Full list" ));
+ d->levelButtons->insert(fullLevel, FULL);
+
+ d->toolButtons = new TQHButtonGroup(this);
+ d->toolButtons->setInsideMargin( 0 );
+ d->toolButtons->setFrameShape(TQFrame::NoFrame);
+
+ TQPushButton *saveMetadata = new TQPushButton( d->toolButtons );
+ saveMetadata->setPixmap( iconLoader->loadIcon( "document-save", (TDEIcon::Group)TDEIcon::Toolbar ) );
+ TQWhatsThis::add( saveMetadata, i18n( "Save metadata to a binary file" ) );
+ TQToolTip::add( saveMetadata, i18n( "Save metadata" ));
+ d->toolButtons->insert(saveMetadata);
+
+ TQPushButton *printMetadata = new TQPushButton( d->toolButtons );
+ printMetadata->setPixmap( iconLoader->loadIcon( "document-print", (TDEIcon::Group)TDEIcon::Toolbar ) );
+ TQWhatsThis::add( printMetadata, i18n( "Print metadata to printer" ) );
+ TQToolTip::add( printMetadata, i18n( "Print metadata" ));
+ d->toolButtons->insert(printMetadata);
+
+ TQPushButton *copy2ClipBoard = new TQPushButton( d->toolButtons );
+ copy2ClipBoard->setPixmap( iconLoader->loadIcon( "edit-copy", (TDEIcon::Group)TDEIcon::Toolbar ) );
+ TQWhatsThis::add( copy2ClipBoard, i18n( "Copy metadata to clipboard" ) );
+ TQToolTip::add( copy2ClipBoard, i18n( "Copy metadata to clipboard" ));
+ d->toolButtons->insert(copy2ClipBoard);
+
+ d->view = new MetadataListView(this);
+ TQString barName = TQString(name) + "SearchBar";
+ d->searchBar = new SearchTextBar(this, barName.ascii());
+
+ // -----------------------------------------------------------------
+
+ d->mainLayout->addMultiCellWidget(d->levelButtons, 0, 0, 0, 1);
+ d->mainLayout->addMultiCellWidget(d->toolButtons, 0, 0, 4, 4);
+ d->mainLayout->addMultiCellWidget(d->view, 1, 1, 0, 4);
+ d->mainLayout->addMultiCellWidget(d->searchBar, 2, 2, 0, 4);
+ d->mainLayout->setRowStretch(1, 10);
+ d->mainLayout->setColStretch(3, 10);
+
+ // -----------------------------------------------------------------
+
+ connect(d->levelButtons, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotModeChanged(int)));
+
+ connect(copy2ClipBoard, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotCopy2Clipboard()));
+
+ connect(printMetadata, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotPrintMetadata()));
+
+ connect(saveMetadata, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotSaveMetadataToFile()));
+
+ connect(d->searchBar, TQ_SIGNAL(signalTextChanged(const TQString&)),
+ d->view, TQ_SLOT(slotSearchTextChanged(const TQString&)));
+
+ connect(d->view, TQ_SIGNAL(signalTextFilterMatch(bool)),
+ d->searchBar, TQ_SLOT(slotSearchResult(bool)));
+}
+
+MetadataWidget::~MetadataWidget()
+{
+ delete d;
+}
+
+MetadataListView* MetadataWidget::view()
+{
+ return d->view;
+}
+
+void MetadataWidget::enabledToolButtons(bool b)
+{
+ d->toolButtons->setEnabled(b);
+}
+
+bool MetadataWidget::setMetadata(const TQByteArray& data)
+{
+ d->metadata = data;
+
+ // Cleanup all metadata contents.
+ setMetadataMap();
+
+ if (d->metadata.isEmpty())
+ {
+ setMetadataEmpty();
+ return false;
+ }
+
+ // Try to decode current metadata.
+ if (decodeMetadata())
+ enabledToolButtons(true);
+ else
+ enabledToolButtons(false);
+
+ // Refresh view using decoded metadata.
+ buildView();
+
+ return true;
+}
+
+void MetadataWidget::setMetadataEmpty()
+{
+ d->view->clear();
+ enabledToolButtons(false);
+}
+
+const TQByteArray& MetadataWidget::getMetadata()
+{
+ return d->metadata;
+}
+
+bool MetadataWidget::storeMetadataToFile(const KURL& url)
+{
+ if( url.isEmpty() )
+ return false;
+
+ TQFile file(url.path());
+ if ( !file.open(IO_WriteOnly) )
+ return false;
+
+ TQDataStream stream( &file );
+ stream.writeRawBytes(d->metadata.data(), d->metadata.size());
+ file.close();
+ return true;
+}
+
+void MetadataWidget::setMetadataMap(const DMetadata::MetaDataMap& data)
+{
+ d->metaDataMap = data;
+}
+
+const DMetadata::MetaDataMap& MetadataWidget::getMetadataMap()
+{
+ return d->metaDataMap;
+}
+
+void MetadataWidget::setIfdList(const DMetadata::MetaDataMap &ifds, const TQStringList& tagsFilter)
+{
+ d->view->setIfdList(ifds, tagsFilter);
+}
+
+void MetadataWidget::setIfdList(const DMetadata::MetaDataMap &ifds, const TQStringList& keysFilter,
+ const TQStringList& tagsFilter)
+{
+ d->view->setIfdList(ifds, keysFilter, tagsFilter);
+}
+
+void MetadataWidget::slotModeChanged(int)
+{
+ buildView();
+}
+
+void MetadataWidget::slotCopy2Clipboard()
+{
+ TQString textmetadata = i18n("File name: %1 (%2)").arg(d->fileName).arg(getMetadataTitle());
+ TQListViewItemIterator it( d->view );
+
+ while ( it.current() )
+ {
+ if ( !it.current()->isSelectable() )
+ {
+ MdKeyListViewItem *item = dynamic_cast<MdKeyListViewItem *>(it.current());
+ textmetadata.append("\n\n>>> ");
+ textmetadata.append(item->getMdKey());
+ textmetadata.append(" <<<\n\n");
+ }
+ else
+ {
+ TQListViewItem *item = it.current();
+ textmetadata.append(item->text(0));
+ textmetadata.append(" : ");
+ textmetadata.append(item->text(1));
+ textmetadata.append("\n");
+ }
+
+ ++it;
+ }
+
+ TQApplication::clipboard()->setData(new TQTextDrag(textmetadata), TQClipboard::Clipboard);
+}
+
+void MetadataWidget::slotPrintMetadata()
+{
+ TQString textmetadata = i18n("<p><big><big><b>File name: %1 (%2)</b></big></big>")
+ .arg(d->fileName)
+ .arg(getMetadataTitle());
+ TQListViewItemIterator it( d->view );
+
+ while ( it.current() )
+ {
+ if ( !it.current()->isSelectable() )
+ {
+ MdKeyListViewItem *item = dynamic_cast<MdKeyListViewItem *>(it.current());
+ textmetadata.append("<br><br><b>");
+ textmetadata.append(item->getMdKey());
+ textmetadata.append("</b><br><br>");
+ }
+ else
+ {
+ TQListViewItem *item = it.current();
+ textmetadata.append(item->text(0));
+ textmetadata.append(" : <i>");
+ textmetadata.append(item->text(1));
+ textmetadata.append("</i><br>");
+ }
+
+ ++it;
+ }
+
+ textmetadata.append("</p>");
+
+ KPrinter printer;
+ printer.setFullPage( true );
+
+ if ( printer.setup( this ) )
+ {
+ TQPainter p( &printer );
+
+ if ( !p.device() )
+ return;
+
+ TQPaintDeviceMetrics metrics(p.device());
+ int dpiy = metrics.logicalDpiY();
+ int margin = (int) ( (2/2.54)*dpiy ); // 2 cm margins
+ TQRect view( margin, margin, metrics.width() - 2*margin, metrics.height() - 2*margin );
+ TQFont font(TDEApplication::font());
+ font.setPointSize( 10 ); // we define 10pt to be a nice base size for printing
+ TQSimpleRichText richText( textmetadata, font,
+ TQString(),
+ TQStyleSheet::defaultSheet(),
+ TQMimeSourceFactory::defaultFactory(),
+ view.height() );
+ richText.setWidth( &p, view.width() );
+ int page = 1;
+
+ do
+ {
+ richText.draw( &p, margin, margin, view, colorGroup() );
+ view.moveBy( 0, view.height() );
+ p.translate( 0 , -view.height() );
+ p.setFont( font );
+ p.drawText( view.right() - p.fontMetrics().width( TQString::number( page ) ),
+ view.bottom() + p.fontMetrics().ascent() + 5, TQString::number( page ) );
+
+ if ( view.top() - margin >= richText.height() )
+ break;
+
+ printer.newPage();
+ page++;
+ }
+ while (true);
+ }
+}
+
+KURL MetadataWidget::saveMetadataToFile(const TQString& caption, const TQString& fileFilter)
+{
+ KFileDialog fileSaveDialog(TDEGlobalSettings::documentPath(),
+ TQString(),
+ this,
+ "MetadataFileSaveDialog",
+ false);
+
+ fileSaveDialog.setOperationMode(KFileDialog::Saving);
+ fileSaveDialog.setMode(KFile::File);
+ fileSaveDialog.setSelection(d->fileName);
+ fileSaveDialog.setCaption(caption);
+ fileSaveDialog.setFilter(fileFilter);
+
+ // Check for cancel.
+ if ( fileSaveDialog.exec() == KFileDialog::Accepted )
+ return fileSaveDialog.selectedURL().path();
+
+ return KURL();
+}
+
+void MetadataWidget::setMode(int mode)
+{
+ if (d->levelButtons->selectedId() == mode)
+ return;
+
+ d->levelButtons->setButton(mode);
+ buildView();
+}
+
+int MetadataWidget::getMode()
+{
+ int level = d->levelButtons->selectedId();
+ return level;
+}
+
+TQString MetadataWidget::getCurrentItemKey() const
+{
+ return d->view->getCurrentItemKey();
+}
+
+void MetadataWidget::setCurrentItemByKey(const TQString& itemKey)
+{
+ d->view->setCurrentItemByKey(itemKey);
+}
+
+bool MetadataWidget::loadFromData(const TQString& fileName, const TQByteArray& data)
+{
+ setFileName(fileName);
+ return(setMetadata(data));
+}
+
+TQString MetadataWidget::getTagTitle(const TQString&)
+{
+ return TQString();
+}
+
+TQString MetadataWidget::getTagDescription(const TQString&)
+{
+ return TQString();
+}
+
+void MetadataWidget::setFileName(const TQString& fileName)
+{
+ d->fileName = fileName;
+}
+
+void MetadataWidget::setUserAreaWidget(TQWidget *w)
+{
+ TQVBoxLayout *vLayout = new TQVBoxLayout( KDialog::spacingHint() );
+ vLayout->addWidget(w);
+ vLayout->addStretch();
+ d->mainLayout->addMultiCellLayout(vLayout, 3, 3, 0, 4);
+}
+
+void MetadataWidget::buildView()
+{
+ d->view->slotSearchTextChanged(d->searchBar->text());
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/metadata/metadatawidget.h b/src/libs/widgets/metadata/metadatawidget.h
new file mode 100644
index 00000000..5d2feb64
--- /dev/null
+++ b/src/libs/widgets/metadata/metadatawidget.h
@@ -0,0 +1,120 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-22
+ * Description : a generic widget to display metadata
+ *
+ * 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 METADATAWIDGET_H
+#define METADATAWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Local includes.
+
+#include "dmetadata.h"
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class MetadataListView;
+class MetadataWidgetPriv;
+
+class DIGIKAM_EXPORT MetadataWidget : public TQWidget
+{
+ TQ_OBJECT
+
+
+public:
+
+ enum Mode
+ {
+ SIMPLE=0,
+ FULL
+ };
+
+public:
+
+ MetadataWidget(TQWidget* parent, const char* name=0);
+ ~MetadataWidget();
+
+ int getMode();
+ void setMode(int mode);
+
+ TQString getCurrentItemKey() const;
+ void setCurrentItemByKey(const TQString& itemKey);
+
+ void setUserAreaWidget(TQWidget *w);
+
+ virtual TQString getTagTitle(const TQString& key);
+ virtual TQString getTagDescription(const TQString& key);
+
+ virtual bool loadFromData(const TQString &fileName, const TQByteArray& data=TQByteArray());
+ virtual bool loadFromURL(const KURL& url)=0;
+
+private slots:
+
+ void slotModeChanged(int);
+ void slotCopy2Clipboard();
+ void slotPrintMetadata();
+
+protected slots:
+
+ virtual void slotSaveMetadataToFile()=0;
+
+protected:
+
+ void enabledToolButtons(bool);
+ void setFileName(const TQString& fileName);
+ MetadataListView* view();
+
+ bool setMetadata(const TQByteArray& data=TQByteArray());
+ const TQByteArray& getMetadata();
+
+ void setMetadataMap(const DMetadata::MetaDataMap& data=DMetadata::MetaDataMap());
+ const DMetadata::MetaDataMap& getMetadataMap();
+
+ void setIfdList(const DMetadata::MetaDataMap &ifds, const TQStringList& tagsFilter=TQStringList());
+ void setIfdList(const DMetadata::MetaDataMap &ifds, const TQStringList& keysFilter,
+ const TQStringList& tagsFilter);
+
+ KURL saveMetadataToFile(const TQString& caption, const TQString& fileFilter);
+ bool storeMetadataToFile(const KURL& url);
+
+ virtual void buildView();
+ virtual bool decodeMetadata()=0;
+ virtual TQString getMetadataTitle()=0;
+ virtual void setMetadataEmpty();
+
+private:
+
+ MetadataWidgetPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* METADATAWIDGET_H */
diff --git a/src/libs/widgets/metadata/worldmapwidget.cpp b/src/libs/widgets/metadata/worldmapwidget.cpp
new file mode 100644
index 00000000..811e9148
--- /dev/null
+++ b/src/libs/widgets/metadata/worldmapwidget.cpp
@@ -0,0 +1,211 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-20
+ * Description : a widget to display GPS info on a world map
+ *
+ * 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 <tqstring.h>
+#include <tqpixmap.h>
+#include <tqlabel.h>
+
+// KDE includes.
+
+#include <kstandarddirs.h>
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <kstaticdeleter.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "worldmapwidget.h"
+#include "worldmapwidget.moc"
+
+namespace Digikam
+{
+
+class WorldMapWidgetPriv
+{
+
+public:
+
+ WorldMapWidgetPriv()
+ {
+ latitude = 0;
+ longitude = 0;
+ latLonPos = 0;
+ }
+
+ int xPos;
+ int yPos;
+ int xMousePos;
+ int yMousePos;
+
+ double latitude;
+ double longitude;
+
+ TQLabel *latLonPos;
+
+ static TQPixmap *worldMap;
+};
+
+static KStaticDeleter<TQPixmap> pixmapDeleter;
+
+TQPixmap *WorldMapWidgetPriv::worldMap = 0;
+
+WorldMapWidget::WorldMapWidget(int w, int h, TQWidget *parent)
+ : TQScrollView(parent, 0, TQt::WDestructiveClose)
+{
+ d = new WorldMapWidgetPriv;
+
+ setVScrollBarMode(TQScrollView::AlwaysOff);
+ setHScrollBarMode(TQScrollView::AlwaysOff);
+ viewport()->setMouseTracking(true);
+ viewport()->setPaletteBackgroundColor(colorGroup().background());
+ setMinimumWidth(w);
+ setMaximumHeight(h);
+ resizeContents(worldMapPixmap().width(), worldMapPixmap().height());
+
+ d->latLonPos = new TQLabel(viewport());
+ d->latLonPos->setMaximumHeight(fontMetrics().height());
+ d->latLonPos->setAlignment(TQt::AlignHCenter | TQt::AlignVCenter);
+ d->latLonPos->setFrameStyle(TQFrame::Panel | TQFrame::Sunken);
+ addChild(d->latLonPos);
+}
+
+WorldMapWidget::~WorldMapWidget()
+{
+ delete d;
+}
+
+TQPixmap &WorldMapWidget::worldMapPixmap()
+{
+ if (!d->worldMap)
+ {
+ TDEGlobal::dirs()->addResourceType("worldmap", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("worldmap", "worldmap.jpg");
+ pixmapDeleter.setObject(d->worldMap, new TQPixmap(directory + "worldmap.jpg"));
+ }
+ return *d->worldMap;
+}
+
+double WorldMapWidget::getLatitude()
+{
+ return d->latitude;
+}
+
+double WorldMapWidget::getLongitude()
+{
+ return d->longitude;
+}
+
+void WorldMapWidget::setEnabled(bool b)
+{
+ if (!b)
+ d->latLonPos->hide();
+ else
+ d->latLonPos->show();
+
+ TQScrollView::setEnabled(b);
+}
+
+void WorldMapWidget::setGPSPosition(double lat, double lng)
+{
+ d->latitude = lat;
+ d->longitude = lng;
+
+ double latMid = contentsHeight() / 2.0;
+ double longMid = contentsWidth() / 2.0;
+
+ double latOffset = ( d->latitude * latMid ) / 90.0;
+ double longOffset = ( d->longitude * longMid ) / 180.0;
+
+ d->xPos = (int)(longMid + longOffset);
+ d->yPos = (int)(latMid - latOffset);
+
+ repaintContents(false);
+ center(d->xPos, d->yPos);
+
+ TQString la, lo;
+ d->latLonPos->setText(TQString("(%1, %2)").arg(la.setNum(d->latitude, 'f', 2))
+ .arg(lo.setNum(d->longitude, 'f', 2)));
+
+ moveChild(d->latLonPos, contentsX()+10, contentsY()+10);
+}
+
+void WorldMapWidget::drawContents(TQPainter *p, int x, int y, int w, int h)
+{
+ if (isEnabled())
+ {
+ p->drawPixmap(x, y, worldMapPixmap(), x, y, w, h);
+ p->setPen(TQPen(TQt::white, 0, TQt::SolidLine));
+ p->drawLine(d->xPos, 0, d->xPos, contentsHeight());
+ p->drawLine(0, d->yPos, contentsWidth(), d->yPos);
+ p->setPen(TQPen(TQt::red, 0, TQt::DotLine));
+ p->drawLine(d->xPos, 0, d->xPos, contentsHeight());
+ p->drawLine(0, d->yPos, contentsWidth(), d->yPos);
+ p->setPen( TQt::red );
+ p->setBrush( TQt::red );
+ p->drawEllipse( d->xPos-2, d->yPos-2, 4, 4 );
+ }
+ else
+ {
+ p->fillRect(x, y, w, h, palette().disabled().background());
+ }
+}
+
+void WorldMapWidget::contentsMousePressEvent ( TQMouseEvent * e )
+{
+ if ( e->button() == TQt::LeftButton )
+ {
+ d->xMousePos = e->x();
+ d->yMousePos = e->y();
+ setCursor( KCursor::sizeAllCursor() );
+ }
+}
+
+void WorldMapWidget::contentsMouseReleaseEvent ( TQMouseEvent * )
+{
+ unsetCursor();
+}
+
+void WorldMapWidget::contentsMouseMoveEvent( TQMouseEvent * e )
+{
+ if ( e->state() == TQt::LeftButton )
+ {
+ uint newxpos = e->x();
+ uint newypos = e->y();
+
+ scrollBy (-(newxpos - d->xMousePos), -(newypos - d->yMousePos));
+ repaintContents(false);
+
+ d->xMousePos = newxpos - (newxpos-d->xMousePos);
+ d->yMousePos = newypos - (newypos-d->yMousePos);
+ return;
+ }
+
+ setCursor( KCursor::handCursor() );
+}
+
+} // namespace Digikam
+
diff --git a/src/libs/widgets/metadata/worldmapwidget.h b/src/libs/widgets/metadata/worldmapwidget.h
new file mode 100644
index 00000000..bfb8ad8f
--- /dev/null
+++ b/src/libs/widgets/metadata/worldmapwidget.h
@@ -0,0 +1,73 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-02-20
+ * Description : a widget to display GPS info on a world map
+ *
+ * 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 WORLDMAPWIDGET_H
+#define WORLDMAPWIDGET_H
+
+// TQt includes.
+
+#include <tqscrollview.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class WorldMapWidgetPriv;
+
+class DIGIKAM_EXPORT WorldMapWidget : public TQScrollView
+{
+TQ_OBJECT
+
+
+public:
+
+ WorldMapWidget(int w, int h, TQWidget *parent);
+ ~WorldMapWidget();
+
+ void setGPSPosition(double lat, double lng);
+
+ double getLatitude();
+ double getLongitude();
+ void setEnabled(bool);
+
+private:
+
+ void drawContents(TQPainter *p, int x, int y, int w, int h);
+ void contentsMousePressEvent ( TQMouseEvent * e );
+ void contentsMouseReleaseEvent ( TQMouseEvent * e );
+ void contentsMouseMoveEvent( TQMouseEvent * e );
+
+ TQPixmap &worldMapPixmap();
+
+private:
+
+ WorldMapWidgetPriv *d;
+
+};
+
+} // namespace Digikam
+
+#endif /* WORLDMAPWIDGET_H */