File indexing completed on 2024-05-05 04:53:42
0001 /* 0002 SPDX-FileCopyrightText: 2017 Nicolas Carion 0003 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 0006 #include "profiletreemodel.hpp" 0007 #include "../profilemodel.hpp" 0008 #include "../profilerepository.hpp" 0009 #include "abstractmodel/treeitem.hpp" 0010 0011 #include <KLocalizedString> 0012 #include <QIcon> 0013 #include <array> 0014 #include <functional> 0015 #include <vector> 0016 0017 ProfileTreeModel::ProfileTreeModel(QObject *parent) 0018 : AbstractTreeModel(parent) 0019 { 0020 } 0021 0022 std::shared_ptr<ProfileTreeModel> ProfileTreeModel::construct(QObject *parent) 0023 { 0024 std::shared_ptr<ProfileTreeModel> self(new ProfileTreeModel(parent)); 0025 QList<QVariant> rootData; 0026 rootData << "Description" 0027 << "Path" 0028 << "Height" 0029 << "Width" 0030 << "display_aspect_num" 0031 << "display_aspect_den" 0032 << "sample_aspect_ratio" 0033 << "fps" 0034 << "colorspace"; 0035 self->rootItem = TreeItem::construct(rootData, self, true); 0036 ProfileRepository::get()->refresh(); 0037 QVector<QPair<QString, QString>> profiles = ProfileRepository::get()->getAllProfiles(); 0038 0039 constexpr size_t nbCrit = 3; // number of criterion we check for profile classification 0040 0041 // helper lambda that creates a profile category with the given name 0042 auto createCat = [&](const QString &name) { return self->rootItem->appendChild(QList<QVariant>{name}); }; 0043 // We define the filters as a vector of pairs. The first element correspond to the tree item holding matching profiles, and the array correspond to the 0044 // filter itself 0045 std::vector<std::pair<std::shared_ptr<TreeItem>, std::array<QVariant, nbCrit>>> filters{ 0046 {createCat(i18n("5K (Wide 2160)")), {{5120, 2160, -1}}}, 0047 {createCat(i18n("4K UHD 2160")), {{3840, 2160, -1}}}, 0048 {createCat(i18n("4K DCI 2160")), {{4096, 2160, -1}}}, 0049 {createCat(i18n("2.5K QHD 1440")), {{-1, 1440, -1}}}, 0050 {createCat(i18n("Full HD 1080")), {{1920, 1080, -1}}}, 0051 {createCat(i18n("HD 720")), {{-1, 720, -1}}}, 0052 {createCat(i18n("SD/DVD")), {{720, QVariant::fromValue(QPair<int, int>{480, 576}), 4}}}, 0053 {createCat(i18n("SD/DVD Widescreen")), {{720, QVariant::fromValue(QPair<int, int>{480, 576}), 16}}}, 0054 }; 0055 0056 auto customCat = createCat(i18n("Custom")); 0057 // We define lambdas that controls how a given field should be filtered 0058 std::array<std::function<bool(QVariant, std::unique_ptr<ProfileModel> &)>, nbCrit> filtLambdas; 0059 filtLambdas[0] = [](const QVariant &width, std::unique_ptr<ProfileModel> &ptr) { return width == -1 || ptr->width() == width; }; 0060 filtLambdas[1] = [](const QVariant &height, std::unique_ptr<ProfileModel> &ptr) { 0061 if (height.canConvert<int>()) { 0062 return height.toInt() == -1 || ptr->height() == height.toInt(); 0063 } 0064 QPair<int, int> valid_values = height.value<QPair<int, int>>(); 0065 return ptr->height() == valid_values.first || ptr->height() == valid_values.second; 0066 }; 0067 filtLambdas[2] = [](const QVariant &display_aspect_num, std::unique_ptr<ProfileModel> &ptr) { 0068 return display_aspect_num == -1 || ptr->display_aspect_num() == display_aspect_num; 0069 }; 0070 for (const auto &profile : qAsConst(profiles)) { 0071 bool foundMatch = false; 0072 // we get a pointer to the profilemodel 0073 std::unique_ptr<ProfileModel> &ptr = ProfileRepository::get()->getProfile(profile.second); 0074 // we create the data list corresponding to this profile 0075 QList<QVariant> data; 0076 data << profile.first << profile.second << ptr->height() << ptr->width() << ptr->display_aspect_num() << ptr->display_aspect_den() << ptr->sar() 0077 << ptr->fps() << ProfileRepository::getColorspaceDescription(ptr->colorspace()); 0078 for (const auto &filter : filters) { 0079 bool matching = true; 0080 for (size_t i = 0; i < nbCrit && matching; ++i) { 0081 matching = filtLambdas[i](filter.second[i], ptr); 0082 } 0083 if (matching) { 0084 foundMatch = true; 0085 filter.first->appendChild(data); 0086 break; 0087 } 0088 } 0089 if (!foundMatch) { 0090 // no filter matched, we default to custom 0091 customCat->appendChild(data); 0092 } 0093 } 0094 return self; 0095 } 0096 0097 QVariant ProfileTreeModel::data(const QModelIndex &index, int role) const 0098 { 0099 if (!index.isValid()) { 0100 return QVariant(); 0101 } 0102 0103 auto item = getItemById(int(index.internalId())); 0104 if (role == Qt::DecorationRole) { 0105 if (item->depth() == 1) { 0106 return QIcon::fromTheme(QStringLiteral("folder")); 0107 } 0108 return QIcon::fromTheme(QStringLiteral("file")); 0109 } 0110 0111 if (role != Qt::DisplayRole) { 0112 return QVariant(); 0113 } 0114 return item->dataColumn(index.column()); 0115 } 0116 0117 QString ProfileTreeModel::getProfile(const QModelIndex &index) 0118 { 0119 if (index.isValid()) { 0120 auto item = getItemById(int(index.internalId())); 0121 if (item->depth() == 2) { 0122 return item->dataColumn(1).toString(); 0123 } 0124 } 0125 return QString(); 0126 } 0127 0128 QModelIndex ProfileTreeModel::findProfile(const QString &profile) 0129 { 0130 // we iterate over categories 0131 for (int i = 0; i < rootItem->childCount(); ++i) { 0132 // we iterate over profiles of the category 0133 std::shared_ptr<TreeItem> category = rootItem->child(i); 0134 for (int j = 0; j < category->childCount(); ++j) { 0135 // we retrieve profile path 0136 std::shared_ptr<TreeItem> child = category->child(j); 0137 QString path = child->dataColumn(1).toString(); 0138 if (path == profile) { 0139 return createIndex(j, 0, quintptr(child->getId())); 0140 } 0141 } 0142 } 0143 return {}; 0144 }