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)
Type type() const const
void addPixmap(const QPixmap &pixmap, Mode mode, State state)
int key() const const
Language language() const const
QVariant data(int role) const const
virtual bool eventFilter(QObject *watched, QEvent *event)
void drawText(const QPoint &position, const QString &text)
QSize size() const const
int width() const const
QString fromLatin1(QByteArrayView str)
bool isEmpty() const const
AlignVCenter
WheelFocus
transparent
EditRole
Key_Space
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
virtual bool event(QEvent *event) override
virtual void paintEvent(QPaintEvent *event) override
Type type() const const
bool isNull() const const
bool isValid() const const
bool toBool() const const
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:15:40 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.