1 #include "argumentseditor.h"
3 #include "apitracecall.h"
6 #include <QDoubleSpinBox>
7 #include <QItemEditorFactory>
15 isVariantEditable(const QVariant &var)
17 if (var.canConvert<ApiArray>()) {
18 ApiArray array = var.value<ApiArray>();
19 QVector<QVariant> vals = array.values();
23 return isVariantEditable(vals.first());
25 switch (var.userType()) {
29 case QVariant::LongLong:
30 case QVariant::ULongLong:
31 case QMetaType::Float:
32 case QVariant::Double:
33 case QVariant::String:
41 isVariantStringArray(const QVariant &var)
43 if (var.isNull() || var.userType() != QMetaType::type("ApiArray"))
46 ApiArray array = var.value<ApiArray>();
47 QVector<QVariant> origValues = array.values();
48 if (origValues.isEmpty() ||
49 origValues.first().userType() != QVariant::String)
57 void setArgumentsItemEditorFactory ()
59 QItemEditorCreatorBase *booleanComboBoxEditorCreator =
60 new QStandardItemEditorCreator<BooleanComboBoxEditorCreator>();
61 QItemEditorCreatorBase *uIntEditorCreator =
62 new QStandardItemEditorCreator<UIntEditorCreator>();
63 QItemEditorCreatorBase *intEditorCreator =
64 new QStandardItemEditorCreator<IntEditorCreator>();
65 QItemEditorCreatorBase *uLongLongEditorCreator =
66 new QStandardItemEditorCreator<ULongLongEditorCreator>();
67 QItemEditorCreatorBase *longLongEditorCreator =
68 new QStandardItemEditorCreator<LongLongEditorCreator>();
69 QItemEditorCreatorBase *pixmapEditorCreator =
70 new QStandardItemEditorCreator<PixmapEditorCreator>();
71 QItemEditorCreatorBase *floatEditorCreator =
72 new QStandardItemEditorCreator<FloatEditorCreator>();
73 QItemEditorCreatorBase *doubleEditorCreator =
74 new QStandardItemEditorCreator<DoubleEditorCreator>();
75 QItemEditorCreatorBase *stringEditorCreator =
76 new QStandardItemEditorCreator<StringEditorCreator>();
77 QItemEditorCreatorBase *invalidEditorCreator =
78 new QStandardItemEditorCreator<InvalidEditorCreator>();
80 QItemEditorFactory *factory =
81 new QItemEditorFactory();
83 QVariant::Type typeFloat = static_cast<QVariant::Type> (qMetaTypeId<float>());
85 factory->registerEditor(QVariant::Bool, booleanComboBoxEditorCreator);
86 factory->registerEditor(QVariant::UInt, uIntEditorCreator);
87 factory->registerEditor(QVariant::Int, intEditorCreator);
88 factory->registerEditor(QVariant::ULongLong, uLongLongEditorCreator);
89 factory->registerEditor(QVariant::LongLong, longLongEditorCreator);
90 factory->registerEditor(QVariant::Pixmap, pixmapEditorCreator);
91 factory->registerEditor(typeFloat, floatEditorCreator);
92 factory->registerEditor(QVariant::Double, doubleEditorCreator);
93 factory->registerEditor(QVariant::String, stringEditorCreator);
94 factory->registerEditor(QVariant::Invalid, invalidEditorCreator);
96 QItemEditorFactory::setDefaultFactory(factory);
99 BooleanComboBox::BooleanComboBox(QWidget *parent)
102 addItem(tr("False"));
106 void BooleanComboBox::setValue(bool value)
108 setCurrentIndex(value ? 1 : 0);
111 bool BooleanComboBox::value() const
113 return (currentIndex() == 1);
116 ArgumentsEditor::ArgumentsEditor(QWidget *parent)
118 m_model(new QStandardItemModel()),
124 ArgumentsEditor::~ArgumentsEditor()
129 void ArgumentsEditor::setCall(ApiTraceCall *call)
135 ApiTraceCall * ArgumentsEditor::call() const
140 void ArgumentsEditor::init()
144 connect(m_ui.selectStringCB, SIGNAL(currentIndexChanged(int)),
145 SLOT(currentSourceChanged(int)));
146 connect(m_ui.glslEdit, SIGNAL(textChanged()),
147 SLOT(sourceChanged()));
148 connect(m_ui.revertButton, SIGNAL(clicked()),
151 setArgumentsItemEditorFactory ();
153 m_ui.argsTree->setModel(m_model);
157 void ArgumentsEditor::setupCall()
162 headers.append(tr("Argument"));
163 headers.append(tr("Value"));
164 m_model->setColumnCount(2);
165 m_model->setHorizontalHeaderLabels(headers);
166 m_ui.argsTabWidget->removeTab(
167 m_ui.argsTabWidget->indexOf(m_ui.shaderTab));
172 m_ui.callLabel->setText(m_call->name());
173 QStandardItem *rootItem = m_model->invisibleRootItem();
174 for (int i = 0; i < m_call->argNames().count(); ++i) {
175 QString argName = m_call->argNames()[i];
176 QVariant val = m_call->arguments()[i];
177 QStandardItem *nameItem = new QStandardItem(argName);
178 nameItem->setFlags(nameItem->flags() ^ Qt::ItemIsEditable);
179 QList<QStandardItem*> topRow;
180 topRow.append(nameItem);
182 if (val.canConvert<ApiArray>()) {
183 ApiArray array = val.value<ApiArray>();
184 QVector<QVariant> vals = array.values();
186 QVariant firstVal = vals.value(0);
187 if (firstVal.userType() == QVariant::String) {
188 m_ui.argsTabWidget->addTab(
189 m_ui.shaderTab, argName);
190 setupShaderEditor(vals);
193 } else if (isVariantEditable(firstVal)) {
194 for (int i = 0; i < vals.count(); ++i) {
195 QList<QStandardItem*> row;
197 QStandardItem *idx = new QStandardItem();
198 idx->setFlags(idx->flags() ^ Qt::ItemIsEditable);
199 idx->setText(tr("%1)").arg(i));
201 QStandardItem *col = new QStandardItem();
202 col->setFlags(col->flags() | Qt::ItemIsEditable);
203 col->setData(vals[i], Qt::EditRole);
206 nameItem->appendRow(row);
209 qDebug()<<"\tUnsupported array = "<<firstVal;
213 } else if (val.canConvert<ApiPointer>()) {
214 ApiPointer ptr = val.value<ApiPointer>();
215 QStandardItem *item = new QStandardItem();
216 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
217 item->setText(ptr.toString());
218 QIcon icon(":/resources/emblem-locked.png");
220 item->setToolTip(tr("Argument is read-only"));
222 } else if (val.canConvert<ApiEnum>()) {
223 ApiEnum en = val.value<ApiEnum>();
224 QStandardItem *item = new QStandardItem();
225 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
226 item->setText(en.toString());
227 QIcon icon(":/resources/emblem-locked.png");
229 item->setToolTip(tr("Argument is read-only"));
231 } else if (val.canConvert<ApiBitmask>()) {
232 ApiBitmask mask = val.value<ApiBitmask>();
233 QStandardItem *item = new QStandardItem();
234 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
235 item->setText(mask.toString());
236 QIcon icon(":/resources/emblem-locked.png");
238 item->setToolTip(tr("Argument is read-only"));
240 } else if (val.canConvert<ApiStruct>()) {
241 ApiStruct str = val.value<ApiStruct>();
242 QStandardItem *item = new QStandardItem();
243 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
244 item->setText(str.toString());
245 QIcon icon(":/resources/emblem-locked.png");
247 item->setToolTip(tr("Argument is read-only"));
249 } else if (val.userType() == QVariant::ByteArray) {
250 QByteArray ba = val.value<QByteArray>();
251 QStandardItem *item = new QStandardItem();
252 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
254 tr("<binary data, size = %1 bytes>").arg(ba.size()));
255 QIcon icon(":/resources/emblem-locked.png");
257 item->setToolTip(tr("Argument is read-only"));
261 = new QStandardItem();
263 if (isVariantEditable(val)) {
264 item->setFlags(item->flags() | Qt::ItemIsEditable);
266 QIcon icon(":/resources/emblem-locked.png");
268 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
269 item->setToolTip(tr("Argument is read-only"));
271 item->setData(val, Qt::EditRole);
274 rootItem->appendRow(topRow);
278 void ArgumentsEditor::setupShaderEditor(const QVector<QVariant> &sources)
280 m_ui.selectStringCB->clear();
281 m_ui.glslEdit->clear();
282 for (int i = 0; i < sources.count(); ++i) {
283 m_ui.selectStringCB->addItem(
284 tr("Shader string: %1").arg(i),
287 m_ui.selectStringCB->setCurrentIndex(0);
290 void ArgumentsEditor::currentSourceChanged(int idx)
292 QVariant source = m_ui.selectStringCB->itemData(idx);
293 QString str = source.toString();
294 m_ui.glslEdit->setPlainText(source.toString());
295 m_ui.lengthLabel->setText(
296 tr("%1").arg(str.length()));
299 void ArgumentsEditor::sourceChanged()
301 QString str = m_ui.glslEdit->toPlainText();
302 m_ui.lengthLabel->setText(
303 tr("%1").arg(str.length()));
305 m_ui.selectStringCB->setItemData(
306 m_ui.selectStringCB->currentIndex(),
310 void ArgumentsEditor::accept()
312 QStringList argNames = m_call->argNames();
313 QVector<QVariant> originalValues = m_call->arguments();
314 QVector<QVariant> newValues;
315 bool changed = false;
316 for (int i = 0; i < argNames.count(); ++i) {
317 bool valChanged = false;
318 QString argName = argNames[i];
319 QVariant argValue = originalValues[i];
320 QVariant editorValue = valueForName(argName, argValue, &valChanged);
322 newValues.append(editorValue);
324 qDebug()<<"Arg = "<<argName;
325 qDebug()<<"\toriginal = "<<argValue;
326 qDebug()<<"\teditor = "<<editorValue;
327 qDebug()<<"\tchanged = "<<valChanged;
333 m_call->setEditedValues(newValues);
337 QVariant ArgumentsEditor::valueForName(const QString &name,
338 const QVariant &originalValue,
345 //Handle string arrays specially
346 if (isVariantStringArray(originalValue)) {
347 ApiArray array = originalValue.value<ApiArray>();
348 return arrayFromEditor(array, changed);
351 if (!isVariantEditable(originalValue)) {
352 return originalValue;
355 for (int topRow = 0; topRow < m_model->rowCount(); ++topRow) {
356 QModelIndex nameIdx = m_model->index(topRow, 0, QModelIndex());
357 QString argName = nameIdx.data().toString();
358 /* we display shaders in a separate widget so
359 * the ordering might be different */
360 if (argName == name) {
361 if (originalValue.userType() == QMetaType::type("ApiArray")) {
362 ApiArray array = originalValue.value<ApiArray>();
363 val = arrayFromIndex(nameIdx, array, changed);
365 QModelIndex valIdx = m_model->index(topRow, 1, QModelIndex());
367 if (val != originalValue)
375 QVariant ArgumentsEditor::arrayFromIndex(const QModelIndex &parentIndex,
376 const ApiArray &origArray,
379 QVector<QVariant> origValues = origArray.values();
383 if (origValues.isEmpty())
384 return QVariant::fromValue(ApiArray());
386 QVector<QVariant> lst;
387 for (int i = 0; i < origValues.count(); ++i) {
388 QModelIndex valIdx = m_model->index(i, 1, parentIndex);
389 QVariant var = valIdx.data();
390 QVariant origValue = origValues[i];
391 if (var != origValue)
393 //qDebug()<<"\t\tarray "<<i<<") "<<var;
396 return QVariant::fromValue(ApiArray(lst));
399 QVariant ArgumentsEditor::arrayFromEditor(const ApiArray &origArray,
402 QVector<QVariant> vals;
403 QVector<QVariant> origValues = origArray.values();
405 Q_ASSERT(isVariantStringArray(QVariant::fromValue(origArray)));
408 for (int i = 0; i < m_ui.selectStringCB->count(); ++i) {
409 QVariant val = m_ui.selectStringCB->itemData(i);
410 QVariant origValue = origValues[i];
411 if (origValue != val)
415 return QVariant::fromValue(ApiArray(vals));
418 void ArgumentsEditor::revert()
424 #include "argumentseditor.moc"