Seamly2D
Code documentation
vpropertyformwidget.cpp
Go to the documentation of this file.
1 /************************************************************************
2  **
3  ** @file vpropertyformwidget.cpp
4  ** @author hedgeware <internal(at)hedgeware.net>
5  ** @date
6  **
7  ** @brief
8  ** @copyright
9  ** All rights reserved. This program and the accompanying materials
10  ** are made available under the terms of the GNU Lesser General Public License
11  ** (LGPL) version 2.1 which accompanies this distribution, and is available at
12  ** http://www.gnu.org/licenses/lgpl-2.1.html
13  **
14  ** This library is distributed in the hope that it will be useful,
15  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  ** Lesser General Public License for more details.
18  **
19  *************************************************************************/
20 
21 #include "vpropertyformwidget.h"
22 
23 #include <QEvent>
24 #include <QFormLayout>
25 #include <QKeyEvent>
26 #include <QLayout>
27 #include <QLayoutItem>
28 #include <QMargins>
29 #include <QStyleOptionViewItem>
30 #include <QVariant>
31 #include <QWidget>
32 #include <Qt>
33 
35 #include "vproperty.h"
36 #include "vpropertyformwidget_p.h"
37 
38 VPE::VPropertyFormWidget::VPropertyFormWidget(const QString &title, const QString &description,
39  const QList<VProperty*> &properties, QWidget *parent)
40  : QGroupBox(title, parent), d_ptr(new VPropertyFormWidgetPrivate(properties))
41 {
42  build();
43  setToolTip(description);
44  setWhatsThis(description);
45 }
46 
47 VPE::VPropertyFormWidget::VPropertyFormWidget(VProperty *parent_property, QWidget *parent)
48  : QGroupBox(parent), d_ptr(new VPropertyFormWidgetPrivate())
49 {
50  if (parent_property)
51  {
52  d_ptr->Properties = parent_property->getChildren();
53  build();
54  setTitle(parent_property->getName());
55  setToolTip(parent_property->getDescription());
56  setWhatsThis(parent_property->getDescription());
57  }
58 }
59 
61  const QString &title, const QString &description)
62  : QGroupBox(title, parent), d_ptr(d_pointer)
63 {
64  build();
65  setToolTip(description);
66  setWhatsThis(description);
67 }
68 
70 {
71  delete d_ptr;
72 }
73 
74 
76 {
77  // Clear the old content, delete old widgets
78  d_ptr->EditorWidgets.clear();
79  if (layout())
80  {
81  QLayoutItem *child;
82  while (layout()->count() > 0 && (child = layout()->takeAt(0)) != nullptr)
83  {
84  if (child->widget())
85  {
86  delete child->widget();
87  }
88  delete child;
89  }
90  delete layout();
91  }
92 
93  // Create new content
94  if (d_ptr->Properties.isEmpty())
95  {
96  return; //... only if there are properties
97  }
98 
99  QFormLayout* tmpFormLayout = new QFormLayout(this);
100  setLayout(tmpFormLayout);
101 
102  for (int i = 0; i < d_ptr->Properties.count(); ++i)
103  {
104  // Get the current property
105  VProperty* tmpProperty = d_ptr->Properties.value(i, nullptr);
106  if (!tmpProperty)
107  {
108  continue;
109  }
110 
111  if (tmpProperty->getRowCount() > 0)
112  {
113  if (tmpProperty->propertyType() == Property::Complex)
114  {
115  buildEditor(tmpProperty, tmpFormLayout, Property::Complex);
116  QList<VProperty*> children = tmpProperty->getChildren();
117  for (int j = 0; j < children.size(); ++j)
118  {
119  buildEditor(children[j], tmpFormLayout);
120  connect(children[j], &VProperty::childChanged, tmpProperty, &VProperty::childValueChanged,
121  Qt::UniqueConnection);
122  ++i;
123  d_ptr->Properties.insert(i, children[j]);
124  }
125  }
126  else
127  {
128  VPropertyFormWidget* tmpNewFormWidget = new VPropertyFormWidget(tmpProperty, this);
129  tmpFormLayout->addRow(tmpNewFormWidget);
130  d_ptr->EditorWidgets.append(VPropertyFormWidgetPrivate::SEditorWidget(tmpNewFormWidget));
131  tmpNewFormWidget->setCommitBehaviour(d_ptr->UpdateEditors);
132  }
133  }
134  else if (tmpProperty->propertyType() == Property::Label)
135  {
136  buildEditor(tmpProperty, tmpFormLayout, Property::Label);
137  }
138  else if (tmpProperty->type() == "widget")
139  {
140  VWidgetProperty* tmpWidgetProperty = static_cast<VWidgetProperty*>(tmpProperty);
141  tmpFormLayout->addRow(tmpWidgetProperty->getWidget());
142  d_ptr->EditorWidgets.append(VPropertyFormWidgetPrivate::SEditorWidget(tmpWidgetProperty->getWidget()));
143  }
144  else
145  {
146  buildEditor(tmpProperty, tmpFormLayout);
147  }
148  }
149 }
150 
151 void VPE::VPropertyFormWidget::buildEditor(VProperty* property, QFormLayout* formLayout, Property type)
152 {
153  // Add property (no child properties)
154  // Create the editor (if it doesn't work, create empty widget)
155  QWidget* tmpEditor = property->createEditor(this, QStyleOptionViewItem(), nullptr);
156  if (!tmpEditor)
157  {
158  tmpEditor = new QWidget(this);
159  }
160 
161  // set tooltip and whats this
162  tmpEditor->setToolTip(property->getDescription());
163  tmpEditor->setWhatsThis(property->getDescription());
164 
165  // Install event filter
166  tmpEditor->installEventFilter(this);
167 
168  // Set the editor data
169  property->setEditorData(tmpEditor);
170 
171  // add new row
172  if (type == Property::Complex)
173  {
174  //QLabel *label = new QLabel("<b>"+property->getName()+"</b>");
175  QLabel *label = new QLabel(property->getName());
176  label->setMinimumWidth(80);
177  label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
178  formLayout->addRow(label, tmpEditor);
179  }
180  else if (type == Property::Label)
181  {
182  QLabel *label = new QLabel("<b>"+property->getName()+"</b>");
183  label->setMinimumWidth(80);
184  label->setAlignment(Qt::AlignLeft);
185  formLayout->addRow(label, tmpEditor);
186  formLayout->setLabelAlignment(Qt::AlignLeft);
187  }
188  else
189  {
190  QLabel *label = new QLabel(property->getName());
191  label->setMinimumWidth(80);
192  label->setAlignment(Qt::AlignRight);
193  formLayout->addRow(label, tmpEditor);
194  formLayout->setFormAlignment(Qt::AlignTop);
195  }
196 
197  d_ptr->EditorWidgets.append(VPropertyFormWidgetPrivate::SEditorWidget(tmpEditor));
198 }
199 
201 {
202  for (int i = 0; i < d_ptr->Properties.count(); ++i)
203  {
204  commitData(i);
205  }
206 }
207 
209 {
210  for (int i = 0; i < d_ptr->Properties.count(); ++i)
211  {
212  loadData(i);
213  }
214 }
215 
217 {
218  if (row < 0 || row >= d_ptr->EditorWidgets.count() || row >= d_ptr->Properties.count())
219  {
220  return;
221  }
222 
223  VPropertyFormWidgetPrivate::SEditorWidget &tmpEditorWidget = d_ptr->EditorWidgets[row];
224  VProperty* tmpProperty = d_ptr->Properties[row];
225  if (tmpEditorWidget.FormWidget)
226  {
227  tmpEditorWidget.FormWidget->commitData();
228  }
229  else if (tmpEditorWidget.Editor && tmpProperty)
230  {
231  QVariant newValue = tmpProperty->getEditorData(tmpEditorWidget.Editor);
232  QVariant oldValue = tmpProperty->data(VProperty::DPC_Data, Qt::EditRole);
233  if (oldValue != newValue)
234  {
235  VProperty *parent = tmpProperty->getParent();
236  if (parent == nullptr || parent->propertyType() != Property::Complex)
237  {
238  tmpProperty->setValue(newValue);
239  emit propertyDataSubmitted(tmpProperty);
240  }
241  else if (parent->propertyType() == Property::Complex)
242  {
243  tmpProperty->updateParent(newValue);
244  emit propertyDataSubmitted(parent);
245  }
246  }
247  }
248 }
249 
251 {
252  if (row < 0 || row >= d_ptr->EditorWidgets.count() || row >= d_ptr->Properties.count())
253  {
254  return;
255  }
256 
257  VPropertyFormWidgetPrivate::SEditorWidget &tmpEditorWidget = d_ptr->EditorWidgets[row];
258  VProperty* tmpProperty = d_ptr->Properties[row];
259  if (tmpEditorWidget.FormWidget)
260  {
261  tmpEditorWidget.FormWidget->loadData();
262  }
263  else if (tmpEditorWidget.Editor && tmpProperty)
264  {
265  tmpProperty->setEditorData(tmpEditorWidget.Editor);
266  }
267 }
268 
270 {
271  d_ptr->UpdateEditors = auto_commit;
272 
273  QList<VPropertyFormWidget*> tmpChildFormWidgets = getChildPropertyFormWidgets();
274  foreach(VPropertyFormWidget* tmpChild, tmpChildFormWidgets)
275  {
276  if (tmpChild)
277  {
278  tmpChild->setCommitBehaviour(auto_commit);
279  }
280  }
281 }
282 
284 {
286  foreach(const VPropertyFormWidgetPrivate::SEditorWidget &tmpEditorWidget, d_ptr->EditorWidgets)
287  {
288  if (tmpEditorWidget.FormWidget)
289  {
290  tmpResult.append(tmpEditorWidget.FormWidget);
291  }
292  }
293 
294  return tmpResult;
295 }
296 
297 bool VPE::VPropertyFormWidget::eventFilter(QObject *object, QEvent *event)
298 {
299  if (!d_ptr->UpdateEditors)
300  {
301  return false;
302  }
303 
304  QWidget* editor = qobject_cast<QWidget*>(object);
305  if (!editor)
306  {
307  return false;
308  }
309 
310  if (event->type() == QEvent::KeyPress)
311  {
312  switch (static_cast<QKeyEvent *>(event)->key())
313  {
314  case Qt::Key_Tab:
315  case Qt::Key_Backtab:
316  case Qt::Key_Enter:
317  case Qt::Key_Return:
318  case Qt::Key_Escape:
319  commitData(editor);
320  event->accept();
321  return true;
322  default:
323  return false;
324  }
325  }
326  else if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow()))
327  {
328  commitData(editor);
329  return false;
330  }
331  else if (event->type() == QEvent::ShortcutOverride)
332  {
333  if (static_cast<QKeyEvent*>(event)->key() == Qt::Key_Escape)
334  {
335  commitData(editor);
336  event->accept();
337  return true;
338  }
339  }
340  else if (event->type() == MyCustomEventType)
341  {
342  commitData(editor);
343  event->accept();
344  return true;
345  }
346  else
347  {
348  return QGroupBox::eventFilter(object, event);
349  }
350 
351  // Default:
352  return false;
353 }
354 
355 void VPE::VPropertyFormWidget::commitData(const QWidget *editor)
356 {
357  if (!editor)
358  {
359  return;
360  }
361 
362  for (int i = 0; i < d_ptr->EditorWidgets.count(); ++i)
363  {
364  VPropertyFormWidgetPrivate::SEditorWidget &tmpEditorWidget = d_ptr->EditorWidgets[i];
365  if (tmpEditorWidget.Editor == editor)
366  {
367  commitData(i);
368  }
369  }
370 }
QList< VProperty * > Properties
The root property to use.
Class that displays the sub properties of a property using a form layout.
void setCommitBehaviour(bool auto_commit=true)
Sets the update behaviour.
QList< VPropertyFormWidget * > getChildPropertyFormWidgets() const
Returns a list of all child property form widgets (note that indirect children will not be in the lis...
VPropertyFormWidgetPrivate * d_ptr
The protected data.
VPropertyFormWidget(const QString &title, const QString &description, const QList< VProperty * > &properties, QWidget *parent)
Constructor.
virtual void build()
Rebuilds the whole form.
void loadData()
Refills the editors with the propertie's data.
void buildEditor(VProperty *property, QFormLayout *formLayout, Property type=Property::Simple)
void commitData()
Reads the data from the editors and commits it to the properties.
bool eventFilter(QObject *object, QEvent *event)
Event filter for the editor widgets.
virtual QVariant data(int column=DPC_Name, int role=Qt::DisplayRole) const
Get the data how it should be displayed.
Definition: vproperty.cpp:68
void childChanged(const QVariant &value, int typeForParent)
virtual int getRowCount() const
Gets the number of children.
Definition: vproperty.cpp:245
virtual QString getName() const
Gets the name of the property.
Definition: vproperty.cpp:204
virtual bool setEditorData(QWidget *editor)
Sets the property's data to the editor (returns false, if the standard delegate should do that)
Definition: vproperty.cpp:117
virtual void setValue(const QVariant &value)
Sets the value of the property.
Definition: vproperty.cpp:171
virtual QString getDescription() const
Gets the name of the property.
Definition: vproperty.cpp:216
virtual VProperty * getParent() const
Gets the parent of this property.
Definition: vproperty.cpp:251
virtual QVariant getEditorData(const QWidget *editor) const
Gets the data from the widget.
Definition: vproperty.cpp:138
virtual void childValueChanged(const QVariant &value, int typeForParent)
Definition: vproperty.cpp:410
virtual void updateParent(const QVariant &value)
Definition: vproperty.cpp:405
Property propertyType() const
Definition: vproperty.cpp:395
virtual QList< VProperty * > & getChildren()
Returns a reference to the list of children.
Definition: vproperty.cpp:222
virtual QString type() const
Returns a string containing the type of the property.
Definition: vproperty.cpp:62
This property holds a QWidget and displays it, if the view supports that. If not, it will behave like...
QWidget * getWidget() const
Returns the widget held by this property.
static const int MyCustomEventType
Definition: vproperty.h:45
Property
Definition: vproperty.h:43
Stores either another VPropertyFormWidget (then Editor is null) or an editor widget (then FormWidget ...