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