Allow configuring thickness of status icons
This commit is contained in:
parent
6114949233
commit
3132c006c5
|
@ -25,7 +25,7 @@ namespace Data {
|
|||
/*!
|
||||
* \brief Generates the SVG code for the Syncthing icon with the specified \a colors and status emblem.
|
||||
*/
|
||||
QByteArray makeSyncthingIcon(const StatusIconColorSet &colors, StatusEmblem statusEmblem)
|
||||
QByteArray makeSyncthingIcon(const StatusIconColorSet &colors, StatusEmblem statusEmblem, StatusIconStrokeWidth strokeWidth)
|
||||
{
|
||||
// serialize colors
|
||||
auto gradientStartColor = colors.backgroundStart.name(QColor::HexRgb);
|
||||
|
@ -93,7 +93,11 @@ QByteArray makeSyncthingIcon(const StatusIconColorSet &colors, StatusEmblem stat
|
|||
"</g>"
|
||||
),
|
||||
};
|
||||
static const auto normalStrokeWidth = QStringLiteral("0.81771719"), thickStrokeWidth = QStringLiteral("1.22");
|
||||
static const auto normalCircleRadius = QStringLiteral("1.22"), largeCircleRadius = QStringLiteral("1.5");
|
||||
const auto &emblemData = emblems[static_cast<int>(statusEmblem)];
|
||||
const auto &strokeWidthF = strokeWidth == StatusIconStrokeWidth::Normal ? normalStrokeWidth : thickStrokeWidth;
|
||||
const auto &circleRadius = strokeWidth == StatusIconStrokeWidth::Normal ? normalCircleRadius : largeCircleRadius;
|
||||
return (QStringLiteral(
|
||||
"<?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\">"
|
||||
|
@ -111,16 +115,16 @@ QByteArray makeSyncthingIcon(const StatusIconColorSet &colors, StatusEmblem stat
|
|||
"</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:") % strokeColor % QStringLiteral(";stroke-width:0.81771719\"/>"
|
||||
"<line id=\"arm-l\" x1=\"9.1993189\" y1=\"8.776825\" x2=\"2.262351\" y2=\"9.4173737\" style=\"stroke:") % strokeColor % QStringLiteral(";stroke-width:0.81771719\"/>"
|
||||
"<line id=\"arm-tr\" x1=\"9.1993189\" y1=\"8.776825\" x2=\"13.301533\" y2=\"5.3696747\" style=\"stroke:") % strokeColor % QStringLiteral(";stroke-width:0.81771719\"/>"
|
||||
"<line id=\"arm-br\" x1=\"9.1993189\" y1=\"8.776825\" x2=\"11.788756\" y2=\"12.51107\" style=\"stroke:") % strokeColor % QStringLiteral(";stroke-width:0.81771719\"/>"
|
||||
"<circle id=\"node-c\" cx=\"9.1993189\" cy=\"8.776825\" r=\"1.22\" style=\"fill:") % fillColor % QStringLiteral("\"/>"
|
||||
"<circle id=\"node-l\" cx=\"2.262351\" cy=\"9.4173737\" r=\"1.22\" style=\"fill:") % fillColor % QStringLiteral("\"/>"
|
||||
"<circle id=\"node-tr\" cx=\"13.301533\" cy=\"5.3696747\" r=\"1.22\" style=\"fill:") % fillColor % QStringLiteral("\"/>"
|
||||
"<circle id=\"node-br\" cx=\"11.788756\" cy=\"12.51107\" r=\"1.22\" style=\"fill:") % fillColor % QStringLiteral("\"/>"
|
||||
"<circle id=\"inner\" cx=\"8\" cy=\"7.9727402\" r=\"5.9557071\" style=\"fill:none;stroke:") % strokeColor % QStringLiteral(";stroke-width:") % strokeWidthF % QStringLiteral("\"/>"
|
||||
"<line id=\"arm-l\" x1=\"9.1993189\" y1=\"8.776825\" x2=\"2.262351\" y2=\"9.4173737\" style=\"stroke:") % strokeColor % QStringLiteral(";stroke-width:") % strokeWidthF % QStringLiteral("\"/>"
|
||||
"<line id=\"arm-tr\" x1=\"9.1993189\" y1=\"8.776825\" x2=\"13.301533\" y2=\"5.3696747\" style=\"stroke:") % strokeColor % QStringLiteral(";stroke-width:") % strokeWidthF % QStringLiteral("\"/>"
|
||||
"<line id=\"arm-br\" x1=\"9.1993189\" y1=\"8.776825\" x2=\"11.788756\" y2=\"12.51107\" style=\"stroke:") % strokeColor % QStringLiteral(";stroke-width:") % strokeWidthF % QStringLiteral("\"/>"
|
||||
"<circle id=\"node-c\" cx=\"9.1993189\" cy=\"8.776825\" r=\"") % circleRadius % QStringLiteral("\" style=\"fill:") % fillColor % QStringLiteral("\"/>"
|
||||
"<circle id=\"node-l\" cx=\"2.262351\" cy=\"9.4173737\" r=\"") % circleRadius % QStringLiteral("\" style=\"fill:") % fillColor % QStringLiteral("\"/>"
|
||||
"<circle id=\"node-tr\" cx=\"13.301533\" cy=\"5.3696747\" r=\"") % circleRadius % QStringLiteral("\" style=\"fill:") % fillColor % QStringLiteral("\"/>"
|
||||
"<circle id=\"node-br\" cx=\"11.788756\" cy=\"12.51107\" r=\"") % circleRadius % QStringLiteral("\" style=\"fill:") % fillColor % QStringLiteral("\"/>"
|
||||
"</g>") %
|
||||
(emblemData.isEmpty() ? QString() : emblemData) % QStringLiteral(
|
||||
emblemData % QStringLiteral(
|
||||
"</svg>"
|
||||
)).toUtf8();
|
||||
// clang-format on
|
||||
|
@ -266,16 +270,18 @@ QString StatusIconSettings::toString() const
|
|||
}
|
||||
|
||||
StatusIcons::StatusIcons(const StatusIconSettings &settings)
|
||||
: disconnected(QIcon(renderSvgImage(makeSyncthingIcon(settings.disconnectedColor, StatusEmblem::None), settings.renderSize)))
|
||||
, idling(QIcon(renderSvgImage(makeSyncthingIcon(settings.idleColor, StatusEmblem::None), settings.renderSize)))
|
||||
, scanninig(QIcon(renderSvgImage(makeSyncthingIcon(settings.scanningColor, StatusEmblem::Scanning), settings.renderSize)))
|
||||
, notify(QIcon(renderSvgImage(makeSyncthingIcon(settings.warningColor, StatusEmblem::Alert), settings.renderSize)))
|
||||
, pause(QIcon(renderSvgImage(makeSyncthingIcon(settings.pausedColor, StatusEmblem::Paused), settings.renderSize)))
|
||||
, sync(QIcon(renderSvgImage(makeSyncthingIcon(settings.synchronizingColor, StatusEmblem::Synchronizing), settings.renderSize)))
|
||||
, syncComplete(QIcon(renderSvgImage(makeSyncthingIcon(settings.defaultColor, StatusEmblem::Complete), settings.renderSize)))
|
||||
, error(QIcon(renderSvgImage(makeSyncthingIcon(settings.errorColor, StatusEmblem::Alert), settings.renderSize)))
|
||||
, errorSync(QIcon(renderSvgImage(makeSyncthingIcon(settings.errorColor, StatusEmblem::Synchronizing), settings.renderSize)))
|
||||
, newItem(QIcon(renderSvgImage(makeSyncthingIcon(settings.defaultColor, StatusEmblem::Add), settings.renderSize)))
|
||||
: disconnected(
|
||||
QIcon(renderSvgImage(makeSyncthingIcon(settings.disconnectedColor, StatusEmblem::None, settings.strokeWidth), settings.renderSize)))
|
||||
, idling(QIcon(renderSvgImage(makeSyncthingIcon(settings.idleColor, StatusEmblem::None, settings.strokeWidth), settings.renderSize)))
|
||||
, scanninig(QIcon(renderSvgImage(makeSyncthingIcon(settings.scanningColor, StatusEmblem::Scanning, settings.strokeWidth), settings.renderSize)))
|
||||
, notify(QIcon(renderSvgImage(makeSyncthingIcon(settings.warningColor, StatusEmblem::Alert, settings.strokeWidth), settings.renderSize)))
|
||||
, pause(QIcon(renderSvgImage(makeSyncthingIcon(settings.pausedColor, StatusEmblem::Paused, settings.strokeWidth), settings.renderSize)))
|
||||
, sync(QIcon(
|
||||
renderSvgImage(makeSyncthingIcon(settings.synchronizingColor, StatusEmblem::Synchronizing, settings.strokeWidth), settings.renderSize)))
|
||||
, syncComplete(QIcon(renderSvgImage(makeSyncthingIcon(settings.defaultColor, StatusEmblem::Complete, settings.strokeWidth), settings.renderSize)))
|
||||
, error(QIcon(renderSvgImage(makeSyncthingIcon(settings.errorColor, StatusEmblem::Alert, settings.strokeWidth), settings.renderSize)))
|
||||
, errorSync(QIcon(renderSvgImage(makeSyncthingIcon(settings.errorColor, StatusEmblem::Synchronizing, settings.strokeWidth), settings.renderSize)))
|
||||
, newItem(QIcon(renderSvgImage(makeSyncthingIcon(settings.defaultColor, StatusEmblem::Add, settings.strokeWidth), settings.renderSize)))
|
||||
, isValid(true)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@ enum class StatusEmblem {
|
|||
Add,
|
||||
};
|
||||
|
||||
enum class StatusIconStrokeWidth {
|
||||
Normal,
|
||||
Thick,
|
||||
};
|
||||
|
||||
struct LIB_SYNCTHING_MODEL_EXPORT StatusIconColorSet {
|
||||
StatusIconColorSet(const QColor &backgroundStart, const QColor &backgroundEnd, const QColor &foreground);
|
||||
StatusIconColorSet(QColor &&backgroundStart, QColor &&backgroundEnd, QColor &&foreground);
|
||||
|
@ -61,7 +66,7 @@ inline StatusIconColorSet::StatusIconColorSet(const QString &backgroundStart, co
|
|||
|
||||
LIB_SYNCTHING_MODEL_EXPORT QByteArray makeSyncthingIcon(
|
||||
const StatusIconColorSet &colors = StatusIconColorSet{ QStringLiteral("#26B6DB"), QStringLiteral("#0882C8"), QStringLiteral("#FFFFFF") },
|
||||
StatusEmblem statusEmblem = StatusEmblem::None);
|
||||
StatusEmblem statusEmblem = StatusEmblem::None, StatusIconStrokeWidth strokeWidth = StatusIconStrokeWidth::Normal);
|
||||
LIB_SYNCTHING_MODEL_EXPORT QPixmap renderSvgImage(const QString &path, const QSize &size = QSize(32, 32), int margin = 0);
|
||||
LIB_SYNCTHING_MODEL_EXPORT QPixmap renderSvgImage(const QByteArray &contents, const QSize &size = QSize(32, 32), int margin = 0);
|
||||
|
||||
|
@ -83,6 +88,7 @@ struct LIB_SYNCTHING_MODEL_EXPORT StatusIconSettings {
|
|||
StatusIconColorSet pausedColor;
|
||||
StatusIconColorSet disconnectedColor;
|
||||
QSize renderSize = QSize(32, 32);
|
||||
StatusIconStrokeWidth strokeWidth = StatusIconStrokeWidth::Normal;
|
||||
|
||||
static constexpr auto distinguishableColorCount = 8;
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
<number>16</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>32</number>
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="sliderPosition">
|
||||
<number>16</number>
|
||||
|
@ -100,6 +100,20 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Stroke width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="thickStrokeWidthCheckBox">
|
||||
<property name="text">
|
||||
<string>Thick</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
|
|
@ -354,6 +354,10 @@ void restore()
|
|||
v.icons.tray = StatusIconSettings(settings.value(QStringLiteral("trayIcons")).toString());
|
||||
v.icons.status.renderSize = settings.value(QStringLiteral("statusIconsRenderSize"), v.icons.status.renderSize).toSize();
|
||||
v.icons.tray.renderSize = settings.value(QStringLiteral("trayIconsRenderSize"), v.icons.tray.renderSize).toSize();
|
||||
v.icons.status.strokeWidth = static_cast<StatusIconStrokeWidth>(
|
||||
settings.value(QStringLiteral("statusIconsStrokeWidth"), static_cast<int>(v.icons.status.strokeWidth)).toInt());
|
||||
v.icons.tray.strokeWidth = static_cast<StatusIconStrokeWidth>(
|
||||
settings.value(QStringLiteral("trayIconsStrokeWidth"), static_cast<int>(v.icons.tray.strokeWidth)).toInt());
|
||||
v.icons.distinguishTrayIcons = settings.value(QStringLiteral("distinguishTrayIcons")).toBool();
|
||||
v.icons.preferIconsFromTheme = settings.value(QStringLiteral("preferIconsFromTheme")).toBool();
|
||||
settings.beginGroup(QStringLiteral("positioning"));
|
||||
|
@ -472,6 +476,8 @@ void save()
|
|||
settings.setValue(QStringLiteral("trayIcons"), v.icons.tray.toString());
|
||||
settings.setValue(QStringLiteral("statusIconsRenderSize"), v.icons.status.renderSize);
|
||||
settings.setValue(QStringLiteral("trayIconsRenderSize"), v.icons.tray.renderSize);
|
||||
settings.setValue(QStringLiteral("statusIconsStrokeWidth"), static_cast<int>(v.icons.status.strokeWidth));
|
||||
settings.setValue(QStringLiteral("trayIconsStrokeWidth"), static_cast<int>(v.icons.tray.strokeWidth));
|
||||
settings.setValue(QStringLiteral("distinguishTrayIcons"), v.icons.distinguishTrayIcons);
|
||||
settings.setValue(QStringLiteral("preferIconsFromTheme"), v.icons.preferIconsFromTheme);
|
||||
settings.beginGroup(QStringLiteral("positioning"));
|
||||
|
|
|
@ -583,6 +583,10 @@ QWidget *IconsOptionPage::setupWidget()
|
|||
break;
|
||||
}
|
||||
|
||||
// allow changing stroke thickness
|
||||
QObject::connect(ui()->thickStrokeWidthCheckBox, &QCheckBox::toggled, widget,
|
||||
[this](bool thick) { m_settings.strokeWidth = thick ? StatusIconStrokeWidth::Thick : StatusIconStrokeWidth::Normal; });
|
||||
|
||||
// populate form for status icon colors
|
||||
auto *const gridLayout = ui()->gridLayout;
|
||||
auto *const statusIconsGroupBox = ui()->statusIconsGroupBox;
|
||||
|
@ -606,19 +610,20 @@ QWidget *IconsOptionPage::setupWidget()
|
|||
|
||||
// setup preview
|
||||
gridLayout->addWidget(widgetsForColor.previewLabel, index, 4, Qt::AlignCenter);
|
||||
const auto updatePreview = [&widgetsForColor] {
|
||||
const auto updatePreview = [this, &widgetsForColor] {
|
||||
widgetsForColor.previewLabel->setPixmap(renderSvgImage(makeSyncthingIcon(
|
||||
StatusIconColorSet{
|
||||
widgetsForColor.colorButtons[0]->color(),
|
||||
widgetsForColor.colorButtons[1]->color(),
|
||||
widgetsForColor.colorButtons[2]->color(),
|
||||
},
|
||||
widgetsForColor.statusEmblem),
|
||||
widgetsForColor.statusEmblem, m_settings.strokeWidth),
|
||||
widgetsForColor.previewLabel->maximumSize()));
|
||||
};
|
||||
for (const auto &colorButton : widgetsForColor.colorButtons) {
|
||||
QObject::connect(colorButton, &ColorButton::colorChanged, updatePreview);
|
||||
QObject::connect(colorButton, &ColorButton::colorChanged, widget, updatePreview);
|
||||
}
|
||||
QObject::connect(ui()->thickStrokeWidthCheckBox, &QCheckBox::toggled, widget, updatePreview);
|
||||
|
||||
// setup color buttons
|
||||
widgetsForColor.colorButtons[0]->setColor(colorMapping.setting.backgroundStart);
|
||||
|
@ -635,27 +640,27 @@ QWidget *IconsOptionPage::setupWidget()
|
|||
|
||||
// setup presets menu
|
||||
auto *const presetsMenu = new QMenu(widget);
|
||||
presetsMenu->addAction(QCoreApplication::translate("QtGui::IconsOptionPageBase", "Colorful background with gradient (default)"), [this] {
|
||||
presetsMenu->addAction(QCoreApplication::translate("QtGui::IconsOptionPageBase", "Colorful background with gradient (default)"), widget, [this] {
|
||||
m_settings = Data::StatusIconSettings();
|
||||
update();
|
||||
});
|
||||
presetsMenu->addAction(
|
||||
QCoreApplication::translate("QtGui::IconsOptionPageBase", "Transparent background and dark foreground (for bright themes)"), [this] {
|
||||
QCoreApplication::translate("QtGui::IconsOptionPageBase", "Transparent background and dark foreground (for bright themes)"), widget, [this] {
|
||||
m_settings = Data::StatusIconSettings(Data::StatusIconSettings::BrightTheme{});
|
||||
update();
|
||||
});
|
||||
presetsMenu->addAction(
|
||||
QCoreApplication::translate("QtGui::IconsOptionPageBase", "Transparent background and bright foreground (for dark themes)"), [this] {
|
||||
QCoreApplication::translate("QtGui::IconsOptionPageBase", "Transparent background and bright foreground (for dark themes)"), widget, [this] {
|
||||
m_settings = Data::StatusIconSettings(Data::StatusIconSettings::DarkTheme{});
|
||||
update();
|
||||
});
|
||||
|
||||
// setup additional buttons
|
||||
ui()->restoreDefaultsPushButton->setMenu(presetsMenu);
|
||||
QObject::connect(ui()->restorePreviousPushButton, &QPushButton::clicked, [this] { reset(); });
|
||||
QObject::connect(ui()->restorePreviousPushButton, &QPushButton::clicked, widget, [this] { reset(); });
|
||||
|
||||
// setup slider
|
||||
QObject::connect(ui()->renderingSizeSlider, &QSlider::valueChanged, [this](int value) {
|
||||
QObject::connect(ui()->renderingSizeSlider, &QSlider::valueChanged, widget, [this](int value) {
|
||||
m_settings.renderSize = QSize(value, value);
|
||||
auto *const label = ui()->renderingSizeLabel;
|
||||
if (const auto scaleFactor = label->devicePixelRatioF(); scaleFactor == 1.0) {
|
||||
|
@ -695,6 +700,7 @@ bool IconsOptionPage::apply()
|
|||
void IconsOptionPage::update()
|
||||
{
|
||||
ui()->renderingSizeSlider->setValue(std::max(m_settings.renderSize.width(), m_settings.renderSize.height()));
|
||||
ui()->thickStrokeWidthCheckBox->setChecked(m_settings.strokeWidth == StatusIconStrokeWidth::Thick);
|
||||
for (auto &widgetsForColor : m_widgets) {
|
||||
widgetsForColor.colorButtons[0]->setColor(widgetsForColor.setting->backgroundStart);
|
||||
widgetsForColor.colorButtons[1]->setColor(widgetsForColor.setting->backgroundEnd);
|
||||
|
|
Loading…
Reference in New Issue