8#include "platformtheme.h"
9#include "basictheme_p.h"
12#include <QGuiApplication>
17#include <QQuickWindow>
23#include <unordered_map>
43struct TypeInitializer {
53static TypeInitializer initializer;
58class PlatformThemeData :
public QObject
78 AlternateBackgroundColor,
80 ActiveBackgroundColor,
82 VisitedLinkBackgroundColor,
83 NegativeBackgroundColor,
84 NeutralBackgroundColor,
85 PositiveBackgroundColor,
94 using ColorMap = std::unordered_map<std::underlying_type<ColorRole>::type,
QColor>;
101 PlatformTheme::ColorGroup colorGroup = PlatformTheme::Active;
103 std::array<QColor, ColorRoleCount> colors;
111 using Watcher = PlatformTheme *;
116 if (
sender != owner || colorSet == set) {
120 auto oldValue = colorSet;
124 notifyWatchers<PlatformTheme::ColorSet>(
sender, oldValue, set);
127 inline void setColorGroup(PlatformTheme *
sender, PlatformTheme::ColorGroup group)
129 if (
sender != owner || colorGroup == group) {
133 auto oldValue = colorGroup;
138 notifyWatchers<PlatformTheme::ColorGroup>(
sender, oldValue, group);
141 inline void setColor(PlatformTheme *
sender, ColorRole role,
const QColor &color)
143 if (
sender != owner || colors[role] == color) {
147 auto oldValue = colors[role];
149 colors[role] = color;
150 updatePalette(palette, colors);
152 notifyWatchers<QColor>(
sender, oldValue, colors[role]);
155 inline void addChangeWatcher(PlatformTheme *
object)
160 inline void removeChangeWatcher(PlatformTheme *
object)
166 inline void notifyWatchers(PlatformTheme *
sender,
const T &oldValue,
const T &newValue)
168 for (
auto object : std::as_const(watchers)) {
169 PlatformThemeEvents::PropertyChangedEvent<T>
event(
sender, oldValue, newValue);
175 inline static void updatePalette(
QPalette &palette,
const std::array<QColor, ColorRoleCount> &colors)
177 for (std::size_t i = 0; i < colors.size(); ++i) {
178 setPaletteColor(palette, ColorRole(i), colors.at(i));
183 inline static void updatePalette(
QPalette &palette,
const ColorMap &colors)
185 for (
auto entry : colors) {
186 setPaletteColor(palette, ColorRole(entry.first), entry.second);
190 inline static void setPaletteColor(
QPalette &palette, ColorRole role,
const QColor &color)
198 case BackgroundColor:
203 case AlternateBackgroundColor:
209 case HighlightedTextColor:
215 case VisitedLinkColor:
225class PlatformThemePrivate
228 PlatformThemePrivate()
230 , supportsIconColoring(false)
231 , pendingColorChange(false)
232 , pendingChildUpdate(false)
233 , colorSet(PlatformTheme::
Window)
234 , colorGroup(PlatformTheme::Active)
238 inline QColor color(
const PlatformTheme *theme, PlatformThemeData::ColorRole color)
const
244 QColor value = data->colors.at(color);
246 if (data->owner != theme && localOverrides) {
247 auto itr = localOverrides->find(color);
248 if (itr != localOverrides->end()) {
256 inline void setColor(PlatformTheme *theme, PlatformThemeData::ColorRole color,
const QColor &value)
258 if (!localOverrides) {
259 localOverrides = std::make_unique<PlatformThemeData::ColorMap>();
264 auto itr = localOverrides->find(color);
265 if (itr != localOverrides->end()) {
266 localOverrides->erase(itr);
276 emitCompressedColorChanged(theme);
282 auto itr = localOverrides->find(color);
283 if (itr != localOverrides->end() && itr->second == value && (data && data->owner != theme)) {
287 (*localOverrides)[color] = value;
290 data->setColor(theme, color, value);
293 emitCompressedColorChanged(theme);
296 inline void setDataColor(PlatformTheme *theme, PlatformThemeData::ColorRole color,
const QColor &value)
302 if (localOverrides) {
303 auto itr = localOverrides->find(color);
304 if (itr != localOverrides->end()) {
310 data->setColor(theme, color, value);
314 inline void emitCompressedColorChanged(PlatformTheme *theme)
316 if (pendingColorChange) {
320 pendingColorChange =
true;
324 inline void queueChildUpdate(PlatformTheme *theme)
326 if (pendingChildUpdate) {
330 pendingChildUpdate =
true;
334 pendingChildUpdate =
false;
335 theme->updateChildren(theme->parent());
350 std::shared_ptr<PlatformThemeData> data;
353 std::unique_ptr<PlatformThemeData::ColorMap> localOverrides;
356 bool supportsIconColoring : 1;
357 bool pendingColorChange : 1;
358 bool pendingChildUpdate : 1;
364 uint8_t colorSet : 4;
365 uint8_t colorGroup : 4;
369 static_assert(PlatformTheme::ColorGroupCount <= 16,
"PlatformTheme::ColorGroup contains more elements than can be stored in PlatformThemePrivate");
370 static_assert(
PlatformTheme::ColorSetCount <= 16,
"PlatformTheme::ColorSet contains more elements than can be stored in PlatformThemePrivate");
375PlatformTheme::PlatformTheme(
QObject *parent)
377 , d(new PlatformThemePrivate)
379 if (
QQuickItem *item = qobject_cast<QQuickItem *>(parent)) {
387PlatformTheme::~PlatformTheme()
390 d->data->removeChangeWatcher(
this);
396void PlatformTheme::setColorSet(PlatformTheme::ColorSet colorSet)
398 d->colorSet = colorSet;
401 d->data->setColorSet(
this, colorSet);
405PlatformTheme::ColorSet PlatformTheme::colorSet()
const
407 return d->data ? d->data->colorSet :
Window;
410void PlatformTheme::setColorGroup(PlatformTheme::ColorGroup colorGroup)
412 d->colorGroup = colorGroup;
415 d->data->setColorGroup(
this, colorGroup);
419PlatformTheme::ColorGroup PlatformTheme::colorGroup()
const
421 return d->data ? d->data->colorGroup : Active;
424bool PlatformTheme::inherit()
const
429void PlatformTheme::setInherit(
bool inherit)
431 if (inherit == d->inherit) {
435 d->inherit = inherit;
438 Q_EMIT inheritChanged(inherit);
441QColor PlatformTheme::textColor()
const
443 return d->color(
this, PlatformThemeData::TextColor);
446QColor PlatformTheme::disabledTextColor()
const
448 return d->color(
this, PlatformThemeData::DisabledTextColor);
451QColor PlatformTheme::highlightColor()
const
453 return d->color(
this, PlatformThemeData::HighlightColor);
456QColor PlatformTheme::highlightedTextColor()
const
458 return d->color(
this, PlatformThemeData::HighlightedTextColor);
461QColor PlatformTheme::backgroundColor()
const
463 return d->color(
this, PlatformThemeData::BackgroundColor);
466QColor PlatformTheme::alternateBackgroundColor()
const
468 return d->color(
this, PlatformThemeData::AlternateBackgroundColor);
471QColor PlatformTheme::activeTextColor()
const
473 return d->color(
this, PlatformThemeData::ActiveTextColor);
476QColor PlatformTheme::activeBackgroundColor()
const
478 return d->color(
this, PlatformThemeData::ActiveBackgroundColor);
481QColor PlatformTheme::linkColor()
const
483 return d->color(
this, PlatformThemeData::LinkColor);
486QColor PlatformTheme::linkBackgroundColor()
const
488 return d->color(
this, PlatformThemeData::LinkBackgroundColor);
491QColor PlatformTheme::visitedLinkColor()
const
493 return d->color(
this, PlatformThemeData::VisitedLinkColor);
496QColor PlatformTheme::visitedLinkBackgroundColor()
const
498 return d->color(
this, PlatformThemeData::VisitedLinkBackgroundColor);
501QColor PlatformTheme::negativeTextColor()
const
503 return d->color(
this, PlatformThemeData::NegativeTextColor);
506QColor PlatformTheme::negativeBackgroundColor()
const
508 return d->color(
this, PlatformThemeData::NegativeBackgroundColor);
511QColor PlatformTheme::neutralTextColor()
const
513 return d->color(
this, PlatformThemeData::NeutralTextColor);
516QColor PlatformTheme::neutralBackgroundColor()
const
518 return d->color(
this, PlatformThemeData::NeutralBackgroundColor);
521QColor PlatformTheme::positiveTextColor()
const
523 return d->color(
this, PlatformThemeData::PositiveTextColor);
526QColor PlatformTheme::positiveBackgroundColor()
const
528 return d->color(
this, PlatformThemeData::PositiveBackgroundColor);
531QColor PlatformTheme::focusColor()
const
533 return d->color(
this, PlatformThemeData::FocusColor);
536QColor PlatformTheme::hoverColor()
const
538 return d->color(
this, PlatformThemeData::HoverColor);
542void PlatformTheme::setTextColor(
const QColor &color)
544 d->setDataColor(
this, PlatformThemeData::TextColor, color);
547void PlatformTheme::setDisabledTextColor(
const QColor &color)
549 d->setDataColor(
this, PlatformThemeData::DisabledTextColor, color);
552void PlatformTheme::setBackgroundColor(
const QColor &color)
554 d->setDataColor(
this, PlatformThemeData::BackgroundColor, color);
557void PlatformTheme::setAlternateBackgroundColor(
const QColor &color)
559 d->setDataColor(
this, PlatformThemeData::AlternateBackgroundColor, color);
562void PlatformTheme::setHighlightColor(
const QColor &color)
564 d->setDataColor(
this, PlatformThemeData::HighlightColor, color);
567void PlatformTheme::setHighlightedTextColor(
const QColor &color)
569 d->setDataColor(
this, PlatformThemeData::HighlightedTextColor, color);
572void PlatformTheme::setActiveTextColor(
const QColor &color)
574 d->setDataColor(
this, PlatformThemeData::ActiveTextColor, color);
577void PlatformTheme::setActiveBackgroundColor(
const QColor &color)
579 d->setDataColor(
this, PlatformThemeData::ActiveBackgroundColor, color);
582void PlatformTheme::setLinkColor(
const QColor &color)
584 d->setDataColor(
this, PlatformThemeData::LinkColor, color);
587void PlatformTheme::setLinkBackgroundColor(
const QColor &color)
589 d->setDataColor(
this, PlatformThemeData::LinkBackgroundColor, color);
592void PlatformTheme::setVisitedLinkColor(
const QColor &color)
594 d->setDataColor(
this, PlatformThemeData::VisitedLinkColor, color);
597void PlatformTheme::setVisitedLinkBackgroundColor(
const QColor &color)
599 d->setDataColor(
this, PlatformThemeData::VisitedLinkBackgroundColor, color);
602void PlatformTheme::setNegativeTextColor(
const QColor &color)
604 d->setDataColor(
this, PlatformThemeData::NegativeTextColor, color);
607void PlatformTheme::setNegativeBackgroundColor(
const QColor &color)
609 d->setDataColor(
this, PlatformThemeData::NegativeBackgroundColor, color);
612void PlatformTheme::setNeutralTextColor(
const QColor &color)
614 d->setDataColor(
this, PlatformThemeData::NeutralTextColor, color);
617void PlatformTheme::setNeutralBackgroundColor(
const QColor &color)
619 d->setDataColor(
this, PlatformThemeData::NeutralBackgroundColor, color);
622void PlatformTheme::setPositiveTextColor(
const QColor &color)
624 d->setDataColor(
this, PlatformThemeData::PositiveTextColor, color);
627void PlatformTheme::setPositiveBackgroundColor(
const QColor &color)
629 d->setDataColor(
this, PlatformThemeData::PositiveBackgroundColor, color);
632void PlatformTheme::setHoverColor(
const QColor &color)
634 d->setDataColor(
this, PlatformThemeData::HoverColor, color);
637void PlatformTheme::setFocusColor(
const QColor &color)
639 d->setDataColor(
this, PlatformThemeData::FocusColor, color);
643void PlatformTheme::setCustomTextColor(
const QColor &color)
645 d->setColor(
this, PlatformThemeData::TextColor, color);
648void PlatformTheme::setCustomDisabledTextColor(
const QColor &color)
650 d->setColor(
this, PlatformThemeData::DisabledTextColor, color);
653void PlatformTheme::setCustomBackgroundColor(
const QColor &color)
655 d->setColor(
this, PlatformThemeData::BackgroundColor, color);
658void PlatformTheme::setCustomAlternateBackgroundColor(
const QColor &color)
660 d->setColor(
this, PlatformThemeData::AlternateBackgroundColor, color);
663void PlatformTheme::setCustomHighlightColor(
const QColor &color)
665 d->setColor(
this, PlatformThemeData::HighlightColor, color);
668void PlatformTheme::setCustomHighlightedTextColor(
const QColor &color)
670 d->setColor(
this, PlatformThemeData::HighlightedTextColor, color);
673void PlatformTheme::setCustomActiveTextColor(
const QColor &color)
675 d->setColor(
this, PlatformThemeData::ActiveTextColor, color);
678void PlatformTheme::setCustomActiveBackgroundColor(
const QColor &color)
680 d->setColor(
this, PlatformThemeData::ActiveBackgroundColor, color);
683void PlatformTheme::setCustomLinkColor(
const QColor &color)
685 d->setColor(
this, PlatformThemeData::LinkColor, color);
688void PlatformTheme::setCustomLinkBackgroundColor(
const QColor &color)
690 d->setColor(
this, PlatformThemeData::LinkBackgroundColor, color);
693void PlatformTheme::setCustomVisitedLinkColor(
const QColor &color)
695 d->setColor(
this, PlatformThemeData::TextColor, color);
698void PlatformTheme::setCustomVisitedLinkBackgroundColor(
const QColor &color)
700 d->setColor(
this, PlatformThemeData::VisitedLinkBackgroundColor, color);
703void PlatformTheme::setCustomNegativeTextColor(
const QColor &color)
705 d->setColor(
this, PlatformThemeData::NegativeTextColor, color);
708void PlatformTheme::setCustomNegativeBackgroundColor(
const QColor &color)
710 d->setColor(
this, PlatformThemeData::NegativeBackgroundColor, color);
713void PlatformTheme::setCustomNeutralTextColor(
const QColor &color)
715 d->setColor(
this, PlatformThemeData::NeutralTextColor, color);
718void PlatformTheme::setCustomNeutralBackgroundColor(
const QColor &color)
720 d->setColor(
this, PlatformThemeData::NeutralBackgroundColor, color);
723void PlatformTheme::setCustomPositiveTextColor(
const QColor &color)
725 d->setColor(
this, PlatformThemeData::PositiveTextColor, color);
728void PlatformTheme::setCustomPositiveBackgroundColor(
const QColor &color)
730 d->setColor(
this, PlatformThemeData::PositiveBackgroundColor, color);
733void PlatformTheme::setCustomHoverColor(
const QColor &color)
735 d->setColor(
this, PlatformThemeData::HoverColor, color);
738void PlatformTheme::setCustomFocusColor(
const QColor &color)
740 d->setColor(
this, PlatformThemeData::FocusColor, color);
743QPalette PlatformTheme::palette()
const
749 auto palette = d->data->palette;
751 if (d->localOverrides) {
752 PlatformThemeData::updatePalette(palette, *d->localOverrides);
760 Q_UNUSED(customColor);
765bool PlatformTheme::supportsIconColoring()
const
767 return d->supportsIconColoring;
770void PlatformTheme::setSupportsIconColoring(
bool support)
772 d->supportsIconColoring = support;
775PlatformTheme *PlatformTheme::qmlAttachedProperties(
QObject *
object)
777 return new BasicTheme(
object);
780bool PlatformTheme::event(
QEvent *event)
782 if (
event->type() == PlatformThemeEvents::DataChangedEvent::type) {
783 auto changeEvent =
static_cast<PlatformThemeEvents::DataChangedEvent *
>(
event);
785 if (changeEvent->sender !=
this) {
789 if (changeEvent->oldValue) {
790 changeEvent->oldValue->removeChangeWatcher(
this);
793 if (changeEvent->newValue) {
794 auto data = changeEvent->newValue;
795 data->addChangeWatcher(
this);
797 Q_EMIT colorSetChanged(data->colorSet);
798 Q_EMIT colorGroupChanged(data->colorGroup);
800 d->emitCompressedColorChanged(
this);
806 if (
event->type() == PlatformThemeEvents::ColorSetChangedEvent::type) {
808 Q_EMIT colorSetChanged(d->data->colorSet);
813 if (
event->type() == PlatformThemeEvents::ColorGroupChangedEvent::type) {
815 Q_EMIT colorGroupChanged(d->data->colorGroup);
820 if (
event->type() == PlatformThemeEvents::ColorChangedEvent::type) {
821 d->emitCompressedColorChanged(
this);
825 if (
event->type() == PlatformThemeEvents::FontChangedEvent::type) {
836void PlatformTheme::update()
838 d->queueChildUpdate(
this);
840 auto oldData = d->data;
845 candidate = determineParent(candidate);
850 auto t =
static_cast<PlatformTheme *
>(qmlAttachedPropertiesObject<PlatformTheme>(candidate,
false));
851 if (t && t->d->data && t->d->data->owner == t) {
852 if (d->data == t->d->data) {
857 d->data = t->d->data;
859 PlatformThemeEvents::DataChangedEvent
event{
this, oldData, t->d->data};
865 }
else if (d->data->owner !=
this) {
872 d->data = std::make_shared<PlatformThemeData>();
873 d->data->owner =
this;
874 d->data->setColorSet(
this,
static_cast<ColorSet
>(d->colorSet));
875 d->data->setColorGroup(
this,
static_cast<ColorGroup
>(d->colorGroup));
878 if (d->localOverrides) {
879 for (
auto entry : *d->localOverrides) {
880 d->data->setColor(
this, PlatformThemeData::ColorRole(entry.first), entry.second);
884 PlatformThemeEvents::DataChangedEvent
event{
this, oldData, d->data};
888void PlatformTheme::updateChildren(
QObject *
object)
894 const auto children =
object->children();
895 for (
auto child : children) {
896 auto t =
static_cast<PlatformTheme *
>(qmlAttachedPropertiesObject<PlatformTheme>(child,
false));
900 updateChildren(child);
905void PlatformTheme::emitColorChanged()
908 Q_EMIT paletteChanged(d->data->palette);
911 Q_EMIT colorsChanged();
912 d->pendingColorChange =
false;
924 auto item = qobject_cast<QQuickItem *>(
object);
926 return item->parentItem();
928 return object->parent();
934#include "platformtheme.moc"
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
void update(Part *part, const QByteArray &data, qint64 dataSize)
bool isValid() const const
bool sendEvent(QObject *receiver, QEvent *event)
int registerEventType(int hint)
QIcon fromTheme(const QString &name)
void append(QList< T > &&value)
bool removeOne(const AT &t)
virtual bool event(QEvent *e)
QObject * sender() const const
void setColor(ColorGroup group, ColorRole role, const QColor &color)
void setCurrentColorGroup(ColorGroup cg)
void parentChanged(QQuickItem *)
void windowChanged(QQuickWindow *window)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)