rework ColorScope

Since some time PlasmaCore had the very useful ColorScope class,
which can semi-automatically make children take colors of the
View, Button or Complementary color groups.
Unfortunately it didn't support dynamic reparenting, giving
wrong colors in some cases (see black on black battery on the phone)

even tough is a bit complicated, now by cascading signals down the
children tree, support on the fly apply of the new context upon
reparenting.

also add a manual test case showing text, rectangles and icons
dynamically changing color as they get moved from one scope
to the other

REVIEW:126654
Change-Id: I3d746b73eac55a359c4706fb719b4d5018677fb5
This commit is contained in:
Marco Martin 2016-01-06 19:02:38 +01:00
parent e4ea8d55b7
commit e565c5c225
3 changed files with 121 additions and 33 deletions

View File

@ -24,6 +24,7 @@
#include <QQmlContext>
#include <QQmlEngine>
QHash<QObject *, ColorScope *> ColorScope::s_attachedScopes = QHash<QObject *, ColorScope *>();
ColorScope::ColorScope(QQuickItem *parent)
: QQuickItem(parent),
@ -31,17 +32,29 @@ ColorScope::ColorScope(QQuickItem *parent)
m_group(Plasma::Theme::NormalColorGroup)
{
connect(&m_theme, &Plasma::Theme::themeChanged, this, &ColorScope::colorsChanged);
if (parent) {
connect(parent, &QQuickItem::parentChanged, this, &ColorScope::colorGroupChanged);
connect(parent, &QQuickItem::parentChanged, this, &ColorScope::colorsChanged);
}
}
ColorScope::~ColorScope()
{
s_attachedScopes.remove(parentItem());
}
ColorScope *ColorScope::qmlAttachedProperties(QObject *object)
{
QQuickItem *qp = qobject_cast<QQuickItem *>(object);
if (ColorScope::s_attachedScopes.contains(object)) {
return s_attachedScopes.value(object);
}
ColorScope *s = new ColorScope(qp);
s_attachedScopes[object] = s;
if (!qp) {
s->setParent(object);
}
@ -51,46 +64,43 @@ ColorScope *ColorScope::qmlAttachedProperties(QObject *object)
ColorScope *ColorScope::findParentScope() const
{
QObject *p = parentItem();
if (!p) {
p = parent();
QQuickItem *p = 0;
if (parentItem()) {
p = parentItem()->parentItem();
}
while (p) {
ColorScope *c = qobject_cast<ColorScope *>(p);
if (c) {
if (c != m_parentScope) {
if (m_parentScope) {
disconnect(m_parentScope.data(), &ColorScope::colorGroupChanged,
this, &ColorScope::colorGroupChanged);
disconnect(m_parentScope.data(), &ColorScope::colorsChanged,
this, &ColorScope::colorsChanged);
}
connect(c, &ColorScope::colorGroupChanged,
this, &ColorScope::colorGroupChanged);
connect(c, &ColorScope::colorsChanged,
this, &ColorScope::colorsChanged);
//HACK
const_cast<ColorScope *>(this)->m_parentScope = c;
}
return m_parentScope;
}
if (QQuickItem *qi = qobject_cast<QQuickItem *>(p)) {
p = qi->parentItem();
} else {
p = p->parent();
if (!p || !parentItem()) {
if (m_parentScope) {
disconnect(m_parentScope.data(), &ColorScope::colorGroupChanged,
this, &ColorScope::colorGroupChanged);
disconnect(m_parentScope.data(), &ColorScope::colorsChanged,
this, &ColorScope::colorsChanged);
}
return 0;
}
if (m_parentScope) {
disconnect(m_parentScope.data(), &ColorScope::colorGroupChanged,
ColorScope *c = qobject_cast<ColorScope *>(p);
if (!c) {
c = qmlAttachedProperties(p);
}
if (c != m_parentScope) {
if (m_parentScope) {
disconnect(m_parentScope.data(), &ColorScope::colorGroupChanged,
this, &ColorScope::colorGroupChanged);
disconnect(m_parentScope.data(), &ColorScope::colorsChanged,
this, &ColorScope::colorsChanged);
}
connect(c, &ColorScope::colorGroupChanged,
this, &ColorScope::colorGroupChanged);
disconnect(m_parentScope.data(), &ColorScope::colorsChanged,
connect(c, &ColorScope::colorsChanged,
this, &ColorScope::colorsChanged);
//HACK
const_cast<ColorScope *>(this)->m_parentScope = c;
}
const_cast<ColorScope *>(this)->m_parentScope.clear();
return 0;
return m_parentScope;
}
void ColorScope::setColorGroup(Plasma::Theme::ColorGroup group)

View File

@ -91,6 +91,8 @@ private:
Plasma::Theme m_theme;
Plasma::Theme::ColorGroup m_group;
QPointer<ColorScope> m_parentScope;
static QHash<QObject *, ColorScope *> s_attachedScopes;
};
QML_DECLARE_TYPEINFO(ColorScope, QML_HAS_ATTACHED_PROPERTIES)

76
tests/colorcontext.qml Normal file
View File

@ -0,0 +1,76 @@
/*
* Copyright 2016 Marco Martin <mart@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.1
import QtQuick.Layouts 1.2
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
ColumnLayout {
width: 600
height: 600
PlasmaCore.ColorScope {
id: scope1
colorGroup: PlasmaCore.Theme.NormalColorGroup
Layout.minimumWidth: rect1.width
Layout.minimumHeight: rect1.height
Rectangle {
id: rect1
width: units.gridUnit * 30
height: units.gridUnit * 15
color: PlasmaCore.ColorScope.backgroundColor
Column {
id: widgetsParent
anchors.centerIn: parent
Row {
PlasmaCore.IconItem {
colorGroup: PlasmaCore.ColorScope.colorGroup
source: "audio-volume-medium"
}
PlasmaComponents.Label {
text: "Some text"
}
}
Rectangle {
width: parent.width
height: units.gridUnit * 3
color: PlasmaCore.ColorScope.textColor
}
}
}
}
PlasmaCore.ColorScope {
id: scope2
colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
Layout.minimumWidth: rect1.width
Layout.minimumHeight: rect1.height
Rectangle {
id: rect2
width: units.gridUnit * 30
height: units.gridUnit * 15
color: PlasmaCore.ColorScope.backgroundColor
}
}
PlasmaComponents.Button {
y: 300
text: "switch"
onClicked: widgetsParent.parent == rect2 ? widgetsParent.parent = rect1 : widgetsParent.parent = rect2
}
}