Allow customizing status icon colors

This commit is contained in:
Martchus 2019-05-19 17:56:11 +02:00
parent 92607c3d89
commit 05da0465a7
19 changed files with 352 additions and 216 deletions

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs>
<linearGradient id="grad" gradientUnits="userSpaceOnUse" x1="8" y1="0" x2="8" y2="16">
<stop offset="0" style="stop-color:#3daee6"/>
</linearGradient>
</defs>
<g id="syncthing-logo">
<circle id="outer" cx="8" cy="8" r="8" style="fill:url(#grad)"/>
<circle id="inner" cx="8" cy="7.9727402" r="5.9557071" style="fill:none;stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-l" x1="9.1993189" y1="8.776825" x2="2.262351" y2="9.4173737" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-tr" x1="9.1993189" y1="8.776825" x2="13.301533" y2="5.3696747" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-br" x1="9.1993189" y1="8.776825" x2="11.788756" y2="12.51107" style="stroke:#ffffff;stroke-width:0.81771719"/>
<circle id="node-c" cx="9.1993189" cy="8.776825" r="1.22" style="fill:#ffffff"/>
<circle id="node-l" cx="2.262351" cy="9.4173737" r="1.22" style="fill:#ffffff"/>
<circle id="node-tr" cx="13.301533" cy="5.3696747" r="1.22" style="fill:#ffffff"/>
<circle id="node-br" cx="11.788756" cy="12.51107" r="1.22" style="fill:#ffffff"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs>
<linearGradient id="grad" gradientUnits="userSpaceOnUse" x1="8" y1="0" x2="8" y2="16">
<stop offset="0" style="stop-color:#bfc1c4"/>
</linearGradient>
</defs>
<g id="syncthing-logo">
<circle id="outer" cx="8" cy="8" r="8" style="fill:url(#grad)"/>
<circle id="inner" cx="8" cy="7.9727402" r="5.9557071" style="fill:none;stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-l" x1="9.1993189" y1="8.776825" x2="2.262351" y2="9.4173737" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-tr" x1="9.1993189" y1="8.776825" x2="13.301533" y2="5.3696747" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-br" x1="9.1993189" y1="8.776825" x2="11.788756" y2="12.51107" style="stroke:#ffffff;stroke-width:0.81771719"/>
<circle id="node-c" cx="9.1993189" cy="8.776825" r="1.22" style="fill:#ffffff"/>
<circle id="node-l" cx="2.262351" cy="9.4173737" r="1.22" style="fill:#ffffff"/>
<circle id="node-tr" cx="13.301533" cy="5.3696747" r="1.22" style="fill:#ffffff"/>
<circle id="node-br" cx="11.788756" cy="12.51107" r="1.22" style="fill:#ffffff"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs>
<linearGradient id="grad" gradientUnits="userSpaceOnUse" x1="8" y1="0" x2="8" y2="16">
<stop offset="0" style="stop-color:#ed1515"/>
</linearGradient>
<mask id="bitemask" maskUnits="userSpaceOnUse">
<g>
<rect id="mask-bg" x="0" y="0" width="16" height="16" style="fill:#ffffff"/>
<circle id="mask-subtract" cx="11.5" cy="11.5" r="5.5" style="fill:#000000"/>
</g>
</mask>
</defs>
<g id="syncthing-logo" mask="url(#bitemask)">
<circle id="outer" cx="8" cy="8" r="8" style="fill:url(#grad)"/>
<circle id="inner" cx="8" cy="7.9727402" r="5.9557071" style="fill:none;stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-l" x1="9.1993189" y1="8.776825" x2="2.262351" y2="9.4173737" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-tr" x1="9.1993189" y1="8.776825" x2="13.301533" y2="5.3696747" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-br" x1="9.1993189" y1="8.776825" x2="11.788756" y2="12.51107" style="stroke:#ffffff;stroke-width:0.81771719"/>
<circle id="node-c" cx="9.1993189" cy="8.776825" r="1.22" style="fill:#ffffff"/>
<circle id="node-l" cx="2.262351" cy="9.4173737" r="1.22" style="fill:#ffffff"/>
<circle id="node-tr" cx="13.301533" cy="5.3696747" r="1.22" style="fill:#ffffff"/>
<circle id="node-br" cx="11.788756" cy="12.51107" r="1.22" style="fill:#ffffff"/>
</g>
<circle id="bubble" cx="11.5" cy="11.5" r="4.5" style="fill:#000000"/>
<g id="arrows" transform="rotate(0 11.5 11.5)">
<path id="arrow-left" d="m 11.5,14 0,-1 c -1.5,0 -1.5,0 -1.5,-2 l 1,0 -1.5,-2 -1.5,2 1,0 c 0,3 0,3 2.5,3 z" style="fill:#ffffff" />
<path id="arrow-right" d="m 11.5,9 0,1 c 1.5,0 1.5,0 1.5,2 l -1,0 1.5,2 1.5,-2 -1,0 C 14,9 14,9 11.5,9 Z" style="fill:#ffffff" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs>
<linearGradient id="grad" gradientUnits="userSpaceOnUse" x1="8" y1="0" x2="8" y2="16">
<stop offset="0" style="stop-color:#ed1515"/>
</linearGradient>
<mask id="bitemask" maskUnits="userSpaceOnUse">
<g>
<rect id="mask-bg" x="0" y="0" width="16" height="16" style="fill:#ffffff"/>
<circle id="mask-subtract" cx="11.5" cy="11.5" r="5.5" style="fill:#000000"/>
</g>
</mask>
</defs>
<g id="syncthing-logo" mask="url(#bitemask)">
<circle id="outer" cx="8" cy="8" r="8" style="fill:url(#grad)"/>
<circle id="inner" cx="8" cy="7.9727402" r="5.9557071" style="fill:none;stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-l" x1="9.1993189" y1="8.776825" x2="2.262351" y2="9.4173737" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-tr" x1="9.1993189" y1="8.776825" x2="13.301533" y2="5.3696747" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-br" x1="9.1993189" y1="8.776825" x2="11.788756" y2="12.51107" style="stroke:#ffffff;stroke-width:0.81771719"/>
<circle id="node-c" cx="9.1993189" cy="8.776825" r="1.22" style="fill:#ffffff"/>
<circle id="node-l" cx="2.262351" cy="9.4173737" r="1.22" style="fill:#ffffff"/>
<circle id="node-tr" cx="13.301533" cy="5.3696747" r="1.22" style="fill:#ffffff"/>
<circle id="node-br" cx="11.788756" cy="12.51107" r="1.22" style="fill:#ffffff"/>
</g>
<circle id="bubble" cx="11.5" cy="11.5" r="4.5" style="fill:#000000"/>
<g id="exclaim">
<rect id="exclaim-top" x="11" y="9" width="1" height="3" style="fill:#ffffff"/>
<rect id="exclaim-bottom" x="11" y="13" width="1" height="1" style="fill:#ffffff"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs>
<linearGradient id="grad" gradientUnits="userSpaceOnUse" x1="8" y1="0" x2="8" y2="16">
<stop offset="0" style="stop-color:#c9ce3b"/>
</linearGradient>
<mask id="bitemask" maskUnits="userSpaceOnUse">
<g>
<rect id="mask-bg" x="0" y="0" width="16" height="16" style="fill:#ffffff"/>
<circle id="mask-subtract" cx="11.5" cy="11.5" r="5.5" style="fill:#000000"/>
</g>
</mask>
</defs>
<g id="syncthing-logo" mask="url(#bitemask)">
<circle id="outer" cx="8" cy="8" r="8" style="fill:url(#grad)"/>
<circle id="inner" cx="8" cy="7.9727402" r="5.9557071" style="fill:none;stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-l" x1="9.1993189" y1="8.776825" x2="2.262351" y2="9.4173737" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-tr" x1="9.1993189" y1="8.776825" x2="13.301533" y2="5.3696747" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-br" x1="9.1993189" y1="8.776825" x2="11.788756" y2="12.51107" style="stroke:#ffffff;stroke-width:0.81771719"/>
<circle id="node-c" cx="9.1993189" cy="8.776825" r="1.22" style="fill:#ffffff"/>
<circle id="node-l" cx="2.262351" cy="9.4173737" r="1.22" style="fill:#ffffff"/>
<circle id="node-tr" cx="13.301533" cy="5.3696747" r="1.22" style="fill:#ffffff"/>
<circle id="node-br" cx="11.788756" cy="12.51107" r="1.22" style="fill:#ffffff"/>
</g>
<circle id="bubble" cx="11.5" cy="11.5" r="4.5" style="fill:#000000"/>
<g id="exclaim">
<rect id="exclaim-top" x="11" y="9" width="1" height="3" style="fill:#ffffff"/>
<rect id="exclaim-bottom" x="11" y="13" width="1" height="1" style="fill:#ffffff"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs>
<linearGradient id="grad" gradientUnits="userSpaceOnUse" x1="8" y1="0" x2="8" y2="16">
<stop offset="0" style="stop-color:#11d116"/>
</linearGradient>
</defs>
<g id="syncthing-logo">
<circle id="outer" cx="8" cy="8" r="8" style="fill:url(#grad)"/>
<circle id="inner" cx="8" cy="7.9727402" r="5.9557071" style="fill:none;stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-l" x1="9.1993189" y1="8.776825" x2="2.262351" y2="9.4173737" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-tr" x1="9.1993189" y1="8.776825" x2="13.301533" y2="5.3696747" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-br" x1="9.1993189" y1="8.776825" x2="11.788756" y2="12.51107" style="stroke:#ffffff;stroke-width:0.81771719"/>
<circle id="node-c" cx="9.1993189" cy="8.776825" r="1.22" style="fill:#ffffff"/>
<circle id="node-l" cx="2.262351" cy="9.4173737" r="1.22" style="fill:#ffffff"/>
<circle id="node-tr" cx="13.301533" cy="5.3696747" r="1.22" style="fill:#ffffff"/>
<circle id="node-br" cx="11.788756" cy="12.51107" r="1.22" style="fill:#ffffff"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs>
<linearGradient id="grad" gradientUnits="userSpaceOnUse" x1="8" y1="0" x2="8" y2="16">
<stop offset="0" style="stop-color:#bfc1c4"/>
</linearGradient>
<mask id="bitemask" maskUnits="userSpaceOnUse">
<g>
<rect id="mask-bg" x="0" y="0" width="16" height="16" style="fill:#ffffff"/>
<circle id="mask-subtract" cx="11.5" cy="11.5" r="5.5" style="fill:#000000"/>
</g>
</mask>
</defs>
<g id="syncthing-logo" mask="url(#bitemask)">
<circle id="outer" cx="8" cy="8" r="8" style="fill:url(#grad)"/>
<circle id="inner" cx="8" cy="7.9727402" r="5.9557071" style="fill:none;stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-l" x1="9.1993189" y1="8.776825" x2="2.262351" y2="9.4173737" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-tr" x1="9.1993189" y1="8.776825" x2="13.301533" y2="5.3696747" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-br" x1="9.1993189" y1="8.776825" x2="11.788756" y2="12.51107" style="stroke:#ffffff;stroke-width:0.81771719"/>
<circle id="node-c" cx="9.1993189" cy="8.776825" r="1.22" style="fill:#ffffff"/>
<circle id="node-l" cx="2.262351" cy="9.4173737" r="1.22" style="fill:#ffffff"/>
<circle id="node-tr" cx="13.301533" cy="5.3696747" r="1.22" style="fill:#ffffff"/>
<circle id="node-br" cx="11.788756" cy="12.51107" r="1.22" style="fill:#ffffff"/>
</g>
<circle id="bubble" cx="11.5" cy="11.5" r="4.5" style="fill:#000000"/>
<g id="pause">
<rect id="pause-leftbar" x="10" y="9" width="1" height="5" style="fill:#ffffff"/>
<rect id="pause-rightbar" x="12" y="9" width="1" height="5" style="fill:#ffffff"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs>
<linearGradient id="grad" gradientUnits="userSpaceOnUse" x1="8" y1="0" x2="8" y2="16">
<stop offset="0" style="stop-color:#3daee6"/>
</linearGradient>
<mask id="bitemask" maskUnits="userSpaceOnUse">
<g>
<rect id="mask-bg" x="0" y="0" width="16" height="16" style="fill:#ffffff"/>
<circle id="mask-subtract" cx="11.5" cy="11.5" r="5.5" style="fill:#000000"/>
</g>
</mask>
</defs>
<g id="syncthing-logo" mask="url(#bitemask)">
<circle id="outer" cx="8" cy="8" r="8" style="fill:url(#grad)"/>
<circle id="inner" cx="8" cy="7.9727402" r="5.9557071" style="fill:none;stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-l" x1="9.1993189" y1="8.776825" x2="2.262351" y2="9.4173737" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-tr" x1="9.1993189" y1="8.776825" x2="13.301533" y2="5.3696747" style="stroke:#ffffff;stroke-width:0.81771719"/>
<line id="arm-br" x1="9.1993189" y1="8.776825" x2="11.788756" y2="12.51107" style="stroke:#ffffff;stroke-width:0.81771719"/>
<circle id="node-c" cx="9.1993189" cy="8.776825" r="1.22" style="fill:#ffffff"/>
<circle id="node-l" cx="2.262351" cy="9.4173737" r="1.22" style="fill:#ffffff"/>
<circle id="node-tr" cx="13.301533" cy="5.3696747" r="1.22" style="fill:#ffffff"/>
<circle id="node-br" cx="11.788756" cy="12.51107" r="1.22" style="fill:#ffffff"/>
</g>
<circle id="bubble" cx="11.5" cy="11.5" r="4.5" style="fill:#000000"/>
<g id="arrows" transform="rotate(0 11.5 11.5)">
<path id="arrow-left" d="m 11.5,14 0,-1 c -1.5,0 -1.5,0 -1.5,-2 l 1,0 -1.5,-2 -1.5,2 1,0 c 0,3 0,3 2.5,3 z" style="fill:#ffffff" />
<path id="arrow-right" d="m 11.5,9 0,1 c 1.5,0 1.5,0 1.5,2 l -1,0 1.5,2 1.5,-2 -1,0 C 14,9 14,9 11.5,9 Z" style="fill:#ffffff" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -161,17 +161,67 @@ StatusIconSettings::StatusIconSettings()
, errorColor({ QStringLiteral("#DB3C26"), QStringLiteral("#C80828") })
, warningColor({ QStringLiteral("#c9ce3b"), QStringLiteral("#ebb83b") })
, idleColor({ QStringLiteral("#2D9D69"), QStringLiteral("#2D9D69") })
, scanningColor({ QStringLiteral("#26B6DB"), QStringLiteral("#0882C8") })
, synchronizingColor({ QStringLiteral("#26B6DB"), QStringLiteral("#0882C8") })
, pausedColor({ QStringLiteral("#A9A9A9"), QStringLiteral("#58656C") })
, disconnectedColor({ QStringLiteral("#A9A9A9"), QStringLiteral("#58656C") })
{
}
std::vector<StatusIconSettings::ColorMapping> StatusIconSettings::colorMapping()
{
return std::vector<ColorMapping>({
{ QStringLiteral("Default"), StatusEmblem::None, defaultColor },
{ QStringLiteral("Error"), StatusEmblem::Alert, errorColor },
{ QStringLiteral("Warning"), StatusEmblem::Alert, warningColor },
{ QStringLiteral("Idle"), StatusEmblem::None, idleColor },
{ QStringLiteral("Scanning"), StatusEmblem::Scanning, scanningColor },
{ QStringLiteral("Synchronizing"), StatusEmblem::Synchronizing, synchronizingColor },
{ QStringLiteral("Paused"), StatusEmblem::Paused, pausedColor },
{ QStringLiteral("Disconnected"), StatusEmblem::None, disconnectedColor },
});
}
StatusIconSettings::StatusIconSettings(const QString &str)
: StatusIconSettings()
{
const auto parts = str.splitRef(QChar(';'));
int index = 0;
for (auto *field :
{ &defaultColor, &errorColor, &warningColor, &idleColor, &scanningColor, &synchronizingColor, &pausedColor, &disconnectedColor }) {
if (index >= parts.size()) {
break;
}
const auto colors = parts[index].split(QChar(','));
if (colors.size() >= 2) {
field->start = colors[0].toString();
field->end = colors[1].toString();
}
++index;
}
}
QString StatusIconSettings::toString() const
{
QString res;
res.reserve(128);
for (auto *field :
{ &defaultColor, &errorColor, &warningColor, &idleColor, &scanningColor, &synchronizingColor, &pausedColor, &disconnectedColor }) {
if (!res.isEmpty()) {
res += QChar(';');
}
res += field->start % QChar(',') % field->end;
}
return res;
}
StatusIcons::StatusIcons(const StatusIconSettings &settings)
: disconnected(QIcon(renderSvgImage(makeSyncthingIcon(settings.disconnectedColor, StatusEmblem::None))))
, idling(QIcon(renderSvgImage(makeSyncthingIcon(settings.defaultColor, StatusEmblem::None))))
, scanninig(QIcon(renderSvgImage(makeSyncthingIcon(settings.defaultColor, StatusEmblem::Scanning))))
, idling(QIcon(renderSvgImage(makeSyncthingIcon(settings.idleColor, StatusEmblem::None))))
, scanninig(QIcon(renderSvgImage(makeSyncthingIcon(settings.scanningColor, StatusEmblem::Scanning))))
, notify(QIcon(renderSvgImage(makeSyncthingIcon(settings.warningColor, StatusEmblem::Alert))))
, pause(QIcon(renderSvgImage(makeSyncthingIcon(settings.defaultColor, StatusEmblem::Paused))))
, sync(QIcon(renderSvgImage(makeSyncthingIcon(settings.defaultColor, StatusEmblem::Synchronizing))))
, pause(QIcon(renderSvgImage(makeSyncthingIcon(settings.pausedColor, StatusEmblem::Paused))))
, sync(QIcon(renderSvgImage(makeSyncthingIcon(settings.synchronizingColor, StatusEmblem::Synchronizing))))
, syncComplete(QIcon(renderSvgImage(makeSyncthingIcon(settings.defaultColor, StatusEmblem::Complete))))
, error(QIcon(renderSvgImage(makeSyncthingIcon(settings.errorColor, StatusEmblem::Alert))))
, errorSync(QIcon(renderSvgImage(makeSyncthingIcon(settings.errorColor, StatusEmblem::Synchronizing))))

View File

@ -6,6 +6,8 @@
#include <QIcon>
#include <QSize>
#include <vector>
QT_FORWARD_DECLARE_CLASS(QColor)
namespace Data {
@ -21,23 +23,58 @@ enum class StatusEmblem {
};
struct GradientColor {
GradientColor(const QString &start, const QString &end);
GradientColor(QString &&start, QString &&end);
GradientColor(const QColor &start, const QColor &end);
QString start;
QString end;
};
inline GradientColor::GradientColor(const QString &start, const QString &end)
: start(start)
, end(end)
{
}
inline GradientColor::GradientColor(QString &&start, QString &&end)
: start(start)
, end(end)
{
}
inline GradientColor::GradientColor(const QColor &start, const QColor &end)
: GradientColor(start.name(), end.name())
{
}
QByteArray LIB_SYNCTHING_MODEL_EXPORT makeSyncthingIcon(const GradientColor &gradientColor, StatusEmblem statusEmblem);
QPixmap LIB_SYNCTHING_MODEL_EXPORT renderSvgImage(const QString &path, const QSize &size = QSize(128, 128), int margin = 0);
QPixmap LIB_SYNCTHING_MODEL_EXPORT renderSvgImage(const QByteArray &contents, const QSize &size = QSize(128, 128), int margin = 0);
QByteArray LIB_SYNCTHING_MODEL_EXPORT loadFontAwesomeIcon(const QString &iconName, const QColor &color, bool solid = true);
struct StatusIconSettings {
StatusIconSettings();
struct LIB_SYNCTHING_MODEL_EXPORT StatusIconSettings {
explicit StatusIconSettings();
explicit StatusIconSettings(const QString &str);
GradientColor defaultColor;
GradientColor errorColor;
GradientColor warningColor;
GradientColor idleColor;
GradientColor scanningColor;
GradientColor synchronizingColor;
GradientColor pausedColor;
GradientColor disconnectedColor;
static constexpr auto distinguishableColorCount = 8;
struct ColorMapping {
QString colorName;
StatusEmblem defaultEmblem;
GradientColor &setting;
};
std::vector<ColorMapping> colorMapping();
QString toString() const;
};
struct StatusIcons {

View File

@ -126,7 +126,7 @@ SettingsDialog::SettingsDialog(Plasmoid::SyncthingApplet &applet)
category->setDisplayName(QCoreApplication::translate("Plasmoid::SettingsDialog", "Plasmoid"));
category->assignPages(QList<Dialogs::OptionPage *>()
<< new ConnectionOptionPage(applet.connection()) << new NotificationsOptionPage(GuiType::Plasmoid) << m_appearanceOptionPage
<< new ShortcutOptionPage(applet));
<< new IconsOptionPage << new ShortcutOptionPage(applet));
category->setIcon(QIcon::fromTheme(QStringLiteral("plasma")));
categories << category;

View File

@ -391,6 +391,7 @@ void SyncthingApplet::handleSettingsChanged()
m_dirModel.setBrightColors(brightColors);
m_devModel.setBrightColors(brightColors);
m_downloadModel.setBrightColors(brightColors);
IconManager::instance().applySettings(settings.statusIcons);
// restore selected states
// note: The settings dialog writes this to the Plasmoid's config like the other settings. However, it

View File

@ -416,6 +416,7 @@ void TrayWidget::applySettings(const QString &connectionConfig)
m_dirModel.setBrightColors(settings.appearance.brightTextColors);
m_devModel.setBrightColors(settings.appearance.brightTextColors);
m_dlModel.setBrightColors(settings.appearance.brightTextColors);
IconManager::instance().applySettings(settings.statusIcons);
// show warning when explicitely specified connection configuration was not found
if (!specifiedConnectionConfigFound && !connectionConfig.isEmpty()) {

View File

@ -43,6 +43,7 @@ set(WIDGETS_UI_FILES
settings/connectionoptionpage.ui
settings/notificationsoptionpage.ui
settings/appearanceoptionpage.ui
settings/iconsoptionpage.ui
settings/autostartoptionpage.ui
settings/launcheroptionpage.ui
settings/systemdoptionpage.ui

View File

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QtGui::IconsOptionPage</class>
<widget class="QWidget" name="QtGui::IconsOptionPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>390</width>
<height>167</height>
</rect>
</property>
<property name="windowTitle">
<string>Icons</string>
</property>
<property name="windowIcon">
<iconset theme="preferences-desktop-icons">
<normaloff>.</normaloff>.</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="statusColorsGroupBox">
<property name="title">
<string>Status colors</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QLabel" name="color1Label">
<property name="text">
<string>Color 1</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="color2Label">
<property name="text">
<string>Color 2</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="previewLabel">
<property name="text">
<string>Preview</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QWidget" name="widget" native="true"/>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="infoLabel">
<property name="text">
<string>Requires (so far) a restart to be applied.</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="restorePreviousPushButton">
<property name="text">
<string>Restore previous settings</string>
</property>
<property name="icon">
<iconset theme="edit-undo"/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="restoreDefaultsPushButton">
<property name="text">
<string>Restore defaults</string>
</property>
<property name="icon">
<iconset theme="edit-undo">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -177,6 +177,7 @@ void restore()
appearance.frameStyle = settings.value(QStringLiteral("frameStyle"), appearance.frameStyle).toInt();
appearance.tabPosition = settings.value(QStringLiteral("tabPos"), appearance.tabPosition).toInt();
appearance.brightTextColors = settings.value(QStringLiteral("brightTextColors"), appearance.brightTextColors).toBool();
v.statusIcons = StatusIconSettings(settings.value(QStringLiteral("statusIcons")).toString());
settings.endGroup();
settings.beginGroup(QStringLiteral("startup"));
@ -264,6 +265,7 @@ void save()
settings.setValue(QStringLiteral("frameStyle"), appearance.frameStyle);
settings.setValue(QStringLiteral("tabPos"), appearance.tabPosition);
settings.setValue(QStringLiteral("brightTextColors"), appearance.brightTextColors);
settings.setValue(QStringLiteral("statusIcons"), v.statusIcons.toString());
settings.endGroup();
settings.beginGroup(QStringLiteral("startup"));

View File

@ -2,6 +2,7 @@
#define SETTINGS_H
#include "../../connector/syncthingconnectionsettings.h"
#include "../../model/syncthingicons.h"
#include "../global.h"
#include <qtutilities/settingsdialog/qtsettings.h>
@ -106,6 +107,7 @@ struct SYNCTHINGWIDGETS_EXPORT Settings {
#endif
unsigned int ignoreInavailabilityAfterStart = 15;
Appearance appearance;
Data::StatusIconSettings statusIcons;
Launcher launcher;
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
Systemd systemd;

View File

@ -9,11 +9,13 @@
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
#include "../../connector/syncthingservice.h"
#include "../../model/colors.h"
#include "../../model/syncthingicons.h"
#endif
#include "ui_appearanceoptionpage.h"
#include "ui_autostartoptionpage.h"
#include "ui_connectionoptionpage.h"
#include "ui_iconsoptionpage.h"
#include "ui_launcheroptionpage.h"
#include "ui_notificationsoptionpage.h"
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
@ -24,6 +26,7 @@
// use meta-data of syncthingtray application here
#include "resources/../../tray/resources/config.h"
#include <qtutilities/paletteeditor/colorbutton.h>
#include <qtutilities/settingsdialog/optioncategory.h>
#include <qtutilities/settingsdialog/optioncategorymodel.h>
#include <qtutilities/settingsdialog/qtsettings.h>
@ -489,6 +492,93 @@ void AppearanceOptionPage::reset()
ui()->brightTextColorsCheckBox->setChecked(settings.brightTextColors);
}
// IconsOptionPage
IconsOptionPage::IconsOptionPage(QWidget *parentWidget)
: IconsOptionPageBase(parentWidget)
{
}
IconsOptionPage::~IconsOptionPage()
{
}
QWidget *IconsOptionPage::setupWidget()
{
auto *const widget = IconsOptionPageBase::setupWidget();
// populate form for status icon colors
auto *const gridLayout = ui()->gridLayout;
auto *const statusColorsGroupBox = ui()->statusColorsGroupBox;
int index = 0;
for (auto &colorMapping : m_settings.colorMapping()) {
// populate widgets array
auto &widgetsForColor = m_widgets[index++] = {
{
new Widgets::ColorButton(statusColorsGroupBox),
new Widgets::ColorButton(statusColorsGroupBox),
},
new QLabel(statusColorsGroupBox),
&colorMapping.setting,
colorMapping.defaultEmblem,
};
// add label for color name
gridLayout->addWidget(new QLabel(colorMapping.colorName, statusColorsGroupBox), index, 0, Qt::AlignRight | Qt::AlignVCenter);
// setup preview
gridLayout->addWidget(widgetsForColor.previewLabel, index, 3, Qt::AlignCenter);
const auto updatePreview = [&widgetsForColor] {
widgetsForColor.previewLabel->setPixmap(
renderSvgImage(makeSyncthingIcon(*widgetsForColor.setting, widgetsForColor.statusEmblem), QSize(32, 32)));
};
for (const auto &colorButton : widgetsForColor.colorButtons) {
QObject::connect(colorButton, &Widgets::ColorButton::colorChanged, updatePreview);
}
// setup color buttons
widgetsForColor.colorButtons[0]->setColor(colorMapping.setting.start);
widgetsForColor.colorButtons[1]->setColor(colorMapping.setting.end);
gridLayout->addWidget(widgetsForColor.colorButtons[0], index, 1);
gridLayout->addWidget(widgetsForColor.colorButtons[1], index, 2);
if (index >= StatusIconSettings::distinguishableColorCount) {
break;
}
}
// setup additional buttons
QObject::connect(ui()->restoreDefaultsPushButton, &QPushButton::clicked, [this] {
m_settings = Data::StatusIconSettings();
update();
});
QObject::connect(ui()->restorePreviousPushButton, &QPushButton::clicked, [this] { reset(); });
return widget;
}
bool IconsOptionPage::apply()
{
for (auto &widgetsForColor : m_widgets) {
*widgetsForColor.setting = GradientColor{ widgetsForColor.colorButtons[0]->color(), widgetsForColor.colorButtons[1]->color() };
}
values().statusIcons = m_settings;
return true;
}
void IconsOptionPage::update()
{
for (auto &widgetsForColor : m_widgets) {
widgetsForColor.colorButtons[0]->setColor(widgetsForColor.setting->start);
widgetsForColor.colorButtons[1]->setColor(widgetsForColor.setting->end);
}
}
void IconsOptionPage::reset()
{
m_settings = values().statusIcons;
update();
}
// AutostartOptionPage
AutostartOptionPage::AutostartOptionPage(QWidget *parentWidget)
: AutostartOptionPageBase(parentWidget)
@ -980,8 +1070,8 @@ SettingsDialog::SettingsDialog(Data::SyncthingConnection *connection, QWidget *p
category = new OptionCategory(this);
category->setDisplayName(tr("Tray"));
category->assignPages(
QList<Dialogs::OptionPage *>() << new ConnectionOptionPage(connection) << new NotificationsOptionPage << new AppearanceOptionPage);
category->assignPages(QList<Dialogs::OptionPage *>()
<< new ConnectionOptionPage(connection) << new NotificationsOptionPage << new AppearanceOptionPage << new IconsOptionPage);
category->setIcon(QIcon(QStringLiteral(":/icons/hicolor/scalable/app/syncthingtray.svg")));
categories << category;
@ -1027,6 +1117,7 @@ void SettingsDialog::init()
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE_NS(QtGui, ConnectionOptionPage)
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE_NS(QtGui, NotificationsOptionPage)
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE_NS(QtGui, AppearanceOptionPage)
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE_NS(QtGui, IconsOptionPage)
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE_NS(QtGui, AutostartOptionPage)
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE_NS(QtGui, LauncherOptionPage)
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD

View File

@ -5,6 +5,8 @@
#include "../webview/webviewdefs.h"
#include "../../model/syncthingicons.h"
#include <qtutilities/settingsdialog/optionpage.h>
#include <qtutilities/settingsdialog/qtsettings.h>
#include <qtutilities/settingsdialog/settingsdialog.h>
@ -12,6 +14,8 @@
#include <QProcess>
#include <QWidget>
QT_FORWARD_DECLARE_CLASS(QLabel)
namespace ChronoUtilities {
class DateTime;
}
@ -23,6 +27,10 @@ class SyncthingProcess;
class SyncthingLauncher;
} // namespace Data
namespace Widgets {
class ColorButton;
}
namespace QtGui {
/*!
@ -70,6 +78,19 @@ END_DECLARE_OPTION_PAGE
DECLARE_UI_FILE_BASED_OPTION_PAGE(AppearanceOptionPage)
BEGIN_DECLARE_UI_FILE_BASED_OPTION_PAGE(IconsOptionPage)
DECLARE_SETUP_WIDGETS
private:
void update();
Data::StatusIconSettings m_settings;
struct {
Widgets::ColorButton *colorButtons[2] = {};
QLabel *previewLabel = nullptr;
Data::GradientColor *setting = nullptr;
Data::StatusEmblem statusEmblem = Data::StatusEmblem::None;
} m_widgets[Data::StatusIconSettings::distinguishableColorCount];
END_DECLARE_OPTION_PAGE
DECLARE_UI_FILE_BASED_OPTION_PAGE_CUSTOM_SETUP(AutostartOptionPage)
BEGIN_DECLARE_UI_FILE_BASED_OPTION_PAGE_CUSTOM_CTOR(LauncherOptionPage)
@ -125,6 +146,7 @@ private:
DECLARE_EXTERN_UI_FILE_BASED_OPTION_PAGE_NS(QtGui, ConnectionOptionPage)
DECLARE_EXTERN_UI_FILE_BASED_OPTION_PAGE_NS(QtGui, NotificationsOptionPage)
DECLARE_EXTERN_UI_FILE_BASED_OPTION_PAGE_NS(QtGui, AppearanceOptionPage)
DECLARE_EXTERN_UI_FILE_BASED_OPTION_PAGE_NS(QtGui, IconsOptionPage)
DECLARE_EXTERN_UI_FILE_BASED_OPTION_PAGE_NS(QtGui, AutostartOptionPage)
DECLARE_EXTERN_UI_FILE_BASED_OPTION_PAGE_NS(QtGui, LauncherOptionPage)
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD