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:
40 isVariantStringArray(const QVariant &var)
42 if (var.isNull() || var.userType() != QMetaType::type("ApiArray"))
45 ApiArray array = var.value<ApiArray>();
46 QVector<QVariant> origValues = array.values();
47 if (origValues.isEmpty() ||
48 origValues.first().userType() != QVariant::String)
56 void setArgumentsItemEditorFactory ()
58 QItemEditorCreatorBase *booleanComboBoxEditorCreator =
59 new QStandardItemEditorCreator<BooleanComboBoxEditorCreator>();
60 QItemEditorCreatorBase *uIntEditorCreator =
61 new QStandardItemEditorCreator<UIntEditorCreator>();
62 QItemEditorCreatorBase *intEditorCreator =
63 new QStandardItemEditorCreator<IntEditorCreator>();
64 QItemEditorCreatorBase *uLongLongEditorCreator =
65 new QStandardItemEditorCreator<ULongLongEditorCreator>();
66 QItemEditorCreatorBase *longLongEditorCreator =
67 new QStandardItemEditorCreator<LongLongEditorCreator>();
68 QItemEditorCreatorBase *pixmapEditorCreator =
69 new QStandardItemEditorCreator<PixmapEditorCreator>();
70 QItemEditorCreatorBase *floatEditorCreator =
71 new QStandardItemEditorCreator<FloatEditorCreator>();
72 QItemEditorCreatorBase *doubleEditorCreator =
73 new QStandardItemEditorCreator<DoubleEditorCreator>();
74 QItemEditorCreatorBase *invalidEditorCreator =
75 new QStandardItemEditorCreator<InvalidEditorCreator>();
77 QItemEditorFactory *factory =
78 new QItemEditorFactory();
80 QVariant::Type typeFloat = static_cast<QVariant::Type> (qMetaTypeId<float>());
82 factory->registerEditor(QVariant::Bool, booleanComboBoxEditorCreator);
83 factory->registerEditor(QVariant::UInt, uIntEditorCreator);
84 factory->registerEditor(QVariant::Int, intEditorCreator);
85 factory->registerEditor(QVariant::ULongLong, uLongLongEditorCreator);
86 factory->registerEditor(QVariant::LongLong, longLongEditorCreator);
87 factory->registerEditor(QVariant::Pixmap, pixmapEditorCreator);
88 factory->registerEditor(typeFloat, floatEditorCreator);
89 factory->registerEditor(QVariant::Double, doubleEditorCreator);
90 factory->registerEditor(QVariant::Invalid, invalidEditorCreator);
92 QItemEditorFactory::setDefaultFactory(factory);
95 BooleanComboBox::BooleanComboBox(QWidget *parent)
102 void BooleanComboBox::setValue(bool value)
104 setCurrentIndex(value ? 1 : 0);
107 bool BooleanComboBox::value() const
109 return (currentIndex() == 1);
112 ArgumentsEditor::ArgumentsEditor(QWidget *parent)
114 m_model(new QStandardItemModel()),
120 ArgumentsEditor::~ArgumentsEditor()
125 void ArgumentsEditor::setCall(ApiTraceCall *call)
131 ApiTraceCall * ArgumentsEditor::call() const
136 void ArgumentsEditor::init()
140 connect(m_ui.selectStringCB, SIGNAL(currentIndexChanged(int)),
141 SLOT(currentSourceChanged(int)));
142 connect(m_ui.glslEdit, SIGNAL(textChanged()),
143 SLOT(sourceChanged()));
144 connect(m_ui.revertButton, SIGNAL(clicked()),
147 setArgumentsItemEditorFactory ();
149 m_ui.argsTree->setModel(m_model);
153 void ArgumentsEditor::setupCall()
158 headers.append(tr("Argument"));
159 headers.append(tr("Value"));
160 m_model->setColumnCount(2);
161 m_model->setHorizontalHeaderLabels(headers);
162 m_ui.argsTabWidget->removeTab(
163 m_ui.argsTabWidget->indexOf(m_ui.shaderTab));
168 m_ui.callLabel->setText(m_call->name());
169 QStandardItem *rootItem = m_model->invisibleRootItem();
170 for (int i = 0; i < m_call->argNames().count(); ++i) {
171 QString argName = m_call->argNames()[i];
172 QVariant val = m_call->arguments()[i];
173 QStandardItem *nameItem = new QStandardItem(argName);
174 nameItem->setFlags(nameItem->flags() ^ Qt::ItemIsEditable);
175 QList<QStandardItem*> topRow;
176 topRow.append(nameItem);
178 if (val.canConvert<ApiArray>()) {
179 ApiArray array = val.value<ApiArray>();
180 QVector<QVariant> vals = array.values();
182 QVariant firstVal = vals.value(0);
183 if (firstVal.userType() == QVariant::String) {
184 m_ui.argsTabWidget->addTab(
185 m_ui.shaderTab, argName);
186 setupShaderEditor(vals);
189 } else if (isVariantEditable(firstVal)) {
190 for (int i = 0; i < vals.count(); ++i) {
191 QList<QStandardItem*> row;
193 QStandardItem *idx = new QStandardItem();
194 idx->setFlags(idx->flags() ^ Qt::ItemIsEditable);
195 idx->setText(tr("%1)").arg(i));
197 QStandardItem *col = new QStandardItem();
198 col->setFlags(col->flags() | Qt::ItemIsEditable);
199 col->setData(vals[i], Qt::EditRole);
202 nameItem->appendRow(row);
205 qDebug()<<"\tUnsupported array = "<<firstVal;
209 } else if (val.canConvert<ApiPointer>()) {
210 ApiPointer ptr = val.value<ApiPointer>();
211 QStandardItem *item = new QStandardItem();
212 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
213 item->setText(ptr.toString());
214 QIcon icon(":/resources/emblem-locked.png");
216 item->setToolTip(tr("Argument is read-only"));
218 } else if (val.canConvert<ApiEnum>()) {
219 ApiEnum en = val.value<ApiEnum>();
220 QStandardItem *item = new QStandardItem();
221 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
222 item->setText(en.toString());
223 QIcon icon(":/resources/emblem-locked.png");
225 item->setToolTip(tr("Argument is read-only"));
227 } else if (val.canConvert<ApiBitmask>()) {
228 ApiBitmask mask = val.value<ApiBitmask>();
229 QStandardItem *item = new QStandardItem();
230 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
231 item->setText(mask.toString());
232 QIcon icon(":/resources/emblem-locked.png");
234 item->setToolTip(tr("Argument is read-only"));
236 } else if (val.canConvert<ApiStruct>()) {
237 ApiStruct str = val.value<ApiStruct>();
238 QStandardItem *item = new QStandardItem();
239 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
240 item->setText(str.toString());
241 QIcon icon(":/resources/emblem-locked.png");
243 item->setToolTip(tr("Argument is read-only"));
245 } else if (val.userType() == QVariant::ByteArray) {
246 QByteArray ba = val.value<QByteArray>();
247 QStandardItem *item = new QStandardItem();
248 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
250 tr("<binary data, size = %1 bytes>").arg(ba.size()));
251 QIcon icon(":/resources/emblem-locked.png");
253 item->setToolTip(tr("Argument is read-only"));
257 = new QStandardItem();
259 if (isVariantEditable(val)) {
260 item->setFlags(item->flags() | Qt::ItemIsEditable);
262 QIcon icon(":/resources/emblem-locked.png");
264 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
265 item->setToolTip(tr("Argument is read-only"));
267 item->setData(val, Qt::EditRole);
270 rootItem->appendRow(topRow);
274 void ArgumentsEditor::setupShaderEditor(const QVector<QVariant> &sources)
276 m_ui.selectStringCB->clear();
277 m_ui.glslEdit->clear();
278 for (int i = 0; i < sources.count(); ++i) {
279 m_ui.selectStringCB->addItem(
280 tr("Shader string: %1").arg(i),
283 m_ui.selectStringCB->setCurrentIndex(0);
286 void ArgumentsEditor::currentSourceChanged(int idx)
288 QVariant source = m_ui.selectStringCB->itemData(idx);
289 QString str = source.toString();
290 m_ui.glslEdit->setPlainText(source.toString());
291 m_ui.lengthLabel->setText(
292 tr("%1").arg(str.length()));
295 void ArgumentsEditor::sourceChanged()
297 QString str = m_ui.glslEdit->toPlainText();
298 m_ui.lengthLabel->setText(
299 tr("%1").arg(str.length()));
301 m_ui.selectStringCB->setItemData(
302 m_ui.selectStringCB->currentIndex(),
306 void ArgumentsEditor::accept()
308 QStringList argNames = m_call->argNames();
309 QVector<QVariant> originalValues = m_call->arguments();
310 QVector<QVariant> newValues;
311 bool changed = false;
312 for (int i = 0; i < argNames.count(); ++i) {
313 bool valChanged = false;
314 QString argName = argNames[i];
315 QVariant argValue = originalValues[i];
316 QVariant editorValue = valueForName(argName, argValue, &valChanged);
318 newValues.append(editorValue);
320 qDebug()<<"Arg = "<<argName;
321 qDebug()<<"\toriginal = "<<argValue;
322 qDebug()<<"\teditor = "<<editorValue;
323 qDebug()<<"\tchanged = "<<valChanged;
329 m_call->setEditedValues(newValues);
333 QVariant ArgumentsEditor::valueForName(const QString &name,
334 const QVariant &originalValue,
341 //Handle string arrays specially
342 if (isVariantStringArray(originalValue)) {
343 ApiArray array = originalValue.value<ApiArray>();
344 return arrayFromEditor(array, changed);
347 if (!isVariantEditable(originalValue)) {
348 return originalValue;
351 for (int topRow = 0; topRow < m_model->rowCount(); ++topRow) {
352 QModelIndex nameIdx = m_model->index(topRow, 0, QModelIndex());
353 QString argName = nameIdx.data().toString();
354 /* we display shaders in a separate widget so
355 * the ordering might be different */
356 if (argName == name) {
357 if (originalValue.userType() == QMetaType::type("ApiArray")) {
358 ApiArray array = originalValue.value<ApiArray>();
359 val = arrayFromIndex(nameIdx, array, changed);
361 QModelIndex valIdx = m_model->index(topRow, 1, QModelIndex());
363 if (val != originalValue)
371 QVariant ArgumentsEditor::arrayFromIndex(const QModelIndex &parentIndex,
372 const ApiArray &origArray,
375 QVector<QVariant> origValues = origArray.values();
379 if (origValues.isEmpty())
380 return QVariant::fromValue(ApiArray());
382 QVector<QVariant> lst;
383 for (int i = 0; i < origValues.count(); ++i) {
384 QModelIndex valIdx = m_model->index(i, 1, parentIndex);
385 QVariant var = valIdx.data();
386 QVariant origValue = origValues[i];
387 if (var != origValue)
389 //qDebug()<<"\t\tarray "<<i<<") "<<var;
392 return QVariant::fromValue(ApiArray(lst));
395 QVariant ArgumentsEditor::arrayFromEditor(const ApiArray &origArray,
398 QVector<QVariant> vals;
399 QVector<QVariant> origValues = origArray.values();
401 Q_ASSERT(isVariantStringArray(QVariant::fromValue(origArray)));
404 for (int i = 0; i < m_ui.selectStringCB->count(); ++i) {
405 QVariant val = m_ui.selectStringCB->itemData(i);
406 QVariant origValue = origValues[i];
407 if (origValue != val)
411 return QVariant::fromValue(ApiArray(vals));
414 void ArgumentsEditor::revert()
420 #include "argumentseditor.moc"