File indexing completed on 2024-04-14 04:53:13

0001 /* This file is part of the KDE project
0002     SPDX-FileCopyrightText: 2000 Carsten Pfeiffer <pfeiffer@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "konqpixmapprovider.h"
0008 
0009 #include <QMimeDatabase>
0010 #include <QMimeType>
0011 #include <QIcon>
0012 #include "konqdebug.h"
0013 
0014 #include <KIO/FavIconRequestJob>
0015 #include <kio/global.h>
0016 #include <kprotocolinfo.h>
0017 #include <kconfiggroup.h>
0018 #include <KIconLoader>
0019 
0020 class KonqPixmapProviderSingleton
0021 {
0022 public:
0023     KonqPixmapProvider self;
0024 };
0025 Q_GLOBAL_STATIC(KonqPixmapProviderSingleton, globalPixmapProvider)
0026 
0027 KonqPixmapProvider *KonqPixmapProvider::self()
0028 {
0029     return &globalPixmapProvider->self;
0030 }
0031 
0032 KonqPixmapProvider::KonqPixmapProvider()
0033     : QObject()
0034 {
0035 }
0036 
0037 KonqPixmapProvider::~KonqPixmapProvider()
0038 {
0039 }
0040 
0041 void KonqPixmapProvider::downloadHostIcon(const QUrl &hostUrl)
0042 {
0043     //Only attempt to download icon for http(s) URLs
0044     if (!hostUrl.scheme().startsWith(QLatin1String("http"))) {
0045         return;
0046     }
0047     KIO::FavIconRequestJob *job = new KIO::FavIconRequestJob(hostUrl);
0048     connect(job, &KIO::FavIconRequestJob::result, this, [job, this](KJob *) {
0049         bool modified = false;
0050         const QUrl _hostUrl = job->hostUrl();
0051         QMap<QUrl, QString>::iterator itEnd = iconMap.end();
0052         for (QMap<QUrl, QString>::iterator it = iconMap.begin(); it != itEnd; ++it) {
0053             const QUrl url(it.key());
0054             if (url.host() == _hostUrl.host()) {
0055                 // For host default-icons still query the favicon manager to get
0056                 // the correct icon for pages that have an own one.
0057                 const QString icon = KIO::favIconForUrl(url);
0058                 if (!icon.isEmpty() && *it != icon) {
0059                     *it = icon;
0060                     modified = true;
0061                 }
0062             }
0063         }
0064         if (modified) {
0065             emit changed();
0066         }
0067     });
0068 }
0069 
0070 void KonqPixmapProvider::setIconForUrl(const QUrl &hostUrl, const QUrl &iconUrl)
0071 {
0072     KIO::FavIconRequestJob *job = new KIO::FavIconRequestJob(hostUrl);
0073     job->setIconUrl(iconUrl);
0074     connect(job, &KIO::FavIconRequestJob::result, this, [job, this](KJob *) {
0075         bool modified = false;
0076         const QUrl _hostUrl = job->hostUrl();
0077         QMap<QUrl, QString>::iterator itEnd = iconMap.end();
0078         for (QMap<QUrl, QString>::iterator it = iconMap.begin(); it != itEnd; ++it) {
0079             const QUrl url(it.key());
0080             if (url.host() == _hostUrl.host() && url.path() == _hostUrl.path()) {
0081                 const QString icon = job->iconFile();
0082                 if (!icon.isEmpty() && *it != icon) {
0083                     *it = icon;
0084                     modified = true;
0085                 }
0086             }
0087         }
0088         if (modified) {
0089             emit changed();
0090         }
0091     });
0092 }
0093 
0094 // at first, tries to find the iconname in the cache
0095 // if not available, tries to find the pixmap for the mimetype of url
0096 // if that fails, gets the icon for the protocol
0097 // finally, inserts the url/icon pair into the cache
0098 QString KonqPixmapProvider::iconNameFor(const QUrl &url)
0099 {
0100     QMap<QUrl, QString>::iterator it = iconMap.find(url);
0101     QString icon;
0102     if (it != iconMap.end()) {
0103         icon = it.value();
0104         if (!icon.isEmpty()) {
0105             return icon;
0106         }
0107     }
0108 
0109     if (url.url().isEmpty()) {
0110         // Use the Konqueror icon for the empty URL
0111         icon = "konqueror";
0112     } else {
0113         icon = KIO::iconNameForUrl(url);
0114         Q_ASSERT(!icon.isEmpty());
0115     }
0116 
0117     // cache the icon found for url
0118     iconMap.insert(url, icon);
0119 
0120     return icon;
0121 }
0122 
0123 QPixmap KonqPixmapProvider::pixmapFor(const QString &url, int size)
0124 {
0125     return loadIcon(iconNameFor(QUrl::fromUserInput(url)), size);
0126 }
0127 
0128 void KonqPixmapProvider::load(KConfigGroup &kc, const QString &key)
0129 {
0130     iconMap.clear();
0131     const QStringList list = kc.readPathEntry(key, QStringList());
0132     QStringList::const_iterator it = list.begin();
0133     QStringList::const_iterator itEnd = list.end();
0134     while (it != itEnd) {
0135         const QString url(*it);
0136         if ((++it) == itEnd) {
0137             break;
0138         }
0139         const QString icon(*it);
0140         iconMap.insert(QUrl::fromUserInput(url), icon);
0141         ++it;
0142     }
0143 }
0144 
0145 // only saves the cache for the given list of items to prevent the cache
0146 // from growing forever.
0147 void KonqPixmapProvider::save(KConfigGroup &kc, const QString &key,
0148                               const QStringList &items)
0149 {
0150     QStringList list;
0151     QStringList::const_iterator itEnd = items.end();
0152     for (QStringList::const_iterator it = items.begin(); it != itEnd; ++it) {
0153         QMap<QUrl, QString>::const_iterator mit = iconMap.constFind(QUrl::fromUserInput(*it));
0154         if (mit != iconMap.constEnd()) {
0155             list.append(mit.key().url());
0156             list.append(mit.value());
0157         }
0158     }
0159     kc.writePathEntry(key, list);
0160 }
0161 
0162 void KonqPixmapProvider::clear()
0163 {
0164     iconMap.clear();
0165 }
0166 
0167 QPixmap KonqPixmapProvider::loadIcon(const QString &icon, int size)
0168 {
0169     if (size == 0) {
0170         size = KIconLoader::SizeSmall;
0171     }
0172     return QIcon::fromTheme(icon).pixmap(size);
0173 }
0174 
0175 QIcon KonqPixmapProvider::iconForUrl(const QUrl &url)
0176 {
0177     return QIcon::fromTheme(iconNameFor(url));
0178 }
0179 
0180 QIcon KonqPixmapProvider::iconForUrl(const QString &url_str)
0181 {
0182     return iconForUrl(QUrl::fromUserInput(url_str));
0183 }
0184