/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Data Visualization module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 or (at your option) any later version ** approved by the KDE Free Qt Foundation. The licenses are as published by ** the Free Software Foundation and appearing in the file LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "declarativetheme_p.h" QT_BEGIN_NAMESPACE_DATAVISUALIZATION DeclarativeTheme3D::DeclarativeTheme3D(QObject *parent) : Q3DTheme(parent), m_colors(QList()), m_gradients(QList()), m_singleHLGradient(0), m_multiHLGradient(0), m_dummyGradients(false), m_dummyColors(false) { connect(this, &Q3DTheme::typeChanged, this, &DeclarativeTheme3D::handleTypeChange); } DeclarativeTheme3D::~DeclarativeTheme3D() { } QQmlListProperty DeclarativeTheme3D::themeChildren() { return QQmlListProperty(this, this, &DeclarativeTheme3D::appendThemeChildren, 0, 0, 0); } void DeclarativeTheme3D::appendThemeChildren(QQmlListProperty *list, QObject *element) { Q_UNUSED(list) Q_UNUSED(element) // Nothing to do, themeChildren is there only to enable scoping gradient items in Theme3D item. } void DeclarativeTheme3D::handleTypeChange(Theme themeType) { Q_UNUSED(themeType) // Theme changed, disconnect base color/gradient connections if (!m_colors.isEmpty()) { foreach (DeclarativeColor *item, m_colors) disconnect(item, 0, this, 0); m_colors.clear(); } if (!m_gradients.isEmpty()) { foreach (ColorGradient *item, m_gradients) disconnect(item, 0, this, 0); m_gradients.clear(); } } void DeclarativeTheme3D::handleBaseColorUpdate() { int colorCount = m_colors.size(); int changed = 0; // Check which one changed DeclarativeColor *color = qobject_cast(QObject::sender()); for (int i = 0; i < colorCount; i++) { if (color == m_colors.at(i)) { changed = i; break; } } // Update the changed one from the list QList list = Q3DTheme::baseColors(); list[changed] = m_colors.at(changed)->color(); // Set the changed list Q3DTheme::setBaseColors(list); } void DeclarativeTheme3D::handleBaseGradientUpdate() { int gradientCount = m_gradients.size(); int changed = 0; // Check which one changed ColorGradient *gradient = qobject_cast(QObject::sender()); for (int i = 0; i < gradientCount; i++) { if (gradient == m_gradients.at(i)) { changed = i; break; } } // Update the changed one from the list QList list = Q3DTheme::baseGradients(); list[changed] = convertGradient(gradient); // Set the changed list Q3DTheme::setBaseGradients(list); } void DeclarativeTheme3D::handleSingleHLGradientUpdate() { if (m_singleHLGradient) setThemeGradient(m_singleHLGradient, GradientTypeSingleHL); } void DeclarativeTheme3D::handleMultiHLGradientUpdate() { if (m_multiHLGradient) setThemeGradient(m_multiHLGradient, GradientTypeMultiHL); } void DeclarativeTheme3D::setSingleHighlightGradient(ColorGradient *gradient) { // connect new / disconnect old if (gradient != m_singleHLGradient) { if (m_singleHLGradient) QObject::disconnect(m_singleHLGradient, 0, this, 0); m_singleHLGradient = gradient; if (m_singleHLGradient) { QObject::connect(m_singleHLGradient, &ColorGradient::updated, this, &DeclarativeTheme3D::handleSingleHLGradientUpdate); } emit singleHighlightGradientChanged(m_singleHLGradient); } if (m_singleHLGradient) setThemeGradient(m_singleHLGradient, GradientTypeSingleHL); } ColorGradient *DeclarativeTheme3D::singleHighlightGradient() const { return m_singleHLGradient; } void DeclarativeTheme3D::setMultiHighlightGradient(ColorGradient *gradient) { // connect new / disconnect old if (gradient != m_multiHLGradient) { if (m_multiHLGradient) QObject::disconnect(m_multiHLGradient, 0, this, 0); m_multiHLGradient = gradient; if (m_multiHLGradient) { QObject::connect(m_multiHLGradient, &ColorGradient::updated, this, &DeclarativeTheme3D::handleMultiHLGradientUpdate); } emit multiHighlightGradientChanged(m_multiHLGradient); } if (m_multiHLGradient) setThemeGradient(m_multiHLGradient, GradientTypeMultiHL); } ColorGradient *DeclarativeTheme3D::multiHighlightGradient() const { return m_multiHLGradient; } void DeclarativeTheme3D::classBegin() { // Turn off predefined type forcing for the duration of initial class construction // so that predefined type customization can be done. d_ptr->setForcePredefinedType(false); } void DeclarativeTheme3D::componentComplete() { d_ptr->setForcePredefinedType(true); } void DeclarativeTheme3D::setThemeGradient(ColorGradient *gradient, GradientType type) { QLinearGradient newGradient = convertGradient(gradient); switch (type) { case GradientTypeSingleHL: Q3DTheme::setSingleHighlightGradient(newGradient); break; case GradientTypeMultiHL: Q3DTheme::setMultiHighlightGradient(newGradient); break; default: qWarning("Incorrect usage. Type may be GradientTypeSingleHL or GradientTypeMultiHL."); break; } } QLinearGradient DeclarativeTheme3D::convertGradient(ColorGradient *gradient) { QLinearGradient newGradient; QGradientStops stops; QList qmlstops = gradient->m_stops; // Get sorted gradient stops for (int i = 0; i < qmlstops.size(); i++) { int j = 0; while (j < stops.size() && stops.at(j).first < qmlstops[i]->position()) j++; stops.insert(j, QGradientStop(qmlstops.at(i)->position(), qmlstops.at(i)->color())); } newGradient.setStops(stops); return newGradient; } ColorGradient *DeclarativeTheme3D::convertGradient(const QLinearGradient &gradient) { ColorGradient *newGradient = new ColorGradient(this); QGradientStops stops = gradient.stops(); ColorGradientStop *qmlstop; // Convert stops for (int i = 0; i < stops.size(); i++) { qmlstop = new ColorGradientStop(newGradient); qmlstop->setColor(stops.at(i).second); qmlstop->setPosition(stops.at(i).first); newGradient->m_stops.append(qmlstop); } return newGradient; } void DeclarativeTheme3D::addColor(DeclarativeColor *color) { if (!color) { qWarning("Color is invalid, use ThemeColor"); return; } clearDummyColors(); m_colors.append(color); connect(color, &DeclarativeColor::colorChanged, this, &DeclarativeTheme3D::handleBaseColorUpdate); QList list = Q3DTheme::baseColors(); list.append(color->color()); Q3DTheme::setBaseColors(list); } QList DeclarativeTheme3D::colorList() { if (m_colors.isEmpty()) { // Create dummy ThemeColors from theme's colors m_dummyColors = true; QList list = Q3DTheme::baseColors(); foreach (QColor item, list) { DeclarativeColor *color = new DeclarativeColor(this); color->setColor(item); m_colors.append(color); connect(color, &DeclarativeColor::colorChanged, this, &DeclarativeTheme3D::handleBaseColorUpdate); } } return m_colors; } void DeclarativeTheme3D::clearColors() { clearDummyColors(); foreach (DeclarativeColor *item, m_colors) disconnect(item, 0, this, 0); m_colors.clear(); Q3DTheme::setBaseColors(QList()); } void DeclarativeTheme3D::clearDummyColors() { if (m_dummyColors) { foreach (DeclarativeColor *item, m_colors) delete item; m_colors.clear(); m_dummyColors = false; } } void DeclarativeTheme3D::addGradient(ColorGradient *gradient) { if (!gradient) { qWarning("Gradient is invalid, use ColorGradient"); return; } clearDummyGradients(); m_gradients.append(gradient); connect(gradient, &ColorGradient::updated, this, &DeclarativeTheme3D::handleBaseGradientUpdate); QList list = Q3DTheme::baseGradients(); list.append(convertGradient(gradient)); Q3DTheme::setBaseGradients(list); } QList DeclarativeTheme3D::gradientList() { if (m_gradients.isEmpty()) { // Create dummy ColorGradients from theme's gradients m_dummyGradients = true; QList list = Q3DTheme::baseGradients(); foreach (QLinearGradient item, list) { ColorGradient *gradient = convertGradient(item); m_gradients.append(gradient); connect(gradient, &ColorGradient::updated, this, &DeclarativeTheme3D::handleBaseGradientUpdate); } } return m_gradients; } void DeclarativeTheme3D::clearGradients() { clearDummyGradients(); foreach (ColorGradient *item, m_gradients) disconnect(item, 0, this, 0); m_gradients.clear(); Q3DTheme::setBaseGradients(QList()); } void DeclarativeTheme3D::clearDummyGradients() { if (m_dummyGradients) { foreach (ColorGradient *item, m_gradients) delete item; m_gradients.clear(); m_dummyGradients = false; } } QQmlListProperty DeclarativeTheme3D::baseColors() { return QQmlListProperty(this, this, &DeclarativeTheme3D::appendBaseColorsFunc, &DeclarativeTheme3D::countBaseColorsFunc, &DeclarativeTheme3D::atBaseColorsFunc, &DeclarativeTheme3D::clearBaseColorsFunc); } void DeclarativeTheme3D::appendBaseColorsFunc(QQmlListProperty *list, DeclarativeColor *color) { reinterpret_cast(list->data)->addColor(color); } int DeclarativeTheme3D::countBaseColorsFunc(QQmlListProperty *list) { return reinterpret_cast(list->data)->colorList().size(); } DeclarativeColor *DeclarativeTheme3D::atBaseColorsFunc(QQmlListProperty *list, int index) { return reinterpret_cast(list->data)->colorList().at(index); } void DeclarativeTheme3D::clearBaseColorsFunc(QQmlListProperty *list) { reinterpret_cast(list->data)->clearColors(); } QQmlListProperty DeclarativeTheme3D::baseGradients() { return QQmlListProperty(this, this, &DeclarativeTheme3D::appendBaseGradientsFunc, &DeclarativeTheme3D::countBaseGradientsFunc, &DeclarativeTheme3D::atBaseGradientsFunc, &DeclarativeTheme3D::clearBaseGradientsFunc); } void DeclarativeTheme3D::appendBaseGradientsFunc(QQmlListProperty *list, ColorGradient *gradient) { reinterpret_cast(list->data)->addGradient(gradient); } int DeclarativeTheme3D::countBaseGradientsFunc(QQmlListProperty *list) { return reinterpret_cast(list->data)->gradientList().size(); } ColorGradient *DeclarativeTheme3D::atBaseGradientsFunc(QQmlListProperty *list, int index) { return reinterpret_cast(list->data)->gradientList().at(index); } void DeclarativeTheme3D::clearBaseGradientsFunc(QQmlListProperty *list) { reinterpret_cast(list->data)->clearGradients(); } QT_END_NAMESPACE_DATAVISUALIZATION