KProperty

booledit.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2004 Alexander Dymo <[email protected]>
3  Copyright (C) 2006-2018 Jarosław Staniek <[email protected]>
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 
30 namespace {
31 
32 
36 enum ThreeStateIndex {
37  TrueIndex,
38  FalseIndex,
39  NoneIndex
40 };
41 
43 QString 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 
76 void 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 
88 ThreeStateIndex 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 
99 class BoolEditGlobal
100 {
101 public:
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 
118 Q_GLOBAL_STATIC(BoolEditGlobal, g_boolEdit)
119 
120 class Q_DECL_HIDDEN KPropertyBoolEditor::Private
121 {
122 public:
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 
133 KPropertyBoolEditor::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 
142 KPropertyBoolEditor::~KPropertyBoolEditor()
143 {
144  delete d;
145 }
146 
147 QVariant KPropertyBoolEditor::value() const
148 {
149  return d->value;
150 }
151 
152 void KPropertyBoolEditor::setValue(const QVariant &value)
153 {
154  d->value = value;
155  if (value.type() == QVariant::Bool) {
156  setChecked(value.toBool());
157  }
158 }
159 
160 void
161 KPropertyBoolEditor::slotValueChanged(bool state)
162 {
163  d->value = state;
164  emit commitData(this);
165 }
166 
167 void 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 
193 void 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 
202 bool 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 
217 class ThreeStateBoolIconProvider : public KPropertyComboBoxEditorIconProviderInterface
218 {
219 public:
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 
238 static KPropertyComboBoxEditorOptions initThreeStateBoolOptions()
239 {
240  KPropertyComboBoxEditorOptions options;
241  options.iconProvider = new ThreeStateBoolIconProvider();
242  return options;
243 }
244 
245 class Q_DECL_HIDDEN KPropertyThreeStateBoolEditor::Private
246 {
247 public:
248  Private() {
249  }
250 };
251 
252 KPropertyThreeStateBoolEditor::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 
262 KPropertyThreeStateBoolEditor::~KPropertyThreeStateBoolEditor()
263 {
264  delete d;
265 }
266 
267 QVariant 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 
292 void KPropertyThreeStateBoolEditor::setValue(const QVariant &value)
293 {
294  setCurrentIndex( valueToIndex(value) );
295 }
296 
297 //---------------
298 
299 KPropertyBoolDelegate::KPropertyBoolDelegate()
300 {
301  options()->setBordersVisible(true);
302 }
303 
304 QWidget * 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 
322 void 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 
336 QString 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 
348 QString KPropertyBoolDelegate::valueToString(const QVariant& value, const QLocale &locale) const
349 {
350  // assume 2-state
351  return stateName(value.toBool() ? TrueIndex : FalseIndex, locale);
352 }
QSize size() const const
WheelFocus
QEvent::Type type() const const
int width() const const
void setNamesAsStringList(const QStringList &names)
Sets a list containing all possible keys for a property as strings.
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 ...
Definition: KProperty.cpp:564
QIcon icon() const const
AlignVCenter
A bool editor supporting three states: true, false and null.
Definition: booledit.h:71
bool isNull() const const
virtual void paintEvent(QPaintEvent *event) override
EditRole
bool isEmpty() const const
void drawText(const QPointF &position, const QString &text)
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) const const
QLocale::Language language() const const
QRect translated(int dx, int dy) const const
virtual bool event(QEvent *event) override
virtual bool eventFilter(QObject *watched, QEvent *event)
void paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment, QIcon::Mode mode, QIcon::State state) const const
QLocale locale() const const
QRect rect() const const
int key() const const
The base class representing a single property.
Definition: KProperty.h:95
void setChecked(bool)
QVariant value() const
Definition: KProperty.cpp:394
QVariant data(int role) const const
int currentIndex() const const
bool toBool() const const
QString text() const const
QString fromLatin1(const char *str, int size)
A bool editor supporting two states: true and false.
Definition: booledit.h:35
bool isValid() const const
void setKeys(const QVariantList &keys)
Sets a list containing all possible keys for a property.
QVariant::Type type() const const
transparent
QString toString() const const
Key_Space
A data container for properties of list type.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sun Aug 9 2020 23:10:56 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.