File indexing completed on 2025-01-19 03:59:13

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2008-08-20
0007  * Description : Image editor interface used by editor tools.
0008  *
0009  * SPDX-FileCopyrightText: 2008-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "editortooliface.h"
0016 
0017 // Qt includes
0018 
0019 #include <QWidget>
0020 
0021 // KDE includes
0022 
0023 #include <klocalizedstring.h>
0024 
0025 // Local includes
0026 
0027 #include "sidebar.h"
0028 #include "canvas.h"
0029 #include "statusprogressbar.h"
0030 #include "editortool.h"
0031 #include "editortoolsettings.h"
0032 #include "editorstackview.h"
0033 #include "editorwindow.h"
0034 #include "imageguidewidget.h"
0035 #include "imageregionwidget.h"
0036 #include "previewlayout.h"
0037 #include "dcategorizedview.h"
0038 
0039 namespace Digikam
0040 {
0041 
0042 class Q_DECL_HIDDEN EditorToolIface::Private
0043 {
0044 
0045 public:
0046 
0047     explicit Private()
0048       : toolsIconView(nullptr),
0049         lastActiveTab(nullptr),
0050         tool         (nullptr),
0051         editor       (nullptr),
0052         splitterSize (0)
0053     {
0054     }
0055 
0056     DCategorizedView* toolsIconView;
0057     QWidget*          lastActiveTab;
0058     EditorTool*       tool;
0059     EditorWindow*     editor;
0060 
0061     int               splitterSize;
0062 };
0063 
0064 EditorToolIface* EditorToolIface::m_iface = nullptr;
0065 
0066 EditorToolIface* EditorToolIface::editorToolIface()
0067 {
0068     return m_iface;
0069 }
0070 
0071 EditorToolIface::EditorToolIface(EditorWindow* const editor)
0072     : QObject(),
0073       d      (new Private)
0074 {
0075     d->editor = editor;
0076     m_iface   = this;
0077 }
0078 
0079 EditorToolIface::~EditorToolIface()
0080 {
0081     delete d->tool;
0082     delete d;
0083 
0084     if (m_iface == this)
0085     {
0086         m_iface = nullptr;
0087     }
0088 }
0089 
0090 void EditorToolIface::setToolsIconView(DCategorizedView* const view)
0091 {
0092     d->toolsIconView = view;
0093     d->editor->rightSideBar()->appendTab(d->toolsIconView,
0094                                          QIcon::fromTheme(QLatin1String("document-edit")),
0095                                          i18n("Tools"));
0096 }
0097 
0098 EditorTool* EditorToolIface::currentTool() const
0099 {
0100     return d->tool;
0101 }
0102 
0103 void EditorToolIface::loadTool(EditorTool* const tool)
0104 {
0105     if (d->tool)
0106     {
0107         unLoadTool();
0108     }
0109 
0110     d->tool          = tool;
0111     d->lastActiveTab = d->editor->rightSideBar()->getActiveTab();
0112     d->splitterSize  = d->editor->sidebarSplitter()->size(d->editor->rightSideBar());
0113 
0114     d->editor->editorStackView()->setToolView(d->tool->toolView());
0115     d->editor->editorStackView()->setViewMode(EditorStackView::ToolViewMode);
0116 
0117     d->editor->rightSideBar()->deleteTab(d->toolsIconView);
0118     d->editor->rightSideBar()->appendTab(d->tool->toolSettings(), d->tool->toolIcon(), d->tool->toolName());
0119     d->editor->rightSideBar()->setActiveTab(d->tool->toolSettings());
0120 
0121     int w = qMax(d->splitterSize, d->tool->toolSettings()->minimumSizeHint().width());
0122     d->editor->sidebarSplitter()->setSize(d->editor->rightSideBar(), w);
0123 
0124     d->editor->toggleActions(false);
0125     d->editor->toggleToolActions(d->tool);
0126 
0127     // If editor tool has zoomable preview, switch on zoom actions.
0128 
0129     d->editor->toggleZoomActions(d->editor->editorStackView()->isZoomablePreview());
0130 
0131     ImageGuideWidget* const view = dynamic_cast<ImageGuideWidget*>(d->tool->toolView());
0132 
0133     if (view)
0134     {
0135         connect(d->editor, SIGNAL(signalPreviewModeChanged(int)),
0136                 view, SLOT(slotPreviewModeChanged(int)));
0137 
0138         view->slotPreviewModeChanged(d->editor->previewMode());
0139     }
0140 
0141     // To set zoomable preview zoom level and position accordingly with main canvas.
0142 
0143     ImageRegionWidget* const view2 = dynamic_cast<ImageRegionWidget*>(d->tool->toolView());
0144 
0145     if (view2)
0146     {
0147         connect(d->editor, SIGNAL(signalPreviewModeChanged(int)),
0148                 view2, SLOT(slotPreviewModeChanged(int)));
0149 
0150         connect(d->editor->editorStackView(), SIGNAL(signalZoomChanged(bool,bool,double)),
0151                 view2, SLOT(slotOriginalImageRegionChangedDelayed()));
0152 
0153         if (d->editor->editorStackView()->canvas()->layout()->isFitToWindow())
0154         {
0155             view2->fitToWindow();
0156         }
0157         else
0158         {
0159             view2->layout()->setZoomFactor(d->editor->editorStackView()->canvas()->layout()->zoomFactor());
0160             QPoint tl = d->editor->editorStackView()->canvas()->visibleArea().topLeft();
0161             view2->setContentsPos(tl.x(), tl.y());
0162         }
0163 
0164         view2->slotPreviewModeChanged(d->editor->previewMode());
0165     }
0166 
0167     themeChanged();
0168     updateExposureSettings();
0169     updateICCSettings();
0170     setToolInfoMessage(QString());
0171 
0172     connect(d->editor, SIGNAL(signalPreviewModeChanged(int)),
0173             d->tool, SLOT(slotPreviewModeChanged()));
0174 
0175     connect(d->tool, SIGNAL(okClicked()),
0176             this, SLOT(slotToolApplied()));
0177 
0178     d->tool->init();
0179 }
0180 
0181 void EditorToolIface::unLoadTool()
0182 {
0183     if (!d->tool)
0184     {
0185         return;
0186     }
0187 
0188     // To restore  zoom level and position accordingly with zoomable preview.
0189 
0190     ImageRegionWidget* const view2 = dynamic_cast<ImageRegionWidget*>(d->tool->toolView());
0191 
0192     if (view2)
0193     {
0194         if (view2->layout()->isFitToWindow())
0195         {
0196             d->editor->editorStackView()->canvas()->fitToWindow();
0197         }
0198         else
0199         {
0200             d->editor->editorStackView()->canvas()->layout()->setZoomFactor(view2->layout()->zoomFactor());
0201             QPoint tl = view2->visibleArea().topLeft();
0202             d->editor->editorStackView()->canvas()->setContentsPos(tl.x(), tl.y());
0203         }
0204     }
0205 
0206     d->editor->editorStackView()->setViewMode(EditorStackView::CanvasMode);
0207     d->editor->editorStackView()->setToolView(nullptr);
0208     d->editor->rightSideBar()->deleteTab(d->tool->toolSettings());
0209     d->editor->rightSideBar()->appendTab(d->toolsIconView,
0210                                          QIcon::fromTheme(QLatin1String("document-edit")),
0211                                          i18n("Tools"));
0212 
0213     d->editor->rightSideBar()->setActiveTab(d->lastActiveTab);
0214 
0215     if (d->splitterSize > 0)
0216     {
0217         d->editor->sidebarSplitter()->setSize(d->editor->rightSideBar(),
0218                                               d->splitterSize);
0219     }
0220     else
0221     {
0222         d->editor->rightSideBar()->shrink();
0223     }
0224 
0225     d->editor->toggleActions(true);
0226     d->editor->toggleToolActions();
0227     d->editor->slotUpdateItemInfo();
0228     d->editor->setPreviewModeMask(PreviewToolBar::NoPreviewMode);
0229 
0230     delete d->tool;
0231     d->tool = nullptr;
0232 
0233     // Reset info label in status bar with canvas selection info.
0234 
0235     d->editor->slotSelected(!d->editor->m_canvas->getSelectedArea().isNull());
0236     d->editor->editorStackView()->canvas()->layout()->updateZoomAndSize();
0237 }
0238 
0239 void EditorToolIface::setToolInfoMessage(const QString& txt)
0240 {
0241     d->editor->setToolInfoMessage(txt);
0242 }
0243 
0244 void EditorToolIface::setToolStartProgress(const QString& toolName)
0245 {
0246     d->editor->setToolStartProgress(toolName);
0247     d->editor->toggleZoomActions(!d->editor->editorStackView()->isZoomablePreview());
0248 }
0249 
0250 void EditorToolIface::setToolProgress(int progress)
0251 {
0252     d->editor->setToolProgress(progress);
0253 }
0254 
0255 void EditorToolIface::setToolStopProgress()
0256 {
0257     d->editor->setToolStopProgress();
0258     d->editor->toggleZoomActions(d->editor->editorStackView()->isZoomablePreview());
0259 }
0260 
0261 void EditorToolIface::slotToolAborted()
0262 {
0263     EditorToolThreaded* const tool = dynamic_cast<EditorToolThreaded*>(d->tool);
0264 
0265     if (tool)
0266     {
0267         tool->slotAbort();
0268     }
0269 }
0270 
0271 void EditorToolIface::slotCloseTool()
0272 {
0273     EditorTool* const tool = dynamic_cast<EditorTool*>(d->tool);
0274 
0275     if (tool)
0276     {
0277         tool->slotCloseTool();
0278     }
0279 }
0280 
0281 void EditorToolIface::slotApplyTool()
0282 {
0283     EditorTool* const tool = dynamic_cast<EditorTool*>(d->tool);
0284 
0285     if (tool)
0286     {
0287         tool->slotApplyTool();
0288     }
0289 }
0290 
0291 void EditorToolIface::setupICC()
0292 {
0293     d->editor->slotSetupICC();
0294 }
0295 
0296 void EditorToolIface::themeChanged()
0297 {
0298     EditorTool* const tool = dynamic_cast<EditorTool*>(d->tool);
0299 
0300     if (tool)
0301     {
0302         tool->setBackgroundColor(d->editor->m_bgColor);
0303     }
0304 }
0305 
0306 void EditorToolIface::updateICCSettings()
0307 {
0308     EditorTool* const tool = dynamic_cast<EditorTool*>(d->tool);
0309 
0310     if (tool)
0311     {
0312         tool->ICCSettingsChanged();
0313     }
0314 }
0315 
0316 void EditorToolIface::updateExposureSettings()
0317 {
0318     ExposureSettingsContainer* const expoSettings = d->editor->exposureSettings();
0319     d->editor->editorStackView()->canvas()->setExposureSettings(expoSettings);
0320     EditorTool* const tool                        = dynamic_cast<EditorTool*>(d->tool);
0321 
0322     if (tool)
0323     {
0324         tool->exposureSettingsChanged();
0325     }
0326 }
0327 
0328 void EditorToolIface::setPreviewModeMask(int mask)
0329 {
0330     d->editor->setPreviewModeMask(mask);
0331 }
0332 
0333 void EditorToolIface::slotToolApplied()
0334 {
0335     Q_EMIT d->editor->signalToolApplied();
0336 }
0337 
0338 } // namespace Digikam
0339 
0340 #include "moc_editortooliface.cpp"