diff --git a/NEWS b/NEWS index 63e55fde72..02f3e14df7 100644 --- a/NEWS +++ b/NEWS @@ -1,85 +1,85 @@ digiKam 6.1.0 - Release date: 2019-03-10 ***************************************************************************************************** NEW FEATURES: General : New plugins interface for digiKam and Showfoto named dplugins. General : All export tools become generic plugins and are shared with Showfoto. General : Update internal libpgf to last 07193. General : Add compatiblity with OpenCV version 4. BQM : Add new advanced settings in resize tool. BQM : All Batch Queue Manager tools become Bqm plugins. Editor : All Image Editor tools become Editor plugins and are shared with Showfoto. Item View : Add sort items by modification date. ***************************************************************************************************** BUGFIXES: 001 ==> 279216 - "Resize image" feature is missing some useful options [patch]. 002 ==> 368779 - Missing translations to Plugin Categories columns in setup page. 003 ==> 165852 - Google Youtube video uploader. 004 ==> 404578 - Links broken on downloadpage for 6.0.0. 005 ==> 402069 - FAQ link on Support page is broken. 006 ==> 404503 - There is a typo in support section of website. 007 ==> 404621 - I can not import the album Google Photo. 008 ==> 404642 - digiKam flatpak: Please include mysql driver (for using an external mysql db). 009 ==> 404690 - There is an unwanted bar in the left screen edge in full screen view. 010 ==> 404736 - Merging tags keeps popping up confirmation dialogs every second. 011 ==> 404737 - digiKam does not compile with opencv 3.4.1. 012 ==> 404735 - F2 should edit tag name when tag name has focus. 013 ==> 404748 - Default Album rename dialog should be larger (or save its size when changed). 014 ==> 304811 - Offer a "stretch histogram" functionality to automatically adjust brightness & gamma. 015 ==> 374464 - Can start print wizzard. 016 ==> 316687 - ImageMagick-6.8.3.9 could not be found. 017 ==> 305137 - wish for integrated(?) clip-generator. 018 ==> 404821 - Presentation offset from full screen when OpenGL transitions selected. 019 ==> 404894 - 6.0.0 x86-64 appimage startup complains about mssing ']' (startup bash script being called). 020 ==> 368262 - Google services tool does not use kaccounts. 021 ==> 376913 - Can't create a new album in picasa/googlephoto. 022 ==> 404896 - Vertical video are displayed horizontally. 023 ==> 404859 - Using Batch Queue Manager to make a JPG copy of the images on completion the "arw" images are no longer visible in the originating album. 024 ==> 404893 - Digikam::DigikamApp::slotSolidDeviceChanged: slotSolidDeviceChanged: messages referring to directory that digikam should not care about. 025 ==> 264296 - Lack of right-click delete of points in Curves [patch]. 026 ==> 404954 - Places, Devices, and Removable Devices no longer show in "Select Target Location". 027 ==> 404962 - List of subfolders: incorrect encoding (spaces -> %20, accents). 028 ==> 402724 - digiKam Settings/Configuration: missing section "Plugins" in Windows/6.0.0B3. 029 ==> 404987 - Ability to select which import/export options are included in menu. 030 ==> 404999 - Inconsistency in facetag font size. 031 ==> 244259 - Last image is displayed twice when Advanced Slideshow with KenBurns effect is run more than once. 032 ==> 405043 - Add volume control to video playback. 033 ==> 401253 - Face detect crashes every time. 034 ==> 405042 - Ability to loop video playback. 035 ==> 405138 - Can not disable webservice plugin. 036 ==> 405137 - Original items visible in Thumbnails view. 037 ==> 400606 - Dead space above thumbnails. 038 ==> 380434 - 5.6.0-pre pkg does not detect filesystem changes. 039 ==> 405250 - Menus gone missing. 040 ==> 388198 - Menu Help -> What's this is not used. 041 ==> 392570 - Missing Option to display complete filename. 042 ==> 375474 - Renaming People Tag Causes Unpredictable Sort Order In People Menu. 043 ==> 398868 - Video upside down in Preview (Thumbnail ok). 044 ==> 380065 - "Open with" menu entry missing [patch]. 045 ==> 405258 - Provide an OpenWith... function to get a specific ImageEditor. 046 ==> 402807 - Progress manager doesn't seem to be involved in the fingerprint scanning (v6.0 beta 3). 047 ==> 278935 - Please make XMP Sidecar filename configurable [patch]. 048 ==> 405231 - Monitor Color Profile is not applied in "Presentation". 049 ==> 405347 - Selecting by aspect ratio: abs function in sqlite lowercase, in mariadb uppercase. 050 ==> 405327 - Position and size of faces display depends on configuration setting. 051 ==> 405234 - Refresh does no work. 052 ==> 403649 - Filesystem changes are not visible in album view [patch]. 053 ==> 400768 - Many different trash cans hard & slow to use. 054 ==> 296864 - SETUP : Create interface for changing physical location or path of album. 055 ==> 397189 - digikam is crashing when adding this photo. 056 ==> 405378 - Missing libz.dll on launch. 057 ==> 401306 - digikam-git r41326 doesn't compile with OpenCV 4 058 ==> 379049 - IPTC and XMP metadata not always read when adding a new album. 059 ==> 404939 - AppImage package: integration with the OS with AppImageLauncher. 060 ==> 405514 - Configure Shortcuts : Shortcuts file contains space in assigned_tags. 061 ==> 405149 - The "File Name" in the thumbnail view is not visible. 062 ==> 405512 - Meta Key Not Useful For Key Modifier In Windows. 063 ==> 405513 - Configure Shortcuts : Defaults Button Does Not Apply To New Schemes. 064 ==> 388334 - Auto Filter In People Tag List Confused With Shortcut Keys. 065 ==> 405518 - digiKam can not be added to the Gnome Dash as favorite. -066 ==> - +066 ==> 405342 - Increase slideshow caption font size and keyboard shortcut or button to display/hide it. +067 ==> diff --git a/core/utilities/slideshow/slidehelp.cpp b/core/utilities/slideshow/slidehelp.cpp index 4349e3a445..2364a74df8 100644 --- a/core/utilities/slideshow/slidehelp.cpp +++ b/core/utilities/slideshow/slidehelp.cpp @@ -1,104 +1,105 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2014-10-05 * Description : slideshow help dialog * * Copyright (C) 2014-2019 by Gilles Caulier * * 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. * * ============================================================ */ #include "slidehelp.h" // Qt includes #include #include #include #include // KDE includes #include namespace Digikam { SlideHelp::SlideHelp() : QDialog(0) { setWindowTitle(i18n("Slideshow Usage")); QDialogButtonBox* const buttons = new QDialogButtonBox(QDialogButtonBox::Ok, this); buttons->button(QDialogButtonBox::Ok)->setDefault(true); // ------------------------------------------------------------------------------------------------------------------- QLabel* const label = new QLabel(this); label->setText(i18n("" "" "" - "" "" - "" "" - "" "" - "" "" - "" "" - "" "" - "" "" - "" "" - "" "" - "" "" - "" "" - "" "" + "" "" + "" "" + "" "" + "" "" + "" "" + "" "" + "" "" + "" "" + "" "" + "" "" + "" "" + "" "" + "" "" "" - "" "" - "" "" - "" "" - "" "" + "" "" + "" "" + "" "" + "" "" "" - "" "" + "" "" "
" "

Item Access

" "
Previous Item:Up key
PgUp key
Left key
Mouse wheel up
Left mouse button
Next Item:Down key
PgDown key
Right key
Mouse wheel down
Right mouse button
Pause/Start:Space key
Quit:Esc key
Previous Item:Up key
PgUp key
Left key
Mouse wheel up
Left mouse button
Next Item:Down key
PgDown key
Right key
Mouse wheel down
Right mouse button
Pause/Start:Space key
Hide/Show Properties:F4 key
Quit:Esc key
" "

Item Properties

" "
Change Tags:Use Tags keyboard shortcuts
Change Rating:Use Rating keyboard shortcuts
Change Color Label:Use Color label keyboard shortcuts
Change Pick Label:Use Pick label keyboard shortcuts
Change Tags:Use Tags keyboard shortcuts
Change Rating:Use Rating keyboard shortcuts
Change Color Label:Use Color label keyboard shortcuts
Change Pick Label:Use Pick label keyboard shortcuts
" "

Others

" "
Show this help:F1 key
Show this help:F1 key
" "
")); QVBoxLayout* const vbx = new QVBoxLayout(this); vbx->addWidget(label); vbx->addWidget(buttons); setLayout(vbx); // --------------------------------------------------------------------------------------------------------------------- connect(buttons->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(accept())); adjustSize(); } SlideHelp::~SlideHelp() { } } // namespace Digikam diff --git a/core/utilities/slideshow/slideosd.cpp b/core/utilities/slideshow/slideosd.cpp index 3be6234c6a..ed66495cd2 100644 --- a/core/utilities/slideshow/slideosd.cpp +++ b/core/utilities/slideshow/slideosd.cpp @@ -1,368 +1,373 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2014-09-18 * Description : slideshow OSD widget * * Copyright (C) 2014-2019 by Gilles Caulier * * 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. * * ============================================================ */ #include "slideosd.h" // Qt includes #include #include #include #include #include #include #include // Windows includes #ifdef Q_OS_WIN # include #endif // Local includes #include "digikam_debug.h" #include "slideshow.h" #include "slidetoolbar.h" #include "slideproperties.h" #include "ratingwidget.h" #include "colorlabelwidget.h" #include "picklabelwidget.h" #include "dinfointerface.h" namespace Digikam { class Q_DECL_HIDDEN SlideOSD::Private { public: explicit Private() : paused(false), video(false), blink(false), refresh(1000), // Progress bar refresh in ms progressBar(0), progressTimer(0), labelsBox(0), progressBox(0), parent(0), slideProps(0), toolBar(0), ratingWidget(0), clWidget(0), plWidget(0) { } bool paused; bool video; bool blink; int const refresh; QProgressBar* progressBar; QTimer* progressTimer; DHBox* labelsBox; DHBox* progressBox; SlideShow* parent; SlideProperties* slideProps; SlideToolBar* toolBar; RatingWidget* ratingWidget; ColorLabelSelector* clWidget; PickLabelSelector* plWidget; SlideShowSettings settings; }; SlideOSD::SlideOSD(const SlideShowSettings& settings, SlideShow* const parent) : QWidget(parent), d(new Private) { Qt::WindowFlags flags = Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint; setWindowFlags(flags); setAttribute(Qt::WA_TranslucentBackground, true); setAttribute(Qt::WA_ShowWithoutActivating, true); setMouseTracking(true); d->settings = settings; d->parent = parent; d->slideProps = new SlideProperties(d->settings, this); d->slideProps->installEventFilter(d->parent); // --------------------------------------------------------------- d->labelsBox = new DHBox(this); d->clWidget = new ColorLabelSelector(d->labelsBox); d->clWidget->installEventFilter(this); d->clWidget->installEventFilter(d->parent); d->clWidget->colorLabelWidget()->installEventFilter(this); d->clWidget->setFocusPolicy(Qt::NoFocus); d->clWidget->setMouseTracking(true); d->plWidget = new PickLabelSelector(d->labelsBox); d->plWidget->installEventFilter(this); d->plWidget->installEventFilter(d->parent); d->plWidget->setFocusPolicy(Qt::NoFocus); d->plWidget->pickLabelWidget()->installEventFilter(this); d->plWidget->setMouseTracking(true); d->ratingWidget = new RatingWidget(d->labelsBox); d->ratingWidget->setTracking(false); d->ratingWidget->setFading(false); d->ratingWidget->installEventFilter(this); d->ratingWidget->installEventFilter(d->parent); d->ratingWidget->setFocusPolicy(Qt::NoFocus); d->ratingWidget->setMouseTracking(true); d->labelsBox->layout()->setAlignment(d->ratingWidget, Qt::AlignVCenter | Qt::AlignLeft); d->labelsBox->installEventFilter(d->parent); d->labelsBox->setMouseTracking(true); d->labelsBox->setVisible(d->settings.printLabels || d->settings.printRating); d->ratingWidget->setVisible(d->settings.printRating); d->clWidget->setVisible(d->settings.printLabels); d->plWidget->setVisible(d->settings.printLabels); connect(d->ratingWidget, SIGNAL(signalRatingChanged(int)), parent, SLOT(slotAssignRating(int))); connect(d->clWidget, SIGNAL(signalColorLabelChanged(int)), parent, SLOT(slotAssignColorLabel(int))); connect(d->plWidget, SIGNAL(signalPickLabelChanged(int)), parent, SLOT(slotAssignPickLabel(int))); // --------------------------------------------------------------- d->progressBox = new DHBox(this); d->progressBox->setVisible(d->settings.showProgressIndicator); d->progressBox->installEventFilter(d->parent); d->progressBox->setMouseTracking(true); d->progressBar = new QProgressBar(d->progressBox); d->progressBar->setMinimum(0); d->progressBar->setMaximum(d->settings.delay); d->progressBar->setFocusPolicy(Qt::NoFocus); d->progressBar->installEventFilter(d->parent); d->progressBar->setMouseTracking(true); d->toolBar = new SlideToolBar(d->settings, d->progressBox); d->toolBar->installEventFilter(this); d->toolBar->installEventFilter(d->parent); connect(d->toolBar, SIGNAL(signalPause()), d->parent, SLOT(slotPause())); connect(d->toolBar, SIGNAL(signalPlay()), d->parent, SLOT(slotPlay())); connect(d->toolBar, SIGNAL(signalNext()), d->parent, SLOT(slotLoadNextItem())); connect(d->toolBar, SIGNAL(signalPrev()), d->parent, SLOT(slotLoadPrevItem())); connect(d->toolBar, SIGNAL(signalClose()), d->parent, SLOT(close())); connect(d->toolBar, SIGNAL(signalScreenSelected(int)), d->parent, SLOT(slotScreenSelected(int))); // --------------------------------------------------------------- QGridLayout* const grid = new QGridLayout(this); grid->addWidget(d->slideProps, 1, 0, 1, 2); grid->addWidget(d->labelsBox, 2, 0, 1, 1); grid->addWidget(d->progressBox, 3, 0, 1, 1); grid->setRowStretch(0, 10); grid->setColumnStretch(1, 10); grid->setContentsMargins(QMargins()); grid->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing)); // --------------------------------------------------------------- d->progressTimer = new QTimer(this); d->progressTimer->setSingleShot(false); connect(d->progressTimer, SIGNAL(timeout()), this, SLOT(slotProgressTimer())); QTimer::singleShot(500, this, SLOT(slotStart())); } SlideOSD::~SlideOSD() { d->progressTimer->stop(); delete d; } void SlideOSD::slotStart() { d->parent->slotLoadNextItem(); d->progressTimer->start(d->refresh); pause(!d->settings.autoPlayEnabled); } SlideToolBar* SlideOSD::toolBar() const { return d->toolBar; } void SlideOSD::setCurrentUrl(const QUrl& url) { DInfoInterface::DInfoMap info = d->settings.iface->itemInfo(url); DItemInfo item(info); // Update info text. d->slideProps->setCurrentUrl(url); // Display Labels. if (d->settings.printLabels) { d->clWidget->blockSignals(true); d->plWidget->blockSignals(true); d->clWidget->setColorLabel((ColorLabel)item.colorLabel()); d->plWidget->setPickLabel((PickLabel)item.pickLabel()); d->clWidget->blockSignals(false); d->plWidget->blockSignals(false); } if (d->settings.printRating) { d->ratingWidget->blockSignals(true); d->ratingWidget->setRating(item.rating()); d->ratingWidget->blockSignals(false); } // Make the OSD the proper size layout()->activate(); resize(sizeHint()); QRect geometry(QApplication::desktop()->availableGeometry(parentWidget())); move(10, geometry.bottom() - height()); show(); raise(); } bool SlideOSD::eventFilter(QObject* obj, QEvent* ev) { if (obj == d->labelsBox || obj == d->ratingWidget || obj == d->clWidget || obj == d->plWidget || obj == d->clWidget->colorLabelWidget() || obj == d->plWidget->pickLabelWidget()) { if (ev->type() == QEvent::Enter) { d->paused = isPaused(); d->parent->slotPause(); return false; } if (ev->type() == QEvent::Leave) { if (!d->paused) { d->parent->slotPlay(); } return false; } } // pass the event on to the parent class return QWidget::eventFilter(obj, ev); } void SlideOSD::slotProgressTimer() { QString str = QString::fromUtf8("(%1/%2)") .arg(QString::number(d->settings.fileList.indexOf(d->parent->currentItem()) + 1)) .arg(QString::number(d->settings.fileList.count())); if (isPaused()) { d->blink = !d->blink; if (d->blink) { str = QString(); } d->progressBar->setFormat(str); } else if (d->video) { d->progressBar->setFormat(str); return; } else { d->progressBar->setFormat(str); d->progressBar->setValue(d->progressBar->value()+1); if (d->progressBar->value() == d->settings.delay) { d->parent->slotLoadNextItem(); } } } void SlideOSD::pause(bool b) { d->toolBar->pause(b); if (!b) { d->progressBar->setValue(0); } } void SlideOSD::video(bool b) { d->video = b; } bool SlideOSD::isPaused() const { return d->toolBar->isPaused(); } bool SlideOSD::isUnderMouse() const { return (d->ratingWidget->underMouse() || d->progressBar->underMouse() || d->clWidget->underMouse() || d->plWidget->underMouse() || d->toolBar->underMouse()); } +void SlideOSD::toggleProperties() +{ + d->slideProps->togglePaintEnabled(); +} + } // namespace Digikam diff --git a/core/utilities/slideshow/slideosd.h b/core/utilities/slideshow/slideosd.h index f3b875e061..d5166ca870 100644 --- a/core/utilities/slideshow/slideosd.h +++ b/core/utilities/slideshow/slideosd.h @@ -1,79 +1,80 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2014-09-18 * Description : slideshow OSD widget * * Copyright (C) 2014-2019 by Gilles Caulier * * 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 DIGIKAM_SLIDE_OSD_H #define DIGIKAM_SLIDE_OSD_H // Qt includes #include #include // Local includes #include "slideshowsettings.h" class QEvent; namespace Digikam { class SlideShow; class SlideToolBar; class SlideOSD : public QWidget { Q_OBJECT public: explicit SlideOSD(const SlideShowSettings& settings, SlideShow* const parent = 0); ~SlideOSD(); void setCurrentUrl(const QUrl& url); void pause(bool b); void video(bool b); bool isPaused() const; bool isUnderMouse() const; + void toggleProperties(); SlideToolBar* toolBar() const; private Q_SLOTS: void slotProgressTimer(); void slotStart(); private: bool eventFilter(QObject* obj, QEvent* ev); private: class Private; Private* const d; }; } // namespace Digikam #endif // DIGIKAM_SLIDE_OSD_H diff --git a/core/utilities/slideshow/slideproperties.cpp b/core/utilities/slideshow/slideproperties.cpp index edecc7086e..d7f94ba97b 100644 --- a/core/utilities/slideshow/slideproperties.cpp +++ b/core/utilities/slideshow/slideproperties.cpp @@ -1,365 +1,378 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2014-09-19 * Description : slide properties widget * * Copyright (C) 2014-2019 by Gilles Caulier * * 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. * * ============================================================ */ #include "slideproperties.h" // Qt includes #include #include #include #include #include #include #include // KDE includes #include // Local includes #include "digikam_debug.h" #include "dinfointerface.h" #include "itempropertiestab.h" namespace Digikam { class Q_DECL_HIDDEN SlideProperties::Private { public: explicit Private() - : maxStringLen(80) + : maxStringLen(80), + paintEnabled(true) { } const int maxStringLen; + bool paintEnabled; QUrl url; SlideShowSettings settings; }; SlideProperties::SlideProperties(const SlideShowSettings& settings, QWidget* const parent) : QWidget(parent), d(new Private) { d->settings = settings; setFixedSize(QApplication::desktop()->availableGeometry(parentWidget()).size()/2); setMouseTracking(true); } SlideProperties::~SlideProperties() { delete d; } void SlideProperties::setCurrentUrl(const QUrl& url) { d->url = url; update(); } void SlideProperties::paintEvent(QPaintEvent*) { + if (!d->paintEnabled) + { + return; + } + QPainter p(this); DInfoInterface::DInfoMap info = d->settings.iface->itemInfo(d->url); DItemInfo item(info); QString str; //PhotoInfoContainer photoInfo = d->info.photoInfo; QString comment = item.comment(); QString title = item.title(); QStringList tags = item.keywords(); int offset = 0; // Display tag names. if (d->settings.printTags) { printTags(p, offset, tags); } // Display Titles. if (d->settings.printTitle) { str.clear(); if (!title.isEmpty()) { str += title; printInfoText(p, offset, str); } } // Display Captions if no Titles. if (d->settings.printCapIfNoTitle) { str.clear(); if (title.isEmpty()) { str += comment; printComments(p, offset, str); } } // Display Comments. if (d->settings.printComment) { str = comment; printComments(p, offset, str); } // Display Make and Model. if (d->settings.printMakeModel) { str.clear(); QString make = item.make(); QString model = item.model(); if (!make.isEmpty()) { ItemPropertiesTab::shortenedMakeInfo(make); str = make; } if (!model.isEmpty()) { if (!make.isEmpty()) { str += QLatin1String(" / "); } ItemPropertiesTab::shortenedModelInfo(model); str += model; } printInfoText(p, offset, str); } // Display Exposure and Sensitivity. if (d->settings.printExpoSensitivity) { str.clear(); QString exposureTime = item.exposureTime(); QString sensitivity = item.sensitivity(); if (!exposureTime.isEmpty()) { str = exposureTime; } if (!sensitivity.isEmpty()) { if (!exposureTime.isEmpty()) { str += QLatin1String(" / "); } str += i18n("%1 ISO", sensitivity); } printInfoText(p, offset, str); } // Display Aperture and Focal. if (d->settings.printApertureFocal) { str.clear(); QString aperture = item.aperture(); QString focalLength = item.focalLength(); QString focalLength35mm = item.focalLength35mm(); if (!aperture.isEmpty()) { str = aperture; } if (focalLength35mm.isEmpty()) { if (!focalLength.isEmpty()) { if (!aperture.isEmpty()) { str += QLatin1String(" / "); } str += focalLength; } } else { if (!aperture.isEmpty()) { str += QLatin1String(" / "); } if (!focalLength.isEmpty()) { str += QString::fromUtf8("%1 (%2)").arg(focalLength).arg(focalLength35mm); } else { str += QString::fromUtf8("%1").arg(focalLength35mm); } } printInfoText(p, offset, str); } // Display Creation Date. if (d->settings.printDate) { QDateTime dateTime = item.dateTime(); if (dateTime.isValid()) { str = QLocale().toString(dateTime, QLocale::ShortFormat); printInfoText(p, offset, str); } } // Display image File Name. if (d->settings.printName) { printInfoText(p, offset, d->url.fileName()); } } void SlideProperties::printInfoText(QPainter& p, int& offset, const QString& str, const QColor& pcol) { if (!str.isEmpty()) { p.setFont(d->settings.captionFont); offset += QFontMetrics(p.font()).lineSpacing(); p.setPen(Qt::black); for (int x = -1; x <= 1; ++x) { for (int y = offset + 1; y >= offset - 1; --y) { p.drawText(x, p.window().height() - y, str); } } p.setPen(pcol); p.drawText(0, p.window().height() - offset, str); } } void SlideProperties::printComments(QPainter& p, int& offset, const QString& comments) { QStringList commentsByLines; uint commentsIndex = 0; // Comments QString index while (commentsIndex < (uint)comments.length()) { QString newLine; bool breakLine = false; // End Of Line found uint currIndex; // Comments QString current index // Check minimal lines dimension uint commentsLinesLengthLocal = d->maxStringLen; for (currIndex = commentsIndex ; currIndex < (uint)comments.length() && !breakLine ; ++currIndex) { if (comments.at(currIndex) == QLatin1Char('\n') || comments.at(currIndex).isSpace()) { breakLine = true; } } if (commentsLinesLengthLocal <= (currIndex - commentsIndex)) { commentsLinesLengthLocal = (currIndex - commentsIndex); } breakLine = false; for (currIndex = commentsIndex ; currIndex <= commentsIndex + commentsLinesLengthLocal && currIndex < (uint)comments.length() && !breakLine ; ++currIndex) { breakLine = (comments.at(currIndex) == QLatin1Char('\n')) ? true : false; if (breakLine) { newLine.append(QLatin1Char(' ')); } else { newLine.append(comments.at(currIndex)); } } commentsIndex = currIndex; // The line is ended if (commentsIndex != (uint)comments.length()) { while (!newLine.endsWith(QLatin1Char(' '))) { newLine.truncate(newLine.length() - 1); --commentsIndex; } } commentsByLines.prepend(newLine.trimmed()); } for (int i = 0 ; i < (int)commentsByLines.count() ; ++i) { printInfoText(p, offset, commentsByLines.at(i)); } } void SlideProperties::printTags(QPainter& p, int& offset, QStringList& tags) { tags.sort(); QString str = tags.join(QLatin1String(", ")); if (!str.isEmpty()) { printInfoText(p, offset, str, qApp->palette().color(QPalette::Link).name()); } } +void SlideProperties::togglePaintEnabled() +{ + d->paintEnabled = !d->paintEnabled; + update(); +} + } // namespace Digikam diff --git a/core/utilities/slideshow/slideproperties.h b/core/utilities/slideshow/slideproperties.h index 5aca785d10..b476acd50f 100644 --- a/core/utilities/slideshow/slideproperties.h +++ b/core/utilities/slideshow/slideproperties.h @@ -1,65 +1,66 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2014-09-19 * Description : slide properties widget * * Copyright (C) 2014-2019 by Gilles Caulier * * 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 DIGIKAM_SLIDE_PROPERTIES_H #define DIGIKAM_SLIDE_PROPERTIES_H #include #include #include #include #include // Local includes #include "slideshowsettings.h" namespace Digikam { class SlideProperties : public QWidget { public: explicit SlideProperties(const SlideShowSettings& settings, QWidget* const parent); ~SlideProperties(); void setCurrentUrl(const QUrl& url); + void togglePaintEnabled(); private: void printInfoText(QPainter& p, int& offset, const QString& str, const QColor& pcol=Qt::white); void printComments(QPainter& p, int& offset, const QString& comments); void printTags(QPainter& p, int& offset, QStringList& tags); void paintEvent(QPaintEvent*); private: class Private; Private* const d; }; } // namespace Digikam #endif // DIGIKAM_SLIDE_PROPERTIES_H diff --git a/core/utilities/slideshow/slideshow.cpp b/core/utilities/slideshow/slideshow.cpp index 3f869a1a60..5efb6e947c 100644 --- a/core/utilities/slideshow/slideshow.cpp +++ b/core/utilities/slideshow/slideshow.cpp @@ -1,680 +1,686 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2005-04-21 * Description : slide show tool using preview of pictures. * * Copyright (C) 2005-2019 by Gilles Caulier * Copyright (C) 2004 by Enrico Ros * * 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. * * ============================================================ */ #include "slideshow.h" #include "digikam_config.h" // Qt includes #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_DBUS # include # include # include #endif // KDE includes #include // Local includes #include "digikam_debug.h" #include "slidetoolbar.h" #include "slideimage.h" #include "slideerror.h" #include "slideosd.h" #include "slideend.h" #ifdef HAVE_MEDIAPLAYER # include "slidevideo.h" #endif //HAVE_MEDIAPLAYER namespace Digikam { class Q_DECL_HIDDEN SlideShow::Private { public: explicit Private() : fileIndex(-1), screenSaverCookie(-1), mouseMoveTimer(0), imageView(0), #ifdef HAVE_MEDIAPLAYER videoView(0), #endif errorView(0), endView(0), osd(0) { } int fileIndex; int screenSaverCookie; QTimer* mouseMoveTimer; // To hide cursor when not moved. SlideImage* imageView; #ifdef HAVE_MEDIAPLAYER SlideVideo* videoView; #endif SlideError* errorView; SlideEnd* endView; SlideOSD* osd; SlideShowSettings settings; }; SlideShow::SlideShow(DInfoInterface* const iface, const SlideShowSettings& settings) : QStackedWidget(0), d(new Private) { d->settings = settings; d->settings.iface = iface; setAttribute(Qt::WA_DeleteOnClose); setWindowFlags(Qt::FramelessWindowHint); setContextMenuPolicy(Qt::PreventContextMenu); setWindowState(windowState() | Qt::WindowFullScreen); setWindowTitle(i18n("Slideshow")); setMouseTracking(true); // --------------------------------------------------------------- d->errorView = new SlideError(this); d->errorView->installEventFilter(this); insertWidget(ErrorView, d->errorView); // --------------------------------------------------------------- d->imageView = new SlideImage(this); d->imageView->setPreviewSettings(d->settings.previewSettings); d->imageView->installEventFilter(this); connect(d->imageView, SIGNAL(signalImageLoaded(bool)), this, SLOT(slotImageLoaded(bool))); insertWidget(ImageView, d->imageView); // --------------------------------------------------------------- #ifdef HAVE_MEDIAPLAYER d->videoView = new SlideVideo(this); d->videoView->setInfoInterface(d->settings.iface); d->videoView->installEventFilter(this); connect(d->videoView, SIGNAL(signalVideoLoaded(bool)), this, SLOT(slotVideoLoaded(bool))); connect(d->videoView, SIGNAL(signalVideoFinished()), this, SLOT(slotVideoFinished())); insertWidget(VideoView, d->videoView); #endif // --------------------------------------------------------------- d->endView = new SlideEnd(this); d->endView->installEventFilter(this); insertWidget(EndView, d->endView); // --------------------------------------------------------------- d->osd = new SlideOSD(d->settings, this); d->osd->installEventFilter(this); // --------------------------------------------------------------- d->mouseMoveTimer = new QTimer(this); d->mouseMoveTimer->setSingleShot(true); d->mouseMoveTimer->setInterval(1000); connect(d->mouseMoveTimer, SIGNAL(timeout()), this, SLOT(slotMouseMoveTimeOut())); // --------------------------------------------------------------- QDesktopWidget const* desktop = qApp->desktop(); const int preferenceScreen = d->settings.slideScreen; int screen = 0; if (preferenceScreen == -2) { screen = desktop->screenNumber(qApp->activeWindow()); } else if (preferenceScreen == -1) { screen = desktop->primaryScreen(); } else if ((preferenceScreen >= 0) && (preferenceScreen < desktop->numScreens())) { screen = preferenceScreen; } else { screen = desktop->screenNumber(qApp->activeWindow()); d->settings.slideScreen = -2; d->settings.writeToConfig(); } slotScreenSelected(screen); // --------------------------------------------------------------- setCurrentView(ImageView); inhibitScreenSaver(); slotMouseMoveTimeOut(); } SlideShow::~SlideShow() { emit signalLastItemUrl(currentItem()); d->mouseMoveTimer->stop(); allowScreenSaver(); delete d; } void SlideShow::setCurrentView(SlideShowViewMode view) { switch(view) { case ErrorView: d->osd->video(false); d->errorView->setCurrentUrl(currentItem()); setCurrentIndex(view); d->osd->setCurrentUrl(currentItem()); break; case ImageView: #ifdef HAVE_MEDIAPLAYER d->videoView->stop(); d->osd->video(false); #endif setCurrentIndex(view); d->osd->setCurrentUrl(currentItem()); break; case VideoView: #ifdef HAVE_MEDIAPLAYER d->osd->video(true); d->osd->pause(false); setCurrentIndex(view); d->osd->setCurrentUrl(currentItem()); #endif break; default : // EndView #ifdef HAVE_MEDIAPLAYER d->videoView->stop(); d->osd->video(false); #endif d->osd->pause(true); setCurrentIndex(view); break; } } void SlideShow::setCurrentItem(const QUrl& url) { int index = d->settings.indexOf(url); if (index != -1) { d->fileIndex = index - 1; } } QUrl SlideShow::currentItem() const { return d->settings.fileList.value(d->fileIndex); } void SlideShow::slotLoadNextItem() { int num = d->settings.count(); if (d->fileIndex == (num - 1)) { if (d->settings.loop) { d->fileIndex = -1; } } d->fileIndex++; qCDebug(DIGIKAM_GENERAL_LOG) << "fileIndex: " << d->fileIndex; if (!d->settings.loop) { d->osd->toolBar()->setEnabledPrev(d->fileIndex > 0); d->osd->toolBar()->setEnabledNext(d->fileIndex < (num - 1)); } if (d->fileIndex >= 0 && d->fileIndex < num) { #ifdef HAVE_MEDIAPLAYER QMimeDatabase mimeDB; if (mimeDB.mimeTypeForFile(currentItem().toLocalFile()) .name().startsWith(QLatin1String("video/"))) { d->videoView->setCurrentUrl(currentItem()); return; } #endif d->imageView->setLoadUrl(currentItem()); } else { endOfSlide(); } } void SlideShow::slotLoadPrevItem() { int num = d->settings.count(); if (d->fileIndex == 0) { if (d->settings.loop) { d->fileIndex = num; } } d->fileIndex--; qCDebug(DIGIKAM_GENERAL_LOG) << "fileIndex: " << d->fileIndex; if (!d->settings.loop) { d->osd->toolBar()->setEnabledPrev(d->fileIndex > 0); d->osd->toolBar()->setEnabledNext(d->fileIndex < (num - 1)); } if (d->fileIndex >= 0 && d->fileIndex < num) { #ifdef HAVE_MEDIAPLAYER QMimeDatabase mimeDB; if (mimeDB.mimeTypeForFile(currentItem().toLocalFile()) .name().startsWith(QLatin1String("video/"))) { d->videoView->setCurrentUrl(currentItem()); return; } #endif d->imageView->setLoadUrl(currentItem()); } else { endOfSlide(); } } void SlideShow::slotImageLoaded(bool loaded) { if (loaded) { setCurrentView(ImageView); if (d->fileIndex != -1) { if (!d->osd->isPaused()) { d->osd->pause(false); } preloadNextItem(); } } else { #ifdef HAVE_MEDIAPLAYER // Try to load only GIF Images QMimeDatabase mimeDB; if (mimeDB.mimeTypeForFile(currentItem().toLocalFile()) .name() == QLatin1String("image/gif")) { d->videoView->setCurrentUrl(currentItem()); } #else preloadNextItem(); #endif } } void SlideShow::slotVideoLoaded(bool loaded) { if (loaded) { setCurrentView(VideoView); } else { // Failed to load item setCurrentView(ErrorView); if (d->fileIndex != -1) { if (!d->osd->isPaused()) { d->osd->pause(false); } } } preloadNextItem(); } void SlideShow::slotVideoFinished() { if (d->fileIndex != -1) { d->osd->video(false); slotLoadNextItem(); } } void SlideShow::endOfSlide() { setCurrentView(EndView); d->fileIndex = -1; d->osd->toolBar()->setEnabledPlay(false); d->osd->toolBar()->setEnabledNext(false); d->osd->toolBar()->setEnabledPrev(false); } void SlideShow::preloadNextItem() { int index = d->fileIndex + 1; int num = d->settings.count(); if (index >= num) { if (d->settings.loop) { index = 0; } } if (index < num) { QUrl nextItem = d->settings.fileList.value(index); #ifdef HAVE_MEDIAPLAYER QMimeDatabase mimeDB; if (mimeDB.mimeTypeForFile(nextItem.toLocalFile()) .name().startsWith(QLatin1String("video/"))) { return; } #endif d->imageView->setPreloadUrl(nextItem); } } void SlideShow::wheelEvent(QWheelEvent* e) { if (e->delta() < 0) { d->osd->pause(true); slotLoadNextItem(); } if (e->delta() > 0) { if (d->fileIndex == -1) { // EndView => backward. d->fileIndex = d->settings.count(); } d->osd->pause(true); slotLoadPrevItem(); } } void SlideShow::mousePressEvent(QMouseEvent* e) { if (d->fileIndex == -1) { // EndView => close Slideshow view. close(); } if (e->button() == Qt::LeftButton) { d->osd->pause(true); slotLoadNextItem(); } else if (e->button() == Qt::RightButton) { if (d->fileIndex == -1) { // EndView => backward. d->fileIndex = d->settings.count() - 1; } d->osd->pause(true); slotLoadPrevItem(); } } void SlideShow::keyPressEvent(QKeyEvent* e) { if (!e) { return; } + if (e->key() == Qt::Key_F4) + { + d->osd->toggleProperties(); + return; + } + d->osd->toolBar()->keyPressEvent(e); } bool SlideShow::eventFilter(QObject* obj, QEvent* ev) { if (ev->type() == QEvent::MouseMove) { setCursor(QCursor(Qt::ArrowCursor)); #ifdef HAVE_MEDIAPLAYER d->videoView->showIndicator(true); #endif d->mouseMoveTimer->start(); return false; } // pass the event on to the parent class return QWidget::eventFilter(obj, ev); } void SlideShow::slotMouseMoveTimeOut() { if (!d->osd->isUnderMouse()) { setCursor(QCursor(Qt::BlankCursor)); } #ifdef HAVE_MEDIAPLAYER d->videoView->showIndicator(false); #endif } // From Okular's presentation widget // TODO: Add OSX and Windows support void SlideShow::inhibitScreenSaver() { #ifdef HAVE_DBUS QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.ScreenSaver"), QLatin1String("/ScreenSaver"), QLatin1String("org.freedesktop.ScreenSaver"), QLatin1String("Inhibit")); message << QLatin1String("digiKam"); message << i18nc("Reason for inhibiting the screensaver activation, when the presentation mode is active", "Giving a slideshow"); QDBusReply reply = QDBusConnection::sessionBus().call(message); if (reply.isValid()) { d->screenSaverCookie = reply.value(); } #endif } void SlideShow::allowScreenSaver() { #ifdef HAVE_DBUS if (d->screenSaverCookie != -1) { QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.ScreenSaver"), QLatin1String("/ScreenSaver"), QLatin1String("org.freedesktop.ScreenSaver"), QLatin1String("UnInhibit")); message << (uint)d->screenSaverCookie; QDBusConnection::sessionBus().send(message); } #endif } void SlideShow::slotAssignRating(int rating) { DInfoInterface::DInfoMap info; DItemInfo item(info); item.setRating(rating); d->settings.iface->setItemInfo(currentItem(), info); dispatchCurrentInfoChange(currentItem()); emit signalRatingChanged(currentItem(), rating); } void SlideShow::slotAssignColorLabel(int color) { DInfoInterface::DInfoMap info; DItemInfo item(info); item.setColorLabel(color); d->settings.iface->setItemInfo(currentItem(), info); dispatchCurrentInfoChange(currentItem()); emit signalColorLabelChanged(currentItem(), color); } void SlideShow::slotAssignPickLabel(int pick) { DInfoInterface::DInfoMap info; DItemInfo item(info); item.setPickLabel(pick); d->settings.iface->setItemInfo(currentItem(), info); dispatchCurrentInfoChange(currentItem()); emit signalPickLabelChanged(currentItem(), pick); } void SlideShow::updateTags(const QUrl& url, const QStringList& /*tags*/) { dispatchCurrentInfoChange(url); } void SlideShow::toggleTag(int tag) { emit signalToggleTag(currentItem(), tag); } void SlideShow::dispatchCurrentInfoChange(const QUrl& url) { if (currentItem() == url) { d->osd->setCurrentUrl(currentItem()); } } void SlideShow::slotPause() { #ifdef HAVE_MEDIAPLAYER if (currentIndex() == VideoView) { d->videoView->pause(true); } else #endif { d->osd->pause(true); } } void SlideShow::slotPlay() { #ifdef HAVE_MEDIAPLAYER if (currentIndex() == VideoView) { d->videoView->pause(false); } else #endif { d->osd->pause(false); } } void SlideShow::slotScreenSelected(int screen) { QRect deskRect = qApp->desktop()->screenGeometry(screen); move(deskRect.x(), deskRect.y()); resize(deskRect.width(), deskRect.height()); qCDebug(DIGIKAM_GENERAL_LOG) << "Slideshow: move to screen: " << screen << " :: " << deskRect; } } // namespace Digikam