1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #include "brushpropertymanager.h"
30 #include "qtpropertymanager.h"
31 #include "designerpropertymanager.h"
32 #include "qtpropertybrowserutils_p.h"
33 
34 #include <QtCore/qcoreapplication.h>
35 #include <QtCore/qvariant.h>
36 #include <QtCore/qstring.h>
37 
38 static const char *brushStyles[] = {
39 QT_TRANSLATE_NOOP("BrushPropertyManager", "No brush"),
40 QT_TRANSLATE_NOOP("BrushPropertyManager", "Solid"),
41 QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 1"),
42 QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 2"),
43 QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 3"),
44 QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 4"),
45 QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 5"),
46 QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 6"),
47 QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 7"),
48 QT_TRANSLATE_NOOP("BrushPropertyManager", "Horizontal"),
49 QT_TRANSLATE_NOOP("BrushPropertyManager", "Vertical"),
50 QT_TRANSLATE_NOOP("BrushPropertyManager", "Cross"),
51 QT_TRANSLATE_NOOP("BrushPropertyManager", "Backward diagonal"),
52 QT_TRANSLATE_NOOP("BrushPropertyManager", "Forward diagonal"),
53 QT_TRANSLATE_NOOP("BrushPropertyManager", "Crossing diagonal"),
54 };
55 
56 QT_BEGIN_NAMESPACE
57 
58 namespace qdesigner_internal {
59 
60 BrushPropertyManager::BrushPropertyManager() = default;
61 
brushStyleToIndex(Qt::BrushStyle st)62 int BrushPropertyManager::brushStyleToIndex(Qt::BrushStyle st)
63 {
64     switch (st) {
65     case Qt::NoBrush:       return 0;
66     case Qt::SolidPattern:  return 1;
67     case Qt::Dense1Pattern: return 2;
68     case Qt::Dense2Pattern: return 3;
69     case Qt::Dense3Pattern: return 4;
70     case Qt::Dense4Pattern: return 5;
71     case Qt::Dense5Pattern: return 6;
72     case Qt::Dense6Pattern: return 7;
73     case Qt::Dense7Pattern: return 8;
74     case Qt::HorPattern:    return 9;
75     case Qt::VerPattern:    return 10;
76     case Qt::CrossPattern:  return 11;
77     case Qt::BDiagPattern:  return 12;
78     case Qt::FDiagPattern:  return 13;
79     case Qt::DiagCrossPattern:       return 14;
80     default: break;
81     }
82     return 0;
83 }
84 
brushStyleIndexToStyle(int brushStyleIndex)85 Qt::BrushStyle BrushPropertyManager::brushStyleIndexToStyle(int brushStyleIndex)
86 {
87     switch (brushStyleIndex) {
88     case  0: return Qt::NoBrush;
89     case  1: return Qt::SolidPattern;
90     case  2: return Qt::Dense1Pattern;
91     case  3: return Qt::Dense2Pattern;
92     case  4: return Qt::Dense3Pattern;
93     case  5: return Qt::Dense4Pattern;
94     case  6: return Qt::Dense5Pattern;
95     case  7: return Qt::Dense6Pattern;
96     case  8: return Qt::Dense7Pattern;
97     case  9: return Qt::HorPattern;
98     case 10: return Qt::VerPattern;
99     case 11: return Qt::CrossPattern;
100     case 12: return Qt::BDiagPattern;
101     case 13: return Qt::FDiagPattern;
102     case 14: return Qt::DiagCrossPattern;
103     }
104     return Qt::NoBrush;
105 }
106 
107 static void clearBrushIcons();
108 
109 namespace {
110 class EnumIndexIconMap : public QMap<int, QIcon>
111 {
112 public:
EnumIndexIconMap()113     EnumIndexIconMap()
114     {
115         qAddPostRoutine(clearBrushIcons);
116     }
117 };
118 }
119 
Q_GLOBAL_STATIC(EnumIndexIconMap,brushIcons)120 Q_GLOBAL_STATIC(EnumIndexIconMap, brushIcons)
121 
122 static void clearBrushIcons()
123 {
124     brushIcons()->clear();
125 }
126 
brushStyleIcons()127 const BrushPropertyManager::EnumIndexIconMap &BrushPropertyManager::brushStyleIcons()
128 {
129     // Create a map of icons for the brush style editor
130     if (brushIcons()->empty()) {
131         const int brushStyleCount = sizeof(brushStyles)/sizeof(const char *);
132         QBrush brush(Qt::black);
133         for (int i = 0; i < brushStyleCount; i++) {
134             const Qt::BrushStyle style = brushStyleIndexToStyle(i);
135             brush.setStyle(style);
136             brushIcons()->insert(i, QtPropertyBrowserUtils::brushValueIcon(brush));
137         }
138     }
139     return *(brushIcons());
140 }
141 
brushStyleIndexToString(int brushStyleIndex)142 QString BrushPropertyManager::brushStyleIndexToString(int brushStyleIndex)
143 {
144     const int brushStyleCount = sizeof(brushStyles)/sizeof(const char *);
145     return brushStyleIndex < brushStyleCount ? QCoreApplication::translate("BrushPropertyManager", brushStyles[brushStyleIndex]) :  QString();
146 }
147 
initializeProperty(QtVariantPropertyManager * vm,QtProperty * property,int enumTypeId)148 void BrushPropertyManager::initializeProperty(QtVariantPropertyManager *vm, QtProperty *property, int enumTypeId)
149 {
150     m_brushValues.insert(property, QBrush());
151     // style
152     QtVariantProperty *styleSubProperty = vm->addProperty(enumTypeId, QCoreApplication::translate("BrushPropertyManager", "Style"));
153     property->addSubProperty(styleSubProperty);
154     QStringList styles;
155     for (const char *brushStyle : brushStyles)
156         styles.push_back(QCoreApplication::translate("BrushPropertyManager", brushStyle));
157     styleSubProperty->setAttribute(QStringLiteral("enumNames"), styles);
158     styleSubProperty->setAttribute(QStringLiteral("enumIcons"), QVariant::fromValue(brushStyleIcons()));
159     m_brushPropertyToStyleSubProperty.insert(property, styleSubProperty);
160     m_brushStyleSubPropertyToProperty.insert(styleSubProperty, property);
161     // color
162     QtVariantProperty *colorSubProperty = vm->addProperty(QVariant::Color, QCoreApplication::translate("BrushPropertyManager", "Color"));
163     property->addSubProperty(colorSubProperty);
164     m_brushPropertyToColorSubProperty.insert(property, colorSubProperty);
165     m_brushColorSubPropertyToProperty.insert(colorSubProperty, property);
166 }
167 
uninitializeProperty(QtProperty * property)168 bool BrushPropertyManager::uninitializeProperty(QtProperty *property)
169 {
170     const PropertyBrushMap::iterator brit = m_brushValues.find(property); // Brushes
171     if (brit == m_brushValues.end())
172         return false;
173     m_brushValues.erase(brit);
174     // style
175     PropertyToPropertyMap::iterator subit = m_brushPropertyToStyleSubProperty.find(property);
176     if (subit != m_brushPropertyToStyleSubProperty.end()) {
177         QtProperty *styleProp = subit.value();
178         m_brushStyleSubPropertyToProperty.remove(styleProp);
179         m_brushPropertyToStyleSubProperty.erase(subit);
180         delete styleProp;
181     }
182     // color
183     subit = m_brushPropertyToColorSubProperty.find(property);
184     if (subit != m_brushPropertyToColorSubProperty.end()) {
185         QtProperty *colorProp = subit.value();
186         m_brushColorSubPropertyToProperty.remove(colorProp);
187         m_brushPropertyToColorSubProperty.erase(subit);
188         delete colorProp;
189     }
190     return true;
191 }
192 
slotPropertyDestroyed(QtProperty * property)193 void BrushPropertyManager::slotPropertyDestroyed(QtProperty *property)
194 {
195     PropertyToPropertyMap::iterator subit = m_brushStyleSubPropertyToProperty.find(property);
196     if (subit != m_brushStyleSubPropertyToProperty.end()) {
197         m_brushPropertyToStyleSubProperty[subit.value()] = 0;
198         m_brushStyleSubPropertyToProperty.erase(subit);
199     }
200     subit = m_brushColorSubPropertyToProperty.find(property);
201     if (subit != m_brushColorSubPropertyToProperty.end()) {
202         m_brushPropertyToColorSubProperty[subit.value()] = 0;
203         m_brushColorSubPropertyToProperty.erase(subit);
204     }
205 }
206 
207 
valueChanged(QtVariantPropertyManager * vm,QtProperty * property,const QVariant & value)208 int BrushPropertyManager::valueChanged(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
209 {
210     switch (value.type()) {
211     case QVariant::Int: // Style subproperty?
212         if (QtProperty *brushProperty = m_brushStyleSubPropertyToProperty.value(property, 0)) {
213             const QBrush oldValue = m_brushValues.value(brushProperty);
214             QBrush newBrush = oldValue;
215             const int index = value.toInt();
216             newBrush.setStyle(brushStyleIndexToStyle(index));
217             if (newBrush == oldValue)
218                 return DesignerPropertyManager::Unchanged;
219             vm->variantProperty(brushProperty)->setValue(newBrush);
220             return DesignerPropertyManager::Changed;
221         }
222         break;
223     case QVariant::Color: // Color  subproperty?
224         if (QtProperty *brushProperty = m_brushColorSubPropertyToProperty.value(property, 0)) {
225             const QBrush oldValue = m_brushValues.value(brushProperty);
226             QBrush newBrush = oldValue;
227             newBrush.setColor(qvariant_cast<QColor>(value));
228             if (newBrush == oldValue)
229                 return DesignerPropertyManager::Unchanged;
230             vm->variantProperty(brushProperty)->setValue(newBrush);
231             return DesignerPropertyManager::Changed;
232         }
233         break;
234     default:
235         break;
236     }
237     return DesignerPropertyManager::NoMatch;
238 }
239 
setValue(QtVariantPropertyManager * vm,QtProperty * property,const QVariant & value)240 int BrushPropertyManager::setValue(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
241 {
242     if (value.type() != QVariant::Brush)
243         return DesignerPropertyManager::NoMatch;
244     const PropertyBrushMap::iterator brit = m_brushValues.find(property);
245     if (brit == m_brushValues.end())
246         return DesignerPropertyManager::NoMatch;
247 
248     const QBrush newBrush = qvariant_cast<QBrush>(value);
249     if (newBrush == brit.value())
250         return DesignerPropertyManager::Unchanged;
251     brit.value() = newBrush;
252     if (QtProperty *styleProperty = m_brushPropertyToStyleSubProperty.value(property))
253         vm->variantProperty(styleProperty)->setValue(brushStyleToIndex(newBrush.style()));
254     if (QtProperty *colorProperty = m_brushPropertyToColorSubProperty.value(property))
255         vm->variantProperty(colorProperty)->setValue(newBrush.color());
256 
257     return DesignerPropertyManager::Changed;
258 }
259 
valueText(const QtProperty * property,QString * text) const260 bool BrushPropertyManager::valueText(const QtProperty *property, QString *text) const
261 {
262     const PropertyBrushMap::const_iterator brit = m_brushValues.constFind(const_cast<QtProperty *>(property));
263     if (brit == m_brushValues.constEnd())
264         return false;
265     const QBrush &brush = brit.value();
266     const QString styleName = brushStyleIndexToString(brushStyleToIndex(brush.style()));
267     *text = QCoreApplication::translate("BrushPropertyManager", "[%1, %2]")
268             .arg(styleName, QtPropertyBrowserUtils::colorValueText(brush.color()));
269     return true;
270 }
271 
valueIcon(const QtProperty * property,QIcon * icon) const272 bool BrushPropertyManager::valueIcon(const QtProperty *property, QIcon *icon) const
273 {
274     const PropertyBrushMap::const_iterator brit = m_brushValues.constFind(const_cast<QtProperty *>(property));
275     if (brit == m_brushValues.constEnd())
276         return false;
277     *icon = QtPropertyBrowserUtils::brushValueIcon(brit.value());
278     return true;
279 }
280 
value(const QtProperty * property,QVariant * v) const281 bool BrushPropertyManager::value(const QtProperty *property, QVariant *v) const
282 {
283     const PropertyBrushMap::const_iterator brit = m_brushValues.constFind(const_cast<QtProperty *>(property));
284     if (brit == m_brushValues.constEnd())
285         return false;
286     v->setValue(brit.value());
287     return true;
288 }
289 }
290 
291 QT_END_NAMESPACE
292