This commit is contained in:
Mike Gelfand
2025-11-06 05:12:15 +00:00
parent b27fafca45
commit 0231538d3c
6 changed files with 239 additions and 5 deletions

View File

@@ -11,6 +11,7 @@
#include <QIcon>
#include <QLibraryInfo>
#include <QMessageBox>
#include <QPluginLoader>
#include <QProcess>
#include <QRect>
#include <QSystemTrayIcon>
@@ -140,11 +141,15 @@ Application::Application(
loadTranslations();
initUnits();
auto const old_theme_name = QIcon::themeName();
QIcon::setThemeName(QStringLiteral("TrFontIcons"));
QIcon::setFallbackThemeName(old_theme_name);
#if defined(_WIN32) || defined(__APPLE__)
if (QIcon::themeName().isEmpty())
{
QIcon::setThemeName(QStringLiteral("Faenza"));
QIcon::setThemeName(FontIconEngine::isValidTheme() ? FontIconEngine::themeName() : QStringLiteral("Faenza"));
}
#endif
@@ -529,9 +534,10 @@ bool Application::notifyApp(QString const& title, QString const& body, QStringLi
args.append(title); // summary
args.append(body); // body
args.append(actions);
args.append(QVariantMap{ {
std::make_pair(QStringLiteral("category"), QVariant{ QStringLiteral("transfer.complete") }),
} }); // hints
args.append(
QVariantMap{ {
std::make_pair(QStringLiteral("category"), QVariant{ QStringLiteral("transfer.complete") }),
} }); // hints
args.append(static_cast<int32_t>(-1)); // use the default timeout period
m.setArguments(args);
QDBusReply<quint32> const reply_msg = bus.call(m);

View File

@@ -42,6 +42,9 @@ target_sources(${TR_NAME}-qt
FilterBarComboBoxDelegate.h
Filters.cc
Filters.h
FontIconEngine.cc
FontIconEngine.h
FontIcons.json
Formatter.cc
Formatter.h
FreeSpaceLabel.cc

194
qt/FontIconEngine.cc Normal file
View File

@@ -0,0 +1,194 @@
#define QT_PLUGIN
#define QT_STATICPLUGIN
#include <fmt/format.h>
#include <QIconEnginePlugin>
#include <QOperatingSystemVersion>
#include <QPainter>
#include <QPalette>
#include "FontIconEngine.h"
namespace
{
class FontIconPlugin : public QIconEnginePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QIconEngineFactoryInterface" FILE "FontIcons.json")
public:
explicit FontIconPlugin(QObject* parent = nullptr)
: QIconEnginePlugin(parent)
{
#ifdef Q_OS_WIN
if (auto const current = QOperatingSystemVersion::current(); current >= QOperatingSystemVersion::Windows10)
{
font_ = current >= QOperatingSystemVersion::Windows11 ? QStringLiteral("Segoe Fluent Icons") :
QStringLiteral("Segoe MDL2 Assets");
glyphs_ = {
{ QStringLiteral("application-exit"), QString(QChar::fromUcs4(0xf3b1)) },
{ QStringLiteral("dialog-ok"), QString(QChar::fromUcs4(0xe8fb)) },
{ QStringLiteral("document-new"), QString(QChar::fromUcs4(0xe8a5)) },
{ QStringLiteral("document-open"), QString(QChar::fromUcs4(0xe8e5)) },
{ QStringLiteral("document-properties"), QString(QChar::fromUcs4(0xf259)) }, // 0xec7a // 0xe70f
{ QStringLiteral("edit-clear"), QString(QChar::fromUcs4(0xe750)) },
{ QStringLiteral("edit-delete"), QString(QChar::fromUcs4(0xe74d)) },
{ QStringLiteral("edit-select-all"), QString(QChar::fromUcs4(0xe8b3)) },
{ QStringLiteral("emblem-important"), QString(QChar::fromUcs4(0xe814)) },
{ QStringLiteral("folder-open"), QString(QChar::fromUcs4(0xe838)) },
{ QStringLiteral("go-bottom"), QString(QChar::fromUcs4(0xf0ae)) },
{ QStringLiteral("go-down"), QString(QChar::fromUcs4(0xe74b)) },
{ QStringLiteral("go-top"), QString(QChar::fromUcs4(0xf0ad)) },
{ QStringLiteral("go-up"), QString(QChar::fromUcs4(0xe74a)) },
{ QStringLiteral("help-about"), QString(QChar::fromUcs4(0xe946)) },
{ QStringLiteral("help-contents"), QString(QChar::fromUcs4(0xe897)) },
{ QStringLiteral("insert-link"), QString(QChar::fromUcs4(0xe71b)) },
{ QStringLiteral("list-add"), QString(QChar::fromUcs4(0xe710)) },
{ QStringLiteral("list-remove"), QString(QChar::fromUcs4(0xe738)) },
{ QStringLiteral("media-playback-pause"), QString(QChar::fromUcs4(0xedb4)) },
{ QStringLiteral("media-playback-start"), QString(QChar::fromUcs4(0xedb5)) },
{ QStringLiteral("network-error"), QString() },
{ QStringLiteral("network-idle"), QString() },
{ QStringLiteral("network-receive"), QString(QChar::fromUcs4(0xe896)) },
{ QStringLiteral("network-transmit-receive"), QString(QChar::fromUcs4(0xe8ab)) },
{ QStringLiteral("network-transmit"), QString(QChar::fromUcs4(0xe898)) },
{ QStringLiteral("preferences-system"), QString(QChar::fromUcs4(0xe713)) },
{ QStringLiteral("process-stop"), QString(QChar::fromUcs4(0xe71a)) },
{ QStringLiteral("system-run"), QString(QChar::fromUcs4(0xe9f5)) },
{ QStringLiteral("view-refresh"), QString(QChar::fromUcs4(0xe72c)) },
{ QStringLiteral("view-sort-ascending"), QString(QChar::fromUcs4(0xe8cb)) },
};
}
#else
font_ = QStringLiteral("Material Design Icons Desktop");
glyphs_ = {
{ QStringLiteral("application-exit"), QString(QChar::fromUcs4(0xF0343)) },
{ QStringLiteral("dialog-ok"), QString(QChar::fromUcs4(0xF012C)) },
{ QStringLiteral("document-new"), QString(QChar::fromUcs4(0xF0224)) },
{ QStringLiteral("document-open"), QString(QChar::fromUcs4(0xF0EED)) },
{ QStringLiteral("document-properties"), QString(QChar::fromUcs4(0xF107C)) },
{ QStringLiteral("edit-clear"), QString(QChar::fromUcs4(0xF0B5C)) },
{ QStringLiteral("edit-delete"), QString(QChar::fromUcs4(0xF0A7A)) },
{ QStringLiteral("edit-select-all"), QString(QChar::fromUcs4(0xF0486)) },
{ QStringLiteral("emblem-important"), QString(QChar::fromUcs4(0xF0028)) },
{ QStringLiteral("folder-open"), QString(QChar::fromUcs4(0xF0DCF)) },
{ QStringLiteral("go-bottom"), QString(QChar::fromUcs4(0xF0792)) },
{ QStringLiteral("go-down"), QString(QChar::fromUcs4(0xF0045)) },
{ QStringLiteral("go-top"), QString(QChar::fromUcs4(0xF0795)) },
{ QStringLiteral("go-up"), QString(QChar::fromUcs4(0xF005D)) },
{ QStringLiteral("help-about"), QString(QChar::fromUcs4(0xF02FD)) },
{ QStringLiteral("help-contents"), QString(QChar::fromUcs4(0xF02D6)) },
{ QStringLiteral("insert-link"), QString(QChar::fromUcs4(0xF1100)) },
{ QStringLiteral("list-add"), QString(QChar::fromUcs4(0xF0415)) },
{ QStringLiteral("list-remove"), QString(QChar::fromUcs4(0xF0374)) },
{ QStringLiteral("media-playback-pause"), QString(QChar::fromUcs4(0xF03E4)) },
{ QStringLiteral("media-playback-start"), QString(QChar::fromUcs4(0xF0F1B)) },
{ QStringLiteral("network-error"), QString(QChar::fromUcs4(0xF0C9C)) },
{ QStringLiteral("network-idle"), QString(QChar::fromUcs4(0xF0C9D)) },
{ QStringLiteral("network-receive"), QString(QChar::fromUcs4(0xF0C66)) },
{ QStringLiteral("network-transmit-receive"), QString(QChar::fromUcs4(0xF04E1)) },
{ QStringLiteral("network-transmit"), QString(QChar::fromUcs4(0xF0CD8)) },
{ QStringLiteral("preferences-system"), QString(QChar::fromUcs4(0xF08BB)) },
{ QStringLiteral("process-stop"), QString(QChar::fromUcs4(0xF04DB)) },
{ QStringLiteral("system-run"), QString(QChar::fromUcs4(0xF08D6)) },
{ QStringLiteral("view-refresh"), QString(QChar::fromUcs4(0xF0450)) },
{ QStringLiteral("view-sort-ascending"), QString(QChar::fromUcs4(0xF04BA)) },
};
#endif
}
QIconEngine* create(QString const& name) override
{
auto const glyph_it = glyphs_.find(name);
return new FontIconEngine(font_, glyph_it != glyphs_.end() ? glyph_it->second : QString());
}
private:
QFont font_;
std::map<QString, QString> glyphs_;
};
} // namespace
#include "FontIconEngine.moc"
Q_IMPORT_PLUGIN(FontIconPlugin)
FontIconEngine::FontIconEngine(QFont const& font, QString const& glyph)
: font_(font)
, glyph_(glyph)
{
}
bool FontIconEngine::isValidTheme()
{
#ifdef Q_OS_WIN
return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10;
#else
return false;
#endif
}
QString FontIconEngine::themeName()
{
return QStringLiteral("TrFontIcons");
}
void FontIconEngine::paint(QPainter* painter, QRect const& rect, QIcon::Mode mode, QIcon::State /*state*/)
{
auto const palette = QPalette();
auto color = QColor();
switch (mode)
{
case QIcon::Normal:
color = palette.color(QPalette::Inactive, QPalette::Text);
break;
case QIcon::Disabled:
color = palette.color(QPalette::Disabled, QPalette::Text);
break;
case QIcon::Active:
color = palette.color(QPalette::Active, QPalette::Text);
break;
case QIcon::Selected:
color = palette.color(QPalette::Active, QPalette::HighlightedText);
break;
}
auto font = font_;
font.setPixelSize(rect.height());
painter->save();
painter->setPen(color);
painter->setFont(font);
painter->drawText(rect, Qt::AlignCenter, glyph_);
painter->restore();
}
QPixmap FontIconEngine::pixmap(QSize const& size, QIcon::Mode mode, QIcon::State state)
{
auto pixmap = QPixmap(size);
pixmap.fill(Qt::transparent);
auto painter = QPainter(&pixmap);
paint(&painter, { {}, size }, mode, state);
return pixmap;
}
QIconEngine* FontIconEngine::clone() const
{
return new FontIconEngine(*this);
}
QString FontIconEngine::iconName()
{
return glyph_;
}
bool FontIconEngine::isNull()
{
return glyph_.isEmpty();
}

25
qt/FontIconEngine.h Normal file
View File

@@ -0,0 +1,25 @@
#pragma once
#include <QFont>
#include <QIconEngine>
#include <QString>
class FontIconEngine : public QIconEngine
{
public:
FontIconEngine(QFont const& font, QString const& glyph);
static bool isValidTheme();
static QString themeName();
// QIconEngine
void paint(QPainter* painter, QRect const& rect, QIcon::Mode mode, QIcon::State state) override;
QPixmap pixmap(QSize const& size, QIcon::Mode mode, QIcon::State state) override;
[[nodiscard]] QIconEngine* clone() const override;
QString iconName() override;
bool isNull() override;
private:
QFont font_;
QString glyph_;
};

3
qt/FontIcons.json Normal file
View File

@@ -0,0 +1,3 @@
{
"Keys": ["TrFontIcons"]
}

View File

@@ -149,9 +149,12 @@ MainWindow::MainWindow(Session& session, Prefs& prefs, TorrentModel& model, bool
QIcon const icon_play = icons.getThemeIcon(QStringLiteral("media-playback-start"), QStyle::SP_MediaPlay);
QIcon const icon_pause = icons.getThemeIcon(QStringLiteral("media-playback-pause"), QStyle::SP_MediaPause);
QIcon const icon_open = icons.getThemeIcon(QStringLiteral("document-open"), QStyle::SP_DialogOpenButton);
QIcon const icon_insert_link = icons.getThemeIcon(QStringLiteral("insert-link"));
ui_.action_OpenFile->setIcon(icon_open);
ui_.action_AddURL->setIcon(
addEmblem(icon_open, QStringList{} << QStringLiteral("emblem-web") << QStringLiteral("applications-internet")));
!icon_insert_link.isNull() ?
icon_insert_link :
addEmblem(icon_open, QStringList{} << QStringLiteral("emblem-web") << QStringLiteral("applications-internet")));
ui_.action_New->setIcon(icons.getThemeIcon(QStringLiteral("document-new"), QStyle::SP_DesktopIcon));
ui_.action_Properties->setIcon(icons.getThemeIcon(QStringLiteral("document-properties"), QStyle::SP_DesktopIcon));
ui_.action_OpenFolder->setIcon(icons.getThemeIcon(QStringLiteral("folder-open"), QStyle::SP_DirOpenIcon));