| 779 | } |
| 780 | |
| 781 | void ThemeManager::setColor(const QString& token, const QColor& color) |
| 782 | { |
| 783 | if (!color.isValid()) return; |
| 784 | // Live-edit path stores the QColor as a hex string so cssFragment() / |
| 785 | // resolve() pick it up the same way they pick up freshly-loaded tokens. |
| 786 | // Use colorToTokenString() — bare QColor::name() drops alpha, which |
| 787 | // breaks rgba editing through the picker. |
| 788 | // Skip the emit if nothing actually changed (avoids burning a re-paint |
| 789 | // cycle on a no-op edit). |
| 790 | const QString hex = colorToTokenString(color); |
| 791 | const auto it = m_tokens.constFind(token); |
| 792 | if (it != m_tokens.constEnd() && it.value().toString() == hex) return; |
| 793 | m_tokens.insert(token, QVariant(hex)); |
| 794 | // Smart-invalidation hint scope — reapplyAllTrackedStyleSheets reads |
| 795 | // this during the synchronous themeChanged dispatch and skips every |
| 796 | // tracked widget whose template doesn't reference `token`. Cleared |
| 797 | // before returning so subsequent full-theme reloads (setActiveTheme) |
| 798 | // walk every widget. |
| 799 | m_currentEditToken = token; |
| 800 | emit themeChanged(); |
| 801 | m_currentEditToken.clear(); |
| 802 | saveActiveTheme(); |
| 803 | } |
| 804 | |
| 805 | void ThemeManager::setSizing(const QString& token, int value) |
| 806 | { |