summaryrefslogtreecommitdiffstats
path: root/src/utilities/imageeditor/rawimport/rawpreview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/utilities/imageeditor/rawimport/rawpreview.cpp')
-rw-r--r--src/utilities/imageeditor/rawimport/rawpreview.cpp336
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