diff --git a/NEWS b/NEWS index cfd2d77444..490131545f 100644 --- a/NEWS +++ b/NEWS @@ -1,132 +1,133 @@ digiKam 6.1.0 - Release date: 2019-03-31 ***************************************************************************************************** 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. General : MacOS and AppImage bundles are now published with Qt 5.11.3. General : Add new optional configuration option to compile with Faces Engine Neural Network. 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 ==> 405342 - Increase slideshow caption font size and keyboard shortcut or button to display/hide it. 067 ==> 405636 - When importing picture not all people tags are present. 068 ==> 379916 - Some people tags are missing. 069 ==> 386967 - digiKam with Adobe Bridge keywords under Windows. 070 ==> 402433 - Google Maps Doesn't Zoom With Mouse Wheel. 071 ==> 396920 - EXIF info not written when files from some cameras (Pentax K3) are edited and saved. 072 ==> 375468 - Cannot turn on Menubar. 073 ==> 387253 - No more menu bar in the Gnome desktop environment. 074 ==> 397405 - Large empty space in Digikams main icon view since ~20180707 appimage. 075 ==> 399237 - Thumbnails view shows an empty dock for thumbnails. 076 ==> 393935 - Segmentation fault during face detection. 077 ==> 388533 - UpdateSchemaFromV7ToV9 fails. 078 ==> 281493 - digiKam fails to install on Windows XP. 079 ==> 405537 - Strange behavior with tag in attached file. 080 ==> 405233 - digikam: symbol lookup error: /tmp/.mount_digika5N9rGH/usr/lib/libQt5XcbQpa.so.5: undefined symbol: FT_Property_Set. 081 ==> 404853 - digikam-6.0.0 faces engine fails to compile on PowerPC. 082 ==> 405625 - digiKam 6.0.0 faces engine fails to compile on PowerPC with AltiVec enabled. 083 ==> 372340 - Tagged face areas on portait (vertical) oriented images are mispositioned. 084 ==> 405743 - Customise Tool tab in editor. 085 ==> 376014 - Moving grouped photos from one folder to another breaks the group. 086 ==> 377782 - Group is lost when moved to another album. 087 ==> 385147 - Moving grouped images into another album removes groups. 088 ==> 342017 - Reverse Geocoding doesn't work. 089 ==> 405174 - Right-click advice menu. Open with another program. 090 ==> 399285 - Would it be possible to drop kio for a better 'open with' functionality across all platforms? 091 ==> 383079 - Open the photo in GIMP under windows. 092 ==> 374356 - "Show item in file explorer" as well as "open with". 093 ==> 208201 - Icons appears and disappears. 094 ==> 202955 - thumbnails in album view are flickering with high frequency. 095 ==> 208201 - Icons appears and disappears. 096 ==> 396933 - Tooltips of thumbnails and albums not readable in light designs. 097 ==> 393777 - Item Tool Tips are unreadable in Windows 10 (white on yellow). 098 ==> 240237 - Not possible to rotate the image. 099 ==> 366446 - Creating new albums fails due to invalid path name. 100 ==> 369235 - Menu bar is not translated. 101 ==> 403132 - Lazy Update not working (or: Stop when I say so). 102 ==> 404797 - digikam-6.0.0-x86-64.appimage: stack trace shortly after startup. 103 ==> 405789 - Sidebar widths revert to their defaults after switching back from full-screen view. 104 ==> 405813 - Tab-View do not show Rating information. 105 ==> 404138 - can't connect to my account. 106 ==> 403819 - Export to Google Photos not working (bad request). 107 ==> 382367 - Unreadable light on light tooltip. 108 ==> 405825 - Feature request: "Video date" in XMP Metadata Editor. 109 ==> 405799 - Not possible to add collection. 110 ==> 389549 - "Clear all faces on this image" Does Not Remove All People Tags. 111 ==> 405904 - The saved version of the image is not linked to the original. -112 ==> +112 ==> 372308 - Buttons for rotate does not show very well. +113 ==> diff --git a/core/app/utils/digikam_globals.cpp b/core/app/utils/digikam_globals.cpp index 1d9c71d67f..09e529c806 100644 --- a/core/app/utils/digikam_globals.cpp +++ b/core/app/utils/digikam_globals.cpp @@ -1,236 +1,264 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2009-09-08 * Description : global macros, variables and flags * * Copyright (C) 2009-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 "digikam_globals.h" // Qt includes #include #include #include #include #include #include #include #include #include // KDE includes #include // Local includes #include "digikam_config.h" #include "digikam_debug.h" #include "drawdecoder.h" #include "rawcameradlg.h" // Windows includes #ifdef HAVE_DRMINGW # include #endif namespace Digikam { QShortcut* defineShortcut(QWidget* const w, const QKeySequence& key, const QObject* receiver, const char* slot) { QShortcut* const s = new QShortcut(w); s->setKey(key); s->setContext(Qt::WidgetWithChildrenShortcut); QObject::connect(s, SIGNAL(activated()), receiver, slot); return s; } QStringList supportedImageMimeTypes(QIODevice::OpenModeFlag mode, QString& allTypes) { QStringList formats; QList supported; switch(mode) { case QIODevice::ReadOnly: supported = QImageReader::supportedImageFormats(); break; case QIODevice::WriteOnly: supported = QImageWriter::supportedImageFormats(); break; case QIODevice::ReadWrite: supported = QImageWriter::supportedImageFormats() + QImageReader::supportedImageFormats(); break; default: qCDebug(DIGIKAM_GENERAL_LOG) << "Unsupported mode!"; break; } bool tiff = false; bool jpeg = false; #ifdef HAVE_JASPER bool jp2k = false; #endif // HAVE_JASPER foreach(const QByteArray& frm, supported) { if (QString::fromLatin1(frm).contains(QLatin1String("tif"), Qt::CaseInsensitive) || QString::fromLatin1(frm).contains(QLatin1String("tiff"), Qt::CaseInsensitive)) { tiff = true; continue; } if (QString::fromLatin1(frm).contains(QLatin1String("jpg"), Qt::CaseInsensitive) || QString::fromLatin1(frm).contains(QLatin1String("jpeg"), Qt::CaseInsensitive)) { jpeg = true; continue; } #ifdef HAVE_JASPER if (QString::fromLatin1(frm).contains(QLatin1String("jp2"), Qt::CaseInsensitive) || QString::fromLatin1(frm).contains(QLatin1String("j2k"), Qt::CaseInsensitive) || QString::fromLatin1(frm).contains(QLatin1String("jpx"), Qt::CaseInsensitive) || QString::fromLatin1(frm).contains(QLatin1String("jpc"), Qt::CaseInsensitive) || QString::fromLatin1(frm).contains(QLatin1String("pgx"), Qt::CaseInsensitive)) { jp2k = true; continue; } #endif // HAVE_JASPER formats.append(i18n("%1 Image (%2)", QString::fromLatin1(frm).toUpper(), QLatin1String("*.") + QLatin1String(frm))); allTypes.append(QString::fromLatin1("*.%1 ").arg(QLatin1String(frm))); } if (tiff) { formats.append(i18n("TIFF Image (*.tiff *.tif)")); allTypes.append(QLatin1String("*.tiff *.tif ")); } if (jpeg) { formats.append(i18n("JPEG Image (*.jpg *.jpeg *.jpe)")); allTypes.append(QLatin1String("*.jpg *.jpeg *.jpe ")); } #ifdef HAVE_JASPER if (jp2k) { formats.append(i18n("JPEG2000 Image (*.jp2 *.j2k *.jpx *.pgx)")); allTypes.append(QLatin1String("*.jp2 *.j2k *.jpx *.pgx ")); } #endif // HAVE_JASPER formats << i18n("Progressive Graphics file (*.pgf)"); allTypes.append(QLatin1String("*.pgf ")); if (mode != QIODevice::WriteOnly) { formats << i18n("Raw Images (%1)", QLatin1String(DRawDecoder::rawFiles())); allTypes.append(QLatin1String(DRawDecoder::rawFiles())); formats << i18n("All supported files (%1)", allTypes); } return formats; } void showRawCameraList() { RawCameraDlg* const dlg = new RawCameraDlg(qApp->activeWindow()); dlg->show(); } QProcessEnvironment adjustedEnvironmentForAppImage() { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); // If we are running into AppImage bundle, switch env var to the right values. if (env.contains(QLatin1String("APPIMAGE_ORIGINAL_LD_LIBRARY_PATH")) && env.contains(QLatin1String("APPIMAGE_ORIGINAL_QT_PLUGIN_PATH")) && env.contains(QLatin1String("APPIMAGE_ORIGINAL_XDG_DATA_DIRS")) && env.contains(QLatin1String("APPIMAGE_ORIGINAL_PATH"))) { qCDebug(DIGIKAM_GENERAL_LOG) << "Adjusting environment variables for AppImage bundle"; env.insert(QLatin1String("LD_LIBRARY_PATH"), env.value(QLatin1String("APPIMAGE_ORIGINAL_LD_LIBRARY_PATH"))); env.insert(QLatin1String("QT_PLUGIN_PATH"), env.value(QLatin1String("APPIMAGE_ORIGINAL_QT_PLUGIN_PATH"))); env.insert(QLatin1String("XDG_DATA_DIRS"), env.value(QLatin1String("APPIMAGE_ORIGINAL_XDG_DATA_DIRS"))); env.insert(QLatin1String("PATH"), env.value(QLatin1String("APPIMAGE_ORIGINAL_PATH"))); } return env; } void tryInitDrMingw() { #ifdef HAVE_DRMINGW qCDebug(DIGIKAM_GENERAL_LOG) << "Loading DrMinGw run-time..."; wchar_t path[MAX_PATH]; QString pathStr = QCoreApplication::applicationDirPath().replace(L'/', L'\\') + QLatin1String("\\exchndl.dll"); if (pathStr.size() > MAX_PATH - 1) { qCDebug(DIGIKAM_GENERAL_LOG) << "DrMinGw: cannot find crash handler dll."; return; } int pathLen = pathStr.toWCharArray(path); path[pathLen] = L'\0'; // toWCharArray doesn't add NULL terminator HMODULE hMod = LoadLibraryW(path); if (!hMod) { qCDebug(DIGIKAM_GENERAL_LOG) << "DrMinGw: cannot init crash handler dll."; return; } // No need to call ExcHndlInit since the crash handler is installed on DllMain auto myExcHndlSetLogFileNameA = reinterpret_cast(GetProcAddress(hMod, "ExcHndlSetLogFileNameA")); if (!myExcHndlSetLogFileNameA) { qCDebug(DIGIKAM_GENERAL_LOG) << "DrMinGw: cannot init customized crash file."; return; } // Set the log file path to %LocalAppData%\kritacrash.log QString logFile = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation).replace(L'/', L'\\') + QLatin1String("\\digikam_crash.log"); myExcHndlSetLogFileNameA(logFile.toLocal8Bit().data()); qCDebug(DIGIKAM_GENERAL_LOG) << "DrMinGw run-time loaded."; qCDebug(DIGIKAM_GENERAL_LOG) << "DrMinGw crash-file will be located at: " << logFile; #endif // HAVE_DRMINGW } +QString toolButtonStyleSheet() +{ + return QLatin1String("QToolButton { padding: 1px; background-color: " + " qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, " + " stop: 0 rgba(100, 100, 100, 50%), " + " stop: 1 rgba(170, 170, 170, 50%)); " + "border: 1px solid rgba(200, 200, 200, 30%); " + "border-radius: 4px; } " + + "QToolButton:hover { border-color: white; } " + + "QToolButton:pressed { background-color: " + " qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, " + " stop: 0 rgba(40, 40, 40, 50%), " + " stop: 1 rgba(90, 90, 90, 50%)); " + "border-color: white; } " + + "QToolButton:checked { background-color: " + " qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, " + " stop: 0 rgba(40, 40, 40, 50%), " + " stop: 1 rgba(90, 90, 90, 50%)); } " + + "QToolButton:disabled { background-color: " + " qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, " + " stop: 0 rgba(40, 40, 40, 50%), " + " stop: 1 rgba(50, 50, 50, 50%)); }"); +} + } // namespace Digikam diff --git a/core/app/utils/digikam_globals.h b/core/app/utils/digikam_globals.h index 00232662ae..a798b8e809 100644 --- a/core/app/utils/digikam_globals.h +++ b/core/app/utils/digikam_globals.h @@ -1,180 +1,184 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2009-09-08 * Description : global macros, variables and flags * * Copyright (C) 2009-2010 by Andi Clemens * Copyright (C) 2009-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_GLOBALS_H #define DIGIKAM_GLOBALS_H // Qt includes #include #include #include // Local includes #include "digikam_export.h" class QWidget; class QObject; class QShortcut; class QKeySequence; /** Macros for image filters. */ #define CLAMP0255(a) qBound(0,a,255) #define CLAMP065535(a) qBound(0,a,65535) #define CLAMP(x,l,u) qBound(l,x,u) #define MAX3(a, b, c) (qMax(qMax(a,b),c)) #define MIN3(a, b, c) (qMin(qMin(a,b),c)) /** Degrees to radian conversion coeff (PI/180). To optimize computation. */ #define DEG2RAD 0.017453292519943 namespace Digikam { /** Field value limits for all digiKam-specific fields (not EXIF/IPTC fields) */ static const int RatingMin = 0; static const int RatingMax = 5; static const int NoRating = -1; // -------------------------------------------------------- /** segments for histograms and curves */ static const int NUM_SEGMENTS_16BIT = 65536; static const int NUM_SEGMENTS_8BIT = 256; static const int MAX_SEGMENT_16BIT = NUM_SEGMENTS_16BIT - 1; static const int MAX_SEGMENT_8BIT = NUM_SEGMENTS_8BIT - 1; // -------------------------------------------------------- /** Delay in milliseconds to automatically expands album tree-view with D&D * See bug #286263 for details. */ static const int AUTOEXPANDDELAY = 800; // -------------------------------------------------------- enum ColorLabel { NoColorLabel = 0, RedLabel, OrangeLabel, YellowLabel, GreenLabel, BlueLabel, MagentaLabel, GrayLabel, BlackLabel, WhiteLabel, FirstColorLabel = NoColorLabel, LastColorLabel = WhiteLabel, NumberOfColorLabels = LastColorLabel + 1 }; // -------------------------------------------------------- enum PickLabel { NoPickLabel = 0, RejectedLabel, PendingLabel, AcceptedLabel, FirstPickLabel = NoPickLabel, LastPickLabel = AcceptedLabel, NumberOfPickLabels = LastPickLabel + 1 }; // -------------------------------------------------------- enum HistogramBoxType { RGB = 0, RGBA, LRGB, LRGBA, LRGBC, LRGBAC }; enum HistogramScale { LinScaleHistogram = 0, // Linear scale LogScaleHistogram // Logarithmic scale }; enum HistogramRenderingType { FullImageHistogram = 0, // Full image histogram rendering. ImageSelectionHistogram // Image selection histogram rendering. }; // -------------------------------------------------------- enum ChannelType { LuminosityChannel = 0, RedChannel, GreenChannel, BlueChannel, AlphaChannel, ColorChannels }; // -------------------------------------------------------- /** Convenience method for creating keyboard shortcuts. */ DIGIKAM_EXPORT QShortcut* defineShortcut(QWidget* const w, const QKeySequence& key, const QObject* receiver, const char* slot); /** Return list of supported image formats by Qt for reading or writing operations if suitable * container used by QFileDialog. * For simple container of type mime, use 'allTypes' string. * Supported modes are QIODevice::ReadOnly, QIODevice::WriteOnly, and QIODevice::ReadWrite. */ DIGIKAM_EXPORT QStringList supportedImageMimeTypes(QIODevice::OpenModeFlag mode, QString& allTypes); /** Show a dialog with all RAW camera supported by digiKam, through libraw. */ DIGIKAM_EXPORT void showRawCameraList(); /** If digiKam run into AppImage, return a cleaned environment for QProcess to execute a * program outside the bundle without broken run-time dependencies. * Use case : system based Hugin CLI tools called by Panorama wizard. * If digiKam do not run as AppImage bundle, this method return a QProcessEnvironment instance * based on system environment. */ DIGIKAM_EXPORT QProcessEnvironment adjustedEnvironmentForAppImage(); /** Static method to initialize DrMinGw crash handler under windows. * This method is typically called from main() function. */ DIGIKAM_EXPORT void tryInitDrMingw(); +/** Style sheet for transparent QToolButtons over image and video preview. + */ +DIGIKAM_EXPORT QString toolButtonStyleSheet(); + } // namespace Digikam #endif // DIGIKAM_GLOBALS_H diff --git a/core/app/views/preview/itempreviewview.cpp b/core/app/views/preview/itempreviewview.cpp index 0b8ed54d1e..ae66cad176 100644 --- a/core/app/views/preview/itempreviewview.cpp +++ b/core/app/views/preview/itempreviewview.cpp @@ -1,577 +1,579 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2006-21-12 * Description : a embedded view to show item preview widget. * * Copyright (C) 2006-2019 by Gilles Caulier * Copyright (C) 2009-2012 by Andi Clemens * Copyright (C) 2010-2011 by Aditya Bhatt * * 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 "itempreviewview.h" // Qt includes #include #include #include #include #include #include #include #include #include #include // KDE includes #include // Local includes #include "digikam_debug.h" #include "digikam_config.h" +#include "digikam_globals.h" #include "itempreviewcanvas.h" #include "applicationsettings.h" #include "contextmenuhelper.h" #include "ddragobjects.h" #include "digikamapp.h" #include "dimg.h" #include "dimgpreviewitem.h" #include "iteminfo.h" #include "fileactionmngr.h" #include "metaenginesettings.h" #include "regionframeitem.h" #include "tagspopupmenu.h" #include "thememanager.h" #include "previewlayout.h" #include "previewsettings.h" #include "tagscache.h" #include "itemtagpair.h" #include "albummanager.h" #include "facegroup.h" namespace Digikam { class Q_DECL_HIDDEN ItemPreviewView::Private { public: explicit Private() { fullSize = 0; scale = 1.0; item = 0; isValid = false; rotationLock = false; toolBar = 0; prevAction = 0; nextAction = 0; rotLeftAction = 0; rotRightAction = 0; mode = ItemPreviewView::IconViewPreview; faceGroup = 0; peopleToggleAction = 0; addPersonAction = 0; forgetFacesAction = 0; fullscreenAction = 0; currAlbum = 0; } bool fullSize; double scale; bool isValid; bool rotationLock; ItemPreviewView::Mode mode; ItemPreviewCanvas* item; QAction* prevAction; QAction* nextAction; QAction* rotLeftAction; QAction* rotRightAction; QToolBar* toolBar; FaceGroup* faceGroup; QAction* peopleToggleAction; QAction* addPersonAction; QAction* forgetFacesAction; QAction* fullscreenAction; Album* currAlbum; }; ItemPreviewView::ItemPreviewView(QWidget* const parent, Mode mode, Album* const currAlbum) : GraphicsDImgView(parent), d(new Private()) { d->mode = mode; d->item = new ItemPreviewCanvas(); d->currAlbum = currAlbum; setItem(d->item); d->faceGroup = new FaceGroup(this); d->faceGroup->setShowOnHover(true); d->item->setFaceGroup(d->faceGroup); connect(d->item, SIGNAL(loaded()), this, SLOT(imageLoaded())); connect(d->item, SIGNAL(loadingFailed()), this, SLOT(imageLoadingFailed())); connect(d->item, SIGNAL(imageChanged()), this, SLOT(slotUpdateFaces())); connect(d->item, SIGNAL(showContextMenu(QGraphicsSceneContextMenuEvent*)), this, SLOT(slotShowContextMenu(QGraphicsSceneContextMenuEvent*))); // set default zoom layout()->fitToWindow(); // ------------------------------------------------------------ installPanIcon(); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // ------------------------------------------------------------ d->prevAction = new QAction(QIcon::fromTheme(QLatin1String("go-previous")), i18nc("go to previous image", "Back"), this); d->nextAction = new QAction(QIcon::fromTheme(QLatin1String("go-next")), i18nc("go to next image", "Forward"), this); d->rotLeftAction = new QAction(QIcon::fromTheme(QLatin1String("object-rotate-left")), i18nc("@info:tooltip", "Rotate Left"), this); d->rotRightAction = new QAction(QIcon::fromTheme(QLatin1String("object-rotate-right")), i18nc("@info:tooltip", "Rotate Right"), this); d->addPersonAction = new QAction(QIcon::fromTheme(QLatin1String("list-add-user")), i18n("Add a Face Tag"), this); d->forgetFacesAction = new QAction(QIcon::fromTheme(QLatin1String("list-remove-user")), i18n("Clear all faces on this image"), this); d->peopleToggleAction = new QAction(QIcon::fromTheme(QLatin1String("im-user")), i18n("Show Face Tags"), this); d->peopleToggleAction->setCheckable(true); d->fullscreenAction = new QAction(QIcon::fromTheme(QLatin1String("media-playback-start")), i18n("Show Fullscreen"), this); d->toolBar = new QToolBar(this); + d->toolBar->setStyleSheet(toolButtonStyleSheet()); if (mode == IconViewPreview) { d->toolBar->addAction(d->prevAction); d->toolBar->addAction(d->nextAction); } d->toolBar->addAction(d->rotLeftAction); d->toolBar->addAction(d->rotRightAction); d->toolBar->addAction(d->peopleToggleAction); d->toolBar->addAction(d->addPersonAction); d->toolBar->addAction(d->fullscreenAction); connect(d->prevAction, SIGNAL(triggered()), this, SIGNAL(toPreviousImage())); connect(d->nextAction, SIGNAL(triggered()), this, SIGNAL(toNextImage())); connect(d->rotLeftAction, SIGNAL(triggered()), this, SLOT(slotRotateLeft())); connect(d->rotRightAction, SIGNAL(triggered()), this, SLOT(slotRotateRight())); connect(d->peopleToggleAction, SIGNAL(toggled(bool)), d->faceGroup, SLOT(setVisible(bool))); connect(d->addPersonAction, SIGNAL(triggered()), d->faceGroup, SLOT(addFace())); connect(d->forgetFacesAction, SIGNAL(triggered()), d->faceGroup, SLOT(rejectAll())); connect(d->fullscreenAction, SIGNAL(triggered()), this, SIGNAL(signalSlideShowCurrent())); // ------------------------------------------------------------ connect(this, SIGNAL(toNextImage()), this, SIGNAL(signalNextItem())); connect(this, SIGNAL(toPreviousImage()), this, SIGNAL(signalPrevItem())); connect(this, SIGNAL(activated()), this, SIGNAL(signalEscapePreview())); connect(ThemeManager::instance(), SIGNAL(signalThemeChanged()), this, SLOT(slotThemeChanged())); connect(ApplicationSettings::instance(), SIGNAL(setupChanged()), this, SLOT(slotSetupChanged())); slotSetupChanged(); } ItemPreviewView::~ItemPreviewView() { delete d->item; delete d; } void ItemPreviewView::reload() { previewItem()->reload(); } void ItemPreviewView::imageLoaded() { emit signalPreviewLoaded(true); d->rotLeftAction->setEnabled(true); d->rotRightAction->setEnabled(true); d->faceGroup->setInfo(d->item->imageInfo()); } void ItemPreviewView::imageLoadingFailed() { emit signalPreviewLoaded(false); d->rotLeftAction->setEnabled(false); d->rotRightAction->setEnabled(false); d->faceGroup->setInfo(ItemInfo()); } void ItemPreviewView::setItemInfo(const ItemInfo& info, const ItemInfo& previous, const ItemInfo& next) { d->faceGroup->aboutToSetInfo(info); d->item->setItemInfo(info); d->prevAction->setEnabled(!previous.isNull()); d->nextAction->setEnabled(!next.isNull()); QStringList previewPaths; if (next.category() == DatabaseItem::Image) { previewPaths << next.filePath(); } if (previous.category() == DatabaseItem::Image) { previewPaths << previous.filePath(); } d->item->setPreloadPaths(previewPaths); } ItemInfo ItemPreviewView::getItemInfo() const { return d->item->imageInfo(); } bool ItemPreviewView::acceptsMouseClick(QMouseEvent* e) { if (!GraphicsDImgView::acceptsMouseClick(e)) { return false; } return d->faceGroup->acceptsMouseClick(mapToScene(e->pos())); } void ItemPreviewView::enterEvent(QEvent* e) { d->faceGroup->enterEvent(e); } void ItemPreviewView::leaveEvent(QEvent* e) { d->faceGroup->leaveEvent(e); } void ItemPreviewView::showEvent(QShowEvent* e) { GraphicsDImgView::showEvent(e); d->faceGroup->setVisible(d->peopleToggleAction->isChecked()); } void ItemPreviewView::slotShowContextMenu(QGraphicsSceneContextMenuEvent* event) { ItemInfo info = d->item->imageInfo(); if (info.isNull()) { return; } event->accept(); QList idList; idList << info.id(); // -------------------------------------------------------- QMenu popmenu(this); ContextMenuHelper cmHelper(&popmenu); cmHelper.addAction(QLatin1String("full_screen")); cmHelper.addAction(QLatin1String("options_show_menubar")); cmHelper.addSeparator(); // -------------------------------------------------------- if (d->mode == IconViewPreview) { cmHelper.addAction(d->prevAction, true); cmHelper.addAction(d->nextAction, true); cmHelper.addSeparator(); } // -------------------------------------------------------- cmHelper.addAction(d->peopleToggleAction, true); cmHelper.addAction(d->addPersonAction, true); cmHelper.addAction(d->forgetFacesAction, true); cmHelper.addSeparator(); // -------------------------------------------------------- cmHelper.addOpenAndNavigateActions(idList); cmHelper.addSeparator(); // -------------------------------------------------------- cmHelper.addAction(QLatin1String("image_scan_for_faces")); cmHelper.addAction(QLatin1String("image_find_similar")); if (d->mode == IconViewPreview) { cmHelper.addStandardActionLightTable(); } cmHelper.addQueueManagerMenu(); cmHelper.addSeparator(); // -------------------------------------------------------- cmHelper.addAction(QLatin1String("image_rotate")); cmHelper.addStandardActionItemDelete(this, SLOT(slotDeleteItem())); cmHelper.addSeparator(); // -------------------------------------------------------- if (d->mode == IconViewPreview && d->currAlbum) { cmHelper.addStandardActionThumbnail(idList, d->currAlbum); } cmHelper.addAssignTagsMenu(idList); cmHelper.addRemoveTagsMenu(idList); cmHelper.addLabelsAction(); // special action handling -------------------------------- connect(&cmHelper, SIGNAL(signalAssignTag(int)), this, SLOT(slotAssignTag(int))); connect(&cmHelper, SIGNAL(signalPopupTagsView()), this, SIGNAL(signalPopupTagsView())); connect(&cmHelper, SIGNAL(signalRemoveTag(int)), this, SLOT(slotRemoveTag(int))); connect(&cmHelper, SIGNAL(signalAssignPickLabel(int)), this, SLOT(slotAssignPickLabel(int))); connect(&cmHelper, SIGNAL(signalAssignColorLabel(int)), this, SLOT(slotAssignColorLabel(int))); connect(&cmHelper, SIGNAL(signalAssignRating(int)), this, SLOT(slotAssignRating(int))); connect(&cmHelper, SIGNAL(signalAddToExistingQueue(int)), this, SIGNAL(signalAddToExistingQueue(int))); connect(&cmHelper, SIGNAL(signalGotoTag(int)), this, SIGNAL(signalGotoTagAndItem(int))); connect(&cmHelper, SIGNAL(signalGotoAlbum(ItemInfo)), this, SIGNAL(signalGotoAlbumAndItem(ItemInfo))); connect(&cmHelper, SIGNAL(signalGotoDate(ItemInfo)), this, SIGNAL(signalGotoDateAndItem(ItemInfo))); cmHelper.exec(event->screenPos()); } void ItemPreviewView::slotAssignTag(int tagID) { FileActionMngr::instance()->assignTag(d->item->imageInfo(), tagID); } void ItemPreviewView::slotRemoveTag(int tagID) { FileActionMngr::instance()->removeTag(d->item->imageInfo(), tagID); } void ItemPreviewView::slotAssignPickLabel(int pickId) { FileActionMngr::instance()->assignPickLabel(d->item->imageInfo(), pickId); } void ItemPreviewView::slotAssignColorLabel(int colorId) { FileActionMngr::instance()->assignColorLabel(d->item->imageInfo(), colorId); } void ItemPreviewView::slotAssignRating(int rating) { FileActionMngr::instance()->assignRating(d->item->imageInfo(), rating); } void ItemPreviewView::slotThemeChanged() { QPalette plt(palette()); plt.setColor(backgroundRole(), qApp->palette().color(QPalette::Base)); setPalette(plt); } void ItemPreviewView::slotSetupChanged() { previewItem()->setPreviewSettings(ApplicationSettings::instance()->getPreviewSettings()); d->toolBar->setVisible(ApplicationSettings::instance()->getPreviewShowIcons()); setShowText(ApplicationSettings::instance()->getPreviewShowIcons()); // pass auto-suggest? } void ItemPreviewView::slotRotateLeft() { if (d->rotationLock) return; d->rotationLock = true; /** * Setting lock won't allow mouse hover events in ItemPreviewCanvas class */ d->item->setAcceptHoverEvents(false); /** * aboutToSetInfo will delete all face tags from FaceGroup storage */ d->faceGroup->aboutToSetInfo(ItemInfo()); FileActionMngr::instance()->transform(QList() << d->item->imageInfo(), MetaEngineRotation::Rotate270); } void ItemPreviewView::slotRotateRight() { if (d->rotationLock) return; d->rotationLock = true; /** * Setting lock won't allow mouse hover events in ItemPreviewCanvas class */ d->item->setAcceptHoverEvents(false); /** * aboutToSetInfo will delete all face tags from FaceGroup storage */ d->faceGroup->aboutToSetInfo(ItemInfo()); FileActionMngr::instance()->transform(QList() << d->item->imageInfo(), MetaEngineRotation::Rotate90); } void ItemPreviewView::slotDeleteItem() { emit signalDeleteItem(); } void Digikam::ItemPreviewView::slotUpdateFaces() { //d->faceGroup->aboutToSetInfo(ItemInfo()); d->faceGroup->aboutToSetInfoAfterRotate(ItemInfo()); d->item->setAcceptHoverEvents(true); /** * Release rotation lock after rotation */ d->rotationLock = false; } void ItemPreviewView::dragMoveEvent(QDragMoveEvent* e) { if (DTagListDrag::canDecode(e->mimeData())) { e->accept(); return; } e->ignore(); } void ItemPreviewView::dragEnterEvent(QDragEnterEvent* e) { if (DTagListDrag::canDecode(e->mimeData())) { e->accept(); return; } e->ignore(); } void ItemPreviewView::dropEvent(QDropEvent* e) { if (DTagListDrag::canDecode(e->mimeData())) { QList tagIDs; if (!DTagListDrag::decode(e->mimeData(), tagIDs)) { return; } QMenu popMenu(this); QAction* const assignToThisAction = popMenu.addAction(QIcon::fromTheme(QLatin1String("tag")), i18n("Assign Tags to &This Item")); popMenu.addSeparator(); popMenu.addAction(QIcon::fromTheme(QLatin1String("dialog-cancel")), i18n("&Cancel")); popMenu.setMouseTracking(true); QAction* const choice = popMenu.exec(this->mapToGlobal(e->pos())); if (choice == assignToThisAction) { FileActionMngr::instance()->assignTags(d->item->imageInfo(), tagIDs); } } e->accept(); return; } void ItemPreviewView::mousePressEvent(QMouseEvent* e) { if (e->button() == Qt::LeftButton && QApplication::keyboardModifiers() == Qt::ControlModifier) { d->faceGroup->addFace(); } GraphicsDImgView::mousePressEvent(e); } } // namespace Digikam diff --git a/core/libs/video/player/mediaplayerview.cpp b/core/libs/video/player/mediaplayerview.cpp index b1431873a5..59b0f7c989 100644 --- a/core/libs/video/player/mediaplayerview.cpp +++ b/core/libs/video/player/mediaplayerview.cpp @@ -1,561 +1,563 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2006-20-12 * Description : a view to embed QtAv media player. * * Copyright (C) 2006-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 "mediaplayerview.h" // Qt includes #include #include #include #include #include #include #include #include #include #include #include #include // QtAV includes #include // krazy:exclude=includes #include // krazy:exclude=includes // KDE includes #include // Local includes #include "metaenginesettings.h" +#include "digikam_globals.h" #include "digikam_debug.h" #include "thememanager.h" #include "dlayoutbox.h" using namespace QtAV; namespace Digikam { class Q_DECL_HIDDEN MediaPlayerMouseClickFilter : public QObject { public: explicit MediaPlayerMouseClickFilter(QObject* const parent) : QObject(parent), m_parent(parent) { } protected: bool eventFilter(QObject* obj, QEvent* event) { if ((qApp->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) && event->type() == QEvent::MouseButtonRelease) || (!qApp->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) && event->type() == QEvent::MouseButtonDblClick)) { QMouseEvent* const mouseEvent = dynamic_cast(event); if (mouseEvent && (mouseEvent->button() == Qt::LeftButton || mouseEvent->button() == Qt::RightButton)) { if (m_parent) { MediaPlayerView* const mplayer = dynamic_cast(m_parent); if (mplayer) { if (mouseEvent->button() == Qt::LeftButton) { mplayer->slotEscapePressed(); } else { mplayer->slotRotateVideo(); } return true; } } } } return QObject::eventFilter(obj, event); } private: QObject* m_parent; }; class Q_DECL_HIDDEN VideoStyle : public QProxyStyle { public: using QProxyStyle::QProxyStyle; int styleHint(QStyle::StyleHint hint, const QStyleOption* option = 0, const QWidget* widget = 0, QStyleHintReturn* returnData = 0) const { if (hint == QStyle::SH_Slider_AbsoluteSetButtons) { return (Qt::LeftButton | Qt::MidButton | Qt::RightButton); } return QProxyStyle::styleHint(hint, option, widget, returnData); } }; // -------------------------------------------------------- class Q_DECL_HIDDEN MediaPlayerView::Private { public: enum MediaPlayerViewMode { ErrorView=0, PlayerView }; public: explicit Private() : errorView(0), playerView(0), prevAction(0), nextAction(0), playAction(0), loopPlay(0), toolBar(0), iface(0), videoWidget(0), player(0), slider(0), volume(0), tlabel(0), videoOrientation(0) { } QFrame* errorView; QFrame* playerView; QAction* prevAction; QAction* nextAction; QAction* playAction; QPushButton* loopPlay; QToolBar* toolBar; DInfoInterface* iface; WidgetRenderer* videoWidget; AVPlayer* player; QSlider* slider; QSlider* volume; QLabel* tlabel; QUrl currentItem; int videoOrientation; }; MediaPlayerView::MediaPlayerView(QWidget* const parent) : QStackedWidget(parent), d(new Private) { setAttribute(Qt::WA_DeleteOnClose); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing); d->prevAction = new QAction(QIcon::fromTheme(QLatin1String("go-previous")), i18nc("go to previous image", "Back"), this); d->nextAction = new QAction(QIcon::fromTheme(QLatin1String("go-next")), i18nc("go to next image", "Forward"), this); d->playAction = new QAction(QIcon::fromTheme(QLatin1String("media-playback-start")), i18nc("pause/play video", "Pause/Play"), this); d->errorView = new QFrame(this); QLabel* const errorMsg = new QLabel(i18n("An error has occurred with the media player..."), this); errorMsg->setAlignment(Qt::AlignCenter); d->errorView->setFrameStyle(QFrame::StyledPanel | QFrame::Plain); d->errorView->setLineWidth(1); QVBoxLayout* const vbox1 = new QVBoxLayout(d->errorView); vbox1->addWidget(errorMsg, 10); vbox1->setContentsMargins(QMargins()); vbox1->setSpacing(spacing); insertWidget(Private::ErrorView, d->errorView); // -------------------------------------------------------------------------- d->playerView = new QFrame(this); d->videoWidget = new WidgetRenderer(this); d->player = new AVPlayer(this); DHBox* const hbox = new DHBox(this); d->slider = new QSlider(Qt::Horizontal, hbox); d->slider->setStyle(new VideoStyle(d->slider->style())); d->slider->setRange(0, 0); d->tlabel = new QLabel(hbox); d->tlabel->setText(QLatin1String("00:00:00 / 00:00:00")); d->loopPlay = new QPushButton(hbox); d->loopPlay->setIcon(QIcon::fromTheme(QLatin1String("media-playlist-normal"))); d->loopPlay->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); d->loopPlay->setFocusPolicy(Qt::NoFocus); d->loopPlay->setMinimumSize(22, 22); d->loopPlay->setCheckable(true); QLabel* const spk = new QLabel(hbox); spk->setPixmap(QIcon::fromTheme(QLatin1String("audio-volume-high")).pixmap(22, 22)); d->volume = new QSlider(Qt::Horizontal, hbox); d->volume->setRange(0, 100); d->volume->setValue(50); hbox->setContentsMargins(0, spacing, 0, 0); hbox->setStretchFactor(d->slider, 10); hbox->setSpacing(4); d->videoWidget->setOutAspectRatioMode(VideoRenderer::VideoAspectRatio); d->videoWidget->setMouseTracking(true); d->player->setRenderer(d->videoWidget); d->playerView->setFrameStyle(QFrame::StyledPanel | QFrame::Plain); d->playerView->setLineWidth(1); QVBoxLayout* const vbox2 = new QVBoxLayout(d->playerView); vbox2->addWidget(d->videoWidget, 10); vbox2->addWidget(hbox, 0); vbox2->setContentsMargins(0, 0, 0, spacing); vbox2->setSpacing(spacing); insertWidget(Private::PlayerView, d->playerView); d->toolBar = new QToolBar(this); d->toolBar->addAction(d->prevAction); d->toolBar->addAction(d->nextAction); d->toolBar->addAction(d->playAction); + d->toolBar->setStyleSheet(toolButtonStyleSheet()); setPreviewMode(Private::PlayerView); d->errorView->installEventFilter(new MediaPlayerMouseClickFilter(this)); d->videoWidget->installEventFilter(new MediaPlayerMouseClickFilter(this)); // -------------------------------------------------------------------------- connect(ThemeManager::instance(), SIGNAL(signalThemeChanged()), this, SLOT(slotThemeChanged())); connect(d->prevAction, SIGNAL(triggered()), this, SIGNAL(signalPrevItem())); connect(d->nextAction, SIGNAL(triggered()), this, SIGNAL(signalNextItem())); connect(d->playAction, SIGNAL(triggered()), this, SLOT(slotPausePlay())); connect(d->slider, SIGNAL(sliderMoved(int)), this, SLOT(slotPosition(int))); connect(d->slider, SIGNAL(valueChanged(int)), this, SLOT(slotPosition(int))); connect(d->volume, SIGNAL(valueChanged(int)), this, SLOT(slotVolumeChanged(int))); connect(d->loopPlay, SIGNAL(toggled(bool)), this, SLOT(slotLoopToggled(bool))); connect(d->player, SIGNAL(stateChanged(QtAV::AVPlayer::State)), this, SLOT(slotPlayerStateChanged(QtAV::AVPlayer::State))); connect(d->player, SIGNAL(mediaStatusChanged(QtAV::MediaStatus)), this, SLOT(slotMediaStatusChanged(QtAV::MediaStatus))); connect(d->player, SIGNAL(positionChanged(qint64)), this, SLOT(slotPositionChanged(qint64))); connect(d->player, SIGNAL(durationChanged(qint64)), this, SLOT(slotDurationChanged(qint64))); connect(d->player, SIGNAL(error(QtAV::AVError)), this, SLOT(slotHandlePlayerError(QtAV::AVError))); slotVolumeChanged(d->volume->value()); qCDebug(DIGIKAM_GENERAL_LOG) << "AudioOutput backends:" << d->player->audio()->backendsAvailable(); } MediaPlayerView::~MediaPlayerView() { d->player->stop(); delete d; } void MediaPlayerView::setInfoInterface(DInfoInterface* const iface) { d->iface = iface; } void MediaPlayerView::reload() { d->player->stop(); d->player->setFile(d->currentItem.toLocalFile()); d->player->play(); } void MediaPlayerView::slotPlayerStateChanged(QtAV::AVPlayer::State state) { if (state == QtAV::AVPlayer::PlayingState) { int rotate = 0; #if QTAV_VERSION > QTAV_VERSION_CHK(1, 12, 0) // fix wrong rotation from QtAV git/master rotate = d->player->statistics().video_only.rotate; #endif d->videoWidget->setOrientation((-rotate) + d->videoOrientation); qCDebug(DIGIKAM_GENERAL_LOG) << "Found video orientation:" << d->videoOrientation; d->playAction->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause"))); } else if (state == QtAV::AVPlayer::PausedState || state == QtAV::AVPlayer::StoppedState) { d->playAction->setIcon(QIcon::fromTheme(QLatin1String("media-playback-start"))); } } void MediaPlayerView::slotMediaStatusChanged(QtAV::MediaStatus status) { if (status == QtAV::InvalidMedia) { setPreviewMode(Private::ErrorView); } } void MediaPlayerView::escapePreview() { d->player->stop(); } void MediaPlayerView::slotThemeChanged() { QPalette palette; palette.setColor(d->errorView->backgroundRole(), qApp->palette().color(QPalette::Base)); d->errorView->setPalette(palette); QPalette palette2; palette2.setColor(d->playerView->backgroundRole(), qApp->palette().color(QPalette::Base)); d->playerView->setPalette(palette2); } void MediaPlayerView::slotEscapePressed() { escapePreview(); emit signalEscapePreview(); } void MediaPlayerView::slotRotateVideo() { if (d->player->isPlaying()) { int orientation = 0; switch (d->videoWidget->orientation()) { case 0: orientation = 90; break; case 90: orientation = 180; break; case 180: orientation = 270; break; default: orientation = 0; } d->videoWidget->setOrientation(orientation); } } void MediaPlayerView::slotPausePlay() { if (!d->player->isPlaying()) { d->player->play(); return; } d->player->pause(!d->player->isPaused()); } int MediaPlayerView::previewMode() { return indexOf(currentWidget()); } void MediaPlayerView::setPreviewMode(int mode) { if (mode != Private::ErrorView && mode != Private::PlayerView) { return; } setCurrentIndex(mode); d->toolBar->adjustSize(); d->toolBar->raise(); } void MediaPlayerView::setCurrentItem(const QUrl& url, bool hasPrevious, bool hasNext) { d->prevAction->setEnabled(hasPrevious); d->nextAction->setEnabled(hasNext); if (url.isEmpty()) { d->currentItem = url; d->player->stop(); return; } if (d->currentItem == url) { return; } d->currentItem = url; d->player->stop(); int orientation = 0; bool supportedCodec = true; if (d->iface) { DItemInfo info(d->iface->itemInfo(url)); orientation = info.orientation(); if (info.videoCodec() == QLatin1String("none")) { supportedCodec = false; } } if (MetaEngineSettings::instance()->settings().exifRotate) { switch (orientation) { case MetaEngine::ORIENTATION_ROT_90: case MetaEngine::ORIENTATION_ROT_90_HFLIP: case MetaEngine::ORIENTATION_ROT_90_VFLIP: d->videoOrientation = 90; break; case MetaEngine::ORIENTATION_ROT_180: d->videoOrientation = 180; break; case MetaEngine::ORIENTATION_ROT_270: d->videoOrientation = 270; break; default: d->videoOrientation = 0; break; } } if (supportedCodec) { d->player->setFile(d->currentItem.toLocalFile()); setPreviewMode(Private::PlayerView); d->player->play(); } else { d->currentItem = QUrl(); d->player->setFile(QString()); setPreviewMode(Private::ErrorView); } } void MediaPlayerView::slotPositionChanged(qint64 position) { if (!d->slider->isSliderDown()) { d->slider->blockSignals(true); d->slider->setValue(position); d->slider->blockSignals(false); } d->tlabel->setText(QString::fromLatin1("%1 / %2") .arg(QTime(0, 0, 0).addMSecs(position).toString(QLatin1String("HH:mm:ss"))) .arg(QTime(0, 0, 0).addMSecs(d->slider->maximum()).toString(QLatin1String("HH:mm:ss")))); } void MediaPlayerView::slotVolumeChanged(int volume) { d->player->audio()->setVolume((qreal)volume / 100.0); } void MediaPlayerView::slotLoopToggled(bool loop) { if (loop) { d->loopPlay->setIcon(QIcon::fromTheme(QLatin1String("media-playlist-repeat"))); d->player->setRepeat(-1); } else { d->loopPlay->setIcon(QIcon::fromTheme(QLatin1String("media-playlist-normal"))); d->player->setRepeat(0); } } void MediaPlayerView::slotDurationChanged(qint64 duration) { qint64 max = qMax((qint64)1, duration); d->slider->setRange(0, max); } void MediaPlayerView::slotPosition(int position) { if (d->player->isSeekable()) { d->player->setPosition((qint64)position); } } void MediaPlayerView::slotHandlePlayerError(const QtAV::AVError& err) { setPreviewMode(Private::ErrorView); qCDebug(DIGIKAM_GENERAL_LOG) << "Error: " << err.string(); } } // namespace Digikam