File indexing completed on 2024-05-12 04:52:54

0001 /*
0002     SPDX-FileCopyrightText: 2021 Jean-Baptiste Mardelle
0003     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 
0006 #include "listdependencyparamwidget.h"
0007 #include "assets/model/assetparametermodel.hpp"
0008 #include "core.h"
0009 #include "mainwindow.h"
0010 
0011 #include <QDir>
0012 #include <QDomDocument>
0013 #include <QDomElement>
0014 #include <QStandardPaths>
0015 
0016 #include <kio_version.h>
0017 #if KIO_VERSION >= QT_VERSION_CHECK(5, 98, 0)
0018 #include <KIO/JobUiDelegateFactory>
0019 #else
0020 #include <KIO/JobUiDelegate>
0021 #endif
0022 #include <KIO/OpenUrlJob>
0023 
0024 ListDependencyParamWidget::ListDependencyParamWidget(std::shared_ptr<AssetParameterModel> model, QModelIndex index, QWidget *parent)
0025     : AbstractParamWidget(std::move(model), index, parent)
0026 {
0027     setupUi(this);
0028 
0029     // Get data from model
0030     QString comment = m_model->data(m_index, AssetParameterModel::CommentRole).toString();
0031 
0032     // setup the comment
0033     setToolTip(comment);
0034     m_infoMessage->hide();
0035     connect(m_infoMessage, &KMessageWidget::linkActivated, this, [this](const QString &contents) {
0036         auto *job = new KIO::OpenUrlJob(QUrl(contents));
0037 #if KIO_VERSION >= QT_VERSION_CHECK(5, 98, 0)
0038         job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this));
0039 #else
0040         job->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this));
0041 #endif
0042         // methods like setRunExecutables, setSuggestedFilename, setEnableExternalBrowser, setFollowRedirections
0043         // exist in both classes
0044         job->start();
0045     });
0046     setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
0047     m_list->setIconSize(QSize(50, 30));
0048     setMinimumHeight(m_list->sizeHint().height());
0049     // setup the name
0050     m_labelName->setText(m_model->data(m_index, Qt::DisplayRole).toString());
0051 
0052     QString dependencies = m_model->data(m_index, AssetParameterModel::ListDependenciesRole).toString();
0053     if (!dependencies.isEmpty()) {
0054         // We have conditionnal dependencies, some values in the list might not be available.
0055         QDomDocument doc;
0056         doc.setContent(dependencies);
0057         QDomNodeList deps = doc.elementsByTagName(QLatin1String("paramdependencies"));
0058         for (int i = 0; i < deps.count(); i++) {
0059             const QString modelName = deps.at(i).toElement().attribute(QLatin1String("value"));
0060             QString infoText = deps.at(i).toElement().text();
0061             const QString folder = deps.at(i).toElement().attribute(QLatin1String("folder"));
0062             if (!folder.isEmpty()) {
0063                 m_dependencyFiles.insert(modelName, {folder, deps.at(i).toElement().attribute(QLatin1String("files")).split(QLatin1Char(';'))});
0064                 QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + folder);
0065                 infoText.replace(QLatin1String("%folder"), dir.absolutePath());
0066             }
0067             m_dependencyInfos.insert(modelName, infoText);
0068         }
0069     }
0070 
0071     slotRefresh();
0072 
0073     // Q_EMIT the signal of the base class when appropriate
0074     connect(this->m_list, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this](int) {
0075         const QString val = m_list->itemData(m_list->currentIndex()).toString();
0076         Q_EMIT valueChanged(m_index, val, true);
0077         checkDependencies(val);
0078     });
0079 }
0080 
0081 void ListDependencyParamWidget::setCurrentIndex(int index)
0082 {
0083     m_list->setCurrentIndex(index);
0084 }
0085 
0086 void ListDependencyParamWidget::setCurrentText(const QString &text)
0087 {
0088     m_list->setCurrentText(text);
0089 }
0090 
0091 void ListDependencyParamWidget::addItem(const QString &text, const QVariant &value)
0092 {
0093     m_list->addItem(text, value);
0094 }
0095 
0096 void ListDependencyParamWidget::setItemIcon(int index, const QIcon &icon)
0097 {
0098     m_list->setItemIcon(index, icon);
0099 }
0100 
0101 void ListDependencyParamWidget::setIconSize(const QSize &size)
0102 {
0103     m_list->setIconSize(size);
0104 }
0105 
0106 void ListDependencyParamWidget::slotShowComment(bool /*show*/) {}
0107 
0108 QString ListDependencyParamWidget::getValue()
0109 {
0110     return m_list->currentData().toString();
0111 }
0112 
0113 void ListDependencyParamWidget::checkDependencies(const QString &val)
0114 {
0115     bool missingDep = false;
0116     if (m_dependencyInfos.contains(val)) {
0117         // Check dependency
0118         if (m_dependencyFiles.contains(val)) {
0119             QPair<QString, QStringList> fileData = m_dependencyFiles.value(val);
0120             QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + fileData.first);
0121             if (fileData.first == QLatin1String("/opencvmodels")) {
0122                 m_model->setParameter(QStringLiteral("modelsfolder"), dir.absolutePath(), false);
0123             }
0124             for (const QString &file : qAsConst(fileData.second)) {
0125                 if (!dir.exists(file)) {
0126                     m_infoMessage->setText(m_dependencyInfos.value(val));
0127                     m_infoMessage->animatedShow();
0128                     setMinimumHeight(m_list->sizeHint().height() + m_infoMessage->sizeHint().height());
0129                     Q_EMIT updateHeight();
0130                     missingDep = true;
0131                     break;
0132                 }
0133             }
0134         }
0135     }
0136     if (!missingDep) {
0137         m_infoMessage->hide();
0138         setMinimumHeight(m_list->sizeHint().height());
0139         Q_EMIT updateHeight();
0140     }
0141 }
0142 
0143 void ListDependencyParamWidget::slotRefresh()
0144 {
0145     const QSignalBlocker bk(m_list);
0146     m_list->clear();
0147     QStringList names = m_model->data(m_index, AssetParameterModel::ListNamesRole).toStringList();
0148     QStringList values = m_model->data(m_index, AssetParameterModel::ListValuesRole).toStringList();
0149     QString value = m_model->data(m_index, AssetParameterModel::ValueRole).toString();
0150     if (value != m_lastProcessedAlgo) {
0151         // Ensure dependencies are met
0152         checkDependencies(value);
0153     }
0154     m_lastProcessedAlgo = value;
0155     if (values.first() == QLatin1String("%lumaPaths")) {
0156         // Special case: Luma files
0157         // Create thumbnails
0158         if (pCore->getCurrentFrameSize().width() > 1000) {
0159             // HD project
0160             values = MainWindow::m_lumaFiles.value(QStringLiteral("16_9"));
0161         } else if (pCore->getCurrentFrameSize().height() > 1000) {
0162             values = MainWindow::m_lumaFiles.value(QStringLiteral("9_16"));
0163         } else if (pCore->getCurrentFrameSize().height() == pCore->getCurrentFrameSize().width()) {
0164             values = MainWindow::m_lumaFiles.value(QStringLiteral("square"));
0165         } else if (pCore->getCurrentFrameSize().height() == 480) {
0166             values = MainWindow::m_lumaFiles.value(QStringLiteral("NTSC"));
0167         } else {
0168             values = MainWindow::m_lumaFiles.value(QStringLiteral("PAL"));
0169         }
0170         m_list->addItem(i18n("None (Dissolve)"));
0171         for (int j = 0; j < values.count(); ++j) {
0172             const QString &entry = values.at(j);
0173             const QString name = values.at(j).section(QLatin1Char('/'), -1);
0174             m_list->addItem(pCore->nameForLumaFile(name), entry);
0175             if (!entry.isEmpty() && (entry.endsWith(QLatin1String(".png")) || entry.endsWith(QLatin1String(".pgm")))) {
0176                 if (MainWindow::m_lumacache.contains(entry)) {
0177                     m_list->setItemIcon(j + 1, QPixmap::fromImage(MainWindow::m_lumacache.value(entry)));
0178                 }
0179             }
0180         }
0181         if (!value.isEmpty() && values.contains(value)) {
0182             m_list->setCurrentIndex(values.indexOf(value) + 1);
0183         }
0184     } else {
0185         if (names.count() != values.count()) {
0186             names = values;
0187         }
0188         for (int i = 0; i < names.count(); i++) {
0189             m_list->addItem(names.at(i), values.at(i));
0190         }
0191         if (!value.isEmpty()) {
0192             int ix = m_list->findData(value);
0193             if (ix > -1) {
0194                 m_list->setCurrentIndex(ix);
0195             }
0196         }
0197     }
0198 }