File indexing completed on 2025-01-19 03:53:53

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2008-07-11
0007  * Description : shared libraries list dialog common to digiKam and Showfoto
0008  *
0009  * SPDX-FileCopyrightText: 2008-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "libsinfodlg.h"
0016 #include "digikam_config.h"
0017 
0018 // Qt includes
0019 
0020 #include <QStringList>
0021 #include <QString>
0022 #include <QTreeWidget>
0023 #include <QHeaderView>
0024 #include <QThread>
0025 #include <QStandardPaths>
0026 #include <QFile>
0027 #include <QTextStream>
0028 
0029 #ifdef HAVE_QWEBENGINE
0030 #   include <QtWebEngineWidgetsVersion>
0031 #else
0032 #   include <QtWebKitWidgetsVersion>
0033 #endif
0034 
0035 // KDE includes
0036 
0037 #include <klocalizedstring.h>
0038 #include <kmemoryinfo.h>
0039 #include <kxmlgui_version.h>
0040 
0041 // Local includes
0042 
0043 #include "digikam_debug.h"
0044 #include "drawdecoder.h"
0045 #include "greycstorationfilter.h"
0046 #include "pgfutils.h"
0047 #include "digikam-lcms.h"
0048 #include "metaengine.h"
0049 #include "dngwriter.h"
0050 #include "exiftoolparser.h"
0051 #include "loadingcache.h"
0052 #include "itempropertiestab.h"
0053 
0054 #ifdef HAVE_LENSFUN
0055 #   include "lensfuniface.h"
0056 #endif
0057 
0058 #ifdef HAVE_GEOLOCATION
0059 #   include "backendmarble.h"
0060 #endif
0061 
0062 #ifdef HAVE_IMAGE_MAGICK
0063 
0064 // Pragma directives to reduce warnings from ImageMagick header files.
0065 #   if !defined(Q_OS_DARWIN) && defined(Q_CC_GNU)
0066 #       pragma GCC diagnostic push
0067 #       pragma GCC diagnostic ignored "-Wignored-qualifiers"
0068 #       pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
0069 #   endif
0070 
0071 #   if defined(Q_CC_CLANG)
0072 #       pragma clang diagnostic push
0073 #       pragma clang diagnostic ignored "-Wignored-qualifiers"
0074 #       pragma clang diagnostic ignored "-Wkeyword-macro"
0075 #       pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
0076 #   endif
0077 
0078 #   include <Magick++.h>
0079 
0080 // Restore warnings
0081 
0082 #   if defined(Q_CC_CLANG)
0083 #       pragma clang diagnostic pop
0084 #   endif
0085 
0086 #   if !defined(Q_OS_DARWIN) && defined(Q_CC_GNU)
0087 #       pragma GCC diagnostic pop
0088 #   endif
0089 
0090 #endif
0091 
0092 // C ANSI includes
0093 
0094 #ifndef Q_OS_WIN
0095 extern "C"
0096 {
0097 #endif
0098 
0099 #ifdef HAVE_JASPER
0100 
0101 #   if defined(Q_CC_CLANG)
0102 #       pragma clang diagnostic push
0103 #       pragma clang diagnostic ignored "-Werror"
0104 #       pragma clang diagnostic ignored "-Wundef"
0105 #   endif
0106 
0107 #   include <jasper/jas_version.h>
0108 
0109 #   if defined(Q_CC_CLANG)
0110 #       pragma clang diagnostic pop
0111 #   endif
0112 
0113 #endif
0114 
0115 #include <png.h>
0116 #include <tiffvers.h>
0117 
0118 #ifdef HAVE_HEIF
0119 #   include <libheif/heif_version.h>
0120 #endif
0121 
0122 // libx265 includes
0123 
0124 #if defined(__clang__)
0125 #   pragma clang diagnostic push
0126 #   pragma clang diagnostic ignored "-Wundef"
0127 #   pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
0128 #   pragma clang diagnostic ignored "-Wnested-anon-types"
0129 #   pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
0130 #endif
0131 
0132 #ifdef HAVE_X265
0133 #   include <x265.h>
0134 #endif
0135 
0136 #if defined(__clang__)
0137 #   pragma clang diagnostic pop
0138 #endif
0139 
0140 // Avoid Warnings under Win32
0141 #undef HAVE_STDLIB_H
0142 #undef HAVE_STDDEF_H
0143 #include <jpeglib.h>
0144 
0145 #ifndef Q_OS_WIN
0146 }
0147 #endif
0148 
0149 #include "digikam_opencv.h"
0150 
0151 // defined in OpenCV core/private.hpp
0152 namespace cv
0153 {
0154 const char* currentParallelFramework();
0155 }
0156 
0157 namespace Digikam
0158 {
0159 
0160 LibsInfoDlg::LibsInfoDlg(QWidget* const parent)
0161     : InfoDlg(parent)
0162 {
0163     setWindowTitle(i18nc("@title:window", "Shared Libraries and Components Information"));
0164 
0165     static const char* CONTEXT         = "@item: Component information, see help->components";
0166     static const QString SUPPORTED_YES = i18nc("@item: component is supported/available",     "Yes");
0167     static const QString SUPPORTED_NO  = i18nc("@item: component is not available/supported", "No");
0168 
0169     listView()->setHeaderLabels(QStringList() << QLatin1String("Properties") << QLatin1String("Value")); // Hidden header -> no i18n
0170     listView()->setSortingEnabled(true);
0171     listView()->setRootIsDecorated(true);
0172     listView()->setSelectionMode(QAbstractItemView::SingleSelection);
0173     listView()->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0174     listView()->setAllColumnsShowFocus(true);
0175     listView()->setColumnCount(2);
0176     listView()->header()->setSectionResizeMode(QHeaderView::Stretch);
0177     listView()->header()->hide();
0178 
0179     // NOTE: by default set a list of common components information used by Showfoto and digiKam.
0180 
0181     m_features = new QTreeWidgetItem(listView(), QStringList() << i18nc("@title", "Features"));
0182     listView()->addTopLevelItem(m_features);
0183 
0184     new QTreeWidgetItem(m_features, QStringList() <<
0185                         i18nc(CONTEXT, "Parallelized demosaicing") <<        checkTriState(DRawDecoder::librawUseGomp()));
0186 
0187 #ifdef HAVE_QTXMLPATTERNS
0188     new QTreeWidgetItem(m_features, QStringList() <<
0189                         i18nc(CONTEXT, "Rajce support") <<                   SUPPORTED_YES);
0190 #else
0191     new QTreeWidgetItem(m_features, QStringList() <<
0192                         i18nc(CONTEXT, "Rajce support") <<                   SUPPORTED_NO);
0193 #endif
0194 
0195     new QTreeWidgetItem(m_features, QStringList() <<
0196                         i18nc(CONTEXT, "Exiv2 supports XMP metadata") <<     (MetaEngine::supportXmp() ?  SUPPORTED_YES : SUPPORTED_NO));
0197 
0198     new QTreeWidgetItem(m_features, QStringList() <<
0199                         i18nc(CONTEXT, "Exiv2 supports Base Media") <<       (MetaEngine::supportBmff() ? SUPPORTED_YES : SUPPORTED_NO));
0200 
0201     new QTreeWidgetItem(m_features, QStringList() <<
0202                         i18nc(CONTEXT, "Exiv2 supports JPEG-XL metadata") << (MetaEngine::supportJpegXL() ? SUPPORTED_YES : SUPPORTED_NO));
0203 
0204     // ---
0205 
0206     m_libraries = new QTreeWidgetItem(listView(), QStringList() << i18nc("@title", "Libraries"));
0207     listView()->addTopLevelItem(m_libraries);
0208 
0209 
0210     new QTreeWidgetItem(m_libraries, QStringList() <<
0211                         i18nc(CONTEXT, "Qt Framework") <<                   QLatin1String(qVersion()));
0212 
0213     new QTreeWidgetItem(m_libraries, QStringList() <<
0214                         i18nc(CONTEXT, "KDE Framework") <<                  QLatin1String(KXMLGUI_VERSION_STRING));
0215 
0216     new QTreeWidgetItem(m_libraries, QStringList() <<
0217                         i18nc(CONTEXT, "LibRaw") <<                         DRawDecoder::librawVersion());
0218 
0219 #ifdef HAVE_EIGEN3
0220     new QTreeWidgetItem(m_libraries, QStringList() <<
0221                         i18nc(CONTEXT, "Eigen") <<                          QLatin1String(EIGEN3_VERSION_STRING));
0222 #else
0223     new QTreeWidgetItem(m_features, QStringList() <<
0224                         i18nc(CONTEXT, "Eigen support") <<                  SUPPORTED_NO);
0225 #endif
0226 
0227 #ifdef HAVE_QWEBENGINE
0228     new QTreeWidgetItem(m_libraries, QStringList() <<
0229                         i18nc(CONTEXT, "Qt WebEngine version") <<           QLatin1String(QTWEBENGINEWIDGETS_VERSION_STR));
0230 #else
0231     new QTreeWidgetItem(m_libraries, QStringList() <<
0232                         i18nc(CONTEXT, "Qt WebKit version") <<              QLatin1String(QTWEBKITWIDGETS_VERSION_STR));
0233 #endif
0234 
0235 #ifdef HAVE_QMULTIMEDIA
0236     new QTreeWidgetItem(m_features, QStringList() <<
0237                         i18nc(CONTEXT, "Qt Multimedia support") <<          SUPPORTED_YES);
0238 #else
0239     new QTreeWidgetItem(m_features, QStringList() <<
0240                         i18nc(CONTEXT, "Qt Multimedia support") <<          SUPPORTED_YES);
0241 #endif
0242 
0243     new QTreeWidgetItem(m_libraries, QStringList() <<
0244                         i18nc(CONTEXT, "Exiv2") <<                          MetaEngine::Exiv2Version());
0245 
0246     ExifToolParser* const parser = new ExifToolParser(this);
0247     ExifToolParser::ExifToolData parsed;
0248 
0249     if (parser->version())
0250     {
0251         parsed            = parser->currentData();
0252         QString etVersion = parsed.find(QLatin1String("VERSION_STRING")).value()[0].toString();
0253         new QTreeWidgetItem(m_libraries, QStringList() <<
0254                             i18nc(CONTEXT, "ExifTool") <<                   etVersion);
0255     }
0256     else
0257     {
0258         new QTreeWidgetItem(m_features, QStringList() <<
0259                             i18nc(CONTEXT, "ExifTool support") <<           SUPPORTED_NO);
0260     }
0261 
0262 #ifdef HAVE_LENSFUN
0263     new QTreeWidgetItem(m_libraries, QStringList() <<
0264                         i18nc(CONTEXT, "LensFun") <<                        LensFunIface::lensFunVersion());
0265 #else
0266     new QTreeWidgetItem(m_features, QStringList() <<
0267                         i18nc(CONTEXT, "LensFun support") <<                SUPPORTED_NO);
0268 #endif
0269 
0270 #ifdef HAVE_IMAGE_MAGICK
0271     new QTreeWidgetItem(m_libraries, QStringList() <<
0272                         i18nc(CONTEXT, "ImageMagick codecs") <<             QLatin1String(MagickLibVersionText));
0273 #else
0274     new QTreeWidgetItem(m_features, QStringList() <<
0275                         i18nc(CONTEXT, "ImageMagick codecs support") <<     SUPPORTED_NO);
0276 #endif
0277 
0278 #ifdef HAVE_HEIF
0279     new QTreeWidgetItem(m_libraries, QStringList() <<
0280                         i18nc(CONTEXT, "LibHEIF") <<                        QLatin1String(LIBHEIF_VERSION));
0281     new QTreeWidgetItem(m_features, QStringList() <<
0282                         i18nc(CONTEXT, "HEIF reading support") <<           SUPPORTED_YES);
0283 #else
0284     new QTreeWidgetItem(m_features, QStringList() <<
0285                         i18nc(CONTEXT, "HEIF reading support") <<           SUPPORTED_NO);
0286 #endif
0287 
0288 #ifdef HAVE_X265
0289     const x265_api* const x265api = x265_api_get(0);
0290 
0291     new QTreeWidgetItem(m_libraries, QStringList() <<
0292                         i18nc(CONTEXT, "Libx265") <<             (x265api ? QLatin1String(x265api->version_str)
0293                                                                           : i18nc("@info: version", "Unknown")));
0294     new QTreeWidgetItem(m_features, QStringList() <<
0295                         i18nc(CONTEXT, "HEIF writing support") <<           SUPPORTED_YES);
0296 #else
0297     new QTreeWidgetItem(m_features, QStringList() <<
0298                         i18nc(CONTEXT, "HEIF Writing support") <<           SUPPORTED_NO);
0299 #endif
0300 
0301     QString tiffver = QLatin1String(TIFFLIB_VERSION_STR);
0302     tiffver         = tiffver.left(tiffver.indexOf(QLatin1Char('\n')));
0303     tiffver         = tiffver.section(QLatin1Char(' '), 2, 2);
0304     new QTreeWidgetItem(m_libraries, QStringList() <<
0305                         i18nc(CONTEXT, "LibTIFF") <<                        tiffver);
0306 
0307     new QTreeWidgetItem(m_libraries, QStringList() <<
0308                         i18nc(CONTEXT, "LibPNG") <<                         QLatin1String(PNG_LIBPNG_VER_STRING));
0309 
0310     new QTreeWidgetItem(m_libraries, QStringList() <<
0311                         i18nc(CONTEXT, "LibJPEG") <<                        QString::number(JPEG_LIB_VERSION));
0312 
0313     new QTreeWidgetItem(m_libraries, QStringList() <<
0314                         i18nc(CONTEXT, "LibCImg") <<                        GreycstorationFilter::cimgVersionString());
0315 
0316     new QTreeWidgetItem(m_libraries, QStringList() <<
0317                         i18nc(CONTEXT, "LibLCMS") <<                        QString::number(LCMS_VERSION));
0318 
0319     new QTreeWidgetItem(m_libraries, QStringList() <<
0320                         i18nc(CONTEXT, "LibPGF") <<                         PGFUtils::libPGFVersion());
0321 
0322     new QTreeWidgetItem(m_libraries, QStringList() <<
0323                         i18nc(CONTEXT, "XMP SDK") <<                        DNGWriter::xmpSdkVersion());
0324 
0325     new QTreeWidgetItem(m_libraries, QStringList() <<
0326                         i18nc(CONTEXT, "DNG SDK") <<                        DNGWriter::dngSdkVersion());
0327 
0328 #ifdef HAVE_JASPER
0329     new QTreeWidgetItem(m_libraries, QStringList() <<
0330                         i18nc(CONTEXT, "LibJasper") <<                      QLatin1String(jas_getversion()));
0331 #else
0332     new QTreeWidgetItem(m_features, QStringList() <<
0333                         i18nc(CONTEXT, "LibJasper support") <<              SUPPORTED_NO);
0334 #endif
0335 
0336 #ifdef HAVE_GEOLOCATION
0337     new QTreeWidgetItem(m_libraries, QStringList() <<
0338                         i18nc(CONTEXT, "Geolocation support") <<            SUPPORTED_YES);
0339 #else
0340     new QTreeWidgetItem(m_features, QStringList() <<
0341                         i18nc(CONTEXT, "Geolocation support") <<            SUPPORTED_NO);
0342 #endif
0343 
0344 #ifdef HAVE_SONNET
0345 
0346     new QTreeWidgetItem(m_features, QStringList() <<
0347                         i18nc(CONTEXT, "Spell-Checking support") <<         SUPPORTED_YES);
0348 
0349 #else
0350 
0351     new QTreeWidgetItem(m_features, QStringList() <<
0352                         i18nc(CONTEXT, "Spell-Checking support") <<         SUPPORTED_NO);
0353 
0354 #endif
0355 
0356     int nbcore         = QThread::idealThreadCount();
0357     new QTreeWidgetItem(m_features, QStringList() <<
0358                         i18ncp(CONTEXT, "CPU core", "CPU cores", nbcore) << QString::fromLatin1("%1").arg(nbcore));
0359 
0360     KMemoryInfo memInfo;
0361 
0362     if (!memInfo.isNull())
0363     {
0364         quint64 available = memInfo.totalPhysical();
0365 
0366         if (available > 0)
0367         {
0368             new QTreeWidgetItem(m_features, QStringList() <<
0369                                 i18nc(CONTEXT, "Memory available") << ItemPropertiesTab::humanReadableBytesCount(available));
0370         }
0371         else
0372         {
0373             new QTreeWidgetItem(m_features, QStringList() <<
0374                                 i18nc(CONTEXT, "Memory available") << i18nc("@item: information about memory", "Unknown"));
0375         }
0376     }
0377 
0378     quint64 cacheSize = LoadingCache::cache()->getCacheSize();
0379 
0380     new QTreeWidgetItem(m_features, QStringList() <<
0381                         i18nc(CONTEXT, "Image cache size") << ItemPropertiesTab::humanReadableBytesCount(cacheSize));
0382 
0383     // NOTE: MANIFEST.txt is a text file generated with the bundles and listing all git revisions of rolling release components.
0384     //       One section title start with '+'.
0385     //       All component revisions are listed below line by line with the name and the revision separated by ':'.
0386     //       More than one section can be listed in manifest.
0387 
0388     const QString gitRevs = QStandardPaths::locate(QStandardPaths::AppDataLocation,
0389                                                    QLatin1String("MANIFEST.txt"));
0390 
0391     if (!gitRevs.isEmpty() && QFile::exists(gitRevs))
0392     {
0393         QFile file(gitRevs);
0394 
0395         if (!file.open(QIODevice::ReadOnly))
0396         {
0397             return;
0398         }
0399 
0400         qCDebug(DIGIKAM_WIDGETS_LOG) << "Git revisions manifest file found:" << gitRevs;
0401 
0402         QTreeWidgetItem* const manifestHead = new QTreeWidgetItem(listView(), QStringList() << i18nc("@item: component info", "Manifests"));
0403         listView()->addTopLevelItem(manifestHead);
0404 
0405         QTextStream in(&file);
0406         QTreeWidgetItem* manifestEntry = nullptr;
0407 
0408         while (!in.atEnd())
0409         {
0410             QString line = in.readLine();
0411 
0412             if (line.isEmpty())
0413             {
0414                 continue;
0415             }
0416 
0417             if      (line.startsWith(QLatin1Char('+')))
0418             {
0419                 manifestEntry = new QTreeWidgetItem(manifestHead, QStringList() << line.remove(QLatin1Char('+')));
0420             }
0421             else if (manifestEntry)
0422             {
0423                 new QTreeWidgetItem(manifestEntry, line.split(QLatin1Char(':')));
0424             }
0425         }
0426 
0427         file.close();
0428     }
0429 
0430     QTreeWidgetItem* const opencvHead = new QTreeWidgetItem(listView(), QStringList() << i18nc("@item: opencv info", "OpenCV Configuration"));
0431     listView()->addTopLevelItem(opencvHead);
0432 
0433     // --- OpenCV::OpenCL features
0434 
0435     try
0436     {
0437         if (!cv::ocl::haveOpenCL() || !cv::ocl::useOpenCL())
0438         {
0439             new QTreeWidgetItem(opencvHead, QStringList() <<
0440                                 i18nc(CONTEXT, "OpenCL availability") << SUPPORTED_NO);
0441         }
0442         else
0443         {
0444             std::vector<cv::ocl::PlatformInfo> platforms;
0445             cv::ocl::getPlatfomsInfo(platforms);
0446 
0447             if (platforms.empty())
0448             {
0449                 new QTreeWidgetItem(opencvHead, QStringList() <<
0450                                     i18nc(CONTEXT, "OpenCL availability") << SUPPORTED_NO);
0451 
0452             }
0453             else
0454             {
0455                 QTreeWidgetItem* const oclplfrm = new QTreeWidgetItem(opencvHead, QStringList() << i18nc(CONTEXT, "OpenCL platform"));
0456 
0457                 for (size_t i = 0 ; i < platforms.size() ; i++)
0458                 {
0459                     const cv::ocl::PlatformInfo* platform = &platforms[i];
0460                     QTreeWidgetItem* const plfrm = new QTreeWidgetItem(oclplfrm, QStringList() << QString::fromStdString(platform->name()));
0461 
0462                     cv::ocl::Device current_device;
0463 
0464                     for (int j = 0 ; j < platform->deviceNumber() ; j++)
0465                     {
0466                         platform->getDevice(current_device, j);
0467                         QString deviceTypeStr = openCVGetDeviceTypeString(current_device);
0468 
0469                         new QTreeWidgetItem(plfrm, QStringList()
0470                             << deviceTypeStr << QString::fromStdString(current_device.name()) +
0471                                QLatin1String(" (") + QString::fromStdString(current_device.version()) + QLatin1Char(')'));
0472                     }
0473                 }
0474 
0475                 const cv::ocl::Device& device = cv::ocl::Device::getDefault();
0476 
0477                 if (!device.available())
0478                 {
0479                     new QTreeWidgetItem(opencvHead, QStringList() <<
0480                                         i18nc(CONTEXT, "OpenCL device") << SUPPORTED_NO);
0481                 }
0482                 else
0483                 {
0484                     QTreeWidgetItem* const ocldev = new QTreeWidgetItem(opencvHead, QStringList() << i18nc(CONTEXT, "OpenCL Device"));
0485                     QString deviceTypeStr         = openCVGetDeviceTypeString(device);
0486 
0487                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Type")                       << deviceTypeStr);
0488                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Name")                       << QString::fromStdString(device.name()));
0489                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Version")                    << QString::fromStdString(device.version()));
0490                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Driver version")             << QString::fromStdString(device.driverVersion()));
0491                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Address bits")               << QString::number(device.addressBits()));
0492                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Compute units")              << QString::number(device.maxComputeUnits()));
0493                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Max work group size")        << QString::number(device.maxWorkGroupSize()));
0494 
0495                     QString localMemorySizeStr = openCVBytesToStringRepr(device.localMemSize());
0496                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Local memory size")          << localMemorySizeStr);
0497 
0498                     QString maxMemAllocSizeStr = openCVBytesToStringRepr(device.maxMemAllocSize());
0499                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Max memory allocation size") << maxMemAllocSizeStr);
0500 
0501                     QString doubleSupportStr = (device.doubleFPConfig() > 0) ? SUPPORTED_YES : SUPPORTED_NO;
0502                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Double support")             << doubleSupportStr);
0503 
0504                     QString halfSupportStr = (device.halfFPConfig() > 0) ? SUPPORTED_YES : SUPPORTED_NO;
0505                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Half support")               << halfSupportStr);
0506 
0507                     QString isUnifiedMemoryStr = device.hostUnifiedMemory() ? SUPPORTED_YES : SUPPORTED_NO;
0508                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Host unified memory")        << isUnifiedMemoryStr);
0509 
0510                     QString haveAmdBlasStr = cv::ocl::haveAmdBlas() ? SUPPORTED_YES : SUPPORTED_NO;
0511                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Has AMD Blas")                  << haveAmdBlasStr);
0512 
0513                     QString haveAmdFftStr  = cv::ocl::haveAmdFft() ? SUPPORTED_YES : SUPPORTED_NO;
0514                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Has AMD Fft")                   << haveAmdFftStr);
0515                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Preferred vector width char")   << QString::number(device.preferredVectorWidthChar()));
0516                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Preferred vector width short")  << QString::number(device.preferredVectorWidthShort()));
0517                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Preferred vector width int")    << QString::number(device.preferredVectorWidthInt()));
0518                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Preferred vector width long")   << QString::number(device.preferredVectorWidthLong()));
0519                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Preferred vector width float")  << QString::number(device.preferredVectorWidthFloat()));
0520                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Preferred vector width double") << QString::number(device.preferredVectorWidthDouble()));
0521                     new QTreeWidgetItem(ocldev, QStringList() << i18nc(CONTEXT, "Preferred vector width half")   << QString::number(device.preferredVectorWidthHalf()));
0522 
0523                     QTreeWidgetItem* const ocldevext = new QTreeWidgetItem(opencvHead, QStringList() << i18nc(CONTEXT, "OpenCL Device extensions"));
0524                     QString extensionsStr            = QString::fromStdString(device.extensions());
0525                     int pos                          = 0;
0526 
0527                     while (pos < extensionsStr.size())
0528                     {
0529                         int pos2 = extensionsStr.indexOf(QLatin1Char(' '), pos);
0530 
0531                         if (pos2 == -1)
0532                         {
0533                             pos2 = extensionsStr.size();
0534                         }
0535 
0536                         if (pos2 > pos)
0537                         {
0538                             QString extensionName = extensionsStr.mid(pos, pos2 - pos);
0539                             new QTreeWidgetItem(ocldevext, QStringList() << extensionName << SUPPORTED_YES);
0540                         }
0541 
0542                         pos = pos2 + 1;
0543                     }
0544                 }
0545             }
0546         }
0547     }
0548     catch (...)
0549     {
0550         new QTreeWidgetItem(opencvHead, QStringList() << i18nc(CONTEXT, "OpenCL availability") << SUPPORTED_NO);
0551     }
0552 
0553     // --- OpenCV::Hardware features
0554 
0555     try
0556     {
0557         QTreeWidgetItem* const ocvhdw = new QTreeWidgetItem(opencvHead, QStringList() << i18nc(CONTEXT, "Hardware features"));
0558         int count                     = 0;
0559 
0560         for (int i = 0 ; i < CV_HARDWARE_MAX_FEATURE ; i++)
0561         {
0562             QString name = QString::fromStdString(cv::getHardwareFeatureName(i));
0563 
0564             if (name.isEmpty())
0565             {
0566                 continue;
0567             }
0568 
0569             bool enabled = cv::checkHardwareSupport(i);
0570 
0571             if (enabled)
0572             {
0573                 count++;
0574                 new QTreeWidgetItem(ocvhdw, QStringList() << name << (enabled ? SUPPORTED_YES : SUPPORTED_NO));
0575             }
0576         }
0577     }
0578     catch (...)
0579     {
0580         new QTreeWidgetItem(opencvHead, QStringList() << i18nc(CONTEXT, "Hardware features availability") << SUPPORTED_NO);
0581     }
0582 
0583     // --- OpenCV::Threads features
0584 
0585     try
0586     {
0587         QTreeWidgetItem* const ocvthreads = new QTreeWidgetItem(opencvHead, QStringList() << i18nc(CONTEXT, "Threads features"));
0588 
0589         QString parallelFramework = QString::fromStdString(cv::currentParallelFramework());
0590 
0591         if (!parallelFramework.isEmpty())
0592         {
0593             new QTreeWidgetItem(ocvthreads, QStringList() << i18nc(CONTEXT, "Number of Threads") << QString::number(cv::getNumThreads()));
0594             new QTreeWidgetItem(ocvthreads, QStringList() << i18nc(CONTEXT, "Parallel framework") << parallelFramework);
0595         }
0596     }
0597     catch (...)
0598     {
0599         new QTreeWidgetItem(opencvHead, QStringList() << i18nc(CONTEXT, "Threads features availability") << SUPPORTED_NO);
0600     }
0601 }
0602 
0603 LibsInfoDlg::~LibsInfoDlg()
0604 {
0605 }
0606 
0607 QString LibsInfoDlg::checkTriState(int value) const
0608 {
0609     switch (value)
0610     {
0611         case true:
0612         {
0613             return i18nc("@info: tri state", "Yes");
0614         }
0615 
0616         case false:
0617         {
0618             return i18nc("@info: tri state", "No");
0619         }
0620 
0621         default:
0622         {
0623             return i18nc("@info: tri state", "Unknown");
0624         }
0625     }
0626 }
0627 
0628 QString LibsInfoDlg::openCVBytesToStringRepr(size_t value) const
0629 {
0630     size_t b = value % 1024;
0631     value /= 1024;
0632 
0633     size_t kb = value % 1024;
0634     value /= 1024;
0635 
0636     size_t mb = value % 1024;
0637     value /= 1024;
0638 
0639     size_t gb = value;
0640 
0641     QString s;
0642     QTextStream stream(&s);
0643 
0644     if (gb > 0)
0645     {
0646         stream << gb << " GB ";
0647     }
0648 
0649     if (mb > 0)
0650     {
0651         stream << mb << " MB ";
0652     }
0653 
0654     if (kb > 0)
0655     {
0656         stream << kb << " KB ";
0657     }
0658 
0659     if (b > 0)
0660     {
0661         stream << b << " B";
0662     }
0663 
0664     if (s[s.size() - 1] == QLatin1Char(' '))
0665     {
0666         s = s.mid(0, s.size() - 1);
0667     }
0668 
0669     return s;
0670 }
0671 
0672 QString LibsInfoDlg::openCVGetDeviceTypeString(const cv::ocl::Device& device)
0673 {
0674     if (device.type() == cv::ocl::Device::TYPE_CPU)
0675     {
0676         return QLatin1String("CPU");
0677     }
0678 
0679     if (device.type() == cv::ocl::Device::TYPE_GPU)
0680     {
0681         if (device.hostUnifiedMemory())
0682         {
0683             return QLatin1String("iGPU");
0684         }
0685         else
0686         {
0687             return QLatin1String("dGPU");
0688         }
0689     }
0690 
0691     return QLatin1String("unknown");
0692 }
0693 
0694 } // namespace Digikam
0695 
0696 #include "moc_libsinfodlg.cpp"