KProperty

booledit.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2004 Alexander Dymo <cloudtemple@mskat.net>
3 Copyright (C) 2006-2018 Jarosław Staniek <staniek@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include "booledit.h"
22#include "KPropertyListData.h"
23#include "KPropertyUtils.h"
24#include "KPropertyUtils_p.h"
25#include "kproperty_debug.h"
26
27#include <QIcon>
28#include <QVariant>
29
30namespace {
31
32
33/**
34 * 3-state Index
35 */
36enum ThreeStateIndex {
37 TrueIndex,
38 FalseIndex,
39 NoneIndex
40};
41
42//! @return name for state with index @a index
43QString stateName(ThreeStateIndex index, const QLocale &locale, const KProperty* prop = nullptr)
44{
45 QString stateNameString;
46 switch (index) {
47 case TrueIndex:
48 stateNameString = prop ? prop->option("yesName", QString()).toString() : QString();
49 if (stateNameString.isEmpty()) {
50 stateNameString = locale.language() == QLocale::C
51 ? QString::fromLatin1("true")
52 : QObject::tr("Yes", "Property value: Boolean state Yes");
53 }
54 break;
55 case FalseIndex:
56 stateNameString = prop ? prop->option("noName", QString()).toString() : QString();
57 if (stateNameString.isEmpty()) {
58 stateNameString = locale.language() == QLocale::C
59 ? QString::fromLatin1("false")
60 : QObject::tr("No", "Property value: Boolean state No");
61 }
62 break;
63 case NoneIndex:
64 stateNameString = prop ? prop->option("3rdStateName", QString()).toString() : QString();
65 if (stateNameString.isEmpty()) {
66 stateNameString = locale.language() == QLocale::C
67 ? QString::fromLatin1("null")
68 : QObject::tr("None", "Property value: Boolean (3rd) undefined state None");
69 }
70 break;
71 }
72 return stateNameString;
73}
74
75//! Sets up @a data list data with keys and names for true, false, none values, respectively
76void setupThreeStateListData(KPropertyListData *data, const KProperty* prop)
77{
78 data->setKeys({ true, false, QVariant() });
79 data->setNamesAsStringList({ stateName(TrueIndex, QLocale(), prop), stateName(FalseIndex, QLocale(), prop),
80 stateName(NoneIndex, QLocale(), prop) });
81}
82
83/**
84 * Returns index for given value
85 *
86 * Assumes that support for 3-state is enabled.
87 */
88ThreeStateIndex valueToIndex(const QVariant& value)
89{
90 if (value.isNull() || !value.isValid())
91 return NoneIndex;
92 else
93 return value.toBool() ? TrueIndex : FalseIndex;
94}
95} // namespace
96
97//-------------------------
98
99class BoolEditGlobal
100{
101public:
102 BoolEditGlobal()
103 : yesIcon(QIcon::fromTheme(QLatin1String("dialog-ok")))
104 , noIcon(QIcon::fromTheme(QLatin1String("kproperty-value-false")))
105 {
106 QPixmap none(16, 16);
107 none.fill(Qt::transparent);
108 noneIcon.addPixmap(none);
109 none = QPixmap(22, 22);
110 none.fill(Qt::transparent);
111 noneIcon.addPixmap(none);
112 }
113 QIcon yesIcon;
114 QIcon noIcon;
115 QIcon noneIcon;
116};
117
118Q_GLOBAL_STATIC(BoolEditGlobal, g_boolEdit)
119
120class Q_DECL_HIDDEN KPropertyBoolEditor::Private
121{
122public:
123 Private(const KProperty *prop)
124 : yesText( stateName(TrueIndex, QLocale(), prop) )
125 , noText( stateName(FalseIndex, QLocale(), prop) )
126 {
127 }
128 QVariant value;
129 QString yesText;
130 QString noText;
131};
132
133KPropertyBoolEditor::KPropertyBoolEditor(const KProperty *prop, QWidget *parent)
134 : QToolButton(parent), d(new Private(prop))
135{
136 setFocusPolicy(Qt::WheelFocus);
137 setCheckable(true);
138 setAutoFillBackground(true);
139 connect(this, SIGNAL(toggled(bool)), this, SLOT(slotValueChanged(bool)));
140}
141
142KPropertyBoolEditor::~KPropertyBoolEditor()
143{
144 delete d;
145}
146
147QVariant KPropertyBoolEditor::value() const
148{
149 return d->value;
150}
151
152void KPropertyBoolEditor::setValue(const QVariant &value)
153{
154 d->value = value;
155 if (value.type() == QVariant::Bool) {
156 setChecked(value.toBool());
157 }
158}
159
160void
161KPropertyBoolEditor::slotValueChanged(bool state)
162{
163 d->value = state;
164 emit commitData(this);
165}
166
167void KPropertyBoolEditor::draw(QPainter *p, const QRect &r, const QVariant &value,
168 const QString& text, bool threeState)
169{
170 QIcon icon;
171 QSize actualIconSize;
172 QPoint textOffset;
173 if (threeState && valueToIndex(value) == NoneIndex) {
174 // draw icon for the 3rd state for Three-State editor
175 icon = g_boolEdit->noneIcon;
176 actualIconSize = g_boolEdit->yesIcon.actualSize(r.size());
177 textOffset = QPoint(actualIconSize.width() + 6, 0);
178 } else {
179 // draw true or false icon regardless of the 2 or 3 state version
180 icon = value.toBool() ? g_boolEdit->yesIcon : g_boolEdit->noIcon;
181 actualIconSize = icon.actualSize(r.size());
182 textOffset = QPoint(actualIconSize.width() + 6, 0);
183 }
184 QRect r2(r);
185 r2.moveTop(r2.top() + 2);
186 r2.setLeft(r2.left() + 3);
187 //r2.setTop(r2.top() + (r.height() - actualIconSize.height()) / 2);
188
189 icon.paint(p, r2, Qt::AlignVCenter | Qt::AlignLeft);
190 p->drawText(r2.translated(textOffset), Qt::AlignVCenter | Qt::AlignLeft, text);
191}
192
193void KPropertyBoolEditor::paintEvent( QPaintEvent * event )
194{
196 QPainter p(this);
197 const QVariant v( value() );
198 KPropertyBoolEditor::draw(&p, rect(), v,
199 v.toBool() ? d->yesText : d->noText, false /*2state*/);
200}
201
202bool KPropertyBoolEditor::eventFilter(QObject* watched, QEvent* e)
203{
204 if (e->type() == QEvent::KeyPress) {
205 QKeyEvent* ev = static_cast<QKeyEvent*>(e);
206 const int k = ev->key();
207 if (k == Qt::Key_Space || k == Qt::Key_Enter || k == Qt::Key_Return) {
208 toggle();
209 return true;
210 }
211 }
212 return QToolButton::eventFilter(watched, e);
213}
214
215//--------------------------------------------------
216
217class ThreeStateBoolIconProvider : public KPropertyComboBoxEditorIconProviderInterface
218{
219public:
220 ThreeStateBoolIconProvider() {}
221 QIcon icon(int index) const override
222 {
223 switch (index) {
224 case TrueIndex:
225 return g_boolEdit->yesIcon;
226 case FalseIndex:
227 return g_boolEdit->noIcon;
228 default:
229 return g_boolEdit->noneIcon;
230 }
231 }
232 KPropertyComboBoxEditorIconProviderInterface* clone() const override
233 {
234 return new ThreeStateBoolIconProvider();
235 }
236};
237
238static KPropertyComboBoxEditorOptions initThreeStateBoolOptions()
239{
240 KPropertyComboBoxEditorOptions options;
241 options.iconProvider = new ThreeStateBoolIconProvider();
242 return options;
243}
244
245class Q_DECL_HIDDEN KPropertyThreeStateBoolEditor::Private
246{
247public:
248 Private() {
249 }
250};
251
252KPropertyThreeStateBoolEditor::KPropertyThreeStateBoolEditor(const KPropertyListData &listData,
253 QWidget *parent)
254 : KPropertyComboBoxEditor(listData, initThreeStateBoolOptions(), parent), d(new Private)
255{
256// QPixmap nullIcon(m_yesIcon.size()); //transparent pixmap of appropriate size
257// nullIcon.fill(Qt::transparent);
258// m_edit->addItem(nullIcon, thirdState.toString().isEmpty() ? tr("None") : thirdState.toString());
259 setCurrentIndex(NoneIndex);
260}
261
262KPropertyThreeStateBoolEditor::~KPropertyThreeStateBoolEditor()
263{
264 delete d;
265}
266
267QVariant KPropertyThreeStateBoolEditor::value() const
268{
269 // list items: true, false, NULL
270 const int i = currentIndex();
271 const ThreeStateIndex index
272 = (i >= TrueIndex && i <= NoneIndex) ? static_cast<ThreeStateIndex>(i) : NoneIndex;
273 switch (index) {
274 case TrueIndex:
275 return true;
276 case FalseIndex:
277 return false;
278 default:
279 return QVariant();
280 }
281}
282
283/*void ThreeStateBoolEdit::setProperty(Property *prop)
284{
285 m_setValueEnabled = false; //setValue() couldn't be called before fillBox()
286 Widget::setProperty(prop);
287 m_setValueEnabled = true;
288 if (prop)
289 setValue(prop->value(), KProperty::ValueOption::IgnoreOld); //now the value can be set
290}*/
291
292void KPropertyThreeStateBoolEditor::setValue(const QVariant &value)
293{
294 setCurrentIndex( valueToIndex(value) );
295}
296
297//---------------
298
299KPropertyBoolDelegate::KPropertyBoolDelegate()
300{
301 options()->setBordersVisible(true);
302}
303
304QWidget * KPropertyBoolDelegate::createEditor( int type, QWidget *parent,
305 const QStyleOptionViewItem & option, const QModelIndex & index ) const
306{
307 Q_UNUSED(type);
308 Q_UNUSED(option);
309 KProperty *prop = KPropertyUtils::propertyForIndex(index);
310
311 // boolean editors can optionally accept 3rd state:
312 if (prop && prop->option("3State", false).toBool()) {
313 KPropertyListData threeStateListData;
314 setupThreeStateListData(&threeStateListData, prop);
315 return new KPropertyThreeStateBoolEditor(threeStateListData, parent);
316 }
317 else {
318 return new KPropertyBoolEditor(prop, parent);
319 }
320}
321
322void KPropertyBoolDelegate::paint( QPainter * painter,
323 const QStyleOptionViewItem & option, const QModelIndex & index ) const
324{
325 const KPropertyUtilsPrivate::PainterSaver saver(painter);
326 KProperty *prop = KPropertyUtils::propertyForIndex(index);
327 if (!prop) {
328 return;
329 }
330 const QVariant value( index.data(Qt::EditRole) );
331 QRect rect(option.rect);
332 const bool threeState = prop->option("3State", false).toBool();
333 KPropertyBoolEditor::draw(painter, rect.translated(0, -2), value, propertyValueToString(prop, QLocale()), threeState);
334}
335
336QString KPropertyBoolDelegate::propertyValueToString(const KProperty* prop, const QLocale &locale) const
337{
338 if (prop->option("3State", false).toBool()) {
339 const ThreeStateIndex listIndex = valueToIndex(prop->value());
340 return stateName(listIndex, locale, prop);
341 }
342 if (prop->value().isNull() && !prop->option("nullName", QString()).toString().isEmpty()) {
343 return prop->option("nullName", QString()).toString();
344 }
345 return valueToString(prop->value(), locale);
346}
347
348QString KPropertyBoolDelegate::valueToString(const QVariant& value, const QLocale &locale) const
349{
350 // assume 2-state
351 return stateName(value.toBool() ? TrueIndex : FalseIndex, locale);
352}
A bool editor supporting two states: true and false.
Definition booledit.h:36
const KPropertyEditorCreatorOptions * options() const
Options for editor creating.
A data container for properties of list type.
void setKeys(const QVariantList &keys)
Sets a list containing all possible keys for a property.
void setNamesAsStringList(const QStringList &names)
Sets a list containing all possible keys for a property as strings.
A bool editor supporting three states: true, false and null.
Definition booledit.h:72
The base class representing a single property.
Definition KProperty.h:96
QVariant option(const char *name, const QVariant &defaultValue=QVariant()) const
Returns value of given option Option is set if returned value is not null. If there is no option for ...
QVariant value() const
char * toString(const EngineQuery &query)
void setChecked(bool)
QEvent::Type type() const const
void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state)
int key() const const
QLocale::Language language() const const
QVariant data(int role) const const
virtual bool eventFilter(QObject *watched, QEvent *event)
void drawText(const QPointF &position, const QString &text)
QSize size() const const
int width() const const
QString fromLatin1(const char *str, int size)
bool isEmpty() const const
AlignVCenter
WheelFocus
transparent
EditRole
Key_Space
virtual bool event(QEvent *event) override
virtual void paintEvent(QPaintEvent *event) override
bool isNull() const const
bool isValid() const const
bool toBool() const const
QString toString() const const
QVariant::Type type() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sun Feb 25 2024 18:41:55 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.