summaryrefslogtreecommitdiffstats
path: root/src/utilities/imageeditor/editor
diff options
context:
space:
mode:
authorMichele Calgaro <[email protected]>2024-11-22 18:41:30 +0900
committerMichele Calgaro <[email protected]>2024-11-22 18:41:30 +0900
commitee0d99607c14cb63d3ebdb3a970b508949fa8219 (patch)
tree94ac1efedb94cb38bf6879ba0610fe75b554216b /src/utilities/imageeditor/editor
parent4adff739380e4ae9f30e443ee95644f184456869 (diff)
downloaddigikam-ee0d99607c14cb63d3ebdb3a970b508949fa8219.tar.gz
digikam-ee0d99607c14cb63d3ebdb3a970b508949fa8219.zip
Rename 'digikam' folder to 'src'
Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'src/utilities/imageeditor/editor')
-rw-r--r--src/utilities/imageeditor/editor/Makefile.am51
-rw-r--r--src/utilities/imageeditor/editor/digikamimageplugin.desktop39
-rw-r--r--src/utilities/imageeditor/editor/digikamimagewindowui.rc125
-rw-r--r--src/utilities/imageeditor/editor/editorstackview.cpp233
-rw-r--r--src/utilities/imageeditor/editor/editorstackview.h97
-rw-r--r--src/utilities/imageeditor/editor/editortool.cpp436
-rw-r--r--src/utilities/imageeditor/editor/editortool.h164
-rw-r--r--src/utilities/imageeditor/editor/editortooliface.cpp147
-rw-r--r--src/utilities/imageeditor/editor/editortooliface.h76
-rw-r--r--src/utilities/imageeditor/editor/editortoolsettings.cpp331
-rw-r--r--src/utilities/imageeditor/editor/editortoolsettings.h110
-rw-r--r--src/utilities/imageeditor/editor/editorwindow.cpp1932
-rw-r--r--src/utilities/imageeditor/editor/editorwindow.h263
-rw-r--r--src/utilities/imageeditor/editor/editorwindowprivate.h143
-rw-r--r--src/utilities/imageeditor/editor/imageiface.cpp444
-rw-r--r--src/utilities/imageeditor/editor/imageiface.h198
-rw-r--r--src/utilities/imageeditor/editor/imagewindow.cpp1263
-rw-r--r--src/utilities/imageeditor/editor/imagewindow.h155
-rw-r--r--src/utilities/imageeditor/editor/savingcontextcontainer.h89
19 files changed, 6296 insertions, 0 deletions
diff --git a/src/utilities/imageeditor/editor/Makefile.am b/src/utilities/imageeditor/editor/Makefile.am
new file mode 100644
index 00000000..71031991
--- /dev/null
+++ b/src/utilities/imageeditor/editor/Makefile.am
@@ -0,0 +1,51 @@
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libdimgeditor.la libshowfoto.la
+
+libdimgeditor_la_SOURCES = editorwindow.cpp imageiface.cpp imagewindow.cpp editorstackview.cpp \
+ editortooliface.cpp editortool.cpp editortoolsettings.cpp
+
+libdimgeditor_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TDEPRINT)
+
+libdimgeditor_la_LIBADD = $(top_builddir)/src/utilities/imageeditor/tools/libdimgeditortools.la \
+ $(top_builddir)/src/utilities/imageeditor/rawimport/librawimport.la
+
+libshowfoto_la_SOURCES = editorwindow.cpp imageiface.cpp editorstackview.cpp \
+ editortooliface.cpp editortool.cpp editortoolsettings.cpp
+
+libshowfoto_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TDEPRINT)
+
+libshowfoto_la_LIBADD = $(top_builddir)/src/libs/dimg/libdimg.la \
+ $(top_builddir)/src/libs/dialogs/libdialogshowfoto.la \
+ $(top_builddir)/src/libs/widgets/libwidgets.la \
+ $(top_builddir)/src/libs/greycstoration/libgreycstoration.la \
+ $(top_builddir)/src/utilities/imageeditor/canvas/libdimgcanvas.la \
+ $(top_builddir)/src/utilities/imageeditor/tools/libdimgeditortools.la \
+ $(top_builddir)/src/utilities/imageeditor/rawimport/librawimport.la
+
+INCLUDES = -I$(top_srcdir)/src/digikam \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/themeengine \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/libs/imageproperties \
+ -I$(top_srcdir)/src/libs/threadimageio \
+ -I$(top_srcdir)/src/utilities/setup \
+ -I$(top_srcdir)/src/utilities/slideshow \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/utilities/imageeditor/tools \
+ -I$(top_builddir)/src/libs/dialogs \
+ $(LIBKEXIV2_CFLAGS) $(LIBKDCRAW_CFLAGS) $(all_includes)
+
+digikaminclude_HEADERS = imageiface.h
+
+digikamincludedir = $(includedir)/digikam
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimagewindowui.rc
+
+kde_servicetypes_DATA = digikamimageplugin.desktop
+
diff --git a/src/utilities/imageeditor/editor/digikamimageplugin.desktop b/src/utilities/imageeditor/editor/digikamimageplugin.desktop
new file mode 100644
index 00000000..31bef621
--- /dev/null
+++ b/src/utilities/imageeditor/editor/digikamimageplugin.desktop
@@ -0,0 +1,39 @@
+[Desktop Entry]
+Encoding=UTF-8
+Type=ServiceType
+X-TDE-ServiceType=Digikam/ImagePlugin
+X-TDE-DerivedName=Digikam ImagePlugin
+Comment=A digiKam Image Plugin
+Comment[bg]=Приставка за снимки в digiKam
+Comment[br]=Ul lugent skeudenn digiKam
+Comment[ca]=Un connector d'imatges del digiKam
+Comment[cs]=Modul pro digiKam
+Comment[da]=Et Digikam billed-plugin
+Comment[de]=Ein Bild-Modul von digiKam
+Comment[el]=Ένα πρόσθετο εικόνας digiKam
+Comment[es]=Plugin de digiKam para imágenes
+Comment[et]=DigiKami pildiplugin
+Comment[fa]=یک وصلۀ تصویر digiKam
+Comment[fi]=digiKam-liitännäinen
+Comment[fr]=Un module externe pour digiKam
+Comment[gl]=Un plugin de Imaxe de digiKam
+Comment[hr]=digiKam dodatak za slike
+Comment[is]=digiKam ljósmynda-íforrit
+Comment[it]=Un plugin per le immagini di digiKam
+Comment[ja]=digiKam 画像プラグイン
+Comment[ms]=Plugin Imej digiKam
+Comment[nds]=En digiKam-Bildmoduul
+Comment[nl]=Een plugin voor Digikam
+Comment[pa]=ਇੱਕ ਡਿਜ਼ੀਕੈਮ ਚਿੱਤਰ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka obrazu digiKama
+Comment[pt]=Um 'Plugin' de Imagem do digiKam
+Comment[pt_BR]=Plugin de imagem digiKam
+Comment[ru]=Модуль изображений digiKam
+Comment[sk]=DigiKam obrázkový plugin
+Comment[sr]=digiKam-ов сликовни прикључак
+Comment[sr@Latn]=digiKam-ov slikovni priključak
+Comment[sv]=Ett bildinsticksprogram för Digikam
+Comment[tr]=Bir digiKam Resim Eklentisi
+Comment[uk]=Втулок зображень digiKam
+Comment[vi]=Một phần bổ sung ảnh digiKam
+Comment[xx]=xxA digiKam Image Pluginxx
diff --git a/src/utilities/imageeditor/editor/digikamimagewindowui.rc b/src/utilities/imageeditor/editor/digikamimagewindowui.rc
new file mode 100644
index 00000000..2c0314ad
--- /dev/null
+++ b/src/utilities/imageeditor/editor/digikamimagewindowui.rc
@@ -0,0 +1,125 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<gui version="24" name="digikamimagewindow" >
+
+<MenuBar>
+
+ <Menu name="File" ><text>&amp;File</text>
+ <Action name="editorwindow_backward" />
+ <Action name="editorwindow_forward" />
+ <Separator/>
+ <Action name="editorwindow_first" />
+ <Action name="editorwindow_last" />
+ <Separator/>
+ <Action name="editorwindow_print" />
+ <Separator/>
+ <Action name="editorwindow_save" />
+ <Action name="editorwindow_saveas" />
+ <Action name="editorwindow_revert" />
+ <Separator/>
+ <Action name="editorwindow_delete" />
+ <Separator/>
+ <Action name="editorwindow_close" />
+ </Menu>
+
+ <Menu name="Edit" ><text>&amp;Edit</text>
+ <Action name="editorwindow_copy" />
+ <Separator/>
+ <Action name="editorwindow_undo" />
+ <Action name="editorwindow_redo" />
+ <Separator/>
+ <Action name="editorwindow_selectAll" />
+ <Action name="editorwindow_selectNone" />
+ </Menu>
+
+ <Menu name="View" ><text>&amp;View</text>
+ <Action name="editorwindow_fullscreen" />
+ <Action name="editorwindow_slideshow" />
+ <Separator/>
+ <Action name="editorwindow_zoomplus" />
+ <Action name="editorwindow_zoomminus" />
+ <Action name="editorwindow_zoomto100percents" />
+ <Action name="editorwindow_zoomfit2window" />
+ <Action name="editorwindow_zoomfit2select" />
+ <Separator/>
+ <Action name="editorwindow_underexposure" />
+ <Action name="editorwindow_overexposure" />
+ <Action name="editorwindow_cmview" />
+ </Menu>
+
+ <Menu name="Color" ><text>&amp;Color</text>
+ </Menu>
+
+ <Menu name="Enhance" ><text>Enh&amp;ance</text>
+ </Menu>
+
+ <Menu name="Transform" ><text>Tra&amp;nsform</text>
+ <Action name="editorwindow_rotate_left" />
+ <Action name="editorwindow_rotate_right" />
+ <Separator/>
+ <Action name="editorwindow_flip_horiz" />
+ <Action name="editorwindow_flip_vert" />
+ <Separator/>
+ <Action name="editorwindow_crop" />
+ <Action name="editorwindow_resize" />
+ </Menu>
+
+ <Menu name="Decorate" ><text>&amp;Decorate</text>
+ </Menu>
+
+ <Menu name="Filters" ><text>F&amp;ilters</text>
+ </Menu>
+
+ <Menu name="help" ><text>&amp;Help</text>
+ <Action name="editorwindow_rawcameralist"/>
+ <Action name="editorwindow_donatemoney" />
+ <Action name="editorwindow_contribute" />
+ </Menu>
+
+ <Merge/>
+
+ <Menu name="settings" noMerge="1"><Text>&amp;Settings</Text>
+ <Merge name="StandardToolBarMenuHandler" />
+ <Action name="options_show_menubar"/>
+ <Action name="options_show_statusbar"/>
+ <Action name="options_show_toolbar"/>
+ <Separator/>
+ <Action name="theme_menu" />
+ <Action name="options_configure_keybinding"/>
+ <Action name="options_configure_toolbars"/>
+ <Action name="options_configure" />
+ </Menu>
+
+</MenuBar>
+
+<ToolBar name="ToolBar" ><text>Main Toolbar</text>
+ <Action name="editorwindow_first" />
+ <Action name="editorwindow_backward" />
+ <Action name="editorwindow_forward" />
+ <Action name="editorwindow_last" />
+ <Separator/>
+ <Action name="editorwindow_save" />
+ <Action name="editorwindow_saveas" />
+ <Action name="editorwindow_undo" />
+ <Action name="editorwindow_redo" />
+ <Action name="editorwindow_revert" />
+ <Separator/>
+ <Action name="editorwindow_zoomplus" />
+ <Action name="editorwindow_zoomto" />
+ <Action name="editorwindow_zoomminus" />
+ <Action name="editorwindow_zoomfit2window" />
+ <Action name="editorwindow_zoomfit2select" />
+ <Separator/>
+ <Action name="editorwindow_rotate_left" />
+ <Action name="editorwindow_rotate_right" />
+ <Action name="editorwindow_crop" />
+ <Separator/>
+ <Action name="editorwindow_fullscreen" />
+ <Action name="editorwindow_slideshow" />
+ <Merge />
+ <WeakSeparator/>
+ <Action name="logo_action" />
+</ToolBar>
+
+<ActionProperties/>
+
+</gui>
diff --git a/src/utilities/imageeditor/editor/editorstackview.cpp b/src/utilities/imageeditor/editor/editorstackview.cpp
new file mode 100644
index 00000000..61550300
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editorstackview.cpp
@@ -0,0 +1,233 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-20
+ * Description : A widget stack to embed editor view.
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+// Local includes.
+
+#include "previewwidget.h"
+#include "imageregionwidget.h"
+#include "imagepanelwidget.h"
+#include "canvas.h"
+#include "editorstackview.h"
+#include "editorstackview.moc"
+
+namespace Digikam
+{
+
+class EditorStackViewPriv
+{
+
+public:
+
+ EditorStackViewPriv()
+ {
+ canvas = 0;
+ toolView = 0;
+ }
+
+ TQWidget *toolView;
+ Canvas *canvas;
+};
+
+EditorStackView::EditorStackView(TQWidget *parent)
+ : TQWidgetStack(parent, 0, TQt::WDestructiveClose)
+{
+ d = new EditorStackViewPriv;
+}
+
+EditorStackView::~EditorStackView()
+{
+ delete d;
+}
+
+void EditorStackView::setCanvas(Canvas* canvas)
+{
+ if (d->canvas) return;
+
+ d->canvas = canvas;
+ addWidget(d->canvas, CanvasMode);
+
+ connect(d->canvas, TQ_SIGNAL(signalZoomChanged(double)),
+ this, TQ_SLOT(slotZoomChanged(double)));
+}
+
+Canvas* EditorStackView::canvas() const
+{
+ return d->canvas;
+}
+
+void EditorStackView::setToolView(TQWidget* view)
+{
+ if (d->toolView)
+ removeWidget(d->toolView);
+
+ d->toolView = view;
+
+ if (d->toolView)
+ addWidget(d->toolView, ToolViewMode);
+
+ PreviewWidget *preview = previewWidget();
+ if (preview)
+ {
+ connect(preview, TQ_SIGNAL(signalZoomFactorChanged(double)),
+ this, TQ_SLOT(slotZoomChanged(double)));
+ }
+}
+
+TQWidget* EditorStackView::toolView() const
+{
+ return d->toolView;
+}
+
+int EditorStackView::viewMode()
+{
+ return id(visibleWidget());
+}
+
+void EditorStackView::setViewMode(int mode)
+{
+ if (mode != CanvasMode && mode != ToolViewMode)
+ return;
+
+ raiseWidget(mode);
+}
+
+void EditorStackView::increaseZoom()
+{
+ if (viewMode() == CanvasMode)
+ {
+ d->canvas->slotIncreaseZoom();
+ }
+ else
+ {
+ PreviewWidget *preview = previewWidget();
+ if (preview)
+ preview->slotIncreaseZoom();
+ }
+}
+
+void EditorStackView::decreaseZoom()
+{
+ if (viewMode() == CanvasMode)
+ {
+ d->canvas->slotDecreaseZoom();
+ }
+ else
+ {
+ PreviewWidget *preview = previewWidget();
+ if (preview)
+ preview->slotDecreaseZoom();
+ }
+}
+
+void EditorStackView::toggleFitToWindow()
+{
+ if (viewMode() == CanvasMode)
+ {
+ d->canvas->toggleFitToWindow();
+ }
+ else
+ {
+ PreviewWidget *preview = previewWidget();
+ if (preview)
+ preview->toggleFitToWindow();
+ }
+}
+
+void EditorStackView::fitToSelect()
+{
+ if (viewMode() == CanvasMode)
+ {
+ d->canvas->fitToSelect();
+ }
+}
+
+void EditorStackView::zoomTo100Percents()
+{
+ if (viewMode() == CanvasMode)
+ {
+ if (d->canvas->zoomFactor() == 1.0)
+ d->canvas->toggleFitToWindow();
+ else
+ d->canvas->setZoomFactor(1.0);
+ }
+ else
+ {
+ PreviewWidget *preview = previewWidget();
+ if (preview)
+ {
+ if (preview->zoomFactor() == 1.0)
+ preview->toggleFitToWindow();
+ else
+ preview->setZoomFactor(1.0);
+ }
+ }
+}
+
+void EditorStackView::setZoomFactor(double zoom)
+{
+ if (viewMode() == CanvasMode)
+ {
+ d->canvas->setZoomFactor(zoom);
+ }
+ else
+ {
+ PreviewWidget *preview = previewWidget();
+ if (preview)
+ preview->setZoomFactor(zoom);
+ }
+}
+
+void EditorStackView::slotZoomChanged(double zoom)
+{
+ bool max, min;
+
+ if (viewMode() == CanvasMode)
+ {
+ max = d->canvas->maxZoom();
+ min = d->canvas->minZoom();
+ emit signalZoomChanged(max, min, zoom);
+ }
+ else
+ {
+ PreviewWidget *preview = previewWidget();
+ if (preview)
+ {
+ max = preview->maxZoom();
+ min = preview->minZoom();
+ emit signalZoomChanged(max, min, zoom);
+ }
+ }
+}
+
+PreviewWidget* EditorStackView::previewWidget() const
+{
+ PreviewWidget *preview = dynamic_cast<PreviewWidget*>(d->toolView);
+ if (preview) return preview;
+
+ ImagePanelWidget *panel = dynamic_cast<ImagePanelWidget*>(d->toolView);
+ if (panel) return (dynamic_cast<PreviewWidget*>(panel->previewWidget()));
+
+ return 0;
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/editor/editorstackview.h b/src/utilities/imageeditor/editor/editorstackview.h
new file mode 100644
index 00000000..e428fcd7
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editorstackview.h
@@ -0,0 +1,97 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-20
+ * Description : A widget stack to embed editor view.
+ *
+ * Copyright (C) 2008-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 EDITORSTACKVIEW_H
+#define EDITORSTACKVIEW_H
+
+// KDE includes.
+
+#include <tqwidgetstack.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class PreviewWidget;
+class Canvas;
+class EditorStackViewPriv;
+
+class DIGIKAM_EXPORT EditorStackView : public TQWidgetStack
+{
+TQ_OBJECT
+
+
+public:
+
+ enum StackViewMode
+ {
+ CanvasMode=0,
+ ToolViewMode
+ };
+
+public:
+
+ EditorStackView(TQWidget *parent=0);
+ ~EditorStackView();
+
+ void setCanvas(Canvas* canvas);
+ Canvas *canvas() const;
+
+ void setToolView(TQWidget* view);
+ TQWidget *toolView() const;
+
+ int viewMode();
+ void setViewMode(int mode);
+
+ void increaseZoom();
+ void decreaseZoom();
+ void toggleFitToWindow();
+ void fitToSelect();
+ void zoomTo100Percents();
+ void setZoomFactor(double zoom);
+
+ /** Two widgets are embedded in Editor Tool to perform preview with panning and zooming:
+ a PreviewWidget derivated class or ImagePanelWidget.
+ This method try to find the right PreviewWidget instance accordingly else return 0.
+ */
+ PreviewWidget* previewWidget() const;
+
+signals:
+
+ void signalZoomChanged(bool isMax, bool isMin, double zoom);
+
+private slots:
+
+ void slotZoomChanged(double);
+
+private:
+
+ EditorStackViewPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* EDITORSTACKVIEW_H */
diff --git a/src/utilities/imageeditor/editor/editortool.cpp b/src/utilities/imageeditor/editor/editortool.cpp
new file mode 100644
index 00000000..b840e673
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editortool.cpp
@@ -0,0 +1,436 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-20
+ * Description : editor tool template class.
+ *
+ * Copyright (C) 2008-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 <tqwidget.h>
+#include <tqtimer.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imagewidget.h"
+#include "imageguidewidget.h"
+#include "imagepanelwidget.h"
+#include "dimgthreadedfilter.h"
+#include "editortoolsettings.h"
+#include "editortooliface.h"
+#include "editortool.h"
+#include "editortool.moc"
+
+namespace Digikam
+{
+
+class EditorToolPriv
+{
+
+public:
+
+ EditorToolPriv()
+ {
+ timer = 0;
+ view = 0;
+ settings = 0;
+ }
+
+ TQString helpAnchor;
+ TQString name;
+
+ TQWidget *view;
+
+ TQPixmap icon;
+
+ TQTimer *timer;
+
+ EditorToolSettings *settings;
+};
+
+EditorTool::EditorTool(TQObject *parent)
+ : TQObject(parent)
+{
+ d = new EditorToolPriv;
+ d->timer = new TQTimer(this);
+
+ connect(d->timer, TQ_SIGNAL(timeout()),
+ this, TQ_SLOT(slotEffect()));
+}
+
+EditorTool::~EditorTool()
+{
+ delete d;
+}
+
+void EditorTool::init()
+{
+ TQTimer::singleShot(0, this, TQ_SLOT(slotInit()));
+}
+
+TQPixmap EditorTool::toolIcon() const
+{
+ return d->icon;
+}
+
+void EditorTool::setToolIcon(const TQPixmap& icon)
+{
+ d->icon = icon;
+}
+
+TQString EditorTool::toolName() const
+{
+ return d->name;
+}
+
+void EditorTool::setToolName(const TQString& name)
+{
+ d->name = name;
+}
+
+TQWidget* EditorTool::toolView() const
+{
+ return d->view;
+}
+
+void EditorTool::setToolView(TQWidget *view)
+{
+ d->view = view;
+ // Will be unblocked in slotInit()
+ // This will prevent resize event signals emit during tool init.
+ d->view->blockSignals(true);
+}
+
+EditorToolSettings* EditorTool::toolSettings() const
+{
+ return d->settings;
+}
+
+void EditorTool::setToolSettings(EditorToolSettings *settings)
+{
+ d->settings = settings;
+
+ connect(d->settings, TQ_SIGNAL(signalOkClicked()),
+ this, TQ_SLOT(slotOk()));
+
+ connect(d->settings, TQ_SIGNAL(signalCancelClicked()),
+ this, TQ_SLOT(slotCancel()));
+
+ connect(d->settings, TQ_SIGNAL(signalDefaultClicked()),
+ this, TQ_SLOT(slotResetSettings()));
+
+ connect(d->settings, TQ_SIGNAL(signalSaveAsClicked()),
+ this, TQ_SLOT(slotSaveAsSettings()));
+
+ connect(d->settings, TQ_SIGNAL(signalLoadClicked()),
+ this, TQ_SLOT(slotLoadSettings()));
+
+ connect(d->settings, TQ_SIGNAL(signalTryClicked()),
+ this, TQ_SLOT(slotEffect()));
+
+ // Will be unblocked in slotInit()
+ // This will prevent signals emit during tool init.
+ d->settings->blockSignals(true);
+}
+
+void EditorTool::slotInit()
+{
+ readSettings();
+ // Unlock signals from preview and settings widgets when init is done.
+ d->view->blockSignals(false);
+ d->settings->blockSignals(false);
+}
+
+void EditorTool::setToolHelp(const TQString& anchor)
+{
+ d->helpAnchor = anchor;
+ // TODO: use this anchor with editor Help menu
+}
+
+TQString EditorTool::toolHelp() const
+{
+ if (d->helpAnchor.isEmpty())
+ return (name() + TQString(".anchor"));
+
+ return d->helpAnchor;
+}
+
+void EditorTool::setBusy(bool state)
+{
+ d->settings->setBusy(state);
+}
+
+void EditorTool::readSettings()
+{
+ d->settings->readSettings();
+}
+
+void EditorTool::writeSettings()
+{
+ d->settings->writeSettings();
+}
+
+void EditorTool::slotResetSettings()
+{
+ d->settings->resetSettings();
+}
+
+void EditorTool::slotTimer()
+{
+ d->timer->start(500, true);
+}
+
+void EditorTool::slotOk()
+{
+ writeSettings();
+ finalRendering();
+ emit okClicked();
+}
+
+void EditorTool::slotCancel()
+{
+ writeSettings();
+ emit cancelClicked();
+}
+
+// ----------------------------------------------------------------
+
+class EditorToolThreadedPriv
+{
+
+public:
+
+ EditorToolThreadedPriv()
+ {
+ threadedFilter = 0;
+ currentRenderingMode = EditorToolThreaded::NoneRendering;
+ }
+
+ EditorToolThreaded::RenderingMode currentRenderingMode;
+
+ TQString progressMess;
+
+ DImgThreadedFilter *threadedFilter;
+};
+
+EditorToolThreaded::EditorToolThreaded(TQObject *parent)
+ : EditorTool(parent)
+{
+ d = new EditorToolThreadedPriv;
+}
+
+EditorToolThreaded::~EditorToolThreaded()
+{
+ delete d->threadedFilter;
+ delete d;
+}
+
+EditorToolThreaded::RenderingMode EditorToolThreaded::renderingMode() const
+{
+ return d->currentRenderingMode;
+}
+
+void EditorToolThreaded::setProgressMessage(const TQString& mess)
+{
+ d->progressMess = mess;
+}
+
+DImgThreadedFilter* EditorToolThreaded::filter() const
+{
+ return d->threadedFilter;
+}
+
+void EditorToolThreaded::setFilter(DImgThreadedFilter *filter)
+{
+ d->threadedFilter = filter;
+}
+
+void EditorToolThreaded::slotResized()
+{
+ if (d->currentRenderingMode == EditorToolThreaded::FinalRendering)
+ {
+ toolView()->update();
+ return;
+ }
+ else if (d->currentRenderingMode == EditorToolThreaded::PreviewRendering)
+ {
+ if (filter())
+ filter()->stopComputation();
+ }
+
+ TQTimer::singleShot(0, this, TQ_SLOT(slotEffect()));
+}
+
+void EditorToolThreaded::slotAbort()
+{
+ d->currentRenderingMode = EditorToolThreaded::NoneRendering;
+
+ if (filter())
+ filter()->stopComputation();
+
+ EditorToolIface::editorToolIface()->setToolStopProgress();
+
+ toolSettings()->enableButton(EditorToolSettings::Ok, true);
+ toolSettings()->enableButton(EditorToolSettings::Load, true);
+ toolSettings()->enableButton(EditorToolSettings::SaveAs, true);
+ toolSettings()->enableButton(EditorToolSettings::Try, true);
+ toolSettings()->enableButton(EditorToolSettings::Default, true);
+
+ renderingFinished();
+}
+
+void EditorToolThreaded::customEvent(TQCustomEvent *e)
+{
+ if (!e) return;
+
+ DImgThreadedFilter::EventData *ed = (DImgThreadedFilter::EventData*)e->data();
+
+ if (!ed) return;
+
+ if (ed->starting) // Computation in progress !
+ {
+ EditorToolIface::editorToolIface()->setToolProgress(ed->progress);
+ }
+ else
+ {
+ if (ed->success) // Computation Completed !
+ {
+ switch (d->currentRenderingMode)
+ {
+ case EditorToolThreaded::PreviewRendering:
+ {
+ DDebug() << "Preview " << toolName() << " completed..." << endl;
+ putPreviewData();
+ slotAbort();
+ break;
+ }
+
+ case EditorToolThreaded::FinalRendering:
+ {
+ DDebug() << "Final" << toolName() << " completed..." << endl;
+ putFinalData();
+ EditorToolIface::editorToolIface()->setToolStopProgress();
+ kapp->restoreOverrideCursor();
+ emit okClicked();
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+ else // Computation Failed !
+ {
+ switch (d->currentRenderingMode)
+ {
+ case EditorToolThreaded::PreviewRendering:
+ {
+ DDebug() << "Preview " << toolName() << " failed..." << endl;
+ slotAbort();
+ break;
+ }
+
+ case EditorToolThreaded::FinalRendering:
+ default:
+ break;
+ }
+ }
+ }
+
+ delete ed;
+}
+
+void EditorToolThreaded::setToolView(TQWidget *view)
+{
+ EditorTool::setToolView(view);
+
+ if (dynamic_cast<ImageWidget*>(view) || dynamic_cast<ImageGuideWidget*>(view) ||
+ dynamic_cast<ImagePanelWidget*>(view))
+ {
+ connect(view, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotResized()));
+ }
+}
+
+void EditorToolThreaded::slotOk()
+{
+ writeSettings();
+
+ d->currentRenderingMode = EditorToolThreaded::FinalRendering;
+ DDebug() << "Final " << toolName() << " started..." << endl;
+ writeSettings();
+
+ toolSettings()->enableButton(EditorToolSettings::Ok, false);
+ toolSettings()->enableButton(EditorToolSettings::SaveAs, false);
+ toolSettings()->enableButton(EditorToolSettings::Load, false);
+ toolSettings()->enableButton(EditorToolSettings::Default, false);
+ toolSettings()->enableButton(EditorToolSettings::Try, false);
+
+ EditorToolIface::editorToolIface()->setToolStartProgress(d->progressMess.isEmpty() ? toolName() : d->progressMess);
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ if (d->threadedFilter)
+ {
+ delete d->threadedFilter;
+ d->threadedFilter = 0;
+ }
+
+ prepareFinal();
+}
+
+void EditorToolThreaded::slotEffect()
+{
+ // Computation already in process.
+ if (d->currentRenderingMode != EditorToolThreaded::NoneRendering)
+ return;
+
+ d->currentRenderingMode = EditorToolThreaded::PreviewRendering;
+ DDebug() << "Preview " << toolName() << " started..." << endl;
+
+ toolSettings()->enableButton(EditorToolSettings::Ok, false);
+ toolSettings()->enableButton(EditorToolSettings::SaveAs, false);
+ toolSettings()->enableButton(EditorToolSettings::Load, false);
+ toolSettings()->enableButton(EditorToolSettings::Default, false);
+ toolSettings()->enableButton(EditorToolSettings::Try, false);
+
+ EditorToolIface::editorToolIface()->setToolStartProgress(d->progressMess.isEmpty() ? toolName() : d->progressMess);
+
+ if (d->threadedFilter)
+ {
+ delete d->threadedFilter;
+ d->threadedFilter = 0;
+ }
+
+ prepareEffect();
+}
+
+void EditorToolThreaded::slotCancel()
+{
+ writeSettings();
+ slotAbort();
+ kapp->restoreOverrideCursor();
+ emit cancelClicked();
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/editor/editortool.h b/src/utilities/imageeditor/editor/editortool.h
new file mode 100644
index 00000000..120ff9f0
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editortool.h
@@ -0,0 +1,164 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-20
+ * Description : editor tool template class.
+ *
+ * Copyright (C) 2008-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 EDITORTOOL_H
+#define EDITORTOOL_H
+
+// TQt includes.
+
+#include <tqobject.h>
+#include <tqstring.h>
+#include <tqpixmap.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DImgThreadedFilter;
+class EditorToolSettings;
+class EditorToolPriv;
+
+class DIGIKAM_EXPORT EditorTool : public TQObject
+{
+ TQ_OBJECT
+
+
+public:
+
+ EditorTool(TQObject *parent);
+ virtual ~EditorTool();
+
+ void init();
+
+ TQString toolHelp() const;
+ TQString toolName() const;
+ TQPixmap toolIcon() const;
+ TQWidget* toolView() const;
+ EditorToolSettings* toolSettings() const;
+
+signals:
+
+ void okClicked();
+ void cancelClicked();
+
+protected:
+
+ void setToolHelp(const TQString& anchor);
+ void setToolName(const TQString& name);
+ void setToolIcon(const TQPixmap& icon);
+
+ virtual void setToolView(TQWidget *view);
+ virtual void setToolSettings(EditorToolSettings *settings);
+ virtual void setBusy(bool);
+ virtual void readSettings();
+ virtual void writeSettings();
+ virtual void finalRendering(){};
+
+protected slots:
+
+ void slotTimer();
+
+ virtual void slotOk();
+ virtual void slotCancel();
+ virtual void slotInit();
+ virtual void slotLoadSettings(){};
+ virtual void slotSaveAsSettings(){};
+ virtual void slotResetSettings();
+ virtual void slotEffect(){};
+
+private:
+
+ EditorToolPriv *d;
+};
+
+// -----------------------------------------------------------------
+
+class EditorToolThreadedPriv;
+
+class DIGIKAM_EXPORT EditorToolThreaded : public EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ enum RenderingMode
+ {
+ NoneRendering=0,
+ PreviewRendering,
+ FinalRendering
+ };
+
+public:
+
+ EditorToolThreaded(TQObject *parent);
+ virtual ~EditorToolThreaded();
+
+ /** Set the small text to show in editor status progress bar during
+ tool computation. If it's not set, tool name is used instead.
+ */
+ void setProgressMessage(const TQString& mess);
+
+ /** return the current tool rendering mode.
+ */
+ RenderingMode renderingMode() const;
+
+public slots:
+
+ virtual void slotAbort();
+
+protected:
+
+ DImgThreadedFilter* filter() const;
+ void setFilter(DImgThreadedFilter *filter);
+
+ void customEvent(TQCustomEvent *event);
+
+ virtual void setToolView(TQWidget *view);
+ virtual void prepareEffect(){};
+ virtual void prepareFinal(){};
+ virtual void putPreviewData(){};
+ virtual void putFinalData(){};
+ virtual void renderingFinished(){};
+
+protected slots:
+
+ virtual void slotOk();
+ virtual void slotCancel();
+ virtual void slotEffect();
+
+private slots:
+
+ void slotResized();
+
+private:
+
+ EditorToolThreadedPriv *d;
+};
+
+} //namespace Digikam
+
+#endif /* IMAGEPLUGIN_H */
diff --git a/src/utilities/imageeditor/editor/editortooliface.cpp b/src/utilities/imageeditor/editor/editortooliface.cpp
new file mode 100644
index 00000000..f666bbf2
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editortooliface.cpp
@@ -0,0 +1,147 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-20
+ * Description : Image editor interface used by editor tools.
+ *
+ * Copyright (C) 2008-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 <tqwidget.h>
+
+// Local includes.
+
+#include "sidebar.h"
+#include "canvas.h"
+#include "statusprogressbar.h"
+#include "editortool.h"
+#include "editortoolsettings.h"
+#include "editorstackview.h"
+#include "editorwindow.h"
+#include "editortooliface.h"
+#include "editortooliface.moc"
+
+namespace Digikam
+{
+
+class EditorToolIfacePriv
+{
+
+public:
+
+ EditorToolIfacePriv()
+ {
+ prevTab = 0;
+ editor = 0;
+ tool = 0;
+ }
+
+ TQWidget *prevTab;
+
+ EditorTool *tool;
+
+ EditorWindow *editor;
+};
+
+EditorToolIface* EditorToolIface::m_iface = 0;
+
+EditorToolIface* EditorToolIface::editorToolIface()
+{
+ return m_iface;
+}
+
+EditorToolIface::EditorToolIface(EditorWindow *editor)
+ : TQObject()
+{
+ d = new EditorToolIfacePriv;
+ d->editor = editor;
+ m_iface = this;
+}
+
+EditorToolIface::~EditorToolIface()
+{
+ delete d;
+ if (m_iface == this)
+ m_iface = 0;
+}
+
+EditorTool* EditorToolIface::currentTool() const
+{
+ return d->tool;
+}
+
+void EditorToolIface::loadTool(EditorTool* tool)
+{
+ if (d->tool) unLoadTool();
+
+ d->tool = tool;
+ d->editor->editorStackView()->setToolView(d->tool->toolView());
+ d->editor->editorStackView()->setViewMode(EditorStackView::ToolViewMode);
+ d->prevTab = d->editor->rightSideBar()->getActiveTab();
+ d->editor->rightSideBar()->appendTab(d->tool->toolSettings(), d->tool->toolIcon(), d->tool->toolName());
+ d->editor->rightSideBar()->setActiveTab(d->tool->toolSettings());
+ d->editor->toggleActions(false);
+
+ // If editor tool has zoomable preview, switch on zoom actions.
+ if (d->editor->editorStackView()->previewWidget())
+ d->editor->toggleZoomActions(true);
+}
+
+void EditorToolIface::unLoadTool()
+{
+ if (!d->tool) return;
+
+ d->editor->editorStackView()->setViewMode(EditorStackView::CanvasMode);
+ d->editor->editorStackView()->setToolView(0);
+ d->editor->rightSideBar()->deleteTab(d->tool->toolSettings());
+ d->editor->rightSideBar()->setActiveTab(d->prevTab);
+ d->editor->toggleActions(true);
+ // To restore canvas zoom level in zoom combobox.
+ if (!d->editor->editorStackView()->canvas()->fitToWindow())
+ d->editor->editorStackView()->setZoomFactor(d->editor->editorStackView()->canvas()->zoomFactor());
+ delete d->tool;
+ d->tool = 0;
+}
+
+void EditorToolIface::setToolStartProgress(const TQString& toolName)
+{
+ d->editor->setToolStartProgress(toolName);
+ if (d->editor->editorStackView()->previewWidget())
+ d->editor->toggleZoomActions(false);
+}
+
+void EditorToolIface::setToolProgress(int progress)
+{
+ d->editor->setToolProgress(progress);
+}
+
+void EditorToolIface::setToolStopProgress()
+{
+ d->editor->setToolStopProgress();
+ if (d->editor->editorStackView()->previewWidget())
+ d->editor->toggleZoomActions(true);
+}
+
+void EditorToolIface::slotToolAborted()
+{
+ EditorToolThreaded *tool = dynamic_cast<EditorToolThreaded*>(d->tool);
+ if (tool) tool->slotAbort();
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/editor/editortooliface.h b/src/utilities/imageeditor/editor/editortooliface.h
new file mode 100644
index 00000000..ce8708cf
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editortooliface.h
@@ -0,0 +1,76 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-20
+ * Description : Image editor interface used by editor tools.
+ *
+ * Copyright (C) 2008-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 EDITORTOOLIFACE_H
+#define EDITORTOOLIFACE_H
+
+// TQt includes.
+
+#include <tqobject.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class EditorTool;
+class EditorWindow;
+class EditorToolIfacePriv;
+
+class DIGIKAM_EXPORT EditorToolIface : public TQObject
+{
+ TQ_OBJECT
+
+
+public:
+
+ static EditorToolIface* editorToolIface();
+
+ EditorToolIface(EditorWindow *editor);
+ ~EditorToolIface();
+
+ EditorTool* currentTool() const;
+
+ void loadTool(EditorTool* tool);
+ void unLoadTool();
+
+ void setToolStartProgress(const TQString& toolName);
+ void setToolProgress(int progress);
+ void setToolStopProgress();
+
+public slots:
+
+ void slotToolAborted();
+
+private:
+
+ static EditorToolIface *m_iface;
+
+ EditorToolIfacePriv *d;
+};
+
+} // namespace Digikam
+
+#endif /* EDITORTOOLIFACE_H */
diff --git a/src/utilities/imageeditor/editor/editortoolsettings.cpp b/src/utilities/imageeditor/editor/editortoolsettings.cpp
new file mode 100644
index 00000000..3ac45ccf
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editortoolsettings.cpp
@@ -0,0 +1,331 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-21
+ * Description : Editor tool settings template box
+ *
+ * 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 <tqhbox.h>
+#include <tqvbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqstring.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <kcolorbutton.h>
+#include <kdialog.h>
+#include <tdeglobalsettings.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kpushbutton.h>
+#include <kstandarddirs.h>
+#include <kstdguiitem.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imagepaniconwidget.h"
+#include "editortoolsettings.h"
+#include "editortoolsettings.moc"
+
+using namespace KDcrawIface;
+
+namespace Digikam
+{
+
+class EditorToolSettingsPriv
+{
+
+public:
+
+ EditorToolSettingsPriv()
+ {
+ okBtn = 0;
+ cancelBtn = 0;
+ tryBtn = 0;
+ defaultBtn = 0;
+ mainVBox = 0;
+ plainPage = 0;
+ btnBox1 = 0;
+ btnBox2 = 0;
+ btnBox3 = 0;
+ saveAsBtn = 0;
+ loadBtn = 0;
+ guideBox = 0;
+ guideColorBt = 0;
+ guideSize = 0;
+ panIconView = 0;
+ }
+
+ TQHBox *btnBox1;
+ TQHBox *btnBox2;
+ TQHBox *btnBox3;
+ TQHBox *guideBox;
+
+ TQVBox *mainVBox;
+ TQWidget *plainPage;
+
+ KPushButton *okBtn;
+ KPushButton *cancelBtn;
+ KPushButton *tryBtn;
+ KPushButton *defaultBtn;
+ KPushButton *saveAsBtn;
+ KPushButton *loadBtn;
+
+ KColorButton *guideColorBt;
+
+ ImagePanIconWidget *panIconView;
+
+ RIntNumInput *guideSize;
+};
+
+EditorToolSettings::EditorToolSettings(int buttonMask, int toolMask, TQWidget *parent)
+ : TQScrollView(parent)
+{
+ d = new EditorToolSettingsPriv;
+
+ viewport()->setBackgroundMode(TQt::PaletteBackground);
+ setResizePolicy(TQScrollView::AutoOneFit);
+ setFrameStyle(TQFrame::NoFrame);
+
+ d->mainVBox = new TQVBox(viewport());
+ addChild(d->mainVBox);
+
+ // ---------------------------------------------------------------
+
+ TQFrame *frame = new TQFrame(d->mainVBox);
+ frame->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+ TQVBoxLayout* vlay = new TQVBoxLayout(frame, 5, 0);
+ d->panIconView = new ImagePanIconWidget(360, 240, frame);
+ TQWhatsThis::add(d->panIconView, i18n("<p>Here you can see the original image panel "
+ "which can help you to select the clip preview."
+ "<p>Click and drag the mouse cursor in the "
+ "red rectangle to change the clip focus."));
+ vlay->addWidget(d->panIconView, 0, TQt::AlignCenter);
+
+ if (!(toolMask & PanIcon))
+ frame->hide();
+
+ // ---------------------------------------------------------------
+
+ d->plainPage = new TQWidget(d->mainVBox);
+ d->guideBox = new TQHBox(d->mainVBox);
+ d->btnBox1 = new TQHBox(d->mainVBox);
+ d->btnBox2 = new TQHBox(d->mainVBox);
+
+ // ---------------------------------------------------------------
+
+ new TQLabel(i18n("Guide:"), d->guideBox);
+ TQLabel *space4 = new TQLabel(d->guideBox);
+ d->guideColorBt = new KColorButton(TQColor(TQt::red), d->guideBox);
+ TQWhatsThis::add(d->guideColorBt, i18n("<p>Set here the color used to draw guides dashed-lines."));
+ d->guideSize = new RIntNumInput(d->guideBox);
+ d->guideSize->setRange(1, 5, 1);
+ d->guideSize->setDefaultValue(1);
+ TQWhatsThis::add(d->guideSize, i18n("<p>Set here the width in pixels used to draw guides dashed-lines."));
+
+ d->guideBox->setStretchFactor(space4, 10);
+ d->guideBox->setSpacing(spacingHint());
+ d->guideBox->setMargin(0);
+
+ if (!(toolMask & ColorGuide))
+ d->guideBox->hide();
+
+ // ---------------------------------------------------------------
+
+ d->defaultBtn = new KPushButton(d->btnBox1);
+ d->defaultBtn->setGuiItem(KStdGuiItem::defaults());
+ d->defaultBtn->setIconSet(SmallIconSet("reload_page"));
+ TQToolTip::add(d->defaultBtn, i18n("<p>Reset all settings to their default values."));
+ if (!(buttonMask & Default))
+ d->defaultBtn->hide();
+
+ TQLabel *space = new TQLabel(d->btnBox1);
+
+ d->okBtn = new KPushButton(d->btnBox1);
+ d->okBtn->setGuiItem(KStdGuiItem::ok());
+ if (!(buttonMask & Ok))
+ d->okBtn->hide();
+
+ d->cancelBtn = new KPushButton(d->btnBox1);
+ d->cancelBtn->setGuiItem(KStdGuiItem::cancel());
+ if (!(buttonMask & Cancel))
+ d->cancelBtn->hide();
+
+ d->btnBox1->setStretchFactor(space, 10);
+ d->btnBox1->setSpacing(spacingHint());
+ d->btnBox1->setMargin(0);
+
+ if (!(buttonMask & Default) && !(buttonMask & Ok) && !(buttonMask & Cancel))
+ d->btnBox1->hide();
+
+ // ---------------------------------------------------------------
+
+ d->loadBtn = new KPushButton(d->btnBox2);
+ d->loadBtn->setGuiItem(KStdGuiItem::open());
+ d->loadBtn->setText(i18n("Load..."));
+ TQToolTip::add(d->loadBtn, i18n("<p>Load all parameters from settings text file."));
+ if (!(buttonMask & Load))
+ d->loadBtn->hide();
+
+ d->saveAsBtn = new KPushButton(d->btnBox2);
+ d->saveAsBtn->setGuiItem(KStdGuiItem::saveAs());
+ TQToolTip::add(d->saveAsBtn, i18n("<p>Save all parameters to settings text file."));
+ if (!(buttonMask & SaveAs))
+ d->saveAsBtn->hide();
+
+ TQLabel *space2 = new TQLabel(d->btnBox2);
+
+ d->tryBtn = new KPushButton(d->btnBox2);
+ d->tryBtn->setGuiItem(KStdGuiItem::apply());
+ d->tryBtn->setText(i18n("Try"));
+ TQToolTip::add(d->tryBtn, i18n("<p>Try all settings."));
+ if (!(buttonMask & Try))
+ d->tryBtn->hide();
+
+ d->btnBox2->setStretchFactor(space2, 10);
+ d->btnBox2->setSpacing(spacingHint());
+ d->btnBox2->setMargin(0);
+
+ if (!(buttonMask & Load) && !(buttonMask & SaveAs) && !(buttonMask & Try))
+ d->btnBox2->hide();
+
+ // ---------------------------------------------------------------
+
+ connect(d->okBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalOkClicked()));
+
+ connect(d->cancelBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalCancelClicked()));
+
+ connect(d->tryBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalTryClicked()));
+
+ connect(d->defaultBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalDefaultClicked()));
+
+ connect(d->saveAsBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalSaveAsClicked()));
+
+ connect(d->loadBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SIGNAL(signalLoadClicked()));
+
+ connect(d->guideColorBt, TQ_SIGNAL(changed(const TQColor&)),
+ this, TQ_SIGNAL(signalColorGuideChanged()));
+
+ connect(d->guideSize, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SIGNAL(signalColorGuideChanged()));
+}
+
+EditorToolSettings::~EditorToolSettings()
+{
+ delete d;
+}
+
+TQSize EditorToolSettings::minimumSizeHint() const
+{
+ // Editor Tools usually require a larger horizontal space than other widgets in right side bar
+ // Set scroll area to a horizontal minimum size sufficient for the settings.
+ // Do not touch vertical size hint.
+ // Limit to 40% of the desktop width.
+ TQSize hint = TQScrollView::minimumSizeHint();
+ TQRect desktopRect = TDEGlobalSettings::desktopGeometry(d->mainVBox);
+ hint.setWidth(TQMIN(d->mainVBox->minimumSizeHint().width(), desktopRect.width() * 2 / 5));
+ return hint;
+}
+
+int EditorToolSettings::marginHint()
+{
+ return KDialog::marginHint();
+}
+
+int EditorToolSettings::spacingHint()
+{
+ return KDialog::spacingHint();
+}
+
+TQWidget *EditorToolSettings::plainPage() const
+{
+ return d->plainPage;
+}
+
+ImagePanIconWidget* EditorToolSettings::panIconView() const
+{
+ return d->panIconView;
+}
+
+KPushButton* EditorToolSettings::button(int buttonCode) const
+{
+ if (buttonCode & Default)
+ return d->defaultBtn;
+
+ if (buttonCode & Try)
+ return d->tryBtn;
+
+ if (buttonCode & Ok)
+ return d->okBtn;
+
+ if (buttonCode & Cancel)
+ return d->cancelBtn;
+
+ if (buttonCode & Load)
+ return d->loadBtn;
+
+ if (buttonCode & SaveAs)
+ return d->saveAsBtn;
+
+ return 0;
+}
+
+void EditorToolSettings::enableButton(int buttonCode, bool state)
+{
+ KPushButton *btn = button(buttonCode);
+ if (btn) btn->setEnabled(state);
+}
+
+TQColor EditorToolSettings::guideColor() const
+{
+ return d->guideColorBt->color();
+}
+
+void EditorToolSettings::setGuideColor(const TQColor& color)
+{
+ d->guideColorBt->setColor(color);
+}
+
+int EditorToolSettings::guideSize() const
+{
+ return d->guideSize->value();
+}
+
+void EditorToolSettings::setGuideSize(int size)
+{
+ d->guideSize->setValue(size);
+}
+
+} // NameSpace Digikam
diff --git a/src/utilities/imageeditor/editor/editortoolsettings.h b/src/utilities/imageeditor/editor/editortoolsettings.h
new file mode 100644
index 00000000..062b2e34
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editortoolsettings.h
@@ -0,0 +1,110 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2008-08-21
+ * Description : Editor tool settings template box
+ *
+ * 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 EDITORTOOLSETTINGS_H
+#define EDITORTOOLSETTINGS_H
+
+// TQt includes.
+
+#include <tqscrollview.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+class KPushButton;
+
+namespace Digikam
+{
+
+class ImagePanIconWidget;
+class EditorToolSettingsPriv;
+
+class DIGIKAM_EXPORT EditorToolSettings : public TQScrollView
+{
+ TQ_OBJECT
+
+
+public:
+
+ enum ButtonCode
+ {
+ Default = 0x00000001,
+ Try = 0x00000002,
+ Ok = 0x00000004,
+ Cancel = 0x00000008,
+ SaveAs = 0x00000010,
+ Load = 0x00000020
+ };
+
+ enum ToolCode
+ {
+ NoTool = 0x00000001,
+ ColorGuide = 0x00000002,
+ PanIcon = 0x00000004
+ };
+
+public:
+
+ EditorToolSettings(int buttonMask, int toolMask=NoTool, TQWidget *parent=0);
+ ~EditorToolSettings();
+
+ virtual void setBusy(bool){};
+ virtual void writeSettings(){};
+ virtual void readSettings(){};
+ virtual void resetSettings(){};
+
+ int marginHint();
+ int spacingHint();
+
+ TQWidget *plainPage() const;
+
+ TQColor guideColor() const;
+ void setGuideColor(const TQColor& color);
+
+ int guideSize() const;
+ void setGuideSize(int size);
+
+ ImagePanIconWidget* panIconView() const;
+ KPushButton* button(int buttonCode) const;
+ void enableButton(int buttonCode, bool state);
+
+ virtual TQSize minimumSizeHint() const;
+
+signals:
+
+ void signalOkClicked();
+ void signalCancelClicked();
+ void signalTryClicked();
+ void signalDefaultClicked();
+ void signalSaveAsClicked();
+ void signalLoadClicked();
+ void signalColorGuideChanged();
+
+private:
+
+ EditorToolSettingsPriv *d;
+};
+
+} // NameSpace Digikam
+
+#endif // EDITORTOOLSETTINGS_H
diff --git a/src/utilities/imageeditor/editor/editorwindow.cpp b/src/utilities/imageeditor/editor/editorwindow.cpp
new file mode 100644
index 00000000..eed7cfea
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editorwindow.cpp
@@ -0,0 +1,1932 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-20
+ * Description : main image editor GUI implementation
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <sys/types.h>
+#include <sys/stat.h>
+}
+
+// C++ includes.
+
+#include <cmath>
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqdockarea.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqtoolbutton.h>
+#include <tqsplitter.h>
+#include <tqdir.h>
+#include <tqfileinfo.h>
+#include <tqfile.h>
+#include <tqcursor.h>
+#include <tqtimer.h>
+#include <tqfileinfo.h>
+
+// KDE includes.
+
+#include <kprinter.h>
+#include <kkeydialog.h>
+#include <tdeversion.h>
+#include <tdeaction.h>
+#include <kedittoolbar.h>
+#include <tdeaboutdata.h>
+#include <kcursor.h>
+#include <kstdaction.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <tdefiledialog.h>
+#include <tdemenubar.h>
+#include <kimageio.h>
+#include <tdeaccel.h>
+#include <tdemessagebox.h>
+#include <tdeglobal.h>
+#include <kstandarddirs.h>
+#include <kiconloader.h>
+#include <tdeio/netaccess.h>
+#include <tdeio/job.h>
+#include <kprotocolinfo.h>
+#include <tdeglobalsettings.h>
+#include <tdetoolbar.h>
+#include <kstatusbar.h>
+#include <kprogress.h>
+#include <twin.h>
+#include <kcombobox.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dpopupmenu.h"
+#include "canvas.h"
+#include "dimginterface.h"
+#include "imagedialog.h"
+#include "imageplugin.h"
+#include "imagepluginloader.h"
+#include "imageresize.h"
+#include "imageprint.h"
+#include "filesaveoptionsbox.h"
+#include "statusprogressbar.h"
+#include "iccsettingscontainer.h"
+#include "exposurecontainer.h"
+#include "iofilesettingscontainer.h"
+#include "savingcontextcontainer.h"
+#include "loadingcacheinterface.h"
+#include "slideshowsettings.h"
+#include "themeengine.h"
+#include "rawcameradlg.h"
+#include "editorstackview.h"
+#include "editortooliface.h"
+#include "editorwindowprivate.h"
+#include "editorwindow.h"
+#include "editorwindow.moc"
+
+void tqt_enter_modal( TQWidget *widget );
+void tqt_leave_modal( TQWidget *widget );
+
+namespace Digikam
+{
+
+EditorWindow::EditorWindow(const char *name)
+ : TDEMainWindow(0, name, WType_TopLevel)
+{
+ d = new EditorWindowPriv;
+
+ m_themeMenuAction = 0;
+ m_contextMenu = 0;
+ m_canvas = 0;
+ m_imagePluginLoader = 0;
+ m_undoAction = 0;
+ m_redoAction = 0;
+ m_fullScreenAction = 0;
+ m_saveAction = 0;
+ m_saveAsAction = 0;
+ m_revertAction = 0;
+ m_fileDeleteAction = 0;
+ m_forwardAction = 0;
+ m_backwardAction = 0;
+ m_firstAction = 0;
+ m_lastAction = 0;
+ m_undoAction = 0;
+ m_redoAction = 0;
+ m_stackView = 0;
+ m_fullScreen = false;
+ m_rotatedOrFlipped = false;
+ m_setExifOrientationTag = true;
+ m_cancelSlideShow = false;
+
+ // Settings containers instance.
+
+ d->ICCSettings = new ICCSettingsContainer();
+ d->exposureSettings = new ExposureSettingsContainer();
+ d->toolIface = new EditorToolIface(this);
+ m_IOFileSettings = new IOFileSettingsContainer();
+ m_savingContext = new SavingContextContainer();
+}
+
+EditorWindow::~EditorWindow()
+{
+ delete m_canvas;
+ delete m_IOFileSettings;
+ delete m_savingContext;
+ delete d->ICCSettings;
+ delete d->exposureSettings;
+ delete d;
+}
+
+EditorStackView* EditorWindow::editorStackView() const
+{
+ return m_stackView;
+}
+
+void EditorWindow::setupContextMenu()
+{
+ m_contextMenu = new DPopupMenu(this);
+ TDEActionCollection *ac = actionCollection();
+ if( ac->action("editorwindow_backward") ) ac->action("editorwindow_backward")->plug(m_contextMenu);
+ if( ac->action("editorwindow_forward") ) ac->action("editorwindow_forward")->plug(m_contextMenu);
+ m_contextMenu->insertSeparator();
+ if( ac->action("editorwindow_slideshow") ) ac->action("editorwindow_slideshow")->plug(m_contextMenu);
+ if( ac->action("editorwindow_rotate_left") ) ac->action("editorwindow_rotate_left")->plug(m_contextMenu);
+ if( ac->action("editorwindow_rotate_right") ) ac->action("editorwindow_rotate_right")->plug(m_contextMenu);
+ if( ac->action("editorwindow_crop") ) ac->action("editorwindow_crop")->plug(m_contextMenu);
+ m_contextMenu->insertSeparator();
+ if( ac->action("editorwindow_delete") ) ac->action("editorwindow_delete")->plug(m_contextMenu);
+}
+
+void EditorWindow::setupStandardConnections()
+{
+ // -- Canvas connections ------------------------------------------------
+
+ connect(m_canvas, TQ_SIGNAL(signalToggleOffFitToWindow()),
+ this, TQ_SLOT(slotToggleOffFitToWindow()));
+
+ connect(m_canvas, TQ_SIGNAL(signalShowNextImage()),
+ this, TQ_SLOT(slotForward()));
+
+ connect(m_canvas, TQ_SIGNAL(signalShowPrevImage()),
+ this, TQ_SLOT(slotBackward()));
+
+ connect(m_canvas, TQ_SIGNAL(signalRightButtonClicked()),
+ this, TQ_SLOT(slotContextMenu()));
+
+ connect(m_stackView, TQ_SIGNAL(signalZoomChanged(bool, bool, double)),
+ this, TQ_SLOT(slotZoomChanged(bool, bool, double)));
+
+ connect(m_canvas, TQ_SIGNAL(signalChanged()),
+ this, TQ_SLOT(slotChanged()));
+
+ connect(m_canvas, TQ_SIGNAL(signalUndoStateChanged(bool, bool, bool)),
+ this, TQ_SLOT(slotUndoStateChanged(bool, bool, bool)));
+
+ connect(m_canvas, TQ_SIGNAL(signalSelected(bool)),
+ this, TQ_SLOT(slotSelected(bool)));
+
+ connect(m_canvas, TQ_SIGNAL(signalPrepareToLoad()),
+ this, TQ_SLOT(slotPrepareToLoad()));
+
+ connect(m_canvas, TQ_SIGNAL(signalLoadingStarted(const TQString &)),
+ this, TQ_SLOT(slotLoadingStarted(const TQString &)));
+
+ connect(m_canvas, TQ_SIGNAL(signalLoadingFinished(const TQString &, bool)),
+ this, TQ_SLOT(slotLoadingFinished(const TQString &, bool)));
+
+ connect(m_canvas, TQ_SIGNAL(signalLoadingProgress(const TQString &, float)),
+ this, TQ_SLOT(slotLoadingProgress(const TQString &, float)));
+
+ connect(m_canvas, TQ_SIGNAL(signalSavingStarted(const TQString&)),
+ this, TQ_SLOT(slotSavingStarted(const TQString&)));
+
+ connect(m_canvas, TQ_SIGNAL(signalSavingFinished(const TQString&, bool)),
+ this, TQ_SLOT(slotSavingFinished(const TQString&, bool)));
+
+ connect(m_canvas, TQ_SIGNAL(signalSavingProgress(const TQString&, float)),
+ this, TQ_SLOT(slotSavingProgress(const TQString&, float)));
+
+ connect(m_canvas, TQ_SIGNAL(signalSelectionChanged(const TQRect&)),
+ this, TQ_SLOT(slotSelectionChanged(const TQRect&)));
+
+ // -- if rotating/flipping set the rotatedflipped flag to true -----------
+
+ connect(d->rotateLeftAction, TQ_SIGNAL(activated()),
+ this, TQ_SLOT(slotRotatedOrFlipped()));
+
+ connect(d->rotateRightAction, TQ_SIGNAL(activated()),
+ this, TQ_SLOT(slotRotatedOrFlipped()));
+
+ connect(d->flipHorizAction, TQ_SIGNAL(activated()),
+ this, TQ_SLOT(slotRotatedOrFlipped()));
+
+ connect(d->flipVertAction, TQ_SIGNAL(activated()),
+ this, TQ_SLOT(slotRotatedOrFlipped()));
+
+ // -- status bar connections --------------------------------------
+
+ connect(m_nameLabel, TQ_SIGNAL(signalCancelButtonPressed()),
+ this, TQ_SLOT(slotNameLabelCancelButtonPressed()));
+
+ connect(m_nameLabel, TQ_SIGNAL(signalCancelButtonPressed()),
+ d->toolIface, TQ_SLOT(slotToolAborted()));
+}
+
+void EditorWindow::setupStandardActions()
+{
+ // -- Standard 'File' menu actions ---------------------------------------------
+
+ m_backwardAction = KStdAction::back(this, TQ_SLOT(slotBackward()),
+ actionCollection(), "editorwindow_backward");
+
+ m_forwardAction = KStdAction::forward(this, TQ_SLOT(slotForward()),
+ actionCollection(), "editorwindow_forward");
+
+ m_firstAction = new TDEAction(i18n("&First"), "go-first",
+ TDEStdAccel::shortcut( TDEStdAccel::Home),
+ this, TQ_SLOT(slotFirst()),
+ actionCollection(), "editorwindow_first");
+
+ m_lastAction = new TDEAction(i18n("&Last"), "go-last",
+ TDEStdAccel::shortcut( TDEStdAccel::End),
+ this, TQ_SLOT(slotLast()),
+ actionCollection(), "editorwindow_last");
+
+ m_saveAction = KStdAction::save(this, TQ_SLOT(slotSave()),
+ actionCollection(), "editorwindow_save");
+
+ m_saveAsAction = KStdAction::saveAs(this, TQ_SLOT(slotSaveAs()),
+ actionCollection(), "editorwindow_saveas");
+
+ m_revertAction = KStdAction::revert(this, TQ_SLOT(slotRevert()),
+ actionCollection(), "editorwindow_revert");
+
+ m_saveAction->setEnabled(false);
+ m_saveAsAction->setEnabled(false);
+ m_revertAction->setEnabled(false);
+
+ d->filePrintAction = new TDEAction(i18n("Print Image..."), "document-print",
+ CTRL+Key_P,
+ this, TQ_SLOT(slotFilePrint()),
+ actionCollection(), "editorwindow_print");
+
+ m_fileDeleteAction = new TDEAction(i18n("Move to Trash"), "edittrash",
+ Key_Delete,
+ this, TQ_SLOT(slotDeleteCurrentItem()),
+ actionCollection(), "editorwindow_delete");
+
+ KStdAction::close(this, TQ_SLOT(close()), actionCollection(), "editorwindow_close");
+
+ // -- Standard 'Edit' menu actions ---------------------------------------------
+
+ d->copyAction = KStdAction::copy(m_canvas, TQ_SLOT(slotCopy()),
+ actionCollection(), "editorwindow_copy");
+
+ d->copyAction->setEnabled(false);
+
+ m_undoAction = new TDEToolBarPopupAction(i18n("Undo"), "edit-undo",
+ TDEStdAccel::shortcut(TDEStdAccel::Undo),
+ m_canvas, TQ_SLOT(slotUndo()),
+ actionCollection(), "editorwindow_undo");
+
+ connect(m_undoAction->popupMenu(), TQ_SIGNAL(aboutToShow()),
+ this, TQ_SLOT(slotAboutToShowUndoMenu()));
+
+ connect(m_undoAction->popupMenu(), TQ_SIGNAL(activated(int)),
+ m_canvas, TQ_SLOT(slotUndo(int)));
+
+ m_undoAction->setEnabled(false);
+
+ m_redoAction = new TDEToolBarPopupAction(i18n("Redo"), "edit-redo",
+ TDEStdAccel::shortcut(TDEStdAccel::Redo),
+ m_canvas, TQ_SLOT(slotRedo()),
+ actionCollection(), "editorwindow_redo");
+
+ connect(m_redoAction->popupMenu(), TQ_SIGNAL(aboutToShow()),
+ this, TQ_SLOT(slotAboutToShowRedoMenu()));
+
+ connect(m_redoAction->popupMenu(), TQ_SIGNAL(activated(int)),
+ m_canvas, TQ_SLOT(slotRedo(int)));
+
+ m_redoAction->setEnabled(false);
+
+ d->selectAllAction = new TDEAction(i18n("Select All"),
+ 0,
+ CTRL+Key_A,
+ m_canvas,
+ TQ_SLOT(slotSelectAll()),
+ actionCollection(),
+ "editorwindow_selectAll");
+
+ d->selectNoneAction = new TDEAction(i18n("Select None"),
+ 0,
+ CTRL+SHIFT+Key_A,
+ m_canvas,
+ TQ_SLOT(slotSelectNone()),
+ actionCollection(),
+ "editorwindow_selectNone");
+
+ // -- Standard 'View' menu actions ---------------------------------------------
+
+ d->zoomPlusAction = KStdAction::zoomIn(this, TQ_SLOT(slotIncreaseZoom()),
+ actionCollection(), "editorwindow_zoomplus");
+
+ d->zoomMinusAction = KStdAction::zoomOut(this, TQ_SLOT(slotDecreaseZoom()),
+ actionCollection(), "editorwindow_zoomminus");
+
+ d->zoomTo100percents = new TDEAction(i18n("Zoom to 100%"), "zoom-original",
+ ALT+CTRL+Key_0, // NOTE: Photoshop 7 use ALT+CTRL+0.
+ this, TQ_SLOT(slotZoomTo100Percents()),
+ actionCollection(), "editorwindow_zoomto100percents");
+
+
+ d->zoomFitToWindowAction = new TDEToggleAction(i18n("Fit to &Window"), "view_fit_window",
+ CTRL+SHIFT+Key_E, // NOTE: Gimp 2 use CTRL+SHIFT+E.
+ this, TQ_SLOT(slotToggleFitToWindow()),
+ actionCollection(), "editorwindow_zoomfit2window");
+
+ d->zoomFitToSelectAction = new TDEAction(i18n("Fit to &Selection"), "zoom-fit-best",
+ ALT+CTRL+Key_S, this, TQ_SLOT(slotFitToSelect()),
+ actionCollection(), "editorwindow_zoomfit2select");
+ d->zoomFitToSelectAction->setEnabled(false);
+ d->zoomFitToSelectAction->setWhatsThis(i18n("This option can be used to zoom the image to the "
+ "current selection area."));
+
+ d->zoomCombo = new KComboBox(true);
+ d->zoomCombo->setDuplicatesEnabled(false);
+ d->zoomCombo->setFocusPolicy(TQWidget::ClickFocus);
+ d->zoomCombo->setInsertionPolicy(TQComboBox::NoInsertion);
+ d->zoomComboAction = new KWidgetAction(d->zoomCombo, i18n("Zoom"), 0, 0, 0,
+ actionCollection(), "editorwindow_zoomto");
+
+ d->zoomCombo->insertItem(TQString("10%"));
+ d->zoomCombo->insertItem(TQString("25%"));
+ d->zoomCombo->insertItem(TQString("50%"));
+ d->zoomCombo->insertItem(TQString("75%"));
+ d->zoomCombo->insertItem(TQString("100%"));
+ d->zoomCombo->insertItem(TQString("150%"));
+ d->zoomCombo->insertItem(TQString("200%"));
+ d->zoomCombo->insertItem(TQString("300%"));
+ d->zoomCombo->insertItem(TQString("450%"));
+ d->zoomCombo->insertItem(TQString("600%"));
+ d->zoomCombo->insertItem(TQString("800%"));
+ d->zoomCombo->insertItem(TQString("1200%"));
+
+ connect(d->zoomCombo, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotZoomSelected()) );
+
+ connect(d->zoomCombo, TQ_SIGNAL(returnPressed(const TQString&)),
+ this, TQ_SLOT(slotZoomTextChanged(const TQString &)) );
+
+ // Do not use std KDE action for full screen because action text is too large for app. toolbar.
+ m_fullScreenAction = new TDEToggleAction(i18n("Full Screen"), "view-fullscreen",
+ CTRL+SHIFT+Key_F, this,
+ TQ_SLOT(slotToggleFullScreen()),
+ actionCollection(), "editorwindow_fullscreen");
+ m_fullScreenAction->setWhatsThis(i18n("Toggle the window to full screen mode"));
+
+ d->slideShowAction = new TDEAction(i18n("Slideshow"), "slideshow", Key_F9,
+ this, TQ_SLOT(slotToggleSlideShow()),
+ actionCollection(),"editorwindow_slideshow");
+
+ d->viewUnderExpoAction = new TDEToggleAction(i18n("Under-Exposure Indicator"), "underexposure",
+ Key_F10, this,
+ TQ_SLOT(slotToggleUnderExposureIndicator()),
+ actionCollection(),"editorwindow_underexposure");
+
+ d->viewOverExpoAction = new TDEToggleAction(i18n("Over-Exposure Indicator"), "overexposure",
+ Key_F11, this,
+ TQ_SLOT(slotToggleOverExposureIndicator()),
+ actionCollection(),"editorwindow_overexposure");
+
+ d->viewCMViewAction = new TDEToggleAction(i18n("Color Managed View"), "tv",
+ Key_F12, this,
+ TQ_SLOT(slotToggleColorManagedView()),
+ actionCollection(),"editorwindow_cmview");
+
+ // -- Standard 'Transform' menu actions ---------------------------------------------
+
+ d->resizeAction = new TDEAction(i18n("&Resize..."), "resize_image", 0,
+ this, TQ_SLOT(slotResize()),
+ actionCollection(), "editorwindow_resize");
+
+ d->cropAction = new TDEAction(i18n("Crop"), "crop",
+ CTRL+Key_X,
+ m_canvas, TQ_SLOT(slotCrop()),
+ actionCollection(), "editorwindow_crop");
+
+ d->cropAction->setEnabled(false);
+ d->cropAction->setWhatsThis(i18n("This option can be used to crop the image. "
+ "Select a region of the image to enable this action."));
+
+ // -- Standard 'Flip' menu actions ---------------------------------------------
+
+ d->flipHorizAction = new TDEAction(i18n("Flip Horizontally"), "mirror", CTRL+Key_Asterisk,
+ m_canvas, TQ_SLOT(slotFlipHoriz()),
+ actionCollection(), "editorwindow_flip_horiz");
+ d->flipHorizAction->setEnabled(false);
+
+ d->flipVertAction = new TDEAction(i18n("Flip Vertically"), "flip", CTRL+Key_Slash,
+ m_canvas, TQ_SLOT(slotFlipVert()),
+ actionCollection(), "editorwindow_flip_vert");
+ d->flipVertAction->setEnabled(false);
+
+ // -- Standard 'Rotate' menu actions ----------------------------------------
+
+ d->rotateLeftAction = new TDEAction(i18n("Rotate Left"),
+ "object-rotate-left", SHIFT+CTRL+Key_Left,
+ m_canvas, TQ_SLOT(slotRotate270()),
+ actionCollection(),
+ "editorwindow_rotate_left");
+ d->rotateLeftAction->setEnabled(false);
+ d->rotateRightAction = new TDEAction(i18n("Rotate Right"),
+ "object-rotate-right", SHIFT+CTRL+Key_Right,
+ m_canvas, TQ_SLOT(slotRotate90()),
+ actionCollection(),
+ "editorwindow_rotate_right");
+ d->rotateRightAction->setEnabled(false);
+
+ // -- Standard 'Configure' menu actions ----------------------------------------
+
+ d->showMenuBarAction = KStdAction::showMenubar(this, TQ_SLOT(slotShowMenuBar()), actionCollection());
+
+ KStdAction::keyBindings(this, TQ_SLOT(slotEditKeys()), actionCollection());
+ KStdAction::configureToolbars(this, TQ_SLOT(slotConfToolbars()), actionCollection());
+ KStdAction::preferences(this, TQ_SLOT(slotSetup()), actionCollection());
+
+ // -----------------------------------------------------------------------------------------
+
+ m_themeMenuAction = new TDESelectAction(i18n("&Themes"), 0, actionCollection(), "theme_menu");
+ m_themeMenuAction->setItems(ThemeEngine::instance()->themeNames());
+
+ connect(m_themeMenuAction, TQ_SIGNAL(activated(const TQString&)),
+ this, TQ_SLOT(slotChangeTheme(const TQString&)));
+
+ connect(ThemeEngine::instance(), TQ_SIGNAL(signalThemeChanged()),
+ this, TQ_SLOT(slotThemeChanged()));
+
+ // -- Standard 'Help' menu actions ---------------------------------------------
+
+ d->donateMoneyAction = new TDEAction(i18n("Donate..."),
+ 0, 0,
+ this, TQ_SLOT(slotDonateMoney()),
+ actionCollection(),
+ "editorwindow_donatemoney");
+
+ d->contributeAction = new TDEAction(i18n("Contribute..."),
+ 0, 0,
+ this, TQ_SLOT(slotContribute()),
+ actionCollection(),
+ "editorwindow_contribute");
+
+ d->rawCameraListAction = new TDEAction(i18n("Supported RAW Cameras"),
+ "kdcraw",
+ 0,
+ this,
+ TQ_SLOT(slotRawCameraList()),
+ actionCollection(),
+ "editorwindow_rawcameralist");
+}
+
+void EditorWindow::setupStandardAccelerators()
+{
+ d->accelerators = new TDEAccel(this);
+
+ d->accelerators->insert("Exit fullscreen", i18n("Exit Fullscreen mode"),
+ i18n("Exit out of the fullscreen mode"),
+ Key_Escape, this, TQ_SLOT(slotEscapePressed()),
+ false, true);
+
+ d->accelerators->insert("Next Image Key_Space", i18n("Next Image"),
+ i18n("Load Next Image"),
+ Key_Space, this, TQ_SLOT(slotForward()),
+ false, true);
+
+ d->accelerators->insert("Previous Image SHIFT+Key_Space", i18n("Previous Image"),
+ i18n("Load Previous Image"),
+ SHIFT+Key_Space, this, TQ_SLOT(slotBackward()),
+ false, true);
+
+ d->accelerators->insert("Previous Image Key_Backspace", i18n("Previous Image"),
+ i18n("Load Previous Image"),
+ Key_Backspace, this, TQ_SLOT(slotBackward()),
+ false, true);
+
+ d->accelerators->insert("Next Image Key_Next", i18n("Next Image"),
+ i18n("Load Next Image"),
+ Key_Next, this, TQ_SLOT(slotForward()),
+ false, true);
+
+ d->accelerators->insert("Previous Image Key_Prior", i18n("Previous Image"),
+ i18n("Load Previous Image"),
+ Key_Prior, this, TQ_SLOT(slotBackward()),
+ false, true);
+
+ d->accelerators->insert("Zoom Plus Key_Plus", i18n("Zoom In"),
+ i18n("Zoom in on Image"),
+ Key_Plus, this, TQ_SLOT(slotIncreaseZoom()),
+ false, true);
+
+ d->accelerators->insert("Zoom Plus Key_Minus", i18n("Zoom Out"),
+ i18n("Zoom out of Image"),
+ Key_Minus, this, TQ_SLOT(slotDecreaseZoom()),
+ false, true);
+
+ d->accelerators->insert("Redo CTRL+Key_Y", i18n("Redo"),
+ i18n("Redo Last action"),
+ CTRL+Key_Y, m_canvas, TQ_SLOT(slotRedo()),
+ false, true);
+}
+
+void EditorWindow::setupStatusBar()
+{
+ m_nameLabel = new StatusProgressBar(statusBar());
+ m_nameLabel->setAlignment(TQt::AlignCenter);
+ m_nameLabel->setMaximumHeight(fontMetrics().height()+2);
+ statusBar()->addWidget(m_nameLabel, 100);
+
+ d->selectLabel = new TQLabel(i18n("No selection"), statusBar());
+ d->selectLabel->setAlignment(TQt::AlignCenter);
+ d->selectLabel->setMaximumHeight(fontMetrics().height()+2);
+ statusBar()->addWidget(d->selectLabel, 100);
+ TQToolTip::add(d->selectLabel, i18n("Information about current selection area"));
+
+ m_resLabel = new TQLabel(statusBar());
+ m_resLabel->setAlignment(TQt::AlignCenter);
+ m_resLabel->setMaximumHeight(fontMetrics().height()+2);
+ statusBar()->addWidget(m_resLabel, 100);
+ TQToolTip::add(m_resLabel, i18n("Information about image size"));
+
+ d->underExposureIndicator = new TQToolButton(statusBar());
+ d->underExposureIndicator->setIconSet(SmallIcon("underexposure"));
+ d->underExposureIndicator->setToggleButton(true);
+ statusBar()->addWidget(d->underExposureIndicator, 1);
+
+ d->overExposureIndicator = new TQToolButton(statusBar());
+ d->overExposureIndicator->setIconSet(SmallIcon("overexposure"));
+ d->overExposureIndicator->setToggleButton(true);
+ statusBar()->addWidget(d->overExposureIndicator, 1);
+
+ d->cmViewIndicator = new TQToolButton(statusBar());
+ d->cmViewIndicator->setIconSet(SmallIcon("tv"));
+ d->cmViewIndicator->setToggleButton(true);
+ statusBar()->addWidget(d->cmViewIndicator, 1);
+
+ connect(d->underExposureIndicator, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotToggleUnderExposureIndicator()));
+
+ connect(d->overExposureIndicator, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotToggleOverExposureIndicator()));
+
+ connect(d->cmViewIndicator, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotToggleColorManagedView()));
+}
+
+void EditorWindow::printImage(KURL url)
+{
+ uchar* ptr = m_canvas->interface()->getImage();
+ int w = m_canvas->interface()->origWidth();
+ int h = m_canvas->interface()->origHeight();
+ bool hasAlpha = m_canvas->interface()->hasAlpha();
+ bool sixteenBit = m_canvas->interface()->sixteenBit();
+
+ if (!ptr || !w || !h)
+ return;
+
+ DImg image(w, h, sixteenBit, hasAlpha, ptr);
+
+ KPrinter printer;
+ TQString appName = TDEApplication::kApplication()->aboutData()->appName();
+ printer.setDocName( url.filename() );
+ printer.setCreator( appName );
+#if KDE_IS_VERSION(3,2,0)
+ printer.setUsePrinterResolution(true);
+#endif
+
+ KPrinter::addDialogPage( new ImageEditorPrintDialogPage(image, this, TQString(appName.append(" page")).ascii() ));
+
+ if ( printer.setup( this, i18n("Print %1").arg(printer.docName().section('/', -1)) ) )
+ {
+ ImagePrint printOperations(image, printer, url.filename());
+ if (!printOperations.printImageWithTQt())
+ {
+ KMessageBox::error(this, i18n("Failed to print file: '%1'")
+ .arg(url.filename()));
+ }
+ }
+}
+
+void EditorWindow::slotEditKeys()
+{
+ KKeyDialog dialog(true, this);
+ dialog.insert( actionCollection(), i18n( "General" ) );
+
+ TQPtrList<ImagePlugin> pluginList = ImagePluginLoader::instance()->pluginList();
+
+ for (ImagePlugin* plugin = pluginList.first();
+ plugin; plugin = pluginList.next())
+ {
+ if (plugin)
+ {
+ dialog.insert( plugin->actionCollection(), plugin->name() );
+ }
+ }
+
+ dialog.configure();
+}
+
+void EditorWindow::slotResize()
+{
+ ImageResize dlg(this);
+ dlg.exec();
+}
+
+void EditorWindow::slotAboutToShowUndoMenu()
+{
+ m_undoAction->popupMenu()->clear();
+ TQStringList titles;
+ m_canvas->getUndoHistory(titles);
+
+ if(!titles.isEmpty())
+ {
+ int id = 1;
+ TQStringList::Iterator iter = titles.begin();
+ for(; iter != titles.end(); ++iter,++id)
+ {
+ m_undoAction->popupMenu()->insertItem(*iter, id);
+ }
+ }
+}
+
+void EditorWindow::slotAboutToShowRedoMenu()
+{
+ m_redoAction->popupMenu()->clear();
+ TQStringList titles;
+ m_canvas->getRedoHistory(titles);
+
+ if(!titles.isEmpty())
+ {
+ int id = 1;
+ TQStringList::Iterator iter = titles.begin();
+ for(; iter != titles.end(); ++iter,++id)
+ {
+ m_redoAction->popupMenu()->insertItem(*iter, id);
+ }
+ }
+}
+
+void EditorWindow::slotConfToolbars()
+{
+ saveMainWindowSettings(TDEGlobal::config(), "ImageViewer Settings");
+ KEditToolbar dlg(factory(), this);
+
+ connect(&dlg, TQ_SIGNAL(newToolbarConfig()),
+ this, TQ_SLOT(slotNewToolbarConfig()));
+
+ dlg.exec();
+}
+
+void EditorWindow::slotNewToolbarConfig()
+{
+ applyMainWindowSettings(TDEGlobal::config(), "ImageViewer Settings");
+}
+
+void EditorWindow::slotIncreaseZoom()
+{
+ m_stackView->increaseZoom();
+}
+
+void EditorWindow::slotDecreaseZoom()
+{
+ m_stackView->decreaseZoom();
+}
+
+void EditorWindow::slotToggleFitToWindow()
+{
+ d->zoomPlusAction->setEnabled(true);
+ d->zoomComboAction->setEnabled(true);
+ d->zoomMinusAction->setEnabled(true);
+ m_stackView->toggleFitToWindow();
+}
+
+void EditorWindow::slotFitToSelect()
+{
+ d->zoomPlusAction->setEnabled(true);
+ d->zoomComboAction->setEnabled(true);
+ d->zoomMinusAction->setEnabled(true);
+ m_stackView->fitToSelect();
+}
+
+void EditorWindow::slotZoomTo100Percents()
+{
+ d->zoomPlusAction->setEnabled(true);
+ d->zoomComboAction->setEnabled(true);
+ d->zoomMinusAction->setEnabled(true);
+ m_stackView->zoomTo100Percents();
+}
+
+void EditorWindow::slotZoomSelected()
+{
+ TQString txt = d->zoomCombo->currentText();
+ txt = txt.left(txt.find('%'));
+ slotZoomTextChanged(txt);
+}
+
+void EditorWindow::slotZoomTextChanged(const TQString &txt)
+{
+ bool r = false;
+ double zoom = TDEGlobal::locale()->readNumber(txt, &r) / 100.0;
+ if (r && zoom > 0.0)
+ m_stackView->setZoomFactor(zoom);
+}
+
+void EditorWindow::slotZoomChanged(bool isMax, bool isMin, double zoom)
+{
+ d->zoomPlusAction->setEnabled(!isMax);
+ d->zoomMinusAction->setEnabled(!isMin);
+
+ d->zoomCombo->blockSignals(true);
+ d->zoomCombo->setCurrentText(TQString::number(lround(zoom*100.0)) + TQString("%"));
+ d->zoomCombo->blockSignals(false);
+}
+
+void EditorWindow::slotToggleOffFitToWindow()
+{
+ d->zoomFitToWindowAction->blockSignals(true);
+ d->zoomFitToWindowAction->setChecked(false);
+ d->zoomFitToWindowAction->blockSignals(false);
+}
+
+void EditorWindow::slotEscapePressed()
+{
+ if (m_fullScreen)
+ m_fullScreenAction->activate();
+}
+
+void EditorWindow::plugActionAccel(TDEAction* action)
+{
+ if (!action)
+ return;
+
+ d->accelerators->insert(action->text(),
+ action->text(),
+ action->whatsThis(),
+ action->shortcut(),
+ action,
+ TQ_SLOT(activate()));
+}
+
+void EditorWindow::unplugActionAccel(TDEAction* action)
+{
+ d->accelerators->remove(action->text());
+}
+
+void EditorWindow::loadImagePlugins()
+{
+ TQPtrList<ImagePlugin> pluginList = m_imagePluginLoader->pluginList();
+
+ for (ImagePlugin* plugin = pluginList.first();
+ plugin; plugin = pluginList.next())
+ {
+ if (plugin)
+ {
+ guiFactory()->addClient(plugin);
+ plugin->setEnabledSelectionActions(false);
+ }
+ else
+ DDebug() << "Invalid plugin to add!" << endl;
+ }
+}
+
+void EditorWindow::unLoadImagePlugins()
+{
+ TQPtrList<ImagePlugin> pluginList = m_imagePluginLoader->pluginList();
+
+ for (ImagePlugin* plugin = pluginList.first();
+ plugin; plugin = pluginList.next())
+ {
+ if (plugin)
+ {
+ guiFactory()->removeClient(plugin);
+ plugin->setEnabledSelectionActions(false);
+ }
+ }
+}
+
+void EditorWindow::readStandardSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("ImageViewer Settings");
+
+ // Restore full screen Mode ?
+
+ if (config->readBoolEntry("FullScreen", false))
+ {
+ m_fullScreenAction->activate();
+ m_fullScreen = true;
+ }
+
+ // Restore Auto zoom action ?
+ bool autoZoom = config->readBoolEntry("AutoZoom", true);
+ if (autoZoom)
+ d->zoomFitToWindowAction->activate();
+}
+
+void EditorWindow::applyStandardSettings()
+{
+ TDEConfig* config = kapp->config();
+
+ // -- Settings for Color Management stuff ----------------------------------------------
+
+ config->setGroup("Color Management");
+
+ d->ICCSettings->enableCMSetting = config->readBoolEntry("EnableCM", false);
+ d->ICCSettings->askOrApplySetting = config->readBoolEntry("BehaviourICC", false);
+ d->ICCSettings->BPCSetting = config->readBoolEntry("BPCAlgorithm",false);
+ d->ICCSettings->managedViewSetting = config->readBoolEntry("ManagedView", false);
+ d->ICCSettings->renderingSetting = config->readNumEntry("RenderingIntent");
+ d->ICCSettings->inputSetting = config->readPathEntry("InProfileFile", TQString());
+ d->ICCSettings->workspaceSetting = config->readPathEntry("WorkProfileFile", TQString());
+ d->ICCSettings->monitorSetting = config->readPathEntry("MonitorProfileFile", TQString());
+ d->ICCSettings->proofSetting = config->readPathEntry("ProofProfileFile", TQString());
+
+ d->viewCMViewAction->setEnabled(d->ICCSettings->enableCMSetting);
+ d->viewCMViewAction->setChecked(d->ICCSettings->managedViewSetting);
+ d->cmViewIndicator->setEnabled(d->ICCSettings->enableCMSetting);
+ d->cmViewIndicator->setOn(d->ICCSettings->managedViewSetting);
+ setColorManagedViewIndicatorToolTip(d->ICCSettings->enableCMSetting, d->ICCSettings->managedViewSetting);
+ m_canvas->setICCSettings(d->ICCSettings);
+
+ // -- JPEG, PNG, TIFF JPEG2000 files format settings --------------------------------------
+
+ config->setGroup("ImageViewer Settings");
+
+ // JPEG quality slider settings : 1 - 100 ==> libjpeg settings : 25 - 100.
+ m_IOFileSettings->JPEGCompression = (int)((75.0/100.0)*
+ (float)config->readNumEntry("JPEGCompression", 75)
+ + 26.0 - (75.0/100.0));
+
+ m_IOFileSettings->JPEGSubSampling = config->readNumEntry("JPEGSubSampling", 1); // Medium subsampling
+
+ // PNG compression slider settings : 1 - 9 ==> libpng settings : 100 - 1.
+ m_IOFileSettings->PNGCompression = (int)(((1.0-100.0)/8.0)*
+ (float)config->readNumEntry("PNGCompression", 1)
+ + 100.0 - ((1.0-100.0)/8.0));
+
+ // TIFF compression setting.
+ m_IOFileSettings->TIFFCompression = config->readBoolEntry("TIFFCompression", false);
+
+ // JPEG2000 quality slider settings : 1 - 100
+ m_IOFileSettings->JPEG2000Compression = config->readNumEntry("JPEG2000Compression", 100);
+
+ // JPEG2000 LossLess setting.
+ m_IOFileSettings->JPEG2000LossLess = config->readBoolEntry("JPEG2000LossLess", true);
+
+ // -- RAW images decoding settings ------------------------------------------------------
+
+ // If digiKam Color Management is enable, no need to correct color of decoded RAW image,
+ // else, sRGB color workspace will be used.
+
+ if (d->ICCSettings->enableCMSetting)
+ m_IOFileSettings->rawDecodingSettings.outputColorSpace = DRawDecoding::RAWCOLOR;
+ else
+ m_IOFileSettings->rawDecodingSettings.outputColorSpace = DRawDecoding::SRGB;
+
+ m_IOFileSettings->rawDecodingSettings.sixteenBitsImage = config->readBoolEntry("SixteenBitsImage", false);
+ m_IOFileSettings->rawDecodingSettings.whiteBalance = (DRawDecoding::WhiteBalance)config->readNumEntry("WhiteBalance",
+ DRawDecoding::CAMERA);
+ m_IOFileSettings->rawDecodingSettings.customWhiteBalance = config->readNumEntry("CustomWhiteBalance", 6500);
+ m_IOFileSettings->rawDecodingSettings.customWhiteBalanceGreen = config->readDoubleNumEntry("CustomWhiteBalanceGreen", 1.0);
+ m_IOFileSettings->rawDecodingSettings.RGBInterpolate4Colors = config->readBoolEntry("RGBInterpolate4Colors", false);
+ m_IOFileSettings->rawDecodingSettings.DontStretchPixels = config->readBoolEntry("DontStretchPixels", false);
+ m_IOFileSettings->rawDecodingSettings.enableNoiseReduction = config->readBoolEntry("EnableNoiseReduction", false);
+ m_IOFileSettings->rawDecodingSettings.unclipColors = config->readNumEntry("UnclipColors", 0);
+ m_IOFileSettings->rawDecodingSettings.RAWQuality = (DRawDecoding::DecodingQuality)config->readNumEntry("RAWQuality",
+ DRawDecoding::BILINEAR);
+ m_IOFileSettings->rawDecodingSettings.NRThreshold = config->readNumEntry("NRThreshold", 100);
+ m_IOFileSettings->rawDecodingSettings.enableCACorrection = config->readBoolEntry("EnableCACorrection", false);
+ m_IOFileSettings->rawDecodingSettings.caMultiplier[0] = config->readDoubleNumEntry("caRedMultiplier", 1.0);
+ m_IOFileSettings->rawDecodingSettings.caMultiplier[1] = config->readDoubleNumEntry("caBlueMultiplier", 1.0);
+ m_IOFileSettings->rawDecodingSettings.brightness = config->readDoubleNumEntry("RAWBrightness", 1.0);
+ m_IOFileSettings->rawDecodingSettings.medianFilterPasses = config->readNumEntry("MedianFilterPasses", 0);
+
+ m_IOFileSettings->useRAWImport = config->readBoolEntry("UseRawImportTool", false);
+
+ // -- GUI Settings -------------------------------------------------------
+
+ TQSizePolicy rightSzPolicy(TQSizePolicy::Preferred, TQSizePolicy::Expanding, 2, 1);
+ if(config->hasKey("Splitter Sizes"))
+ m_splitter->setSizes(config->readIntListEntry("Splitter Sizes"));
+ else
+ m_canvas->setSizePolicy(rightSzPolicy);
+
+ d->fullScreenHideToolBar = config->readBoolEntry("FullScreen Hide ToolBar", false);
+
+ slotThemeChanged();
+
+ // -- Exposure Indicators Settings ---------------------------------------
+
+ TQColor black(TQt::black);
+ TQColor white(TQt::white);
+ d->exposureSettings->underExposureIndicator = config->readBoolEntry("UnderExposureIndicator", false);
+ d->exposureSettings->overExposureIndicator = config->readBoolEntry("OverExposureIndicator", false);
+ d->exposureSettings->underExposureColor = config->readColorEntry("UnderExposureColor", &white);
+ d->exposureSettings->overExposureColor = config->readColorEntry("OverExposureColor", &black);
+
+ d->viewUnderExpoAction->setChecked(d->exposureSettings->underExposureIndicator);
+ d->viewOverExpoAction->setChecked(d->exposureSettings->overExposureIndicator);
+ d->underExposureIndicator->setOn(d->exposureSettings->underExposureIndicator);
+ d->overExposureIndicator->setOn(d->exposureSettings->overExposureIndicator);
+ setUnderExposureToolTip(d->exposureSettings->underExposureIndicator);
+ setOverExposureToolTip(d->exposureSettings->overExposureIndicator);
+ m_canvas->setExposureSettings(d->exposureSettings);
+}
+
+void EditorWindow::saveStandardSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("ImageViewer Settings");
+
+ config->writeEntry("AutoZoom", d->zoomFitToWindowAction->isChecked());
+ config->writeEntry("Splitter Sizes", m_splitter->sizes());
+
+ config->writeEntry("FullScreen", m_fullScreenAction->isChecked());
+ config->writeEntry("UnderExposureIndicator", d->exposureSettings->underExposureIndicator);
+ config->writeEntry("OverExposureIndicator", d->exposureSettings->overExposureIndicator);
+
+ config->sync();
+}
+
+/** Method used by Editor Tools. Only Zoom+ and Zoom- are currently supported.
+ TODO: Fix this behavour when editor tool preview widgets will be factored.
+ */
+void EditorWindow::toggleZoomActions(bool val)
+{
+ d->zoomMinusAction->setEnabled(val);
+ d->zoomPlusAction->setEnabled(val);
+}
+
+void EditorWindow::toggleStandardActions(bool val)
+{
+ d->zoomComboAction->setEnabled(val);
+ d->zoomTo100percents->setEnabled(val);
+ d->zoomFitToWindowAction->setEnabled(val);
+ d->zoomFitToSelectAction->setEnabled(val);
+ toggleZoomActions(val);
+
+ d->rotateLeftAction->setEnabled(val);
+ d->rotateRightAction->setEnabled(val);
+ d->flipHorizAction->setEnabled(val);
+ d->flipVertAction->setEnabled(val);
+ d->filePrintAction->setEnabled(val);
+ d->resizeAction->setEnabled(val);
+ m_fileDeleteAction->setEnabled(val);
+ m_saveAsAction->setEnabled(val);
+ d->selectAllAction->setEnabled(val);
+ d->selectNoneAction->setEnabled(val);
+ d->slideShowAction->setEnabled(val);
+
+ // these actions are special: They are turned off if val is false,
+ // but if val is true, they may be turned on or off.
+ if (val)
+ {
+ // Trigger sending of signalUndoStateChanged
+ // Note that for saving and loading, this is not necessary
+ // because the signal will be sent later anyway.
+ m_canvas->updateUndoState();
+ }
+ else
+ {
+ m_saveAction->setEnabled(val);
+ m_undoAction->setEnabled(val);
+ m_redoAction->setEnabled(val);
+ }
+
+ TQPtrList<ImagePlugin> pluginList = m_imagePluginLoader->pluginList();
+
+ for (ImagePlugin* plugin = pluginList.first();
+ plugin; plugin = pluginList.next())
+ {
+ if (plugin)
+ {
+ plugin->setEnabledActions(val);
+ }
+ }
+}
+
+void EditorWindow::slotToggleFullScreen()
+{
+ if (m_fullScreen) // out of fullscreen
+ {
+ m_canvas->setBackgroundColor(m_bgColor);
+
+ setWindowState( windowState() & ~WindowFullScreen );
+ menuBar()->show();
+ statusBar()->show();
+ leftDock()->show();
+ rightDock()->show();
+ topDock()->show();
+ bottomDock()->show();
+
+ TQObject* obj = child("ToolBar","TDEToolBar");
+
+ if (obj)
+ {
+ TDEToolBar* toolBar = static_cast<TDEToolBar*>(obj);
+
+ if (m_fullScreenAction->isPlugged(toolBar) && d->removeFullScreenButton)
+ m_fullScreenAction->unplug(toolBar);
+
+ if (toolBar->isHidden())
+ showToolBars();
+ }
+
+ // -- remove the gui action accels ----
+
+ unplugActionAccel(m_forwardAction);
+ unplugActionAccel(m_backwardAction);
+ unplugActionAccel(m_firstAction);
+ unplugActionAccel(m_lastAction);
+ unplugActionAccel(m_saveAction);
+ unplugActionAccel(m_saveAsAction);
+ unplugActionAccel(d->zoomPlusAction);
+ unplugActionAccel(d->zoomMinusAction);
+ unplugActionAccel(d->zoomFitToWindowAction);
+ unplugActionAccel(d->zoomFitToSelectAction);
+ unplugActionAccel(d->cropAction);
+ unplugActionAccel(d->filePrintAction);
+ unplugActionAccel(m_fileDeleteAction);
+ unplugActionAccel(d->selectAllAction);
+ unplugActionAccel(d->selectNoneAction);
+
+ toggleGUI2FullScreen();
+ m_fullScreen = false;
+ }
+ else // go to fullscreen
+ {
+ m_canvas->setBackgroundColor(TQColor(TQt::black));
+
+ // hide the menubar and the statusbar
+ menuBar()->hide();
+ statusBar()->hide();
+ topDock()->hide();
+ leftDock()->hide();
+ rightDock()->hide();
+ bottomDock()->hide();
+
+ TQObject* obj = child("ToolBar","TDEToolBar");
+
+ if (obj)
+ {
+ TDEToolBar* toolBar = static_cast<TDEToolBar*>(obj);
+
+ if (d->fullScreenHideToolBar)
+ {
+ hideToolBars();
+ }
+ else
+ {
+ showToolBars();
+
+ if ( !m_fullScreenAction->isPlugged(toolBar) )
+ {
+ m_fullScreenAction->plug(toolBar);
+ d->removeFullScreenButton=true;
+ }
+ else
+ {
+ // If FullScreen button is enable in toolbar settings
+ // We don't remove it when we out of fullscreen mode.
+ d->removeFullScreenButton=false;
+ }
+ }
+ }
+
+ // -- Insert all the gui actions into the accel --
+
+ plugActionAccel(m_forwardAction);
+ plugActionAccel(m_backwardAction);
+ plugActionAccel(m_firstAction);
+ plugActionAccel(m_lastAction);
+ plugActionAccel(m_saveAction);
+ plugActionAccel(m_saveAsAction);
+ plugActionAccel(d->zoomPlusAction);
+ plugActionAccel(d->zoomMinusAction);
+ plugActionAccel(d->zoomFitToWindowAction);
+ plugActionAccel(d->zoomFitToSelectAction);
+ plugActionAccel(d->cropAction);
+ plugActionAccel(d->filePrintAction);
+ plugActionAccel(m_fileDeleteAction);
+ plugActionAccel(d->selectAllAction);
+ plugActionAccel(d->selectNoneAction);
+
+ toggleGUI2FullScreen();
+ showFullScreen();
+ m_fullScreen = true;
+ }
+}
+
+void EditorWindow::slotRotatedOrFlipped()
+{
+ m_rotatedOrFlipped = true;
+}
+
+void EditorWindow::slotLoadingProgress(const TQString&, float progress)
+{
+ m_nameLabel->setProgressValue((int)(progress*100.0));
+}
+
+void EditorWindow::slotSavingProgress(const TQString&, float progress)
+{
+ m_nameLabel->setProgressValue((int)(progress*100.0));
+}
+
+bool EditorWindow::promptForOverWrite()
+{
+ TQFileInfo fi(m_canvas->currentImageFilePath());
+ TQString warnMsg(i18n("About to overwrite file \"%1\"\nAre you sure?")
+ .arg(fi.fileName()));
+ return (KMessageBox::warningContinueCancel(this,
+ warnMsg,
+ i18n("Warning"),
+ i18n("Overwrite"),
+ "editorWindowSaveOverwrite")
+ == KMessageBox::Continue);
+}
+
+bool EditorWindow::promptUserSave(const KURL& url)
+{
+ if (m_saveAction->isEnabled())
+ {
+ // if window is iconified, show it
+ if (isMinimized())
+ {
+ KWin::deIconifyWindow(winId());
+ }
+
+ int result = KMessageBox::warningYesNoCancel(this,
+ i18n("The image '%1' has been modified.\n"
+ "Do you want to save it?")
+ .arg(url.filename()),
+ TQString(),
+ KStdGuiItem::save(),
+ KStdGuiItem::discard());
+
+ if (result == KMessageBox::Yes)
+ {
+ bool saving = false;
+
+ if (m_canvas->isReadOnly())
+ saving = saveAs();
+ else if (promptForOverWrite())
+ saving = save();
+
+ // save and saveAs return false if they were cancelled and did not enter saving at all
+ // In this case, do not call enter_loop because exit_loop will not be called.
+ if (saving)
+ {
+ // Waiting for asynchronous image file saving operation runing in separate thread.
+ m_savingContext->synchronizingState = SavingContextContainer::SynchronousSaving;
+ enter_loop();
+ m_savingContext->synchronizingState = SavingContextContainer::NormalSaving;
+ return m_savingContext->synchronousSavingResult;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (result == KMessageBox::No)
+ {
+ m_saveAction->setEnabled(false);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool EditorWindow::waitForSavingToComplete()
+{
+ // avoid reentrancy - return false means we have reentered the loop already.
+ if (m_savingContext->synchronizingState == SavingContextContainer::SynchronousSaving)
+ return false;
+
+ if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
+ {
+ // Waiting for asynchronous image file saving operation runing in separate thread.
+ m_savingContext->synchronizingState = SavingContextContainer::SynchronousSaving;
+ KMessageBox::queuedMessageBox(this,
+ KMessageBox::Information,
+ i18n("Please wait while the image is being saved..."));
+ enter_loop();
+ m_savingContext->synchronizingState = SavingContextContainer::NormalSaving;
+ }
+ return true;
+}
+
+void EditorWindow::enter_loop()
+{
+ TQWidget dummy(0, 0, WType_Dialog | WShowModal);
+ dummy.setFocusPolicy( TQWidget::NoFocus );
+ tqt_enter_modal(&dummy);
+ tqApp->enter_loop();
+ tqt_leave_modal(&dummy);
+}
+
+void EditorWindow::slotSelected(bool val)
+{
+ // Update menu actions.
+ d->cropAction->setEnabled(val);
+ d->zoomFitToSelectAction->setEnabled(val);
+ d->copyAction->setEnabled(val);
+
+ for (ImagePlugin* plugin = m_imagePluginLoader->pluginList().first();
+ plugin; plugin = m_imagePluginLoader->pluginList().next())
+ {
+ if (plugin)
+ {
+ plugin->setEnabledSelectionActions(val);
+ }
+ }
+
+ TQRect sel = m_canvas->getSelectedArea();
+ // Update histogram into sidebar.
+ emit signalSelectionChanged(sel);
+
+ // Update status bar
+ if (val)
+ d->selectLabel->setText(TQString("(%1, %2) (%3 x %4)").arg(sel.x()).arg(sel.y())
+ .arg(sel.width()).arg(sel.height()));
+ else
+ d->selectLabel->setText(i18n("No selection"));
+}
+
+void EditorWindow::hideToolBars()
+{
+ TQPtrListIterator<TDEToolBar> it = toolBarIterator();
+ TDEToolBar* bar;
+
+ for(;it.current()!=0L; ++it)
+ {
+ bar = it.current();
+
+ if (bar->area())
+ bar->area()->hide();
+ else
+ bar->hide();
+ }
+}
+
+void EditorWindow::showToolBars()
+{
+ TQPtrListIterator<TDEToolBar> it = toolBarIterator();
+ TDEToolBar* bar;
+
+ for( ; it.current()!=0L ; ++it)
+ {
+ bar = it.current();
+
+ if (bar->area())
+ bar->area()->show();
+ else
+ bar->show();
+ }
+}
+
+void EditorWindow::slotPrepareToLoad()
+{
+ // Disable actions as appropriate during loading
+ emit signalNoCurrentItem();
+ toggleActions(false);
+ slotUpdateItemInfo();
+}
+
+void EditorWindow::slotLoadingStarted(const TQString& /*filename*/)
+{
+ setCursor( KCursor::waitCursor() );
+
+ m_nameLabel->progressBarMode(StatusProgressBar::ProgressBarMode, i18n("Loading: "));
+}
+
+void EditorWindow::slotLoadingFinished(const TQString& filename, bool success)
+{
+ m_nameLabel->progressBarMode(StatusProgressBar::TextMode);
+ slotUpdateItemInfo();
+
+ // Enable actions as appropriate after loading
+ // No need to re-enable image properties sidebar here, it's will be done
+ // automatically by a signal from canvas
+ toggleActions(success);
+ unsetCursor();
+
+ // Note: in showfoto, we using a null filename to clear canvas.
+ if (!success && filename != TQString())
+ {
+ TQFileInfo fi(filename);
+ TQString message = i18n("Failed to load image \"%1\"").arg(fi.fileName());
+ KMessageBox::error(this, message);
+ DWarning() << "Failed to load image " << fi.fileName() << endl;
+ }
+}
+
+void EditorWindow::slotNameLabelCancelButtonPressed()
+{
+ // If we saving an image...
+ if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
+ {
+ m_savingContext->abortingSaving = true;
+ m_canvas->abortSaving();
+ }
+
+ // If we preparing SlideShow...
+ m_cancelSlideShow = true;
+}
+
+void EditorWindow::slotSave()
+{
+ if (m_canvas->isReadOnly())
+ saveAs();
+ else if (promptForOverWrite())
+ save();
+}
+
+void EditorWindow::slotSavingStarted(const TQString& /*filename*/)
+{
+ setCursor( KCursor::waitCursor() );
+
+ // Disable actions as appropriate during saving
+ emit signalNoCurrentItem();
+ toggleActions(false);
+
+ m_nameLabel->progressBarMode(StatusProgressBar::CancelProgressBarMode, i18n("Saving: "));
+}
+
+void EditorWindow::slotSavingFinished(const TQString& filename, bool success)
+{
+ if (m_savingContext->savingState == SavingContextContainer::SavingStateSave)
+ {
+ // from save()
+ m_savingContext->savingState = SavingContextContainer::SavingStateNone;
+
+ if (!success)
+ {
+ if (!m_savingContext->abortingSaving)
+ {
+ KMessageBox::error(this, i18n("Failed to save file\n\"%1\"\nto\n\"%2\".")
+ .arg(m_savingContext->destinationURL.filename())
+ .arg(m_savingContext->destinationURL.path()));
+ }
+ finishSaving(false);
+ return;
+ }
+
+ DDebug() << "renaming to " << m_savingContext->destinationURL.path() << endl;
+
+ if (!moveFile())
+ {
+ finishSaving(false);
+ return;
+ }
+
+ m_canvas->setUndoHistoryOrigin();
+
+ // remove image from cache since it has changed
+ LoadingCacheInterface::cleanFromCache(m_savingContext->destinationURL.path());
+ // this won't be in the cache, but does not hurt to do it anyway
+ LoadingCacheInterface::cleanFromCache(filename);
+
+ // restore state of disabled actions. saveIsComplete can start any other task
+ // (loading!) which might itself in turn change states
+ finishSaving(true);
+
+ saveIsComplete();
+
+ // Take all actions necessary to update information and re-enable sidebar
+ slotChanged();
+ }
+ else if (m_savingContext->savingState == SavingContextContainer::SavingStateSaveAs)
+ {
+ m_savingContext->savingState = SavingContextContainer::SavingStateNone;
+
+ // from saveAs()
+ if (!success)
+ {
+ if (!m_savingContext->abortingSaving)
+ {
+ KMessageBox::error(this, i18n("Failed to save file\n\"%1\"\nto\n\"%2\".")
+ .arg(m_savingContext->destinationURL.filename())
+ .arg(m_savingContext->destinationURL.path()));
+ }
+ finishSaving(false);
+ return;
+ }
+
+ // Only try to write exif if both src and destination are jpeg files
+
+ DDebug() << "renaming to " << m_savingContext->destinationURL.path() << endl;
+
+ if (!moveFile())
+ {
+ finishSaving(false);
+ return;
+ }
+
+ m_canvas->setUndoHistoryOrigin();
+
+ LoadingCacheInterface::cleanFromCache(m_savingContext->destinationURL.path());
+ LoadingCacheInterface::cleanFromCache(filename);
+
+ finishSaving(true);
+ saveAsIsComplete();
+
+ // Take all actions necessary to update information and re-enable sidebar
+ slotChanged();
+ }
+}
+
+void EditorWindow::finishSaving(bool success)
+{
+ m_savingContext->synchronousSavingResult = success;
+
+ if (m_savingContext->saveTempFile)
+ {
+ delete m_savingContext->saveTempFile;
+ m_savingContext->saveTempFile = 0;
+ }
+
+ // Exit of internal TQt event loop to unlock promptUserSave() method.
+ if (m_savingContext->synchronizingState == SavingContextContainer::SynchronousSaving)
+ tqApp->exit_loop();
+
+ // Enable actions as appropriate after saving
+ toggleActions(true);
+ unsetCursor();
+
+ m_nameLabel->progressBarMode(StatusProgressBar::TextMode);
+
+ // On error, continue using current image
+ if (!success)
+ {
+ m_canvas->switchToLastSaved(m_savingContext->srcURL.path());
+ }
+}
+
+void EditorWindow::startingSave(const KURL& url)
+{
+ // avoid any reentrancy. Should be impossible anyway since actions will be disabled.
+ if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
+ return;
+
+ if (!checkPermissions(url))
+ return;
+
+ m_savingContext->srcURL = url;
+ m_savingContext->destinationURL = m_savingContext->srcURL;
+ m_savingContext->destinationExisted = true;
+ m_savingContext->originalFormat = m_canvas->currentImageFileFormat();
+ m_savingContext->format = m_savingContext->originalFormat;
+ m_savingContext->abortingSaving = false;
+ m_savingContext->savingState = SavingContextContainer::SavingStateSave;
+ // use magic file extension which tells the digikamalbums ioslave to ignore the file
+ m_savingContext->saveTempFile = new KTempFile(m_savingContext->srcURL.directory(false),
+ ".digikamtempfile.tmp");
+ m_savingContext->saveTempFile->setAutoDelete(true);
+
+ m_canvas->saveAs(m_savingContext->saveTempFile->name(), m_IOFileSettings,
+ m_setExifOrientationTag && (m_rotatedOrFlipped || m_canvas->exifRotated()));
+}
+
+bool EditorWindow::startingSaveAs(const KURL& url)
+{
+ if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
+ return false;
+
+ TQString mimetypes = KImageIO::mimeTypes(KImageIO::Writing).join(" ");
+ mimetypes.append(" image/tiff");
+ DDebug () << "mimetypes=" << mimetypes << endl;
+
+ m_savingContext->srcURL = url;
+
+ FileSaveOptionsBox *options = new FileSaveOptionsBox();
+ KFileDialog imageFileSaveDialog(m_savingContext->srcURL.isLocalFile() ?
+ m_savingContext->srcURL.directory() : TQDir::homeDirPath(),
+ TQString(),
+ this,
+ "imageFileSaveDialog",
+ false,
+ options);
+
+ connect(&imageFileSaveDialog, TQ_SIGNAL(filterChanged(const TQString &)),
+ options, TQ_SLOT(slotImageFileFormatChanged(const TQString &)));
+
+ connect(&imageFileSaveDialog, TQ_SIGNAL(fileSelected(const TQString &)),
+ options, TQ_SLOT(slotImageFileSelected(const TQString &)));
+
+ ImageDialogPreview *preview = new ImageDialogPreview(&imageFileSaveDialog);
+ imageFileSaveDialog.setPreviewWidget(preview);
+ imageFileSaveDialog.setOperationMode(KFileDialog::Saving);
+ imageFileSaveDialog.setMode(KFile::File);
+ imageFileSaveDialog.setCaption(i18n("New Image File Name"));
+ imageFileSaveDialog.setFilter(mimetypes);
+
+ TQFileInfo info(m_savingContext->srcURL.fileName());
+ TDEConfig* config = kapp->config();
+ config->setGroup("ImageViewer Settings");
+ TQString ext = config->readEntry("LastSavedImageTypeMime", "png");
+ TQString fileName = info.baseName(false) + TQString(".") + ext;
+ imageFileSaveDialog.setSelection(fileName);
+
+ // Start dialog and check if canceled.
+ if ( imageFileSaveDialog.exec() != KFileDialog::Accepted )
+ return false;
+
+ // Update file save settings in editor instance.
+ options->applySettings();
+ applyStandardSettings();
+
+ KURL newURL = imageFileSaveDialog.selectedURL();
+
+ // Check if target image format have been selected from Combo List of SaveAs dialog.
+ m_savingContext->format = KImageIO::typeForMime(imageFileSaveDialog.currentMimeFilter());
+
+ if ( m_savingContext->format.isEmpty() )
+ {
+ // Else, check if target image format have been add to target image file name using extension.
+
+ TQFileInfo fi(newURL.path());
+ m_savingContext->format = fi.extension(false);
+
+ if ( m_savingContext->format.isEmpty() )
+ {
+ // If format is empty then file format is same as that of the original file.
+ m_savingContext->format = TQImageIO::imageFormat(m_savingContext->srcURL.path());
+ }
+ else
+ {
+ // Else, check if format from file name extension is include on file mime type list.
+
+ TQString imgExtPattern;
+ TQStringList imgExtList = TQStringList::split(" ", mimetypes);
+ for (TQStringList::ConstIterator it = imgExtList.begin() ; it != imgExtList.end() ; ++it)
+ {
+ imgExtPattern.append (KImageIO::typeForMime(*it).upper());
+ imgExtPattern.append (" ");
+ }
+ imgExtPattern.append (" TIF TIFF");
+ if ( imgExtPattern.contains("JPEG") )
+ {
+ imgExtPattern.append (" JPG");
+ imgExtPattern.append (" JPE");
+ }
+
+ if ( !imgExtPattern.contains( m_savingContext->format.upper() ) )
+ {
+ KMessageBox::error(this, i18n("Target image file format \"%1\" unsupported.")
+ .arg(m_savingContext->format));
+ DWarning() << k_funcinfo << "target image file format " << m_savingContext->format << " unsupported!" << endl;
+ return false;
+ }
+ }
+ }
+
+ if (!newURL.isValid())
+ {
+ KMessageBox::error(this, i18n("Failed to save file\n\"%1\" to\n\"%2\".")
+ .arg(newURL.filename())
+ .arg(newURL.path().section('/', -2, -2)));
+ DWarning() << k_funcinfo << "target URL is not valid !" << endl;
+ return false;
+ }
+
+ config->writeEntry("LastSavedImageTypeMime", m_savingContext->format);
+ config->sync();
+
+ // if new and original url are equal use slotSave() ------------------------------
+
+ KURL currURL(m_savingContext->srcURL);
+ currURL.cleanPath();
+ newURL.cleanPath();
+
+ if (currURL.equals(newURL))
+ {
+ slotSave();
+ return false;
+ }
+
+ // Check for overwrite ----------------------------------------------------------
+
+ TQFileInfo fi(newURL.path());
+ m_savingContext->destinationExisted = fi.exists();
+ if ( m_savingContext->destinationExisted )
+ {
+ int result =
+
+ KMessageBox::warningYesNo( this, i18n("A file named \"%1\" already "
+ "exists. Are you sure you want "
+ "to overwrite it?")
+ .arg(newURL.filename()),
+ i18n("Overwrite File?"),
+ i18n("Overwrite"),
+ KStdGuiItem::cancel() );
+
+ if (result != KMessageBox::Yes)
+ return false;
+
+ // There will be two message boxes if the file is not writable.
+ // This may be controversial, and it may be changed, but it was a deliberate decision.
+ if (!checkPermissions(newURL))
+ return false;
+ }
+
+ // Now do the actual saving -----------------------------------------------------
+
+ // use magic file extension which tells the digikamalbums ioslave to ignore the file
+ m_savingContext->saveTempFile = new KTempFile(newURL.directory(false), ".digikamtempfile.tmp");
+ m_savingContext->destinationURL = newURL;
+ m_savingContext->originalFormat = m_canvas->currentImageFileFormat();
+ m_savingContext->savingState = SavingContextContainer::SavingStateSaveAs;
+ m_savingContext->saveTempFile->setAutoDelete(true);
+ m_savingContext->abortingSaving = false;
+
+ m_canvas->saveAs(m_savingContext->saveTempFile->name(), m_IOFileSettings,
+ m_setExifOrientationTag && (m_rotatedOrFlipped || m_canvas->exifRotated()),
+ m_savingContext->format.lower());
+
+ return true;
+}
+
+bool EditorWindow::checkPermissions(const KURL& url)
+{
+ //TODO: Check that the permissions can actually be changed
+ // if write permissions are not available.
+
+ TQFileInfo fi(url.path());
+
+ if (fi.exists() && !fi.isWritable())
+ {
+ int result =
+
+ KMessageBox::warningYesNo( this, i18n("You do not have write permissions "
+ "for the file named \"%1\". "
+ "Are you sure you want "
+ "to overwrite it?")
+ .arg(url.filename()),
+ i18n("Overwrite File?"),
+ i18n("Overwrite"),
+ KStdGuiItem::cancel() );
+
+ if (result != KMessageBox::Yes)
+ return false;
+ }
+
+ return true;
+}
+
+bool EditorWindow::moveFile()
+{
+ TQCString dstFileName = TQFile::encodeName(m_savingContext->destinationURL.path());
+
+ // Store old permissions:
+ // Just get the current umask.
+ mode_t curr_umask = umask(S_IREAD | S_IWRITE);
+ // Restore the umask.
+ umask(curr_umask);
+
+ // For new files respect the umask setting.
+ mode_t filePermissions = (S_IREAD | S_IWRITE | S_IROTH | S_IWOTH | S_IRGRP | S_IWGRP) & ~curr_umask;
+
+ // For existing files, use the mode of the original file.
+ if (m_savingContext->destinationExisted)
+ {
+ struct stat stbuf;
+ if (::stat(dstFileName, &stbuf) == 0)
+ {
+ filePermissions = stbuf.st_mode;
+ }
+ }
+
+ // rename tmp file to dest
+ if (::rename(TQFile::encodeName(m_savingContext->saveTempFile->name()), dstFileName) != 0)
+ {
+ KMessageBox::error(this, i18n("Failed to overwrite original file"),
+ i18n("Error Saving File"));
+ return false;
+ }
+
+ // restore permissions
+ if (::chmod(dstFileName, filePermissions) != 0)
+ {
+ DWarning() << "Failed to restore file permissions for file " << dstFileName << endl;
+ }
+
+ return true;
+}
+
+void EditorWindow::slotToggleColorManagedView()
+{
+ d->cmViewIndicator->blockSignals(true);
+ d->viewCMViewAction->blockSignals(true);
+ bool cmv = false;
+ if (d->ICCSettings->enableCMSetting)
+ {
+ cmv = !d->ICCSettings->managedViewSetting;
+ d->ICCSettings->managedViewSetting = cmv;
+ m_canvas->setICCSettings(d->ICCSettings);
+
+ // Save Color Managed View setting in config file. For performance
+ // reason, no need to flush file, it cached in memory and will be flushed
+ // to disk at end of session.
+ TDEConfig* config = kapp->config();
+ config->setGroup("Color Management");
+ config->writeEntry("ManagedView", cmv);
+ }
+
+ d->cmViewIndicator->setOn(cmv);
+ d->viewCMViewAction->setChecked(cmv);
+ setColorManagedViewIndicatorToolTip(d->ICCSettings->enableCMSetting, cmv);
+ d->cmViewIndicator->blockSignals(false);
+ d->viewCMViewAction->blockSignals(false);
+}
+
+void EditorWindow::setColorManagedViewIndicatorToolTip(bool available, bool cmv)
+{
+ TQToolTip::remove(d->cmViewIndicator);
+ TQString tooltip;
+ if (available)
+ {
+ if (cmv)
+ tooltip = i18n("Color Managed View is enabled");
+ else
+ tooltip = i18n("Color Managed View is disabled");
+ }
+ else
+ {
+ tooltip = i18n("Color Management is not configured, so the Color Managed View is not available");
+ }
+ TQToolTip::add(d->cmViewIndicator, tooltip);
+}
+
+void EditorWindow::slotToggleUnderExposureIndicator()
+{
+ d->underExposureIndicator->blockSignals(true);
+ d->viewUnderExpoAction->blockSignals(true);
+ bool uei = !d->exposureSettings->underExposureIndicator;
+ d->underExposureIndicator->setOn(uei);
+ d->viewUnderExpoAction->setChecked(uei);
+ d->exposureSettings->underExposureIndicator = uei;
+ m_canvas->setExposureSettings(d->exposureSettings);
+ setUnderExposureToolTip(uei);
+ d->underExposureIndicator->blockSignals(false);
+ d->viewUnderExpoAction->blockSignals(false);
+}
+
+void EditorWindow::setUnderExposureToolTip(bool uei)
+{
+ TQToolTip::remove(d->underExposureIndicator);
+ TQToolTip::add(d->underExposureIndicator,
+ uei ? i18n("Under-Exposure indicator is enabled")
+ : i18n("Under-Exposure indicator is disabled"));
+}
+
+void EditorWindow::slotToggleOverExposureIndicator()
+{
+ d->overExposureIndicator->blockSignals(true);
+ d->viewOverExpoAction->blockSignals(true);
+ bool oei = !d->exposureSettings->overExposureIndicator;
+ d->overExposureIndicator->setOn(oei);
+ d->viewOverExpoAction->setChecked(oei);
+ d->exposureSettings->overExposureIndicator = oei;
+ m_canvas->setExposureSettings(d->exposureSettings);
+ setOverExposureToolTip(oei);
+ d->overExposureIndicator->blockSignals(false);
+ d->viewOverExpoAction->blockSignals(false);
+}
+
+void EditorWindow::setOverExposureToolTip(bool oei)
+{
+ TQToolTip::remove(d->overExposureIndicator);
+ TQToolTip::add(d->overExposureIndicator,
+ oei ? i18n("Over-Exposure indicator is enabled")
+ : i18n("Over-Exposure indicator is disabled"));
+}
+
+void EditorWindow::slotDonateMoney()
+{
+ TDEApplication::kApplication()->invokeBrowser("http://www.digikam.org/?q=donation");
+}
+
+void EditorWindow::slotContribute()
+{
+ TDEApplication::kApplication()->invokeBrowser("http://www.digikam.org/?q=contrib");
+}
+
+void EditorWindow::slotToggleSlideShow()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("ImageViewer Settings");
+ bool startWithCurrent = config->readBoolEntry("SlideShowStartCurrent", false);
+
+ SlideShowSettings settings;
+ settings.delay = config->readNumEntry("SlideShowDelay", 5) * 1000;
+ settings.printName = config->readBoolEntry("SlideShowPrintName", true);
+ settings.printDate = config->readBoolEntry("SlideShowPrintDate", false);
+ settings.printApertureFocal = config->readBoolEntry("SlideShowPrintApertureFocal", false);
+ settings.printExpoSensitivity = config->readBoolEntry("SlideShowPrintExpoSensitivity", false);
+ settings.printMakeModel = config->readBoolEntry("SlideShowPrintMakeModel", false);
+ settings.printComment = config->readBoolEntry("SlideShowPrintComment", false);
+ settings.loop = config->readBoolEntry("SlideShowLoop", false);
+ slideShow(startWithCurrent, settings);
+}
+
+void EditorWindow::slotSelectionChanged(const TQRect& sel)
+{
+ d->selectLabel->setText(TQString("(%1, %2) (%3 x %4)").arg(sel.x()).arg(sel.y())
+ .arg(sel.width()).arg(sel.height()));
+}
+
+void EditorWindow::slotRawCameraList()
+{
+ RawCameraDlg dlg(this);
+ dlg.exec();
+}
+
+void EditorWindow::slotThemeChanged()
+{
+ TQStringList themes(ThemeEngine::instance()->themeNames());
+ int index = themes.findIndex(ThemeEngine::instance()->getCurrentThemeName());
+ if (index == -1)
+ index = themes.findIndex(i18n("Default"));
+
+ m_themeMenuAction->setCurrentItem(index);
+
+ TDEConfig* config = kapp->config();
+ config->setGroup("ImageViewer Settings");
+
+ if (!config->readBoolEntry("UseThemeBackgroundColor", true))
+ m_bgColor = config->readColorEntry("BackgroundColor", &TQt::black);
+ else
+ m_bgColor = ThemeEngine::instance()->baseColor();
+
+ m_canvas->setBackgroundColor(m_bgColor);
+}
+
+void EditorWindow::slotChangeTheme(const TQString& theme)
+{
+ ThemeEngine::instance()->slotChangeTheme(theme);
+}
+
+void EditorWindow::setToolStartProgress(const TQString& toolName)
+{
+ m_nameLabel->setProgressValue(0);
+ m_nameLabel->progressBarMode(StatusProgressBar::CancelProgressBarMode, TQString("%1: ").arg(toolName));
+}
+
+void EditorWindow::setToolProgress(int progress)
+{
+ m_nameLabel->setProgressValue(progress);
+}
+
+void EditorWindow::setToolStopProgress()
+{
+ m_nameLabel->setProgressValue(0);
+ m_nameLabel->progressBarMode(StatusProgressBar::TextMode);
+ slotUpdateItemInfo();
+}
+
+
+void EditorWindow::slotShowMenuBar()
+{
+ if (menuBar()->isVisible())
+ menuBar()->hide();
+ else
+ menuBar()->show();
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/editor/editorwindow.h b/src/utilities/imageeditor/editor/editorwindow.h
new file mode 100644
index 00000000..cbb06221
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editorwindow.h
@@ -0,0 +1,263 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-20
+ * Description : main image editor GUI implementation
+ *
+ * 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 EDITORWINDOW_H
+#define EDITORWINDOW_H
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqstring.h>
+#include <tqrect.h>
+
+// KDE includes.
+
+#include <tdemainwindow.h>
+#include <kurl.h>
+
+// Local includes.
+
+#include "sidebar.h"
+#include "digikam_export.h"
+
+class TQSplitter;
+class TQPopupMenu;
+class TQLabel;
+
+class TDEToolBarPopupAction;
+class TDEToggleAction;
+class TDEAction;
+class TDESelectAction;
+
+namespace Digikam
+{
+
+class Sidebar;
+class DPopupMenu;
+class Canvas;
+class ImagePluginLoader;
+class IOFileSettingsContainer;
+class SavingContextContainer;
+class StatusProgressBar;
+class SlideShowSettings;
+class EditorStackView;
+class EditorWindowPriv;
+
+class DIGIKAM_EXPORT EditorWindow : public TDEMainWindow
+{
+ TQ_OBJECT
+
+
+public:
+
+ EditorWindow(const char *name);
+ ~EditorWindow();
+
+ virtual void applySettings(){};
+ virtual bool setup(bool iccSetupPage=false)=0;
+
+signals:
+
+ void signalSelectionChanged( const TQRect & );
+ void signalNoCurrentItem();
+
+protected:
+
+ bool m_cancelSlideShow;
+ bool m_fullScreen;
+ bool m_rotatedOrFlipped;
+ bool m_setExifOrientationTag;
+
+ TQLabel *m_resLabel;
+
+ TQColor m_bgColor;
+
+ TQSplitter *m_splitter;
+
+ TDEAction *m_saveAction;
+ TDEAction *m_saveAsAction;
+ TDEAction *m_revertAction;
+ TDEAction *m_fileDeleteAction;
+ TDEAction *m_forwardAction;
+ TDEAction *m_backwardAction;
+ TDEAction *m_firstAction;
+ TDEAction *m_lastAction;
+
+ TDEToggleAction *m_fullScreenAction;
+
+ TDESelectAction *m_themeMenuAction;
+
+ TDEToolBarPopupAction *m_undoAction;
+ TDEToolBarPopupAction *m_redoAction;
+
+ DPopupMenu *m_contextMenu;
+ EditorStackView *m_stackView;
+ Canvas *m_canvas;
+ ImagePluginLoader *m_imagePluginLoader;
+ StatusProgressBar *m_nameLabel;
+ IOFileSettingsContainer *m_IOFileSettings;
+ SavingContextContainer *m_savingContext;
+
+protected:
+
+ void saveStandardSettings();
+ void readStandardSettings();
+ void applyStandardSettings();
+
+ void setupStandardConnections();
+ void setupStandardActions();
+ void setupStandardAccelerators();
+ void setupStatusBar();
+ void setupContextMenu();
+ void toggleStandardActions(bool val);
+ void toggleZoomActions(bool val);
+
+ void printImage(KURL url);
+
+ void plugActionAccel(TDEAction* action);
+ void unplugActionAccel(TDEAction* action);
+
+ void unLoadImagePlugins();
+ void loadImagePlugins();
+
+ bool promptForOverWrite();
+ bool promptUserSave(const KURL& url);
+ bool waitForSavingToComplete();
+ void startingSave(const KURL& url);
+ bool startingSaveAs(const KURL& url);
+ bool checkPermissions(const KURL& url);
+ bool moveFile();
+
+ EditorStackView* editorStackView() const;
+
+ virtual void finishSaving(bool success);
+
+ virtual void readSettings() { readStandardSettings(); };
+ virtual void saveSettings() { saveStandardSettings(); };
+ virtual void toggleActions(bool val) { toggleStandardActions(val); };
+ virtual void toggleGUI2FullScreen() {};
+
+ virtual void slideShow(bool startWithCurrent, SlideShowSettings& settings)=0;
+
+ virtual void setupConnections()=0;
+ virtual void setupActions()=0;
+ virtual void setupUserArea()=0;
+ virtual bool saveAs()=0;
+ virtual bool save()=0;
+
+ virtual void saveIsComplete()=0;
+ virtual void saveAsIsComplete()=0;
+
+ virtual Sidebar *rightSideBar() const=0;
+
+protected slots:
+
+ void slotSave();
+ void slotSaveAs() { saveAs(); };
+
+ void slotEditKeys();
+ void slotResize();
+
+ void slotAboutToShowUndoMenu();
+ void slotAboutToShowRedoMenu();
+
+ void slotConfToolbars();
+ void slotNewToolbarConfig();
+
+ void slotToggleFullScreen();
+ void slotEscapePressed();
+
+ void slotSelected(bool);
+
+ void slotLoadingProgress(const TQString& filePath, float progress);
+ void slotSavingProgress(const TQString& filePath, float progress);
+
+ void slotNameLabelCancelButtonPressed();
+
+ void slotThemeChanged();
+
+ virtual void slotLoadingStarted(const TQString& filename);
+ virtual void slotLoadingFinished(const TQString &filename, bool success);
+ virtual void slotSavingStarted(const TQString &filename);
+
+ virtual void slotSetup(){ setup(); };
+ virtual void slotChangeTheme(const TQString& theme);
+
+ virtual void slotFilePrint()=0;
+ virtual void slotDeleteCurrentItem()=0;
+ virtual void slotBackward()=0;
+ virtual void slotForward()=0;
+ virtual void slotFirst()=0;
+ virtual void slotLast()=0;
+ virtual void slotUpdateItemInfo()=0;
+ virtual void slotChanged()=0;
+ virtual void slotContextMenu()=0;
+ virtual void slotRevert()=0;
+
+private slots:
+
+ void slotToggleUnderExposureIndicator();
+ void slotToggleOverExposureIndicator();
+ void slotToggleColorManagedView();
+ void slotRotatedOrFlipped();
+ void slotSavingFinished(const TQString &filename, bool success);
+ void slotDonateMoney();
+ void slotContribute();
+ void slotToggleSlideShow();
+ void slotZoomTo100Percents();
+ void slotZoomSelected();
+ void slotZoomTextChanged(const TQString &);
+ void slotZoomChanged(bool isMax, bool isMin, double zoom);
+ void slotSelectionChanged(const TQRect& sel);
+ void slotToggleFitToWindow();
+ void slotToggleOffFitToWindow();
+ void slotFitToSelect();
+ void slotIncreaseZoom();
+ void slotDecreaseZoom();
+ void slotRawCameraList();
+ void slotPrepareToLoad();
+ void slotShowMenuBar();
+
+private:
+
+ void enter_loop();
+ void hideToolBars();
+ void showToolBars();
+ void setColorManagedViewIndicatorToolTip(bool available, bool cmv);
+ void setUnderExposureToolTip(bool uei);
+ void setOverExposureToolTip(bool oei);
+
+ void setToolStartProgress(const TQString& toolName);
+ void setToolProgress(int progress);
+ void setToolStopProgress();
+
+private:
+
+ EditorWindowPriv *d;
+
+ friend class EditorToolIface;
+};
+
+} // namespace Digikam
+
+#endif /* EDITORWINDOW_H */
diff --git a/src/utilities/imageeditor/editor/editorwindowprivate.h b/src/utilities/imageeditor/editor/editorwindowprivate.h
new file mode 100644
index 00000000..df07d0bd
--- /dev/null
+++ b/src/utilities/imageeditor/editor/editorwindowprivate.h
@@ -0,0 +1,143 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-20
+ * Description : main image editor GUI implementation
+ * private data.
+ *
+ * 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 EDITORWINDOWPRIVATE_H
+#define EDITORWINDOWPRIVATE_H
+
+class TQToolButton;
+class TQLabel;
+
+class KComboBox;
+class TDEAction;
+class TDEToggleAction;
+class KWidgetAction;
+class TDESelectAction;
+class TDEActionMenu;
+class TDEAccel;
+
+namespace Digikam
+{
+
+class EditorToolIface;
+class ExposureSettingsContainer;
+class ICCSettingsContainer;
+
+class EditorWindowPriv
+{
+
+public:
+
+ EditorWindowPriv()
+ {
+ removeFullScreenButton = false;
+ fullScreenHideToolBar = false;
+ selectLabel = 0;
+ donateMoneyAction = 0;
+ accelerators = 0;
+ viewCMViewAction = 0;
+ filePrintAction = 0;
+ copyAction = 0;
+ resizeAction = 0;
+ cropAction = 0;
+ rotateLeftAction = 0;
+ rotateRightAction = 0;
+ flipHorizAction = 0;
+ flipVertAction = 0;
+ ICCSettings = 0;
+ exposureSettings = 0;
+ underExposureIndicator = 0;
+ overExposureIndicator = 0;
+ cmViewIndicator = 0;
+ viewUnderExpoAction = 0;
+ viewOverExpoAction = 0;
+ slideShowAction = 0;
+ zoomFitToWindowAction = 0;
+ zoomFitToSelectAction = 0;
+ zoomPlusAction = 0;
+ zoomMinusAction = 0;
+ zoomTo100percents = 0;
+ zoomCombo = 0;
+ zoomComboAction = 0;
+ selectAllAction = 0;
+ selectNoneAction = 0;
+ rawCameraListAction = 0;
+ contributeAction = 0;
+ toolIface = 0;
+ showMenuBarAction = 0;
+ }
+
+ ~EditorWindowPriv()
+ {
+ }
+
+ bool removeFullScreenButton;
+ bool fullScreenHideToolBar;
+
+ TQLabel *selectLabel;
+
+ TQToolButton *cmViewIndicator;
+ TQToolButton *underExposureIndicator;
+ TQToolButton *overExposureIndicator;
+
+ TDEAction *rawCameraListAction;
+ TDEAction *donateMoneyAction;
+ TDEAction *contributeAction;
+ TDEAction *filePrintAction;
+ TDEAction *copyAction;
+ TDEAction *resizeAction;
+ TDEAction *cropAction;
+ TDEAction *zoomPlusAction;
+ TDEAction *zoomMinusAction;
+ TDEAction *zoomTo100percents;
+ TDEAction *zoomFitToSelectAction;
+ TDEAction *rotateLeftAction;
+ TDEAction *rotateRightAction;
+ TDEAction *flipHorizAction;
+ TDEAction *flipVertAction;
+ TDEAction *slideShowAction;
+ TDEAction *selectAllAction;
+ TDEAction *selectNoneAction;
+
+ TDEToggleAction *zoomFitToWindowAction;
+ TDEToggleAction *viewCMViewAction;
+ TDEToggleAction *viewUnderExpoAction;
+ TDEToggleAction *viewOverExpoAction;
+ TDEToggleAction *showMenuBarAction;
+
+ KWidgetAction *zoomComboAction;
+
+ KComboBox *zoomCombo;
+
+ TDEAccel *accelerators;
+
+ ICCSettingsContainer *ICCSettings;
+
+ ExposureSettingsContainer *exposureSettings;
+
+ EditorToolIface *toolIface;
+};
+
+} // NameSpace Digikam
+
+#endif /* EDITORWINDOWPRIVATE_H */
diff --git a/src/utilities/imageeditor/editor/imageiface.cpp b/src/utilities/imageeditor/editor/imageiface.cpp
new file mode 100644
index 00000000..56cb559c
--- /dev/null
+++ b/src/utilities/imageeditor/editor/imageiface.cpp
@@ -0,0 +1,444 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-02-14
+ * Description : image data interface for image plugins
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2004-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 <tqwidget.h>
+#include <tqsize.h>
+#include <tqpixmap.h>
+#include <tqbitmap.h>
+#include <tqpainter.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "exposurecontainer.h"
+#include "iccsettingscontainer.h"
+#include "icctransform.h"
+#include "dimginterface.h"
+#include "bcgmodifier.h"
+#include "dmetadata.h"
+#include "imageiface.h"
+
+namespace Digikam
+{
+
+class ImageIfacePriv
+{
+public:
+
+ ImageIfacePriv()
+ {
+ usePreviewSelection = false;
+ previewWidth = 0;
+ previewHeight = 0;
+ }
+
+ bool usePreviewSelection;
+
+ int originalWidth;
+ int originalHeight;
+ int originalBytesDepth;
+
+ int constrainWidth;
+ int constrainHeight;
+
+ int previewWidth;
+ int previewHeight;
+
+ TQPixmap qcheck;
+ TQPixmap qpix;
+ TQBitmap qmask;
+
+ DImg previewImage;
+ DImg targetPreviewImage;
+};
+
+ImageIface::ImageIface(int w, int h)
+{
+ d = new ImageIfacePriv;
+
+ d->constrainWidth = w;
+ d->constrainHeight = h;
+
+ d->originalWidth = DImgInterface::defaultInterface()->origWidth();
+ d->originalHeight = DImgInterface::defaultInterface()->origHeight();
+ d->originalBytesDepth = DImgInterface::defaultInterface()->bytesDepth();
+
+ d->qpix.setMask(d->qmask);
+ d->qcheck.resize(8, 8);
+
+ TQPainter p;
+ p.begin(&d->qcheck);
+ p.fillRect(0, 0, 4, 4, TQColor(144,144,144));
+ p.fillRect(4, 4, 4, 4, TQColor(144,144,144));
+ p.fillRect(0, 4, 4, 4, TQColor(100,100,100));
+ p.fillRect(4, 0, 4, 4, TQColor(100,100,100));
+ p.end();
+}
+
+ImageIface::~ImageIface()
+{
+ delete d;
+}
+
+void ImageIface::setPreviewType(bool useSelect)
+{
+ d->usePreviewSelection = useSelect;
+}
+
+bool ImageIface::previewType()
+{
+ return d->usePreviewSelection;
+}
+
+DColor ImageIface::getColorInfoFromOriginalImage(const TQPoint& point)
+{
+ if ( !DImgInterface::defaultInterface()->getImage() || point.x() > originalWidth() || point.y() > originalHeight() )
+ {
+ DWarning() << k_funcinfo << "Coordinate out of range or no image data available!" << endl;
+ return DColor();
+ }
+
+ return DImgInterface::defaultInterface()->getImg()->getPixelColor(point.x(), point.y());
+}
+
+DColor ImageIface::getColorInfoFromPreviewImage(const TQPoint& point)
+{
+ if ( d->previewImage.isNull() || point.x() > previewWidth() || point.y() > previewHeight() )
+ {
+ DWarning() << k_funcinfo << "Coordinate out of range or no image data available!" << endl;
+ return DColor();
+ }
+
+ return d->previewImage.getPixelColor(point.x(), point.y());
+}
+
+DColor ImageIface::getColorInfoFromTargetPreviewImage(const TQPoint& point)
+{
+ if ( d->targetPreviewImage.isNull() || point.x() > previewWidth() || point.y() > previewHeight() )
+ {
+ DWarning() << k_funcinfo << "Coordinate out of range or no image data available!" << endl;
+ return DColor();
+ }
+
+ return d->targetPreviewImage.getPixelColor(point.x(), point.y());
+}
+
+uchar* ImageIface::setPreviewImageSize(int w, int h) const
+{
+ d->previewImage.reset();
+ d->targetPreviewImage.reset();
+
+ d->constrainWidth = w;
+ d->constrainHeight = h;
+
+ return (getPreviewImage());
+}
+
+uchar* ImageIface::getPreviewImage() const
+{
+ if (d->previewImage.isNull())
+ {
+ DImg *im = 0;
+
+ if (!d->usePreviewSelection)
+ {
+ im = DImgInterface::defaultInterface()->getImg();
+ if (!im || im->isNull())
+ return 0;
+ }
+ else
+ {
+ int x, y, w, h;
+ bool s = DImgInterface::defaultInterface()->sixteenBit();
+ bool a = DImgInterface::defaultInterface()->hasAlpha();
+ uchar *data = DImgInterface::defaultInterface()->getImageSelection();
+ DImgInterface::defaultInterface()->getSelectedArea(x, y, w, h);
+ im = new DImg(w, h, s, a, data, true);
+ delete [] data;
+
+ if (!im)
+ return 0;
+
+ if (im->isNull())
+ {
+ delete im;
+ return 0;
+ }
+ }
+
+ TQSize sz(im->width(), im->height());
+ sz.scale(d->constrainWidth, d->constrainHeight, TQSize::ScaleMin);
+
+ d->previewImage = im->smoothScale(sz.width(), sz.height());
+ d->previewWidth = d->previewImage.width();
+ d->previewHeight = d->previewImage.height();
+
+ // only create another copy if needed, in putPreviewImage
+ d->targetPreviewImage = d->previewImage;
+
+ d->qmask.resize(d->previewWidth, d->previewHeight);
+ d->qpix.resize(d->previewWidth, d->previewHeight);
+
+ if (d->usePreviewSelection)
+ delete im;
+ }
+
+ DImg previewData = d->previewImage.copyImageData();
+ return previewData.stripImageData();
+}
+
+uchar* ImageIface::getOriginalImage() const
+{
+ DImg *im = DImgInterface::defaultInterface()->getImg();
+
+ if (!im || im->isNull())
+ return 0;
+
+ DImg origData = im->copyImageData();
+ return origData.stripImageData();
+}
+
+DImg* ImageIface::getOriginalImg() const
+{
+ return DImgInterface::defaultInterface()->getImg();
+}
+
+uchar* ImageIface::getImageSelection() const
+{
+ return DImgInterface::defaultInterface()->getImageSelection();
+}
+
+void ImageIface::putPreviewImage(uchar* data)
+{
+ if (!data)
+ return;
+
+ if (d->targetPreviewImage == d->previewImage)
+ {
+ d->targetPreviewImage = DImg(d->previewImage.width(), d->previewImage.height(),
+ d->previewImage.sixteenBit(), d->previewImage.hasAlpha(), data);
+ d->targetPreviewImage.setICCProfil( d->previewImage.getICCProfil() );
+ }
+ else
+ {
+ d->targetPreviewImage.putImageData(data);
+ }
+}
+
+void ImageIface::putOriginalImage(const TQString &caller, uchar* data, int w, int h)
+{
+ if (!data)
+ return;
+
+ DImgInterface::defaultInterface()->putImage(caller, data, w, h);
+}
+
+void ImageIface::setEmbeddedICCToOriginalImage(const TQString& profilePath)
+{
+ DImgInterface::defaultInterface()->setEmbeddedICCToOriginalImage( profilePath );
+}
+
+void ImageIface::putImageSelection(const TQString &caller, uchar* data)
+{
+ if (!data)
+ return;
+
+ DImgInterface::defaultInterface()->putImageSelection(caller, data);
+}
+
+int ImageIface::previewWidth()
+{
+ return d->previewWidth;
+}
+
+int ImageIface::previewHeight()
+{
+ return d->previewHeight;
+}
+
+bool ImageIface::previewSixteenBit()
+{
+ return originalSixteenBit();
+}
+
+bool ImageIface::previewHasAlpha()
+{
+ return originalHasAlpha();
+}
+
+int ImageIface::originalWidth()
+{
+ return DImgInterface::defaultInterface()->origWidth();
+}
+
+int ImageIface::originalHeight()
+{
+ return DImgInterface::defaultInterface()->origHeight();
+}
+
+bool ImageIface::originalSixteenBit()
+{
+ return DImgInterface::defaultInterface()->sixteenBit();
+}
+
+bool ImageIface::originalHasAlpha()
+{
+ return DImgInterface::defaultInterface()->hasAlpha();
+}
+
+int ImageIface::selectedWidth()
+{
+ int x, y, w, h;
+ DImgInterface::defaultInterface()->getSelectedArea(x, y, w, h);
+ return w;
+}
+
+int ImageIface::selectedHeight()
+{
+ int x, y, w, h;
+ DImgInterface::defaultInterface()->getSelectedArea(x, y, w, h);
+ return h;
+}
+
+int ImageIface::selectedXOrg()
+{
+ int x, y, w, h;
+ DImgInterface::defaultInterface()->getSelectedArea(x, y, w, h);
+ return x;
+}
+
+int ImageIface::selectedYOrg()
+{
+ int x, y, w, h;
+ DImgInterface::defaultInterface()->getSelectedArea(x, y, w, h);
+ return y;
+}
+
+void ImageIface::setPreviewBCG(double brightness, double contrast, double gamma)
+{
+ DImg preview = d->targetPreviewImage.copyImageData();
+ BCGModifier cmod;
+ cmod.setGamma(gamma);
+ cmod.setBrightness(brightness);
+ cmod.setContrast(contrast);
+ cmod.applyBCG(preview);
+ putPreviewImage(preview.bits());
+}
+
+void ImageIface::setOriginalBCG(double brightness, double contrast, double gamma)
+{
+ DImgInterface::defaultInterface()->setBCG(brightness, contrast, gamma);
+}
+
+void ImageIface::convertOriginalColorDepth(int depth)
+{
+ DImgInterface::defaultInterface()->convertDepth(depth);
+}
+
+TQPixmap ImageIface::convertToPixmap(DImg& img)
+{
+ return DImgInterface::defaultInterface()->convertToPixmap(img);
+}
+
+TQByteArray ImageIface::getEmbeddedICCFromOriginalImage()
+{
+ return DImgInterface::defaultInterface()->getEmbeddedICC();
+}
+
+TQByteArray ImageIface::getExifFromOriginalImage()
+{
+ return DImgInterface::defaultInterface()->getExif();
+}
+
+TQByteArray ImageIface::getIptcFromOriginalImage()
+{
+ return DImgInterface::defaultInterface()->getIptc();
+}
+
+PhotoInfoContainer ImageIface::getPhotographInformations() const
+{
+ DMetadata meta;
+ meta.setExif(DImgInterface::defaultInterface()->getExif());
+ meta.setIptc(DImgInterface::defaultInterface()->getIptc());
+ return meta.getPhotographInformations();
+}
+
+void ImageIface::paint(TQPaintDevice* device, int x, int y, int w, int h,
+ bool underExposure, bool overExposure)
+{
+ if ( !d->targetPreviewImage.isNull() )
+ {
+ if (d->targetPreviewImage.hasAlpha())
+ {
+ TQPainter p(&d->qpix);
+ p.drawTiledPixmap(0, 0, d->qpix.width(), d->qpix.height(), d->qcheck);
+ p.end();
+ }
+
+ TQPixmap pixImage;
+ ICCSettingsContainer *iccSettings = DImgInterface::defaultInterface()->getICCSettings();
+
+ if (iccSettings)
+ {
+ IccTransform monitorICCtrans;
+ monitorICCtrans.setProfiles(iccSettings->workspaceSetting, iccSettings->monitorSetting);
+
+ if (iccSettings->enableCMSetting && iccSettings->managedViewSetting)
+ {
+ pixImage = d->targetPreviewImage.convertToPixmap(&monitorICCtrans);
+ }
+ else
+ {
+ pixImage = d->targetPreviewImage.convertToPixmap();
+ }
+ }
+ else
+ {
+ pixImage = d->targetPreviewImage.convertToPixmap();
+ }
+
+ bitBlt(&d->qpix, 0, 0, static_cast<TQPaintDevice*>(&pixImage), 0, 0, w, h, TQt::CopyROP, false);
+
+ // Show the Over/Under exposure pixels indicators
+
+ if (underExposure || overExposure)
+ {
+ ExposureSettingsContainer expoSettings;
+ expoSettings.underExposureIndicator = underExposure;
+ expoSettings.overExposureIndicator = overExposure;
+ expoSettings.underExposureColor = DImgInterface::defaultInterface()->underExposureColor();
+ expoSettings.overExposureColor = DImgInterface::defaultInterface()->overExposureColor();
+
+ TQImage pureColorMask = d->targetPreviewImage.pureColorMask(&expoSettings);
+ TQPixmap pixMask(pureColorMask);
+ bitBlt(&d->qpix, 0, 0, static_cast<TQPaintDevice*>(&pixMask), 0, 0, w, h, TQt::CopyROP, false);
+ }
+ }
+
+ bitBlt(device, x, y, static_cast<TQPaintDevice*>(&d->qpix), 0, 0, -1, -1, TQt::CopyROP, false);
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/editor/imageiface.h b/src/utilities/imageeditor/editor/imageiface.h
new file mode 100644
index 00000000..272c62a5
--- /dev/null
+++ b/src/utilities/imageeditor/editor/imageiface.h
@@ -0,0 +1,198 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-02-14
+ * Description : image data interface for image plugins
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2004-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 IMAGEIFACE_H
+#define IMAGEIFACE_H
+
+// TQt includes.
+
+#include <tqglobal.h>
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "dcolor.h"
+#include "photoinfocontainer.h"
+#include "digikam_export.h"
+
+#define MAX3(a, b, c) (TQMAX(TQMAX(a,b),b))
+#define MIN3(a, b, c) (TQMIN(TQMIN(a,b),b))
+#define ROUND(x) ((int) ((x) + 0.5))
+
+class TQPaintDevice;
+
+namespace Digikam
+{
+
+class ImageIfacePriv;
+
+class DIGIKAM_EXPORT ImageIface
+{
+public:
+
+ ImageIface(int w=0, int h=0);
+ ~ImageIface();
+
+ /** Use this method to use the current selection in editor instead the full
+ image to render the preview.
+ */
+ void setPreviewType(bool useSelect=false);
+
+ /** Return 'true' if the preview is rendered using the current selection in editor.
+ Return 'false' if the preview is rendered using the full image in editor.
+ */
+ bool previewType();
+
+ /** Return image data for the current, scaled preview image.
+ The preview...() methods provide the characteristics of the data
+ (width, heigh, sixteen bit, alpha).
+ Ownership of the returned buffer is passed to the caller.
+ */
+ uchar* getPreviewImage() const;
+
+ /** Return image data for the current original image selection.
+ The selectionWidth(), selectionHeight(), originalSixteenBit()
+ and originalHasAlpha() methods provide the characteristics of the data.
+ Ownership of the returned buffer is passed to the caller.
+ */
+ uchar* getImageSelection() const;
+
+ /** Return image data for the original image.
+ The preview...() methods provide the characteristics of the data.
+ Ownership of the returned buffer is passed to the caller.
+ */
+ uchar* getOriginalImage() const;
+
+ /** Return a pointer to the DImg object representing the original image.
+ This object may not be modified or stored. Make copies if you need.
+ */
+ DImg* getOriginalImg() const;
+
+ /** Replace the image data of the original image with the given data.
+ The characteristics of the data must match the characteristics of
+ the original image as returned by the original...() methods,
+ respectively the given width and height parameters.
+ No ownership of the data pointer is assumed.
+ If w == -1 and h == -1, the size is unchanged.
+ Caller is an i18n'ed string that will be shown as the undo/redo action name.
+ */
+ void putOriginalImage(const TQString &caller, uchar* data, int w=-1, int h=-1);
+
+ /** Embed the Color Profile we have used in ICC plugin when this option is
+ selected
+ */
+ void setEmbeddedICCToOriginalImage(const TQString& profilePath);
+
+ /** Replace the data of the current original image selection with the given data.
+ The characteristics of the data must match the characteristics of the current
+ selection as returned by the selectionWidth(), selectionHeight(),
+ originalSixteenBit() and originalHasAlpha() methods.
+ No ownership of the data pointer is assumed.
+ Caller is an i18n'ed string that will be shown as the undo/redo action name.
+ */
+ void putImageSelection(const TQString &caller, uchar* data);
+
+ /** Replace the stored target preview data with the given data.
+ The characteristics of the data must match the characteristics of the current
+ as returned by the preview...() methods.
+ The target preview data is used by the paint() and
+ getColorInfoFromTargetPreviewImage() methods.
+ The data returned by getPreviewImage() is unaffected.
+ No ownership of the data pointer is assumed.
+ */
+ void putPreviewImage(uchar* data);
+
+ /** Get colors from original, (unchanged) preview
+ or target preview (set by putPreviewImage) image.
+ */
+
+ DColor getColorInfoFromOriginalImage(const TQPoint& point);
+ DColor getColorInfoFromPreviewImage(const TQPoint& point);
+ DColor getColorInfoFromTargetPreviewImage(const TQPoint& point);
+
+ /** Original image information.*/
+ int originalWidth();
+ int originalHeight();
+ bool originalSixteenBit();
+ bool originalHasAlpha();
+
+ /** Original image metadata.*/
+ TQByteArray getEmbeddedICCFromOriginalImage();
+ TQByteArray getExifFromOriginalImage();
+ TQByteArray getIptcFromOriginalImage();
+
+ /** Get photograph information from original image.*/
+ PhotoInfoContainer getPhotographInformations() const;
+
+ /** Standard methods to get/set preview information.*/
+ int previewWidth();
+ int previewHeight();
+ bool previewHasAlpha();
+ bool previewSixteenBit();
+
+ /** Sets preview size and returns new preview data as with getPreviewImage.
+ The parameters are only hints, previewWidth() and previewHeight()
+ may differ from w and h.
+ */
+ uchar* setPreviewImageSize(int w, int h) const;
+
+ /** Standard methods to get image selection information.*/
+ int selectedWidth();
+ int selectedHeight();
+
+ /** Get selected (X, Y) position on the top/left corner of the original image.*/
+ int selectedXOrg();
+ int selectedYOrg();
+
+ /** Set BCG correction for preview and original image */
+ void setPreviewBCG(double brightness, double contrast, double gamma);
+ void setOriginalBCG(double brightness, double contrast, double gamma);
+
+ /** Convert depth of original image */
+ void convertOriginalColorDepth(int depth);
+
+ /** Convert a DImg image to a pixmap for screen using color
+ managemed view if necessary */
+ TQPixmap convertToPixmap(DImg& img);
+
+ /** Paint the current target preview image (or the preview image,
+ if putPreviewImage has not been called) on the given paint device.
+ at x|y, with given maximum width and height.
+ */
+ void paint(TQPaintDevice* device, int x, int y, int w, int h,
+ bool underExposure=false, bool overExposure=false);
+
+private:
+
+ ImageIfacePriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* IMAGEIFACE_H */
diff --git a/src/utilities/imageeditor/editor/imagewindow.cpp b/src/utilities/imageeditor/editor/imagewindow.cpp
new file mode 100644
index 00000000..2c10a6f6
--- /dev/null
+++ b/src/utilities/imageeditor/editor/imagewindow.cpp
@@ -0,0 +1,1263 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-02-12
+ * Description : digiKam image editor GUI
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * 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 <cstdio>
+
+// TQt includes.
+
+#include <tqcursor.h>
+#include <tqtimer.h>
+#include <tqlabel.h>
+#include <tqimage.h>
+#include <tqsplitter.h>
+#include <tqpainter.h>
+#include <tqpixmap.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <tdeconfig.h>
+#include <kstandarddirs.h>
+#include <tdeapplication.h>
+#include <tdemessagebox.h>
+#include <tdetempfile.h>
+#include <kimageio.h>
+#include <tdefiledialog.h>
+#include <tdeversion.h>
+#include <tdemenubar.h>
+#include <tdetoolbar.h>
+#include <tdeaccel.h>
+#include <tdeaction.h>
+#include <tdestdaccel.h>
+#include <kstdaction.h>
+#include <kstdguiitem.h>
+#include <kstatusbar.h>
+#include <kprogress.h>
+#include <twin.h>
+
+// Local includes.
+
+#include "constants.h"
+#include "ddebug.h"
+#include "dlogoaction.h"
+#include "dpopupmenu.h"
+#include "dragobjects.h"
+#include "canvas.h"
+#include "dimginterface.h"
+#include "dimg.h"
+#include "dmetadata.h"
+#include "imageplugin.h"
+#include "imagepluginloader.h"
+#include "imageprint.h"
+#include "albummanager.h"
+#include "album.h"
+#include "albumdb.h"
+#include "albumsettings.h"
+#include "syncjob.h"
+#include "imageinfo.h"
+#include "imagepropertiessidebardb.h"
+#include "tagspopupmenu.h"
+#include "ratingpopupmenu.h"
+#include "slideshow.h"
+#include "setup.h"
+#include "iccsettingscontainer.h"
+#include "iofilesettingscontainer.h"
+#include "loadingcacheinterface.h"
+#include "savingcontextcontainer.h"
+#include "statusprogressbar.h"
+#include "imageattributeswatch.h"
+#include "deletedialog.h"
+#include "metadatahub.h"
+#include "themeengine.h"
+#include "editorstackview.h"
+#include "imagewindow.h"
+#include "imagewindow.moc"
+
+namespace Digikam
+{
+
+class ImageWindowPriv
+{
+
+public:
+
+ ImageWindowPriv()
+ {
+ allowSaving = true;
+ star0 = 0;
+ star1 = 0;
+ star2 = 0;
+ star3 = 0;
+ star4 = 0;
+ star5 = 0;
+ fileDeletePermanentlyAction = 0;
+ fileDeletePermanentlyDirectlyAction = 0;
+ fileTrashDirectlyAction = 0;
+ imageInfoCurrent = 0;
+ rightSidebar = 0;
+ }
+
+ // If image editor is launched by camera interface, current
+ // image cannot be saved.
+ bool allowSaving;
+
+ KURL::List urlList;
+ KURL urlCurrent;
+
+ // Rating actions.
+ TDEAction *star0;
+ TDEAction *star1;
+ TDEAction *star2;
+ TDEAction *star3;
+ TDEAction *star4;
+ TDEAction *star5;
+
+ // Delete actions
+ TDEAction *fileDeletePermanentlyAction;
+ TDEAction *fileDeletePermanentlyDirectlyAction;
+ TDEAction *fileTrashDirectlyAction;
+
+ ImageInfoList imageInfoList;
+ ImageInfo *imageInfoCurrent;
+
+ ImagePropertiesSideBarDB *rightSidebar;
+};
+
+ImageWindow* ImageWindow::m_instance = 0;
+
+ImageWindow* ImageWindow::imagewindow()
+{
+ if (!m_instance)
+ new ImageWindow();
+
+ return m_instance;
+}
+
+bool ImageWindow::imagewindowCreated()
+{
+ return m_instance;
+}
+
+ImageWindow::ImageWindow()
+ : EditorWindow( "Image Editor" )
+{
+ d = new ImageWindowPriv;
+ m_instance = this;
+ setAcceptDrops(true);
+
+ // -- Build the GUI -------------------------------
+
+ setupUserArea();
+ setupStatusBar();
+ setupActions();
+
+ // Load image plugins to GUI
+
+ m_imagePluginLoader = ImagePluginLoader::instance();
+ loadImagePlugins();
+
+ // Create context menu.
+
+ setupContextMenu();
+
+ // Make signals/slots connections
+
+ setupConnections();
+
+ // -- Read settings --------------------------------
+
+ readSettings();
+ applySettings();
+ setAutoSaveSettings("ImageViewer Settings");
+
+ //-------------------------------------------------------------
+
+ d->rightSidebar->loadViewState();
+ d->rightSidebar->populateTags();
+}
+
+ImageWindow::~ImageWindow()
+{
+ m_instance = 0;
+
+ unLoadImagePlugins();
+
+ // No need to delete m_imagePluginLoader instance here, it will be done by main interface.
+
+ delete d->rightSidebar;
+ delete d;
+}
+
+Sidebar* ImageWindow::rightSideBar() const
+{
+ return dynamic_cast<Sidebar*>(d->rightSidebar);
+}
+
+void ImageWindow::closeEvent(TQCloseEvent* e)
+{
+ if (!e)
+ return;
+
+ if (!queryClose())
+ return;
+
+ // put right side bar in a defined state
+ emit signalNoCurrentItem();
+
+ m_canvas->resetImage();
+
+ saveSettings();
+
+ e->accept();
+}
+
+bool ImageWindow::queryClose()
+{
+ // Note: we reimplement closeEvent above for this window.
+ // Additionally, queryClose is called from DigikamApp.
+
+ // wait if a save operation is currently running
+ if (!waitForSavingToComplete())
+ return false;
+
+ return promptUserSave(d->urlCurrent);
+}
+
+void ImageWindow::setupConnections()
+{
+ setupStandardConnections();
+
+ // To toggle properly keyboards shortcuts from comments & tags side bar tab.
+
+ connect(d->rightSidebar, TQ_SIGNAL(signalNextItem()),
+ this, TQ_SLOT(slotForward()));
+
+ connect(d->rightSidebar, TQ_SIGNAL(signalPrevItem()),
+ this, TQ_SLOT(slotBackward()));
+
+ connect(this, TQ_SIGNAL(signalSelectionChanged( const TQRect &)),
+ d->rightSidebar, TQ_SLOT(slotImageSelectionChanged( const TQRect &)));
+
+ connect(this, TQ_SIGNAL(signalNoCurrentItem()),
+ d->rightSidebar, TQ_SLOT(slotNoCurrentItem()));
+
+ ImageAttributesWatch *watch = ImageAttributesWatch::instance();
+
+ connect(watch, TQ_SIGNAL(signalFileMetadataChanged(const KURL &)),
+ this, TQ_SLOT(slotFileMetadataChanged(const KURL &)));
+}
+
+void ImageWindow::setupUserArea()
+{
+ TQWidget* widget = new TQWidget(this);
+ TQHBoxLayout *lay = new TQHBoxLayout(widget);
+
+ m_splitter = new TQSplitter(widget);
+ m_stackView = new EditorStackView(m_splitter);
+ m_canvas = new Canvas(m_stackView);
+ m_stackView->setCanvas(m_canvas);
+ m_stackView->setViewMode(EditorStackView::CanvasMode);
+
+ m_canvas->makeDefaultEditingCanvas();
+
+ TQSizePolicy rightSzPolicy(TQSizePolicy::Preferred, TQSizePolicy::Expanding, 2, 1);
+ m_canvas->setSizePolicy(rightSzPolicy);
+
+ d->rightSidebar = new ImagePropertiesSideBarDB(widget, "ImageEditor Right Sidebar", m_splitter,
+ Sidebar::Right, true);
+ lay->addWidget(m_splitter);
+ lay->addWidget(d->rightSidebar);
+
+ m_splitter->setFrameStyle( TQFrame::NoFrame );
+ m_splitter->setFrameShadow( TQFrame::Plain );
+ m_splitter->setFrameShape( TQFrame::NoFrame );
+ m_splitter->setOpaqueResize(false);
+ setCentralWidget(widget);
+}
+
+void ImageWindow::setupActions()
+{
+ setupStandardActions();
+
+ // Provides a menu entry that allows showing/hiding the toolbar(s)
+ setStandardToolBarMenuEnabled(true);
+
+ // Provides a menu entry that allows showing/hiding the statusbar
+ createStandardStatusBarAction();
+
+ // -- Rating actions ---------------------------------------------------------------
+
+ d->star0 = new TDEAction(i18n("Assign Rating \"No Stars\""), CTRL+Key_0,
+ this, TQ_SLOT(slotAssignRatingNoStar()),
+ actionCollection(), "imageview_ratenostar");
+ d->star1 = new TDEAction(i18n("Assign Rating \"One Star\""), CTRL+Key_1,
+ this, TQ_SLOT(slotAssignRatingOneStar()),
+ actionCollection(), "imageview_rateonestar");
+ d->star2 = new TDEAction(i18n("Assign Rating \"Two Stars\""), CTRL+Key_2,
+ this, TQ_SLOT(slotAssignRatingTwoStar()),
+ actionCollection(), "imageview_ratetwostar");
+ d->star3 = new TDEAction(i18n("Assign Rating \"Three Stars\""), CTRL+Key_3,
+ this, TQ_SLOT(slotAssignRatingThreeStar()),
+ actionCollection(), "imageview_ratethreestar");
+ d->star4 = new TDEAction(i18n("Assign Rating \"Four Stars\""), CTRL+Key_4,
+ this, TQ_SLOT(slotAssignRatingFourStar()),
+ actionCollection(), "imageview_ratefourstar");
+ d->star5 = new TDEAction(i18n("Assign Rating \"Five Stars\""), CTRL+Key_5,
+ this, TQ_SLOT(slotAssignRatingFiveStar()),
+ actionCollection(), "imageview_ratefivestar");
+
+ // -- Special Delete actions ---------------------------------------------------------------
+
+ // Pop up dialog to ask user whether to permanently delete
+ d->fileDeletePermanentlyAction = new TDEAction(i18n("Delete File Permanently"),
+ "edit-delete",
+ SHIFT+Key_Delete,
+ this,
+ TQ_SLOT(slotDeleteCurrentItemPermanently()),
+ actionCollection(),
+ "image_delete_permanently");
+
+ // These two actions are hidden, no menu entry, no toolbar entry, no shortcut.
+ // Power users may add them.
+ d->fileDeletePermanentlyDirectlyAction = new TDEAction(i18n("Delete Permanently without Confirmation"),
+ "edit-delete",
+ 0,
+ this,
+ TQ_SLOT(slotDeleteCurrentItemPermanentlyDirectly()),
+ actionCollection(),
+ "image_delete_permanently_directly");
+
+ d->fileTrashDirectlyAction = new TDEAction(i18n("Move to Trash without Confirmation"),
+ "edittrash",
+ 0,
+ this,
+ TQ_SLOT(slotTrashCurrentItemDirectly()),
+ actionCollection(),
+ "image_trash_directly");
+
+ // ---------------------------------------------------------------------------------
+
+ new DLogoAction(actionCollection(), "logo_action");
+
+ createGUI("digikamimagewindowui.rc", false);
+
+ setupStandardAccelerators();
+}
+
+void ImageWindow::applySettings()
+{
+ applyStandardSettings();
+
+ AlbumSettings *settings = AlbumSettings::instance();
+ m_canvas->setExifOrient(settings->getExifRotate());
+ m_setExifOrientationTag = settings->getExifSetOrientation();
+ refreshView();
+}
+
+void ImageWindow::refreshView()
+{
+ d->rightSidebar->refreshTagsView();
+}
+
+void ImageWindow::loadURL(const KURL::List& urlList, const KURL& urlCurrent,
+ const TQString& caption, bool allowSaving)
+{
+ if (!promptUserSave(d->urlCurrent))
+ return;
+
+ d->urlList = urlList;
+ d->urlCurrent = urlCurrent;
+ d->imageInfoList = ImageInfoList();
+ d->imageInfoCurrent = 0;
+
+ loadCurrentList(caption, allowSaving);
+}
+
+void ImageWindow::loadImageInfos(const ImageInfoList &imageInfoList, ImageInfo *imageInfoCurrent,
+ const TQString& caption, bool allowSaving)
+{
+ // The ownership of objects of imageInfoList is passed to us.
+ // imageInfoCurrent is contained in imageInfoList.
+
+ // Very first thing is to check for changes, user may choose to cancel operation
+ if (!promptUserSave(d->urlCurrent))
+ {
+ // delete objects from list
+ for (ImageInfoList::iterator it = imageInfoList.begin(); it != imageInfoList.end(); ++it)
+ delete *it;
+ return;
+ }
+
+ // take over ImageInfo list
+ d->imageInfoList = imageInfoList;
+ d->imageInfoCurrent = imageInfoCurrent;
+
+ d->imageInfoList.setAutoDelete(true);
+
+ // create URL list
+ d->urlList = KURL::List();
+
+ ImageInfoListIterator it(d->imageInfoList);
+ ImageInfo *info;
+ for (; (info = it.current()); ++it)
+ {
+ d->urlList.append(info->kurl());
+ }
+
+ d->urlCurrent = d->imageInfoCurrent->kurl();
+
+ loadCurrentList(caption, allowSaving);
+}
+
+void ImageWindow::loadCurrentList(const TQString& caption, bool allowSaving)
+{
+ // this method contains the code shared by loadURL and loadImageInfos
+
+ // if window is iconified, show it
+ if (isMinimized())
+ {
+ KWin::deIconifyWindow(winId());
+ }
+
+ if (!caption.isEmpty())
+ setCaption(i18n("Image Editor - %1").arg(caption));
+ else
+ setCaption(i18n("Image Editor"));
+
+ d->allowSaving = allowSaving;
+
+ m_saveAction->setEnabled(false);
+ m_revertAction->setEnabled(false);
+ m_undoAction->setEnabled(false);
+ m_redoAction->setEnabled(false);
+
+ TQTimer::singleShot(0, this, TQ_SLOT(slotLoadCurrent()));
+}
+
+void ImageWindow::slotLoadCurrent()
+{
+ KURL::List::iterator it = d->urlList.find(d->urlCurrent);
+
+ if (it != d->urlList.end())
+ {
+ m_canvas->load(d->urlCurrent.path(), m_IOFileSettings);
+
+ ++it;
+ if (it != d->urlList.end())
+ m_canvas->preload((*it).path());
+ }
+
+ // Do this _after_ the canvas->load(), so that the main view histogram does not load
+ // a smaller version if a raw image, and after that the DImgInterface loads the full version.
+ // So first let DImgInterface create its loading task, only then any external objects.
+ setViewToURL(d->urlCurrent);
+}
+
+void ImageWindow::setViewToURL(const KURL &url)
+{
+ emit signalURLChanged(url);
+}
+
+void ImageWindow::slotForward()
+{
+ if(!promptUserSave(d->urlCurrent))
+ return;
+
+ KURL::List::iterator it = d->urlList.find(d->urlCurrent);
+ int index = d->imageInfoList.find(d->imageInfoCurrent);
+
+ if (it != d->urlList.end())
+ {
+ if (d->urlCurrent != d->urlList.last())
+ {
+ KURL urlNext = *(++it);
+ d->imageInfoCurrent = d->imageInfoList.at(index + 1);
+ d->urlCurrent = urlNext;
+ slotLoadCurrent();
+ }
+ }
+}
+
+void ImageWindow::slotBackward()
+{
+ if(!promptUserSave(d->urlCurrent))
+ return;
+
+ KURL::List::iterator it = d->urlList.find(d->urlCurrent);
+ int index = d->imageInfoList.find(d->imageInfoCurrent);
+
+ if (it != d->urlList.begin())
+ {
+ if (d->urlCurrent != d->urlList.first())
+ {
+ KURL urlPrev = *(--it);
+ d->imageInfoCurrent = d->imageInfoList.at(index - 1);
+ d->urlCurrent = urlPrev;
+ slotLoadCurrent();
+ }
+ }
+}
+
+void ImageWindow::slotFirst()
+{
+ if(!promptUserSave(d->urlCurrent))
+ return;
+
+ d->urlCurrent = d->urlList.first();
+ d->imageInfoCurrent = d->imageInfoList.first();
+ slotLoadCurrent();
+}
+
+void ImageWindow::slotLast()
+{
+ if(!promptUserSave(d->urlCurrent))
+ return;
+
+ d->urlCurrent = d->urlList.last();
+ d->imageInfoCurrent = d->imageInfoList.last();
+ slotLoadCurrent();
+}
+
+void ImageWindow::slotContextMenu()
+{
+ if (m_contextMenu)
+ {
+ RatingPopupMenu *ratingMenu = 0;
+ TagsPopupMenu *assignTagsMenu = 0;
+ TagsPopupMenu *removeTagsMenu = 0;
+ int separatorID1 = -1;
+ int separatorID2 = -1;
+
+ if (d->imageInfoCurrent)
+ {
+ // Bulk assignment/removal of tags --------------------------
+
+ TQ_LLONG id = d->imageInfoCurrent->id();
+ TQValueList<TQ_LLONG> idList;
+ idList.append(id);
+
+ assignTagsMenu = new TagsPopupMenu(idList, 1000, TagsPopupMenu::ASSIGN);
+ removeTagsMenu = new TagsPopupMenu(idList, 2000, TagsPopupMenu::REMOVE);
+
+ separatorID1 = m_contextMenu->insertSeparator();
+
+ m_contextMenu->insertItem(i18n("Assign Tag"), assignTagsMenu);
+ int i = m_contextMenu->insertItem(i18n("Remove Tag"), removeTagsMenu);
+
+ connect(assignTagsMenu, TQ_SIGNAL(signalTagActivated(int)),
+ this, TQ_SLOT(slotAssignTag(int)));
+
+ connect(removeTagsMenu, TQ_SIGNAL(signalTagActivated(int)),
+ this, TQ_SLOT(slotRemoveTag(int)));
+
+ AlbumDB* db = AlbumManager::instance()->albumDB();
+ if (!db->hasTags( idList ))
+ m_contextMenu->setItemEnabled(i, false);
+
+ separatorID2 = m_contextMenu->insertSeparator();
+
+ // Assign Star Rating -------------------------------------------
+
+ ratingMenu = new RatingPopupMenu();
+
+ connect(ratingMenu, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotAssignRating(int)));
+
+ m_contextMenu->insertItem(i18n("Assign Rating"), ratingMenu);
+ }
+
+ m_contextMenu->exec(TQCursor::pos());
+
+ if (separatorID1 != -1)
+ m_contextMenu->removeItem(separatorID1);
+ if (separatorID2 != -1)
+ m_contextMenu->removeItem(separatorID2);
+
+ delete assignTagsMenu;
+ delete removeTagsMenu;
+ delete ratingMenu;
+ }
+}
+
+void ImageWindow::slotChanged()
+{
+ TQString mpixels;
+ TQSize dims(m_canvas->imageWidth(), m_canvas->imageHeight());
+ mpixels.setNum(dims.width()*dims.height()/1000000.0, 'f', 2);
+ TQString str = (!dims.isValid()) ? i18n("Unknown") : i18n("%1x%2 (%3Mpx)")
+ .arg(dims.width()).arg(dims.height()).arg(mpixels);
+ m_resLabel->setText(str);
+
+ if (d->urlCurrent.isValid())
+ {
+ KURL u(d->urlCurrent.directory());
+
+ DImg* img = m_canvas->interface()->getImg();
+
+ if (d->imageInfoCurrent)
+ {
+ d->rightSidebar->itemChanged(d->imageInfoCurrent,
+ m_canvas->getSelectedArea(), img);
+ }
+ else
+ {
+ d->rightSidebar->itemChanged(d->urlCurrent, m_canvas->getSelectedArea(), img);
+ }
+ }
+}
+
+void ImageWindow::slotUndoStateChanged(bool moreUndo, bool moreRedo, bool canSave)
+{
+ m_revertAction->setEnabled(canSave);
+ m_undoAction->setEnabled(moreUndo);
+ m_redoAction->setEnabled(moreRedo);
+
+ if (d->allowSaving)
+ m_saveAction->setEnabled(canSave);
+
+ if (!moreUndo)
+ m_rotatedOrFlipped = false;
+}
+
+void ImageWindow::slotAssignTag(int tagID)
+{
+ if (d->imageInfoCurrent)
+ {
+ MetadataHub hub;
+ hub.load(d->imageInfoCurrent);
+ hub.setTag(tagID, true);
+ hub.write(d->imageInfoCurrent, MetadataHub::PartialWrite);
+ hub.write(d->imageInfoCurrent->filePath(), MetadataHub::FullWriteIfChanged);
+ }
+}
+
+void ImageWindow::slotRemoveTag(int tagID)
+{
+ if (d->imageInfoCurrent)
+ {
+ MetadataHub hub;
+ hub.load(d->imageInfoCurrent);
+ hub.setTag(tagID, false);
+ hub.write(d->imageInfoCurrent, MetadataHub::PartialWrite);
+ hub.write(d->imageInfoCurrent->filePath(), MetadataHub::FullWriteIfChanged);
+ }
+}
+
+void ImageWindow::slotAssignRatingNoStar()
+{
+ slotAssignRating(0);
+}
+
+void ImageWindow::slotAssignRatingOneStar()
+{
+ slotAssignRating(1);
+}
+
+void ImageWindow::slotAssignRatingTwoStar()
+{
+ slotAssignRating(2);
+}
+
+void ImageWindow::slotAssignRatingThreeStar()
+{
+ slotAssignRating(3);
+}
+
+void ImageWindow::slotAssignRatingFourStar()
+{
+ slotAssignRating(4);
+}
+
+void ImageWindow::slotAssignRatingFiveStar()
+{
+ slotAssignRating(5);
+}
+
+void ImageWindow::slotAssignRating(int rating)
+{
+ rating = TQMIN(RatingMax, TQMAX(RatingMin, rating));
+ if (d->imageInfoCurrent)
+ {
+ MetadataHub hub;
+ hub.load(d->imageInfoCurrent);
+ hub.setRating(rating);
+ hub.write(d->imageInfoCurrent, MetadataHub::PartialWrite);
+ hub.write(d->imageInfoCurrent->filePath(), MetadataHub::FullWriteIfChanged);
+ }
+}
+
+void ImageWindow::slotUpdateItemInfo()
+{
+ uint index = d->urlList.findIndex(d->urlCurrent);
+
+ m_rotatedOrFlipped = false;
+
+ TQString text = d->urlCurrent.filename() + i18n(" (%2 of %3)")
+ .arg(TQString::number(index+1))
+ .arg(TQString::number(d->urlList.count()));
+ m_nameLabel->setText(text);
+
+ if (d->urlList.count() == 1)
+ {
+ m_backwardAction->setEnabled(false);
+ m_forwardAction->setEnabled(false);
+ m_firstAction->setEnabled(false);
+ m_lastAction->setEnabled(false);
+ }
+ else
+ {
+ m_backwardAction->setEnabled(true);
+ m_forwardAction->setEnabled(true);
+ m_firstAction->setEnabled(true);
+ m_lastAction->setEnabled(true);
+ }
+
+ if (index == 0)
+ {
+ m_backwardAction->setEnabled(false);
+ m_firstAction->setEnabled(false);
+ }
+
+ if (index == d->urlList.count()-1)
+ {
+ m_forwardAction->setEnabled(false);
+ m_lastAction->setEnabled(false);
+ }
+
+ // Disable some menu actions if the current root image URL
+ // is not include in the digiKam Albums library database.
+ // This is necessary when ImageEditor is opened from cameraclient.
+
+ KURL u(d->urlCurrent.directory());
+ PAlbum *palbum = AlbumManager::instance()->findPAlbum(u);
+
+ if (!palbum)
+ {
+ m_fileDeleteAction->setEnabled(false);
+ }
+ else
+ {
+ m_fileDeleteAction->setEnabled(true);
+ }
+}
+
+bool ImageWindow::setup(bool iccSetupPage)
+{
+ Setup setup(this, 0, iccSetupPage ? Setup::IccProfiles : Setup::LastPageUsed);
+
+ if (setup.exec() != TQDialog::Accepted)
+ return false;
+
+ kapp->config()->sync();
+
+ applySettings();
+ return true;
+}
+
+void ImageWindow::toggleGUI2FullScreen()
+{
+ if (m_fullScreen)
+ d->rightSidebar->restore();
+ else
+ d->rightSidebar->backup();
+}
+
+void ImageWindow::saveIsComplete()
+{
+ // With save(), we do not reload the image but just continue using the data.
+ // This means that a saving operation does not lead to quality loss for
+ // subsequent editing operations.
+
+ // put image in cache, the LoadingCacheInterface cares for the details
+ LoadingCacheInterface::putImage(m_savingContext->destinationURL.path(), m_canvas->currentImage());
+
+ // notify main app that file changed
+ emit signalFileModified(m_savingContext->destinationURL);
+
+ // all that is done in slotLoadCurrent, except for loading
+ KURL::List::iterator it = d->urlList.find(d->urlCurrent);
+ setViewToURL(*it);
+
+ if (++it != d->urlList.end())
+ {
+ m_canvas->preload((*it).path());
+ }
+ //slotLoadCurrent();
+}
+
+void ImageWindow::saveAsIsComplete()
+{
+ // Nothing to be done if operating without database
+ if (!d->imageInfoCurrent)
+ return;
+
+ // Find the src and dest albums ------------------------------------------
+
+ KURL srcDirURL(TQDir::cleanDirPath(m_savingContext->srcURL.directory()));
+ PAlbum* srcAlbum = AlbumManager::instance()->findPAlbum(srcDirURL);
+
+ KURL dstDirURL(TQDir::cleanDirPath(m_savingContext->destinationURL.directory()));
+ PAlbum* dstAlbum = AlbumManager::instance()->findPAlbum(dstDirURL);
+
+ if (dstAlbum && srcAlbum)
+ {
+ // Now copy the metadata of the original file to the new file ------------
+
+ ImageInfo newInfo(d->imageInfoCurrent->copyItem(dstAlbum, m_savingContext->destinationURL.fileName()));
+
+ if ( d->urlList.find(m_savingContext->destinationURL) == d->urlList.end() )
+ { // The image file did not exist in the list.
+ KURL::List::iterator it = d->urlList.find(m_savingContext->srcURL);
+ int index = d->urlList.findIndex(m_savingContext->srcURL);
+ d->urlList.insert(it, m_savingContext->destinationURL);
+ d->imageInfoCurrent = new ImageInfo(newInfo);
+ d->imageInfoList.insert(index, d->imageInfoCurrent);
+ }
+ else if (d->urlCurrent != m_savingContext->destinationURL)
+ {
+ for (ImageInfo *info = d->imageInfoList.first(); info; info = d->imageInfoList.next())
+ {
+ if (info->kurl() == m_savingContext->destinationURL)
+ {
+ d->imageInfoCurrent = new ImageInfo(newInfo);
+ // setAutoDelete is true
+ d->imageInfoList.replace(d->imageInfoList.at(), d->imageInfoCurrent);
+ break;
+ }
+ }
+ }
+
+ d->urlCurrent = m_savingContext->destinationURL;
+ m_canvas->switchToLastSaved(m_savingContext->destinationURL.path());
+
+ slotUpdateItemInfo();
+
+ // If the DImg is put in the cache under the new name, this means the new file will not be reloaded.
+ // This may irritate users who want to check for quality loss in lossy formats.
+ // In any case, only do that if the format did not change - too many assumptions otherwise (see bug #138949).
+ if (m_savingContext->originalFormat == m_savingContext->format)
+ LoadingCacheInterface::putImage(m_savingContext->destinationURL.path(), m_canvas->currentImage());
+
+ // notify main app that file changed or a file is added
+ if(m_savingContext->destinationExisted)
+ emit signalFileModified(m_savingContext->destinationURL);
+ else
+ emit signalFileAdded(m_savingContext->destinationURL);
+
+ // all that is done in slotLoadCurrent, except for loading
+ KURL::List::iterator it = d->urlList.find(d->urlCurrent);
+
+ if (it != d->urlList.end())
+ {
+ setViewToURL(*it);
+ m_canvas->preload((*++it).path());
+ }
+ }
+ else
+ {
+ //TODO: make the user aware that the new path has not been used as new current filename
+ // because it is outside the digikam album hierachy
+ }
+}
+
+bool ImageWindow::save()
+{
+ // Sanity check. Just to be homogenous with SaveAs.
+ if (d->imageInfoCurrent)
+ {
+ // Write metadata from database to DImg
+ MetadataHub hub;
+ hub.load(d->imageInfoCurrent);
+ DImg image(m_canvas->currentImage());
+ hub.write(image, MetadataHub::FullWrite);
+ }
+
+ startingSave(d->urlCurrent);
+ return true;
+}
+
+bool ImageWindow::saveAs()
+{
+ // If image editor is started from CameraGUI, there is no ImageInfo instance to use.
+ if (d->imageInfoCurrent)
+ {
+ // Write metadata from database to DImg
+ MetadataHub hub;
+ hub.load(d->imageInfoCurrent);
+ DImg image(m_canvas->currentImage());
+ hub.write(image, MetadataHub::FullWrite);
+ }
+
+ return ( startingSaveAs(d->urlCurrent) );
+}
+
+void ImageWindow::slotDeleteCurrentItem()
+{
+ deleteCurrentItem(true, false);
+}
+
+void ImageWindow::slotDeleteCurrentItemPermanently()
+{
+ deleteCurrentItem(true, true);
+}
+
+void ImageWindow::slotDeleteCurrentItemPermanentlyDirectly()
+{
+ deleteCurrentItem(false, true);
+}
+
+void ImageWindow::slotTrashCurrentItemDirectly()
+{
+ deleteCurrentItem(false, false);
+}
+
+void ImageWindow::deleteCurrentItem(bool ask, bool permanently)
+{
+ // This function implements all four of the above slots.
+ // The meaning of permanently differs depending on the value of ask
+
+ KURL u;
+ u.setPath(d->urlCurrent.directory());
+ PAlbum *palbum = AlbumManager::instance()->findPAlbum(u);
+
+ // if available, provide a digikamalbums:// URL to TDEIO
+ KURL kioURL;
+ if (d->imageInfoCurrent)
+ kioURL = d->imageInfoCurrent->kurlForKIO();
+ else
+ kioURL = d->urlCurrent;
+ KURL fileURL = d->urlCurrent;
+
+ if (!palbum)
+ return;
+
+ bool useTrash;
+
+ if (ask)
+ {
+ bool preselectDeletePermanently = permanently;
+
+ DeleteDialog dialog(this);
+
+ KURL::List urlList;
+ urlList.append(d->urlCurrent);
+ if (!dialog.confirmDeleteList(urlList,
+ DeleteDialogMode::Files,
+ preselectDeletePermanently ?
+ DeleteDialogMode::NoChoiceDeletePermanently : DeleteDialogMode::NoChoiceTrash))
+ return;
+
+ useTrash = !dialog.shouldDelete();
+ }
+ else
+ {
+ useTrash = !permanently;
+ }
+
+ // bring all (sidebar) to a defined state without letting them sit on the deleted file
+ emit signalNoCurrentItem();
+
+ // trash does not like non-local URLs, put is not implemented
+ if (useTrash)
+ kioURL = fileURL;
+
+ if (!SyncJob::del(kioURL, useTrash))
+ {
+ TQString errMsg(SyncJob::lastErrorMsg());
+ KMessageBox::error(this, errMsg, errMsg);
+ return;
+ }
+
+ emit signalFileDeleted(d->urlCurrent);
+
+ KURL CurrentToRemove = d->urlCurrent;
+ KURL::List::iterator it = d->urlList.find(d->urlCurrent);
+ int index = d->imageInfoList.find(d->imageInfoCurrent);
+
+ if (it != d->urlList.end())
+ {
+ if (d->urlCurrent != d->urlList.last())
+ {
+ // Try to get the next image in the current Album...
+
+ KURL urlNext = *(++it);
+ d->urlCurrent = urlNext;
+ d->imageInfoCurrent = d->imageInfoList.at(index + 1);
+ d->urlList.remove(CurrentToRemove);
+ d->imageInfoList.remove(index);
+ slotLoadCurrent();
+ return;
+ }
+ else if (d->urlCurrent != d->urlList.first())
+ {
+ // Try to get the previous image in the current Album.
+
+ KURL urlPrev = *(--it);
+ d->urlCurrent = urlPrev;
+ d->imageInfoCurrent = d->imageInfoList.at(index - 1);
+ d->urlList.remove(CurrentToRemove);
+ d->imageInfoList.remove(index);
+ slotLoadCurrent();
+ return;
+ }
+ }
+
+ // No image in the current Album -> Quit ImageEditor...
+
+ KMessageBox::information(this,
+ i18n("There is no image to show in the current album.\n"
+ "The image editor will be closed."),
+ i18n("No Image in Current Album"));
+
+ close();
+}
+
+void ImageWindow::slotFileMetadataChanged(const KURL &url)
+{
+ if (url == d->urlCurrent)
+ {
+ m_canvas->readMetadataFromFile(url.path());
+ }
+}
+
+void ImageWindow::slotFilePrint()
+{
+ printImage(d->urlCurrent);
+};
+
+void ImageWindow::slideShow(bool startWithCurrent, SlideShowSettings& settings)
+{
+ float cnt;
+ DMetadata meta;
+ int i = 0;
+ m_cancelSlideShow = false;
+ settings.exifRotate = AlbumSettings::instance()->getExifRotate();
+
+ if (!d->imageInfoList.isEmpty())
+ {
+ // We have started image editor from Album GUI. we get picture comments from database.
+
+ m_nameLabel->progressBarMode(StatusProgressBar::CancelProgressBarMode,
+ i18n("Preparing slideshow. Please wait..."));
+
+ cnt = (float)d->imageInfoList.count();
+
+ for (ImageInfo *info = d->imageInfoList.first() ;
+ !m_cancelSlideShow && info ; info = d->imageInfoList.next())
+ {
+ SlidePictureInfo pictInfo;
+ pictInfo.comment = info->caption();
+
+ // Perform optimizations: only read pictures metadata if necessary.
+ if (settings.printApertureFocal || settings.printExpoSensitivity || settings.printMakeModel)
+ {
+ meta.load(info->kurl().path());
+ pictInfo.photoInfo = meta.getPhotographInformations();
+ }
+
+ // In case of dateTime extraction from metadata failed
+ pictInfo.photoInfo.dateTime = info->dateTime();
+ settings.pictInfoMap.insert(info->kurl(), pictInfo);
+
+ m_nameLabel->setProgressValue((int)((i++/cnt)*100.0));
+ kapp->processEvents();
+ }
+ }
+ else
+ {
+ // We have started image editor from Camera GUI. we get picture comments from metadata.
+
+ m_nameLabel->progressBarMode(StatusProgressBar::CancelProgressBarMode,
+ i18n("Preparing slideshow. Please wait..."));
+
+ cnt = (float)d->urlList.count();
+
+ for (KURL::List::Iterator it = d->urlList.begin() ;
+ !m_cancelSlideShow && (it != d->urlList.end()) ; ++it)
+ {
+ SlidePictureInfo pictInfo;
+ meta.load((*it).path());
+ pictInfo.comment = meta.getImageComment();
+ pictInfo.photoInfo = meta.getPhotographInformations();
+ settings.pictInfoMap.insert(*it, pictInfo);
+
+ m_nameLabel->setProgressValue((int)((i++/cnt)*100.0));
+ kapp->processEvents();
+ }
+ }
+
+ m_nameLabel->progressBarMode(StatusProgressBar::TextMode, TQString());
+
+ if (!m_cancelSlideShow)
+ {
+ settings.exifRotate = AlbumSettings::instance()->getExifRotate();
+ settings.fileList = d->urlList;
+
+ SlideShow *slide = new SlideShow(settings);
+ if (startWithCurrent)
+ slide->setCurrent(d->urlCurrent);
+
+ slide->show();
+ }
+}
+
+void ImageWindow::dragMoveEvent(TQDragMoveEvent *e)
+{
+ int albumID;
+ TQValueList<int> albumIDs;
+ TQValueList<int> imageIDs;
+ KURL::List urls;
+ KURL::List kioURLs;
+
+ if (ItemDrag::decode(e, urls, kioURLs, albumIDs, imageIDs) ||
+ AlbumDrag::decode(e, urls, albumID) ||
+ TagDrag::canDecode(e))
+ {
+ e->accept();
+ return;
+ }
+
+ e->ignore();
+}
+
+void ImageWindow::dropEvent(TQDropEvent *e)
+{
+ int albumID;
+ TQValueList<int> albumIDs;
+ TQValueList<int> imageIDs;
+ KURL::List urls;
+ KURL::List kioURLs;
+
+ if (ItemDrag::decode(e, urls, kioURLs, albumIDs, imageIDs))
+ {
+ ImageInfoList imageInfoList;
+
+ for (TQValueList<int>::const_iterator it = imageIDs.begin();
+ it != imageIDs.end(); ++it)
+ {
+ ImageInfo *info = new ImageInfo(*it);
+ imageInfoList.append(info);
+ }
+
+ if (imageInfoList.isEmpty())
+ {
+ e->ignore();
+ return;
+ }
+
+ TQString ATitle;
+ AlbumManager* man = AlbumManager::instance();
+ PAlbum* palbum = man->findPAlbum(albumIDs.first());
+ if (palbum) ATitle = palbum->title();
+
+ TAlbum* talbum = man->findTAlbum(albumIDs.first());
+ if (talbum) ATitle = talbum->title();
+
+ loadImageInfos(imageInfoList, imageInfoList.first(),
+ i18n("Album \"%1\"").arg(ATitle), true);
+ e->accept();
+ }
+ else if (AlbumDrag::decode(e, urls, albumID))
+ {
+ AlbumManager* man = AlbumManager::instance();
+ TQValueList<TQ_LLONG> itemIDs = man->albumDB()->getItemIDsInAlbum(albumID);
+ ImageInfoList imageInfoList;
+
+ for (TQValueList<TQ_LLONG>::const_iterator it = itemIDs.begin();
+ it != itemIDs.end(); ++it)
+ {
+ ImageInfo *info = new ImageInfo(*it);
+ imageInfoList.append(info);
+ }
+
+ if (imageInfoList.isEmpty())
+ {
+ e->ignore();
+ return;
+ }
+
+ TQString ATitle;
+ PAlbum* palbum = man->findPAlbum(albumIDs.first());
+ if (palbum) ATitle = palbum->title();
+
+ loadImageInfos(imageInfoList, imageInfoList.first(),
+ i18n("Album \"%1\"").arg(ATitle), true);
+ e->accept();
+ }
+ else if(TagDrag::canDecode(e))
+ {
+ TQByteArray ba = e->encodedData("digikam/tag-id");
+ TQDataStream ds(ba, IO_ReadOnly);
+ int tagID;
+ ds >> tagID;
+
+ AlbumManager* man = AlbumManager::instance();
+ TQValueList<TQ_LLONG> itemIDs = man->albumDB()->getItemIDsInTag(tagID, true);
+ ImageInfoList imageInfoList;
+
+ for (TQValueList<TQ_LLONG>::const_iterator it = itemIDs.begin();
+ it != itemIDs.end(); ++it)
+ {
+ ImageInfo *info = new ImageInfo(*it);
+ imageInfoList.append(info);
+ }
+
+ if (imageInfoList.isEmpty())
+ {
+ e->ignore();
+ return;
+ }
+
+ TQString ATitle;
+ TAlbum* talbum = man->findTAlbum(tagID);
+ if (talbum) ATitle = talbum->title();
+
+ loadImageInfos(imageInfoList, imageInfoList.first(),
+ i18n("Album \"%1\"").arg(ATitle), true);
+ e->accept();
+ }
+ else
+ {
+ e->ignore();
+ }
+}
+
+void ImageWindow::slotRevert()
+{
+ if(!promptUserSave(d->urlCurrent))
+ return;
+
+ m_canvas->slotRestore();
+}
+
+void ImageWindow::slotChangeTheme(const TQString& theme)
+{
+ AlbumSettings::instance()->setCurrentTheme(theme);
+ ThemeEngine::instance()->slotChangeTheme(theme);
+}
+
+} // namespace Digikam
diff --git a/src/utilities/imageeditor/editor/imagewindow.h b/src/utilities/imageeditor/editor/imagewindow.h
new file mode 100644
index 00000000..389518a8
--- /dev/null
+++ b/src/utilities/imageeditor/editor/imagewindow.h
@@ -0,0 +1,155 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-02-12
+ * Description : digiKam image editor GUI
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * 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 IMAGEWINDOW_H
+#define IMAGEWINDOW_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Local includes.
+
+#include "editorwindow.h"
+#include "imageinfo.h"
+
+class TQDragMoveEvent;
+class TQDropEvent;
+
+namespace Digikam
+{
+
+class AlbumIconView;
+class ImageWindowPriv;
+class SlideShowSettings;
+
+class ImageWindow : public EditorWindow
+{
+ TQ_OBJECT
+
+
+public:
+
+ ~ImageWindow();
+
+ void loadURL(const KURL::List& urlList, const KURL& urlCurrent,
+ const TQString& caption=TQString(),
+ bool allowSaving=true);
+
+ void loadImageInfos(const ImageInfoList &imageInfoList,
+ ImageInfo *imageInfoCurrent,
+ const TQString& caption, bool allowSaving);
+
+ static ImageWindow* imagewindow();
+ static bool imagewindowCreated();
+
+ void applySettings();
+ void refreshView();
+ bool setup(bool iccSetupPage=false);
+
+ bool queryClose();
+
+signals:
+
+ void signalFileDeleted(const KURL& url);
+ void signalFileAdded(const KURL& url);
+ void signalFileModified(const KURL& url);
+ void signalURLChanged(const KURL& url);
+
+private:
+
+ void loadCurrentList(const TQString& caption, bool allowSaving);
+ void closeEvent(TQCloseEvent* e);
+
+ void dragMoveEvent(TQDragMoveEvent *e);
+ void dropEvent(TQDropEvent *e);
+
+ void setupActions();
+ void setupConnections();
+ void setupUserArea();
+ void toggleGUI2FullScreen();
+
+ bool save();
+ bool saveAs();
+
+ void saveIsComplete();
+ void saveAsIsComplete();
+ void setViewToURL(const KURL &url);
+ void deleteCurrentItem(bool ask, bool permanently);
+
+ void slideShow(bool startWithCurrent, SlideShowSettings& settings);
+
+ Sidebar* rightSideBar() const;
+
+ ImageWindow();
+
+private slots:
+
+ void slotForward();
+ void slotBackward();
+ void slotFirst();
+ void slotLast();
+ void slotFilePrint();
+
+ void slotLoadCurrent();
+ void slotDeleteCurrentItem();
+ void slotDeleteCurrentItemPermanently();
+ void slotDeleteCurrentItemPermanentlyDirectly();
+ void slotTrashCurrentItemDirectly();
+
+ void slotChanged();
+ void slotUndoStateChanged(bool, bool, bool);
+ void slotUpdateItemInfo();
+
+ void slotContextMenu();
+ void slotRevert();
+
+ void slotAssignTag(int tagID);
+ void slotRemoveTag(int tagID);
+
+ void slotAssignRatingNoStar();
+ void slotAssignRatingOneStar();
+ void slotAssignRatingTwoStar();
+ void slotAssignRatingThreeStar();
+ void slotAssignRatingFourStar();
+ void slotAssignRatingFiveStar();
+ void slotAssignRating(int rating);
+
+ void slotFileMetadataChanged(const KURL &);
+ void slotChangeTheme(const TQString& theme);
+
+private:
+
+ ImageWindowPriv *d;
+
+ static ImageWindow *m_instance;
+};
+
+} // namespace Digikam
+
+#endif /* IMAGEWINDOW_H */
diff --git a/src/utilities/imageeditor/editor/savingcontextcontainer.h b/src/utilities/imageeditor/editor/savingcontextcontainer.h
new file mode 100644
index 00000000..c747a357
--- /dev/null
+++ b/src/utilities/imageeditor/editor/savingcontextcontainer.h
@@ -0,0 +1,89 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-20
+ * Description : image editor GUI saving context container
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <[email protected]>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef SAVINGCONTEXTCONTAINER_H
+#define SAVINGCONTEXTCONTAINER_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <kurl.h>
+#include <tdetempfile.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT SavingContextContainer
+{
+
+public:
+
+ SavingContextContainer()
+ {
+ savingState = SavingStateNone;
+ synchronizingState = NormalSaving;
+ saveTempFile = 0;
+ destinationExisted = false;
+ synchronousSavingResult = false;
+ abortingSaving = false;
+ }
+
+ enum SavingState
+ {
+ SavingStateNone,
+ SavingStateSave,
+ SavingStateSaveAs
+ };
+
+ enum SynchronizingState
+ {
+ NormalSaving,
+ SynchronousSaving
+ };
+
+ SavingState savingState;
+ SynchronizingState synchronizingState;
+ bool synchronousSavingResult;
+ bool destinationExisted;
+ bool abortingSaving;
+
+ TQString originalFormat;
+ TQString format;
+
+ KURL srcURL;
+ KURL destinationURL;
+
+ KTempFile *saveTempFile;
+};
+
+} // namespace Digikam
+
+#endif /* SAVINGCONTEXTCONTAINER_H */