diff options
Diffstat (limited to 'src/utilities/imageeditor/rawimport/rawpreview.cpp')
-rw-r--r-- | src/utilities/imageeditor/rawimport/rawpreview.cpp | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/src/utilities/imageeditor/rawimport/rawpreview.cpp b/src/utilities/imageeditor/rawimport/rawpreview.cpp new file mode 100644 index 00000000..3207ba14 --- /dev/null +++ b/src/utilities/imageeditor/rawimport/rawpreview.cpp @@ -0,0 +1,336 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2008-08-04 + * Description : RAW postProcessedImg widget. + * + * Copyright (C) 2008 Gilles Caulier <caulier dot gilles at gmail dot com> + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// TQt includes. + +#include <tqstring.h> +#include <tqpainter.h> +#include <tqtoolbutton.h> +#include <tqtooltip.h> +#include <tqpixmap.h> +#include <tqfileinfo.h> + +// KDE includes. + +#include <tdelocale.h> +#include <kcursor.h> +#include <kdatetbl.h> +#include <kiconloader.h> + +// Local includes. + +#include "ddebug.h" +#include "paniconwidget.h" +#include "managedloadsavethread.h" +#include "loadingdescription.h" +#include "themeengine.h" +#include "rawpreview.h" +#include "rawpreview.moc" + +namespace Digikam +{ + +class RawPreviewPriv +{ +public: + + RawPreviewPriv() + { + panIconPopup = 0; + panIconWidget = 0; + cornerButton = 0; + thread = 0; + url = 0; + currentFitWindowZoom = 0; + } + + double currentFitWindowZoom; + + TQToolButton *cornerButton; + + TDEPopupFrame *panIconPopup; + + KURL url; + + PanIconWidget *panIconWidget; + + DImg demosaicedImg; + + DImg postProcessedImg; + + DRawDecoding settings; + + ManagedLoadSaveThread *thread; + + LoadingDescription loadingDesc; +}; + +RawPreview::RawPreview(const KURL& url, TQWidget *parent) + : PreviewWidget(parent) +{ + d = new RawPreviewPriv; + d->thread = new ManagedLoadSaveThread; + d->url = url; + + setMinimumWidth(500); + setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding); + + d->cornerButton = new TQToolButton(this); + d->cornerButton->setIconSet(SmallIcon("move")); + d->cornerButton->hide(); + TQToolTip::add(d->cornerButton, i18n("Pan the image to a region")); + setCornerWidget(d->cornerButton); + + // ------------------------------------------------------------ + + connect(d->thread, TQ_SIGNAL(signalImageLoaded(const LoadingDescription&, const DImg&)), + this, TQ_SLOT(slotImageLoaded(const LoadingDescription&, const DImg&))); + + connect(d->thread, TQ_SIGNAL(signalLoadingProgress(const LoadingDescription&, float)), + this, TQ_SLOT(slotLoadingProgress(const LoadingDescription&, float))); + + connect(d->cornerButton, TQ_SIGNAL(pressed()), + this, TQ_SLOT(slotCornerButtonPressed())); + + connect(ThemeEngine::instance(), TQ_SIGNAL(signalThemeChanged()), + this, TQ_SLOT(slotThemeChanged())); + + // ------------------------------------------------------------ + + slotReset(); +} + +RawPreview::~RawPreview() +{ + delete d; +} + +void RawPreview::setPostProcessedImage(const DImg& image) +{ + d->postProcessedImg = image; + + updateZoomAndSize(false); + + viewport()->setUpdatesEnabled(true); + viewport()->update(); +} + +DImg& RawPreview::postProcessedImage() const +{ + return d->postProcessedImg; +} + +DImg& RawPreview::demosaicedImage() const +{ + return d->demosaicedImg; +} + +void RawPreview::setDecodingSettings(const DRawDecoding& settings) +{ + // Save post processing settings. + d->settings = settings; + + // All post processing settings will be used after demosaicing. + DRawDecoding demosaisedSettings = settings; + demosaisedSettings.resetPostProcessingSettings(); + + d->loadingDesc = LoadingDescription(d->url.path(), demosaisedSettings); + d->thread->load(d->loadingDesc, ManagedLoadSaveThread::LoadingPolicyFirstRemovePrevious); + emit signalLoadingStarted(); +} + +void RawPreview::cancelLoading() +{ + d->thread->stopLoading(d->loadingDesc); +} + +void RawPreview::slotLoadingProgress(const LoadingDescription& description, float progress) +{ + if (description.filePath != d->loadingDesc.filePath) + return; + + emit signalLoadingProgress(progress); +} + +void RawPreview::slotImageLoaded(const LoadingDescription& description, const DImg& image) +{ + if (description.filePath != d->loadingDesc.filePath) + return; + + if (image.isNull()) + { + TQPixmap pix(visibleWidth(), visibleHeight()); + pix.fill(ThemeEngine::instance()->baseColor()); + TQPainter p(&pix); + p.setPen(TQPen(ThemeEngine::instance()->textRegColor())); + p.drawText(0, 0, pix.width(), pix.height(), + TQt::AlignCenter|TQt::WordBreak, + i18n("Cannot decode RAW image for\n\"%1\"") + .arg(TQFileInfo(d->loadingDesc.filePath).fileName())); + p.end(); + // three copies - but the image is small + setPostProcessedImage(DImg(pix.convertToImage())); + emit signalLoadingFailed(); + } + else + { + d->demosaicedImg = image; + emit signalDemosaicedImage(); + // NOTE: we will apply all Raw post processing corrections into RawImport class. + } +} + +void RawPreview::slotThemeChanged() +{ + setBackgroundColor(ThemeEngine::instance()->baseColor()); +} + +void RawPreview::slotCornerButtonPressed() +{ + if (d->panIconPopup) + { + d->panIconPopup->hide(); + delete d->panIconPopup; + d->panIconPopup = 0; + } + + d->panIconPopup = new TDEPopupFrame(this); + PanIconWidget *pan = new PanIconWidget(d->panIconPopup); + pan->setImage(180, 120, postProcessedImage()); + d->panIconPopup->setMainWidget(pan); + + TQRect r((int)(contentsX() / zoomFactor()), (int)(contentsY() / zoomFactor()), + (int)(visibleWidth() / zoomFactor()), (int)(visibleHeight() / zoomFactor())); + pan->setRegionSelection(r); + pan->setMouseFocus(); + + connect(pan, TQ_SIGNAL(signalSelectionMoved(const TQRect&, bool)), + this, TQ_SLOT(slotPanIconSelectionMoved(const TQRect&, bool))); + + connect(pan, TQ_SIGNAL(signalHiden()), + this, TQ_SLOT(slotPanIconHiden())); + + TQPoint g = mapToGlobal(viewport()->pos()); + g.setX(g.x()+ viewport()->size().width()); + g.setY(g.y()+ viewport()->size().height()); + d->panIconPopup->popup(TQPoint(g.x() - d->panIconPopup->width(), + g.y() - d->panIconPopup->height())); + + pan->setCursorToLocalRegionSelectionCenter(); +} + +void RawPreview::slotPanIconHiden() +{ + d->cornerButton->blockSignals(true); + d->cornerButton->animateClick(); + d->cornerButton->blockSignals(false); +} + +void RawPreview::slotPanIconSelectionMoved(const TQRect& r, bool b) +{ + setContentsPos((int)(r.x()*zoomFactor()), (int)(r.y()*zoomFactor())); + + if (b) + { + d->panIconPopup->hide(); + delete d->panIconPopup; + d->panIconPopup = 0; + slotPanIconHiden(); + } +} + +void RawPreview::zoomFactorChanged(double zoom) +{ + updateScrollBars(); + + if (horizontalScrollBar()->isVisible() || verticalScrollBar()->isVisible()) + d->cornerButton->show(); + else + d->cornerButton->hide(); + + PreviewWidget::zoomFactorChanged(zoom); +} + +void RawPreview::resizeEvent(TQResizeEvent* e) +{ + if (!e) return; + + TQScrollView::resizeEvent(e); + + if (!d->loadingDesc.filePath.isEmpty()) + d->cornerButton->hide(); + + updateZoomAndSize(false); +} + +void RawPreview::updateZoomAndSize(bool alwaysFitToWindow) +{ + // Set zoom for fit-in-window as minimum, but dont scale up images + // that are smaller than the available space, only scale down. + double zoom = calcAutoZoomFactor(ZoomInOnly); + setZoomMin(zoom); + setZoomMax(zoom*12.0); + + // Is currently the zoom factor set to fit to window? Then set it again to fit the new size. + if (zoomFactor() < zoom || alwaysFitToWindow || zoomFactor() == d->currentFitWindowZoom) + { + setZoomFactor(zoom); + } + + // store which zoom factor means it is fit to window + d->currentFitWindowZoom = zoom; + + updateContentsSize(); +} + +int RawPreview::previewWidth() +{ + return d->postProcessedImg.width(); +} + +int RawPreview::previewHeight() +{ + return d->postProcessedImg.height(); +} + +bool RawPreview::previewIsNull() +{ + return d->postProcessedImg.isNull(); +} + +void RawPreview::resetPreview() +{ + d->postProcessedImg = DImg(); + d->loadingDesc = LoadingDescription(); + + updateZoomAndSize(false); +} + +void RawPreview::paintPreview(TQPixmap *pix, int sx, int sy, int sw, int sh) +{ + DImg img = d->postProcessedImg.smoothScaleSection(sx, sy, sw, sh, tileSize(), tileSize()); + TQPixmap pix2 = img.convertToPixmap(); + bitBlt(pix, 0, 0, &pix2, 0, 0); +} + +} // NameSpace Digikam |