File indexing completed on 2025-03-09 03:52:10

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2018-07-30
0007  * Description : a plugin to render slideshow.
0008  *
0009  * SPDX-FileCopyrightText: 2018-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText: 2019-2020 by Minh Nghia Duong <minhnghiaduong997 at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "slideshowplugin.h"
0017 
0018 // Qt includes
0019 
0020 #include <QPointer>
0021 #include <QMenu>
0022 #include <QDebug>
0023 #include <QString>
0024 #include <QApplication>
0025 
0026 // KDE includes
0027 
0028 #include <klocalizedstring.h>
0029 #include <kactioncollection.h>
0030 #include <kxmlguiwindow.h>
0031 
0032 // Local includes
0033 
0034 #include "metaenginesettings.h"
0035 #include "setupslideshow_dialog.h"
0036 #include "slideshowloader.h"
0037 
0038 using namespace Digikam;
0039 
0040 namespace DigikamGenericSlideShowPlugin
0041 {
0042 
0043 SlideShowPlugin::SlideShowPlugin(QObject* const parent)
0044     : DPluginGeneric(parent)
0045 {
0046 }
0047 
0048 SlideShowPlugin::~SlideShowPlugin()
0049 {
0050 }
0051 
0052 QString SlideShowPlugin::name() const
0053 {
0054     return i18n("SlideShow");
0055 }
0056 
0057 QString SlideShowPlugin::iid() const
0058 {
0059     return QLatin1String(DPLUGIN_IID);
0060 }
0061 
0062 QIcon SlideShowPlugin::icon() const
0063 {
0064     return QIcon::fromTheme(QLatin1String("view-presentation"));
0065 }
0066 
0067 QString SlideShowPlugin::description() const
0068 {
0069     return i18n("A tool to render slideshow");
0070 }
0071 
0072 QString SlideShowPlugin::details() const
0073 {
0074     return i18n("<p>This tool render a series of items as a simple slide-show.</p>"
0075                 "<p>Plenty of items properties can be displayed as overlay while running.</p>"
0076                 "<p>This tool can play album contents in recursive mode with children albums if any.</p>"
0077                 "<p><u>Usage:</u></p>"
0078 
0079                 "<table>"
0080 
0081                     "<tr>"
0082                         "<td colspan=\"2\"><nobr><center>"
0083                             "<b><h1>Item Access</h1></b>"
0084                         "</center></nobr></td>"
0085                     "</tr>"
0086 
0087                     "<tr><td>Previous Item:</td>"        "<td><i>Up</i> key</td></tr>"
0088                     "<tr><td></td>"                      "<td><i>PgUp</i> key</td></tr>"
0089                     "<tr><td></td>"                      "<td><i>Left</i> key</td></tr>"
0090                     "<tr><td></td>"                      "<td>Mouse wheel up</td></tr>"
0091                     "<tr><td></td>"                      "<td>Left mouse button</td></tr>"
0092                     "<tr><td>Next Item:</td>"            "<td><i>Down</i> key</td></tr>"
0093                     "<tr><td></td>"                      "<td><i>PgDown</i> key</td></tr>"
0094                     "<tr><td></td>"                      "<td><i>Right</i> key</td></tr>"
0095                     "<tr><td></td>"                      "<td>Mouse wheel down</td></tr>"
0096                     "<tr><td></td>"                      "<td>Right mouse button</td></tr>"
0097                     "<tr><td>Pause/Start:</td>"          "<td><i>Space</i> key</td></tr>"
0098                     "<tr><td>Slideshow Settings:</td>"   "<td><i>F2</i> key</td></tr>"
0099                     "<tr><td>Hide/Show Overlays:</td>"   "<td><i>F4</i> key</td></tr>"
0100                     "<tr><td>Quit:</td>"                 "<td><i>Esc</i> key</td></tr>"
0101 
0102                     "<tr>"
0103                         "<td colspan=\"2\"><nobr><center>"
0104                             "<b><h1>Item Properties</h1></b>"
0105                         "</center></nobr></td>"
0106                     "</tr>"
0107 
0108                     "<tr><td>Change Tags:</td>"          "<td>Use Tags keyboard shortcuts</td></tr>"
0109                     "<tr><td>Change Rating:</td>"        "<td>Use Rating keyboard shortcuts</td></tr>"
0110                     "<tr><td>Change Color Label:</td>"   "<td>Use Color label keyboard shortcuts</td></tr>"
0111                     "<tr><td>Change Pick Label:</td>"    "<td>Use Pick label keyboard shortcuts</td></tr>"
0112 
0113                     "<tr>"
0114                         "<td colspan=\"2\"><nobr><center>"
0115                             "<b><h1>Others</h1></b>"
0116                         "</center></nobr></td>"
0117                     "</tr>"
0118 
0119                     "<tr><td>Show this help:</td>"       "<td><i>F1</i> key</td></tr>"
0120 
0121                 "</table>");
0122 }
0123 
0124 QString SlideShowPlugin::handbookSection() const
0125 {
0126     return QLatin1String("slideshow_tools");
0127 }
0128 
0129 QString SlideShowPlugin::handbookChapter() const
0130 {
0131     return QLatin1String("slide_tool");
0132 }
0133 
0134 QList<DPluginAuthor> SlideShowPlugin::authors() const
0135 {
0136     return QList<DPluginAuthor>()
0137             << DPluginAuthor(QString::fromUtf8("Enrico Ros"),
0138                              QString::fromUtf8("eros dot kde at email dot it"),
0139                              QString::fromUtf8("(C) 2004"))
0140             << DPluginAuthor(QString::fromUtf8("Renchi Raju"),
0141                              QString::fromUtf8("renchi dot raju at gmail dot com"),
0142                              QString::fromUtf8("(C) 2004-2005"))
0143             << DPluginAuthor(QString::fromUtf8("Gilles Caulier"),
0144                              QString::fromUtf8("caulier dot gilles at gmail dot com"),
0145                              QString::fromUtf8("(C) 2005-2023"))
0146             << DPluginAuthor(QString::fromUtf8("Minh Nghia Duong"),
0147                              QString::fromUtf8("minhnghiaduong997 at gmail dot com"),
0148                              QString::fromUtf8("(C) 2019-2021"))
0149             << DPluginAuthor(QString::fromUtf8("Phuoc Khanh Le"),
0150                              QString::fromUtf8("phuockhanhnk94 at gmail dot com"),
0151                              QString::fromUtf8("(C) 2021"))
0152             << DPluginAuthor(QString::fromUtf8("Fady Khalaf"),
0153                              QString::fromUtf8("fadykhalaf01 at gmail dot com"),
0154                              QString::fromUtf8("(C) 2019"))
0155             ;
0156 }
0157 void SlideShowPlugin::setup(QObject* const parent)
0158 {
0159     DPluginAction* const ac     = new DPluginAction(parent);
0160     ac->setIcon(icon());
0161     ac->setText(i18nc("@action", "Slideshow"));
0162     ac->setObjectName(QLatin1String("slideshow_plugin"));
0163     ac->setActionCategory(DPluginAction::GenericView);
0164 
0165     DInfoInterface* const iface = infoIface(ac);
0166 
0167     if (iface && (parent->objectName() == QLatin1String("Digikam")))
0168     {
0169 
0170         QMenu* const slideShowActions = new QMenu(i18n("Slideshow"));
0171         slideShowActions->setIcon(icon());
0172         ac->setMenu(slideShowActions);
0173 
0174         // Action show all
0175 
0176         QAction* const slideShowAllAction = new QAction(i18n("Play All"), ac);
0177         slideShowAllAction->setObjectName(QLatin1String("slideshow_all"));
0178         slideShowActions->addAction(slideShowAllAction);
0179 
0180         connect(slideShowAllAction, SIGNAL(triggered()),
0181                 this, SLOT(slotMenuSlideShowAll()));
0182 
0183         // Action show selection
0184 
0185         QAction* const slideShowSelectionAction = new QAction(i18n("Play Selection"), ac);
0186         slideShowSelectionAction->setObjectName(QLatin1String("slideshow_selected"));
0187         slideShowActions->addAction(slideShowSelectionAction);
0188 
0189         connect(slideShowSelectionAction, SIGNAL(triggered()),
0190                 this, SLOT(slotMenuSlideShowSelection()));
0191 
0192         // Action show recursive
0193 
0194         QAction* const slideShowRecursiveAction = new QAction(i18n("Play With Sub-Albums"), ac);
0195         slideShowRecursiveAction->setObjectName(QLatin1String("slideshow_recursive"));
0196         slideShowActions->addAction(slideShowRecursiveAction);
0197 
0198         connect(slideShowRecursiveAction, SIGNAL(triggered()),
0199                 this, SLOT(slotMenuSlideShowRecursive()));
0200 
0201         connect(ac, SIGNAL(triggered(bool)),
0202                 this, SLOT(slotShowManual()));
0203 
0204         // See bug #425425: register all sub-actions to collection instance to be able to edit keyboard shortcuts
0205 
0206         KXmlGuiWindow* const gui = dynamic_cast<KXmlGuiWindow*>(parent);
0207 
0208         if (gui)
0209         {
0210             KActionCollection* const collection = gui->actionCollection();
0211             collection->setShortcutsConfigurable(slideShowActions->menuAction(), false);
0212 
0213             collection->addAction(slideShowAllAction->objectName(),       slideShowAllAction);
0214             collection->addAction(slideShowSelectionAction->objectName(), slideShowSelectionAction);
0215             collection->addAction(slideShowRecursiveAction->objectName(), slideShowRecursiveAction);
0216 
0217             collection->setDefaultShortcut(slideShowAllAction,       Qt::Key_F9);
0218             collection->setDefaultShortcut(slideShowSelectionAction, Qt::ALT | Qt::Key_F9);
0219             collection->setDefaultShortcut(slideShowRecursiveAction, Qt::SHIFT | Qt::Key_F9);
0220         }
0221     }
0222     else
0223     {
0224         ac->setShortcut(Qt::Key_F9);
0225 
0226         connect(ac, SIGNAL(triggered(bool)),
0227                 this, SLOT(slotMenuSlideShow()));
0228     }
0229 
0230     addAction(ac);
0231 }
0232 
0233 void SlideShowPlugin::addConnectionSlideEnd(QObject* const obj)
0234 {
0235     Q_UNUSED(obj);
0236 }
0237 
0238 void SlideShowPlugin::slotMenuSlideShow()
0239 {
0240     QUrl startFrom;
0241     DPluginAction* const ac = dynamic_cast<DPluginAction*>(sender());
0242 
0243     if (ac)
0244     {
0245         startFrom = ac->data().toUrl();
0246         ac->setData(QVariant());
0247     }
0248 
0249     SlideShowSettings* const settings = new SlideShowSettings();
0250     settings->iface                   = infoIface(ac);
0251     settings->readFromConfig();
0252     settings->exifRotate              = MetaEngineSettings::instance()->settings().exifRotate;
0253     settings->fileList                = settings->iface->currentAlbumItems();
0254 
0255     slideshow(settings, true, startFrom);
0256 }
0257 
0258 void SlideShowPlugin::slotMenuSlideShowAll()
0259 {
0260     SlideShowSettings* const settings = new SlideShowSettings();
0261     settings->iface                   = infoIface(sender()->parent());
0262     settings->readFromConfig();
0263     settings->fileList                = settings->iface->currentAlbumItems();
0264 
0265     slideshow(settings);
0266 }
0267 
0268 void SlideShowPlugin::slotMenuSlideShowSelection()
0269 {
0270     SlideShowSettings* const settings = new SlideShowSettings();
0271     settings->iface                   = infoIface(sender()->parent());
0272     settings->readFromConfig();
0273     settings->fileList                = settings->iface->currentSelectedItems();
0274 
0275     slideshow(settings);
0276 }
0277 
0278 void SlideShowPlugin::slotMenuSlideShowRecursive()
0279 {
0280     DInfoInterface* const iface = infoIface(sender()->parent());
0281 
0282     connect(iface, SIGNAL(signalAlbumItemsRecursiveCompleted(QList<QUrl>)),
0283             this, SLOT(slotShowRecursive(QList<QUrl>)));
0284 
0285     iface->parseAlbumItemsRecursive();
0286 }
0287 
0288 void SlideShowPlugin::slotShowRecursive(const QList<QUrl>& imageList)
0289 {
0290     SlideShowSettings* const settings = new SlideShowSettings();
0291     settings->iface                   = dynamic_cast<DInfoInterface*>(sender());
0292     settings->readFromConfig();
0293     settings->fileList                = imageList;
0294 
0295     slideshow(settings);
0296 }
0297 
0298 void SlideShowPlugin::slotShowManual()
0299 {
0300     DPluginAction* const ac = dynamic_cast<DPluginAction*>(sender());
0301 
0302     if (!ac)
0303     {
0304         return;
0305     }
0306 
0307     QUrl startFrom(ac->data().toUrl());
0308     ac->setData(QVariant());
0309 
0310     SlideShowSettings* const settings = new SlideShowSettings();
0311     settings->iface                   = infoIface(ac);
0312     settings->readFromConfig();
0313     settings->exifRotate              = MetaEngineSettings::instance()->settings().exifRotate;
0314     settings->fileList                = settings->iface->currentAlbumItems();
0315 
0316     slideshow(settings, !startFrom.isValid(), startFrom);
0317 }
0318 
0319 void SlideShowPlugin::slideshow(SlideShowSettings* const settings, bool autoPlayEnabled, const QUrl& startFrom)
0320 {
0321     settings->autoPlayEnabled = autoPlayEnabled;
0322     settings->plugin          = this;
0323 
0324     // TODO: preview settings for digikam
0325     //settings.previewSettings = ApplicationSettings::instance()->getPreviewSettings();
0326 
0327     if (startFrom.isValid())
0328     {
0329         settings->imageUrl = startFrom;
0330     }
0331 
0332     SlideShowLoader* const slide = new SlideShowLoader(settings);
0333     slide->setShortCutPrefixes(settings->iface->passShortcutActionsToWidget(slide));
0334 
0335     if      (settings->imageUrl.isValid())
0336     {
0337         slide->setCurrentItem(settings->imageUrl);
0338     }
0339     else if (settings->startWithCurrent)
0340     {
0341         if (!settings->iface->currentSelectedItems().isEmpty())
0342         {
0343             slide->setCurrentItem(settings->iface->currentSelectedItems()[0]);
0344         }
0345         else
0346         {
0347             // no current selection, do nothing.
0348 
0349             return;
0350         }
0351     }
0352 
0353     connect(slide, SIGNAL(signalLastItemUrl(QUrl)),
0354             settings->iface, SIGNAL(signalLastItemUrl(QUrl)));
0355 
0356     connect(settings->iface, SIGNAL(signalShortcutPressed(QString,int)),
0357             slide, SLOT(slotHandleShortcut(QString,int)));
0358 
0359     slide->show();
0360 }
0361 
0362 } // namespace DigikamGenericSlideShowPlugin
0363 
0364 #include "moc_slideshowplugin.cpp"