File indexing completed on 2024-05-05 17:33:19

0001 /*
0002  *   SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
0003  *
0004  *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 // Own includes
0008 #include "CategoryModel.h"
0009 #include "CategoriesReader.h"
0010 #include "libdiscover_debug.h"
0011 #include <QCollator>
0012 #include <resources/ResourcesModel.h>
0013 #include <utils.h>
0014 
0015 CategoryModel::CategoryModel(QObject *parent)
0016     : QObject(parent)
0017 {
0018     QTimer *t = new QTimer(this);
0019     t->setInterval(0);
0020     t->setSingleShot(true);
0021     connect(t, &QTimer::timeout, this, &CategoryModel::populateCategories);
0022     connect(ResourcesModel::global(), &ResourcesModel::backendsChanged, t, QOverload<>::of(&QTimer::start));
0023 
0024     // Use a timer so to compress the rootCategoriesChanged signal
0025     // It generally triggers when KNS is unavailable at large (as explained in bug 454442)
0026     m_rootCategoriesChanged = new QTimer(this);
0027     m_rootCategoriesChanged->setInterval(0);
0028     m_rootCategoriesChanged->setSingleShot(true);
0029     connect(m_rootCategoriesChanged, &QTimer::timeout, this, &CategoryModel::rootCategoriesChanged);
0030     if (!ResourcesModel::global()->backends().isEmpty()) {
0031         populateCategories();
0032     }
0033 }
0034 
0035 CategoryModel *CategoryModel::global()
0036 {
0037     static CategoryModel *instance = nullptr;
0038     if (!instance) {
0039         instance = new CategoryModel;
0040     }
0041     return instance;
0042 }
0043 
0044 void CategoryModel::populateCategories()
0045 {
0046     const auto backends = ResourcesModel::global()->backends();
0047 
0048     QVector<Category *> ret;
0049     CategoriesReader cr;
0050     for (const auto backend : backends) {
0051         if (!backend->isValid())
0052             continue;
0053 
0054         const QVector<Category *> cats = cr.loadCategoriesFile(backend);
0055 
0056         if (ret.isEmpty()) {
0057             ret = cats;
0058         } else {
0059             for (Category *c : cats)
0060                 Category::addSubcategory(ret, c);
0061         }
0062     }
0063     if (m_rootCategories != ret) {
0064         m_rootCategories = ret;
0065         m_rootCategoriesChanged->start();
0066     }
0067 }
0068 
0069 QVariantList CategoryModel::rootCategoriesVL() const
0070 {
0071     return kTransform<QVariantList>(m_rootCategories, [](Category *cat) {
0072         return QVariant::fromValue<QObject *>(cat);
0073     });
0074 }
0075 
0076 void CategoryModel::blacklistPlugin(const QString &name)
0077 {
0078     const bool ret = Category::blacklistPluginsInVector({name}, m_rootCategories);
0079     if (ret) {
0080         m_rootCategoriesChanged->start();
0081     }
0082 }
0083 
0084 static Category *recFindCategory(Category *root, const QString &name)
0085 {
0086     if (root->untranslatedName() == name)
0087         return root;
0088     else {
0089         const auto subs = root->subCategories();
0090         for (Category *c : subs) {
0091             Category *ret = recFindCategory(c, name);
0092             if (ret)
0093                 return ret;
0094         }
0095     }
0096     return nullptr;
0097 }
0098 
0099 Category *CategoryModel::findCategoryByName(const QString &name) const
0100 {
0101     for (Category *cat : m_rootCategories) {
0102         Category *ret = recFindCategory(cat, name);
0103         if (ret)
0104             return ret;
0105     }
0106     if (!m_rootCategories.isEmpty()) {
0107         qDebug() << "could not find category" << name << m_rootCategories;
0108     }
0109     return nullptr;
0110 }