// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. // SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "themeappicon.h" #include "imageutil.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include ThemeAppIcon::ThemeAppIcon() { } ThemeAppIcon::~ThemeAppIcon() { } /** * @brief ThemeAppIcon::getIcon 根据传入的\a name 参数重新从系统主题中获取一次图标 * @param name 图标名 * @return 获取到的图标 * @note 只有在正常查找图标失败时,才走这个逻辑,如果直接使用QIcon::fromTheme可以获取到图标,是没必要的 */ QIcon ThemeAppIcon::getIcon(const QString &name) { //TODO 这里找图标会耗时,界面轻微卡顿,后面有时间可以放到AppItem里面,单独开启线程去查找 QProcess process; process.start("qtxdg-iconfinder", QStringList() << name); process.closeWriteChannel(); process.waitForFinished(); int exitCode = process.exitCode(); QString outputTxt = process.readAllStandardOutput(); auto list = outputTxt.split("\n"); if (exitCode != 0 || list.size() <= 3) return QIcon::fromTheme(name); // 去掉无用数据 list.removeFirst(); list.removeLast(); list.removeLast(); for (auto &s : list) { s = s.simplified(); } return QIcon::fromTheme(list.first()); } bool ThemeAppIcon::getIcon(QPixmap &pix, const QString iconName, const int size, bool reObtain) { QString tmpName = iconName; QString key; QIcon icon; bool ret = true; // 把size改为小于size的最大偶数 :) const int s = int(size * qApp->devicePixelRatio()) & ~1; if (tmpName == "dde-calendar") { QString name = QStandardPaths::standardLocations(QStandardPaths::TempLocation).first() + "/" + QString::number(QDate::currentDate().year()) + "_" + QString::number(QDate::currentDate().dayOfYear()) + ".svg"; if (!createCalendarIcon(QDate::currentDate(), name)) { qWarning() << "file: "<< name << " ,create failed!"; } tmpName = name; } do { // load pixmap from our Cache if (tmpName.startsWith("data:image/")) { key = QCryptographicHash::hash(tmpName.toUtf8(), QCryptographicHash::Md5).toHex(); // FIXME(hualet): The cache can reduce memory usage, // that is ~2M on HiDPI enabled machine with 9 icons loaded, // but I don't know why since QIcon has its own cache and all of the // icons loaded are loaded by QIcon::fromTheme, really strange here. if (QPixmapCache::find(key, &pix)) break; } // load pixmap from Byte-Data if (tmpName.startsWith("data:image/")) { const QStringList strs = tmpName.split("base64,"); if (strs.size() == 2) pix.loadFromData(QByteArray::fromBase64(strs.at(1).toLatin1())); if (!pix.isNull()) break; } // load pixmap from File if (QFile::exists(tmpName)) { pix = QPixmap(tmpName); if (!pix.isNull()) break; } // 重新从主题中获取一次 // 如果此提交我们使用的qt版本已经包含,那就可以不需要reObtain的逻辑了 // https://codereview.qt-project.org/c/qt/qtbase/+/343396 if (reObtain) icon = getIcon(tmpName); else icon = QIcon::fromTheme(tmpName); if(icon.isNull()) { icon = QIcon::fromTheme("application-x-desktop"); ret = false; } // load pixmap from Icon-Theme const int fakeSize = std::max(48, s); // cannot use 16x16, cause 16x16 is label icon pix = icon.pixmap(QSize(fakeSize, fakeSize)); if (!pix.isNull()) break; // fallback to a Default pixmap pix = QPixmap(":/icons/resources/application-x-desktop.svg"); break; } while (false); if (!key.isEmpty()) { QPixmapCache::insert(key, pix); } if (pix.size().width() != s) { pix = pix.scaled(s, s, Qt::KeepAspectRatio, Qt::SmoothTransformation); } pix.setDevicePixelRatio(qApp->devicePixelRatio()); return ret; } bool ThemeAppIcon::createCalendarIcon(const QDate &date, const QString &fileName) { static const QByteArrayList &dayList= { "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" }; static const QByteArrayList &monthList= { "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n" }; static const QByteArrayList &weekList= { "\n" , "\n" , "\n" , "\n" , "\n" , "\n" , "\n"}; if (!QFile(fileName).exists()) { // create svg QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) return false; file.write(QByteArray("\n" "\n" " 0101\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n")); // 日期 file.write(" " + dayList.at(date.day() - 1)); file.write(QByteArray(" \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n")); // 右下角 file.write(QByteArray(" \n")); // 背景 file.write(QByteArray(" \n" " \n" " \n" " \n" " \n")); // 月份 file.write(" " + monthList.at(date.month() - 1)); // 日期 file.write(QByteArray(" \n" " \n" " \n" " \n" " \n")); // 星期 file.write(" " + weekList.at(date.dayOfWeek() - 1)); // 右下角 file.write(QByteArray(" \n" "")); file.close(); } return true; }