File indexing completed on 2024-04-21 05:45:05

0001 /***************************************************************************
0002  *   Copyright (C) 2010 by Daniel Nicoletti <dantti12@gmail.com>           *
0003  *   Copyright (C) 2012-2013 by Matthias Klumpp <matthias@tenstral.net>    *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or         *
0006  *   modify it under the terms of the GNU General Public License as        *
0007  *   published by the Free Software Foundation; either version 2 of        *
0008  *   the License or (at your option) version 3 or any later version        *
0009  *   accepted by the membership of KDE e.V. (or its successor approved     *
0010  *   by the membership of KDE e.V.), which shall act as a proxy            *
0011  *   defined in Section 14 of version 3 of the license.                    *
0012  *                                                                         *
0013  *   This program is distributed in the hope that it will be useful,       *
0014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0016  *   GNU General Public License for more details.                          *
0017  *                                                                         *
0018  *   You should have received a copy of the GNU General Public License     *
0019  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
0020  ***************************************************************************/
0021 
0022 #include <config.h>
0023 
0024 #include <optional>
0025 #include <AppStreamQt5/pool.h>
0026 #include <AppStreamQt5/icon.h>
0027 #include <AppStreamQt5/image.h>
0028 #include <AppStreamQt5/screenshot.h>
0029 
0030 #include "AppStream.h"
0031 
0032 #include <QApplication>
0033 #include <QLoggingCategory>
0034 
0035 Q_DECLARE_LOGGING_CATEGORY(APPER_LIB)
0036 
0037 AppStreamHelper* AppStreamHelper::m_instance = 0;
0038 
0039 AppStreamHelper* AppStreamHelper::instance()
0040 {
0041     if(!m_instance) {
0042         m_instance = new AppStreamHelper(qApp);
0043         m_instance->open();
0044     }
0045 
0046     return m_instance;
0047 }
0048 
0049 AppStreamHelper::AppStreamHelper(QObject *parent)
0050  : QObject(parent)
0051 {
0052 #ifdef HAVE_APPSTREAM
0053     // create new AppStream metadata pool
0054     m_pool = new AppStream::Pool(this);
0055 #endif //HAVE_APPSTREAM
0056 }
0057 
0058 AppStreamHelper::~AppStreamHelper()
0059 {
0060 }
0061 
0062 bool AppStreamHelper::open()
0063 {
0064 #ifdef HAVE_APPSTREAM    
0065     QString error;
0066     if (!m_pool->load()) {
0067         qCWarning(APPER_LIB) << "Unable to open AppStream metadata pool:" << m_pool->lastError();
0068         return false;
0069     }
0070 
0071 //    // cache application data (we should actually search the data directly via as_pool_search()...)
0072 //    auto cptArray = as_pool_get_components(m_pool);
0073 //    if (cptArray == NULL) {
0074 //        qWarning("AppStream application array way NULL! (This should never happen)");
0075 //        return false;
0076 //    }
0077 
0078 //    for (uint i = 0; i < cptArray->len; i++) {
0079 //        auto cpt = AS_COMPONENT (g_ptr_array_index(cptArray, i));
0080 //        // we only want apps at time
0081 //        auto cptKind = as_component_get_kind (cpt);
0082 //        if ((cptKind != AS_COMPONENT_KIND_DESKTOP_APP) &&
0083 //            (cptKind != AS_COMPONENT_KIND_CONSOLE_APP) &&
0084 //            (cptKind != AS_COMPONENT_KIND_WEB_APP))
0085 //            continue;
0086 
0087 //        Application app;
0088 //        // Application name
0089 //        app.name = QString::fromUtf8(as_component_get_name(cpt));
0090 
0091 //        // Package name
0092 //        auto pkgnameC = as_component_get_pkgname(cpt);
0093 //        QString pkgName;
0094 //        if (pkgnameC != NULL)
0095 //            pkgName = QString::fromUtf8(pkgnameC);
0096 
0097 //        // Desktop file
0098 //        app.id = QString::fromUtf8(as_component_get_id(cpt));
0099 
0100 //        // Summary
0101 //        app.summary = QString::fromUtf8(as_component_get_summary(cpt));
0102 
0103 //        // Description
0104 //        app.description = QString::fromUtf8(as_component_get_description(cpt));
0105 
0106 //        // Application stock icon
0107 //        auto icons = as_component_get_icons(cpt);
0108 //        for (uint i = 0; i < icons->len; i++) {
0109 //            auto icon = AS_ICON (g_ptr_array_index (icons, i));
0110 //            if (as_icon_get_kind (icon) != AS_ICON_KIND_STOCK)
0111 //                 app.icon_url = QString::fromUtf8(as_icon_get_filename (icon));
0112 //        }
0113 
0114 //        // Application categories
0115 //        app.categories = QStringList();
0116 //        auto cats = as_component_get_categories(cpt);
0117 //        for (uint i = 0; i < cats->len; i++) {
0118 //            auto category = (const gchar*) g_ptr_array_index (cats, i);
0119 //            app.categories << QString::fromUtf8(category);
0120 //        }
0121 
0122 //        // add default screenshot urls
0123 //        auto scrs = as_component_get_screenshots (cpt);
0124 
0125 //        // find default screenshot, if possible (otherwise we get a random one)
0126 //        AsScreenshot *scr = NULL;
0127 //        for (uint i = 0; i < scrs->len; i++) {
0128 //            scr = AS_SCREENSHOT (g_ptr_array_index (scrs, i));
0129 //            if (as_screenshot_get_kind (scr) == AS_SCREENSHOT_KIND_DEFAULT)
0130 //                break;
0131 //        }
0132 
0133 //        if (scr != NULL) {
0134 //            auto imgs = as_screenshot_get_images (scr);
0135 //            for (uint i = 0; i < imgs->len; i++) {
0136 //                auto img = AS_IMAGE (g_ptr_array_index (imgs, i));
0137 //                if ((as_image_get_kind (img) == AS_IMAGE_KIND_SOURCE) && (app.screenshot.isEmpty())) {
0138 //                    app.screenshot = QString::fromUtf8(as_image_get_url (img));
0139 //                } else if ((as_image_get_kind (img) == AS_IMAGE_KIND_THUMBNAIL) && (app.thumbnail.isEmpty())) {
0140 //                    app.thumbnail = QString::fromUtf8(as_image_get_url (img));
0141 //                }
0142 
0143 //                if ((!app.screenshot.isEmpty()) && (!app.thumbnail.isEmpty()))
0144 //                    break;
0145 //            }
0146 //        }
0147 
0148 //        m_appInfo.insertMulti(pkgName, app);
0149 //    }
0150 
0151     auto apps = m_pool->componentsByKind(AppStream::Component::KindDesktopApp);
0152     for (const AppStream::Component &app : apps) {
0153         const QStringList pkgNames = app.packageNames();
0154         for (const QString &pkgName : pkgNames) {
0155             m_appInfo.insertMulti(pkgName, app);
0156         }
0157     }
0158 
0159     return true;
0160 #else
0161     return false;
0162 #endif
0163 }
0164 
0165 QList<AppStream::Component> AppStreamHelper::applications(const QString &pkgName) const
0166 {
0167     return m_appInfo.values(pkgName);
0168 }
0169 
0170 QString AppStreamHelper::genericIcon(const QString &pkgName) const
0171 {
0172     if (m_appInfo.contains(pkgName)) {
0173 //        const QList<AppStream::Component> apps = applications(pkgName);
0174 //        for (const AppStream::Component &app : apps) {
0175 //            if (!app.icon_url.isEmpty()) {
0176 //                return app.icon_url;
0177 //            }
0178 //        }
0179     }
0180 
0181     return QString();
0182 }
0183 
0184 QStringList AppStreamHelper::findPkgNames(const CategoryMatcher &/*parser*/) const
0185 {
0186     QStringList packages;
0187 
0188 //    QHash<QString, Application>::const_iterator i = m_appInfo.constBegin();
0189 //    while (i != m_appInfo.constEnd()) {
0190 //        if (parser.match(i.value().categories)) {
0191 ////            kDebug() << i.key() << categories;
0192 //            packages << i.key();
0193 //        }
0194 //        ++i;
0195 //    }
0196 
0197     return packages;
0198 }
0199 
0200 QUrl AppStreamHelper::thumbnail(const QString &pkgName) const
0201 {
0202     QUrl url;
0203 #ifdef HAVE_APPSTREAM
0204     if (m_appInfo.contains(pkgName)) {
0205         AppStream::Image thumb;
0206         AppStream::Component cpt = m_appInfo.value(pkgName);
0207         const QList<AppStream::Screenshot> screenshots = cpt.screenshotsAll();
0208         for (const AppStream::Screenshot &screenshot : screenshots) {
0209             const QList<AppStream::Image> images = screenshot.images();
0210             for (const AppStream::Image &image : images) {
0211                 if (image.kind() == AppStream::Image::KindThumbnail) {
0212                     if (thumb.kind() == AppStream::Image::KindUnknown || image.size().height() < thumb.size().height()) {
0213                         thumb = image;
0214                         url = image.url();
0215                     }
0216                 }
0217             }
0218 
0219             if (screenshot.isDefault() && !url.isEmpty()) {
0220                 break;
0221             }
0222         }
0223     }
0224 
0225     return url;
0226 #else
0227     Q_UNUSED(pkgName)
0228     return url;
0229 #endif //HAVE_APPSTREAM
0230 }
0231 
0232 QUrl AppStreamHelper::screenshot(const QString &pkgName) const
0233 {
0234     QUrl url;
0235 #ifdef HAVE_APPSTREAM
0236     if (m_appInfo.contains(pkgName)) {
0237         AppStream::Component cpt = m_appInfo.value(pkgName);
0238         const QList<AppStream::Screenshot> screenshots = cpt.screenshotsAll();
0239         for (const AppStream::Screenshot &screenshot : screenshots) {
0240             const QList<AppStream::Image> images = screenshot.images();
0241             for (const AppStream::Image &image : images) {
0242                 url = image.url();
0243                 break;
0244             }
0245 
0246             if (screenshot.isDefault() && !url.isEmpty()) {
0247                 break;
0248             }
0249         }
0250     }
0251 
0252 #else
0253     Q_UNUSED(pkgName)
0254 #endif //HAVE_APPSTREAM
0255     return url;
0256 }