File indexing completed on 2025-01-05 03:59:45

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2010-01-10
0007  * Description : a tool bar for preview mode
0008  *
0009  * SPDX-FileCopyrightText: 2010-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 "previewtoolbar.h"
0016 
0017 // Qt includes
0018 
0019 #include <QButtonGroup>
0020 #include <QLayout>
0021 #include <QToolButton>
0022 #include <QAbstractButton>
0023 #include <QStandardPaths>
0024 #include <QActionGroup>
0025 #include <QMenu>
0026 
0027 // KDE includes
0028 
0029 #if !defined(Q_OS_DARWIN) && defined(Q_CC_GNU)
0030 #   pragma GCC diagnostic push
0031 #   pragma GCC diagnostic ignored "-Wdeprecated-declarations"
0032 #endif
0033 
0034 #if defined(Q_CC_CLANG)
0035 #   pragma clang diagnostic push
0036 #   pragma clang diagnostic ignored "-Wdeprecated-declarations"
0037 #endif
0038 
0039 #include <kconfiggroup.h>
0040 #include <klocalizedstring.h>
0041 #include <kactioncollection.h>
0042 
0043 // Restore warnings
0044 #if !defined(Q_OS_DARWIN) && defined(Q_CC_GNU)
0045 #   pragma GCC diagnostic pop
0046 #endif
0047 
0048 #if defined(Q_CC_CLANG)
0049 #   pragma clang diagnostic pop
0050 #endif
0051 
0052 // Local includes
0053 
0054 #include "editorwindow.h"
0055 
0056 namespace Digikam
0057 {
0058 
0059 class Q_DECL_HIDDEN PreviewToolBar::Private
0060 {
0061 public:
0062 
0063     explicit Private()
0064       : previewOriginalButton(nullptr),
0065         previewBothButtonVert(nullptr),
0066         previewBothButtonHorz(nullptr),
0067         previewDuplicateBothButtonVert(nullptr),
0068         previewDupplicateBothButtonHorz(nullptr),
0069         previewtargetButton(nullptr),
0070         previewToggleMouseOverButton(nullptr),
0071         previewButtons(nullptr),
0072         actionsGroup(nullptr),
0073         actionsMenu(nullptr)
0074     {
0075     }
0076 
0077     QToolButton*  previewOriginalButton;
0078     QToolButton*  previewBothButtonVert;
0079     QToolButton*  previewBothButtonHorz;
0080     QToolButton*  previewDuplicateBothButtonVert;
0081     QToolButton*  previewDupplicateBothButtonHorz;
0082     QToolButton*  previewtargetButton;
0083     QToolButton*  previewToggleMouseOverButton;
0084 
0085     QButtonGroup* previewButtons;
0086     QActionGroup* actionsGroup;
0087 
0088     QMenu*        actionsMenu;
0089 };
0090 
0091 PreviewToolBar::PreviewToolBar(QWidget* const parent)
0092     : QWidget(parent),
0093       d(new Private)
0094 {
0095     setAttribute(Qt::WA_DeleteOnClose);
0096 
0097     QHBoxLayout* const hlay = new QHBoxLayout(this);
0098     d->previewButtons       = new QButtonGroup(this);
0099     d->previewButtons->setExclusive(true);
0100     hlay->setContentsMargins(QMargins());
0101     hlay->setSpacing(0);
0102 
0103     d->previewOriginalButton = new QToolButton(this);
0104     d->previewButtons->addButton(d->previewOriginalButton, PreviewOriginalImage);
0105     hlay->addWidget(d->previewOriginalButton);
0106     d->previewOriginalButton->setIcon(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("digikam/data/original.png"))));
0107     d->previewOriginalButton->setCheckable(true);
0108     d->previewOriginalButton->setWhatsThis(i18n("If this option is enabled, the original image will be shown."));
0109     d->previewOriginalButton->setToolTip(i18n("Preview original image"));
0110     d->previewOriginalButton->setObjectName(QLatin1String("preview-original"));
0111 
0112     d->previewBothButtonVert = new QToolButton(this);
0113     d->previewButtons->addButton(d->previewBothButtonVert, PreviewBothImagesVertCont);
0114     hlay->addWidget(d->previewBothButtonVert);
0115     d->previewBothButtonVert->setIcon(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("digikam/data/bothvert.png"))));
0116     d->previewBothButtonVert->setCheckable(true);
0117     d->previewBothButtonVert->setWhatsThis(i18n("If this option is enabled, the preview area will "
0118                                                 "split vertically. "
0119                                                 "A contiguous area of the image will be shown, "
0120                                                 "with one half from the original image, "
0121                                                 "the other half from the target image."));
0122     d->previewBothButtonVert->setToolTip(i18n("Preview vertical split with contiguous image"));
0123     d->previewBothButtonVert->setObjectName(QLatin1String("preview-both-vert"));
0124 
0125     d->previewBothButtonHorz = new QToolButton(this);
0126     d->previewButtons->addButton(d->previewBothButtonHorz, PreviewBothImagesHorzCont);
0127     hlay->addWidget(d->previewBothButtonHorz);
0128     d->previewBothButtonHorz->setIcon(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("digikam/data/bothhorz.png"))));
0129     d->previewBothButtonHorz->setCheckable(true);
0130     d->previewBothButtonHorz->setWhatsThis(i18n("If this option is enabled, the preview area will "
0131                                                 "split horizontally. "
0132                                                 "A contiguous area of the image will be shown, "
0133                                                 "with one half from the original image, "
0134                                                 "the other half from the target image."));
0135     d->previewBothButtonHorz->setToolTip(i18n("Preview horizontal split with contiguous image"));
0136     d->previewBothButtonHorz->setObjectName(QLatin1String("preview--both-horz"));
0137 
0138     d->previewDuplicateBothButtonVert = new QToolButton(this);
0139     d->previewButtons->addButton(d->previewDuplicateBothButtonVert, PreviewBothImagesVert);
0140     hlay->addWidget(d->previewDuplicateBothButtonVert);
0141     d->previewDuplicateBothButtonVert->setIcon(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("digikam/data/duplicatebothvert.png"))));
0142     d->previewDuplicateBothButtonVert->setCheckable(true);
0143     d->previewDuplicateBothButtonVert->setWhatsThis(i18n("If this option is enabled, the preview area will "
0144                                                          "split vertically. "
0145                                                          "The same part of the original and the target image "
0146                                                          "will be shown side by side."));
0147     d->previewDuplicateBothButtonVert->setToolTip(i18n("Preview vertical split with same image region"));
0148     d->previewDuplicateBothButtonVert->setObjectName(QLatin1String("preview-duplicate-both-vert"));
0149 
0150     d->previewDupplicateBothButtonHorz = new QToolButton(this);
0151     d->previewButtons->addButton(d->previewDupplicateBothButtonHorz, PreviewBothImagesHorz);
0152     hlay->addWidget(d->previewDupplicateBothButtonHorz);
0153     d->previewDupplicateBothButtonHorz->setIcon(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("digikam/data/duplicatebothhorz.png"))));
0154     d->previewDupplicateBothButtonHorz->setCheckable(true);
0155     d->previewDupplicateBothButtonHorz->setWhatsThis(i18n("If this option is enabled, the preview area will "
0156                                                           "split horizontally. "
0157                                                           "The same part of the original and the target image "
0158                                                           "will be shown side by side."));
0159     d->previewDupplicateBothButtonHorz->setToolTip(i18n("Preview horizontal split with same image region"));
0160     d->previewDupplicateBothButtonHorz->setObjectName(QLatin1String("preview-duplicate-both-horz"));
0161 
0162     d->previewtargetButton = new QToolButton(this);
0163     d->previewButtons->addButton(d->previewtargetButton, PreviewTargetImage);
0164     hlay->addWidget(d->previewtargetButton);
0165     d->previewtargetButton->setIcon(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("digikam/data/target.png"))));
0166     d->previewtargetButton->setCheckable(true);
0167     d->previewtargetButton->setWhatsThis(i18n("If this option is enabled, the target image will be shown."));
0168     d->previewtargetButton->setToolTip(i18n("Preview target image"));
0169     d->previewtargetButton->setObjectName(QLatin1String("preview-target"));
0170 
0171     d->previewToggleMouseOverButton = new QToolButton(this);
0172     d->previewButtons->addButton(d->previewToggleMouseOverButton, PreviewToggleOnMouseOver);
0173     hlay->addWidget(d->previewToggleMouseOverButton);
0174     d->previewToggleMouseOverButton->setIcon(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("digikam/data/togglemouseover.png"))));
0175     d->previewToggleMouseOverButton->setCheckable(true);
0176     d->previewToggleMouseOverButton->setWhatsThis(i18n("If this option is enabled, the original image will "
0177                                                        "be shown when the mouse is over image area; otherwise, "
0178                                                        "the target image will be shown."));
0179     d->previewToggleMouseOverButton->setToolTip(i18n("Preview on mouse-over"));
0180     d->previewToggleMouseOverButton->setObjectName(QLatin1String("preview-toggle-mouse-over"));
0181 
0182 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
0183 
0184     connect(d->previewButtons, SIGNAL(idReleased(int)),
0185             this, SLOT(slotButtonReleased(int)));
0186 
0187 #else
0188 
0189     connect(d->previewButtons, SIGNAL(buttonReleased(int)),
0190             this, SLOT(slotButtonReleased(int)));
0191 
0192 #endif
0193 
0194 }
0195 
0196 PreviewToolBar::~PreviewToolBar()
0197 {
0198     delete d;
0199 }
0200 
0201 void PreviewToolBar::registerMenuActionGroup(EditorWindow* const editor)
0202 {
0203     d->actionsMenu  = new QMenu(i18nc("@action Select image editor preview mode", "Preview Mode"), editor);
0204     d->actionsGroup = new QActionGroup(d->actionsMenu);
0205 
0206     connect(d->actionsGroup, SIGNAL(triggered(QAction*)),
0207             this, SLOT(slotActionTriggered(QAction*)));
0208 
0209     Q_FOREACH (QAbstractButton* const btn, d->previewButtons->buttons())
0210     {
0211         QAction* const ac = new QAction(btn->toolTip(), d->actionsGroup);
0212         ac->setData(QVariant(d->previewButtons->id(btn)));
0213         ac->setIcon(btn->icon());
0214         ac->setCheckable(true);
0215         editor->actionCollection()->addAction(btn->objectName(), ac);
0216         d->actionsMenu->addAction(ac);
0217     }
0218 
0219     editor->actionCollection()->addAction(QLatin1String("editorwindow_previewmode"), d->actionsMenu->menuAction());
0220 }
0221 
0222 void PreviewToolBar::slotActionTriggered(QAction* ac)
0223 {
0224     int id = ac->data().toInt();
0225     d->previewButtons->button(id)->setChecked(true);
0226 
0227     Q_EMIT signalPreviewModeChanged(id);
0228 }
0229 
0230 void PreviewToolBar::slotButtonReleased(int id)
0231 {
0232     setCheckedAction(id);
0233 
0234     Q_EMIT signalPreviewModeChanged(id);
0235 }
0236 
0237 void PreviewToolBar::setCheckedAction(int id)
0238 {
0239     if (!d->actionsGroup) return;
0240 
0241     Q_FOREACH (QAction* const ac, d->actionsGroup->actions())
0242     {
0243         if (ac->data().toInt() == id)
0244         {   // cppcheck-suppress useStlAlgorithm
0245             ac->setChecked(true);
0246             return;
0247         }
0248     }
0249 }
0250 
0251 void PreviewToolBar::setPreviewModeMask(int mask)
0252 {
0253     if (mask == NoPreviewMode)
0254     {
0255         setDisabled(true);
0256 
0257         if (d->actionsMenu)
0258         {
0259             d->actionsMenu->setDisabled(true);
0260         }
0261 
0262         return;
0263     }
0264 
0265     setDisabled(false);
0266 
0267     if (d->actionsMenu)
0268     {
0269         d->actionsMenu->setDisabled(false);
0270     }
0271 
0272     d->previewOriginalButton->setEnabled(mask           & PreviewOriginalImage);
0273     d->previewBothButtonVert->setEnabled(mask           & PreviewBothImagesHorz);
0274     d->previewBothButtonHorz->setEnabled(mask           & PreviewBothImagesVert);
0275     d->previewDuplicateBothButtonVert->setEnabled(mask  & PreviewBothImagesHorzCont);
0276     d->previewDupplicateBothButtonHorz->setEnabled(mask & PreviewBothImagesVertCont);
0277     d->previewtargetButton->setEnabled(mask             & PreviewTargetImage);
0278     d->previewToggleMouseOverButton->setEnabled(mask    & PreviewToggleOnMouseOver);
0279 
0280     if (d->actionsGroup)
0281     {
0282         Q_FOREACH (QAction* const ac, d->actionsGroup->actions())
0283         {
0284             ac->setEnabled(mask & ac->data().toInt());
0285         }
0286     }
0287 
0288     // When we switch to another mask, check if current mode is valid.
0289 
0290     PreviewToolBar::PreviewMode mode = previewMode();
0291 
0292     if (d->previewButtons->button(mode))
0293     {
0294         if (!d->previewButtons->button(mode)->isEnabled())
0295         {
0296             QList<QAbstractButton*> btns = d->previewButtons->buttons();
0297 
0298             Q_FOREACH (QAbstractButton* const btn, btns)
0299             {
0300                 if (btn && btn->isEnabled())
0301                 {   // cppcheck-suppress useStlAlgorithm
0302                     btn->setChecked(true);
0303                     setCheckedAction(d->previewButtons->id(btn));
0304 
0305                     return;
0306                 }
0307             }
0308         }
0309     }
0310 }
0311 
0312 void PreviewToolBar::setPreviewMode(PreviewMode mode)
0313 {
0314     if (d->previewButtons->button(mode))
0315     {
0316         d->previewButtons->button(mode)->setChecked(true);
0317         setCheckedAction((int)mode);
0318     }
0319 }
0320 
0321 PreviewToolBar::PreviewMode PreviewToolBar::previewMode() const
0322 {
0323     if (!isEnabled())
0324     {
0325         return PreviewToolBar::NoPreviewMode;
0326     }
0327 
0328     return ((PreviewMode)d->previewButtons->checkedId());
0329 }
0330 
0331 void PreviewToolBar::readSettings(KConfigGroup& group)
0332 {
0333     int mode = group.readEntry("PreviewMode", (int)PreviewBothImagesVertCont);
0334     mode     = qMax((int)PreviewOriginalImage, mode);
0335     mode     = qMin((int)PreviewToggleOnMouseOver, mode);
0336     setPreviewMode((PreviewMode)mode);
0337 }
0338 
0339 void PreviewToolBar::writeSettings(KConfigGroup& group)
0340 {
0341     group.writeEntry("PreviewMode", (int)previewMode());
0342 }
0343 
0344 } // namespace Digikam
0345 
0346 #include "moc_previewtoolbar.cpp"